Preload API
Elftia 通过 Electron 的 contextBridge 将后端能力安全地暴露给前端。前端通过 window.api 全局对象调用所有后端功能。
认证机制
所有 IPC 调用都自动携带认证 Token,开发者无需手动处理:
{/* packages/desktop/app/preload/index.ts — 简化示意 */}
const authToken = ipcRenderer.sendSync('auth:bootstrap');
const invoke = (channel: string, ...args: any[]) =>
ipcRenderer.invoke(channel, authToken, ...args);
命名空间索引
| 命名空间 | 职责 | 方法数 |
|---|---|---|
runtime | 运行时环境 | 1 |
authSession | 认证会话 | 8 |
account | 账户管理 | 7 |
projects | 项目管理 | 6 |
files | 文件操作 | 12 |
sessions | 项目会话 | 3 |
chat | 聊天核心 | 6 |
chatSessions | 聊天会话 CRUD | 5 |
chatMessages | 聊天消息 CRUD | 7 |
chatAssistants | 聊天助手 CRUD | 6 |
completion | LLM 补全 | 10 |
llmConfig | LLM 配置 | 30+ |
settings | 应用设置 | 4 |
appPreferences | 应用偏好 | 2 |
config | 文件配置 | 7 |
theme | 主题管理 | 11 |
mcp | MCP 服务器 | 12 |
agent | Agent 操作 | 15+ |
magi | Magi 服务 | 4 |
elfi | Elfi 助手 | 3 |
image | 图片生成 | 3 |
video | 视频生成 | 3 |
music | 音乐生成 | 1 |
media | 媒体管理 | 10 |
webSearch | 网络搜索 | 9 |
windowControls | 窗口控制 | 7 |
diagnostics | 系统诊断 | 6 |
env | 环境检测 | 5 |
git | Git 操作 | 2 |
prompts | 提示词管理 | 9 |
export | 导出功能 | 2 |
channelPlugins | Channel 插件 | 6 |
runtime
window.api.runtime.getEnvironment(): Promise<RuntimeEnvironment>
返回运行时环境信息(平台、版本、路径等)。
authSession
window.api.authSession.getState(): Promise<AuthState>
window.api.authSession.startBrowserLogin(): Promise<void>
window.api.authSession.refresh(): Promise<void>
window.api.authSession.syncProfile(): Promise<void>
window.api.authSession.getAccessToken(): Promise<string>
window.api.authSession.logout(): Promise<void>
window.api.authSession.retrySteamLogin(): Promise<void>
window.api.authSession.subscribe(cb: (state: AuthState) => void): () => void
subscribe 返回取消订阅函数。
account
window.api.account.list(type?: string): Promise<Account[]>
window.api.account.create(payload: CreateAccountInput): Promise<Account>
window.api.account.delete(id: string): Promise<void>
window.api.account.toggle(id: string, isActive: boolean): Promise<void>
window.api.account.reveal(id: string): Promise<string>
window.api.account.export(options?: ExportOptions): Promise<ExportResult>
window.api.account.clear(type?: string): Promise<void>
projects
window.api.projects.list(): Promise<Project[]>
window.api.projects.create(input: { path: string; displayName?: string }): Promise<Project>
window.api.projects.rename(projectId: string, displayName?: string): Promise<void>
window.api.projects.delete(projectId: string): Promise<void>
window.api.projects.browse(dirPath?: string): Promise<BrowseResult>
window.api.projects.createWorkspace(payload: { path: string; workspaceType: string }): Promise<void>
files
window.api.files.snapshot(projectId: string): Promise<FileTree>
window.api.files.subscribe(projectId: string, cb: (patch: FilePatch) => void): () => void
window.api.files.watch(projectId: string): Promise<void>
window.api.files.unwatch(projectId: string): Promise<void>
window.api.files.read(projectId: string, filePath: string): Promise<string>
window.api.files.readBinary(projectId: string, filePath: string): Promise<Buffer>
window.api.files.write(projectId: string, filePath: string, content: string): Promise<void>
window.api.files.shallow(projectId: string, dirPath?: string): Promise<FileEntry[]>
window.api.files.search(projectId: string, params?: SearchParams): Promise<SearchResult[]>
window.api.files.searchMetrics(): Promise<SearchMetrics>
window.api.files.revealInFolder(filePath: string): Promise<void>
window.api.files.clearCache(projectId: string): Promise<void>
chat
window.api.chat.appendMessage(sessionId: string, msg: any): Promise<void>
window.api.chat.getMessages(sessionId: string, query?: any): Promise<Message[]>
window.api.chat.sendCommand(payload: CommandPayload): Promise<void>
window.api.chat.abortSession(payload: { sessionId: string }): Promise<void>
window.api.chat.checkSessionStatus(payload: { sessionId: string }): Promise<SessionStatus>
window.api.chat.onEvent(cb: (data: ChatEvent) => void): () => void
chatSessions
window.api.chatSessions.list(query?: ListQuery): Promise<ChatSession[]>
window.api.chatSessions.get(id: string): Promise<ChatSession>
window.api.chatSessions.create(input: CreateChatSessionInput): Promise<ChatSession>
window.api.chatSessions.update(id: string, input: UpdateInput): Promise<ChatSession>
window.api.chatSessions.delete(id: string): Promise<void>
chatMessages
window.api.chatMessages.getActivePath(sessionId: string): Promise<Message[]>
window.api.chatMessages.getPage(query: PageQuery): Promise<PageResult>
window.api.chatMessages.getBranches(sessionId: string, parentId: string | null): Promise<Message[]>
window.api.chatMessages.append(sessionId: string, message: MessageInput): Promise<Message>
window.api.chatMessages.update(messageId: string, updates: MessageUpdate): Promise<Message>
window.api.chatMessages.switchBranch(messageId: string): Promise<void>
window.api.chatMessages.delete(messageId: string): Promise<void>
chatAssistants
window.api.chatAssistants.list(): Promise<ChatAssistant[]>
window.api.chatAssistants.get(id: string): Promise<ChatAssistant>
window.api.chatAssistants.create(input: CreateAssistantInput): Promise<ChatAssistant>
window.api.chatAssistants.update(id: string, input: UpdateInput): Promise<ChatAssistant>
window.api.chatAssistants.delete(id: string): Promise<void>
window.api.chatAssistants.setDefault(id: string): Promise<void>
completion
window.api.completion.complete(payload: CompletePayload): Promise<CompleteResult>
window.api.completion.stream(payload: StreamPayload): Promise<{ streamId: string }>
window.api.completion.onStreamEvent(streamId: string, cb: (data: StreamEvent) => void): () => void
window.api.completion.getModels(providerId: string): Promise<Model[]>
window.api.completion.testModel(providerId: string, modelId: string): Promise<TestResult>
window.api.completion.chatInSession(payload: ChatInSessionPayload): Promise<void>
window.api.completion.regenerateInSession(payload: RegeneratePayload): Promise<void>
window.api.completion.onChatCompleted(cb: (data: ChatCompletedEvent) => void): () => void
window.api.completion.createRPFirstMessage(payload: { sessionId: string }): Promise<void>
llmConfig
{/* 提供商 CRUD */}
window.api.llmConfig.getProviders(): Promise<Provider[]>
window.api.llmConfig.getProvider(id: string): Promise<Provider>
window.api.llmConfig.addProvider(payload: AddProviderInput): Promise<Provider>
window.api.llmConfig.updateProvider(payload: UpdateProviderInput): Promise<Provider>
window.api.llmConfig.deleteProvider(id: string): Promise<void>
window.api.llmConfig.toggleProvider(id: string, enabled: boolean): Promise<void>
window.api.llmConfig.discoverModels(id: string, options?: { forceRefresh?: boolean }): Promise<Model[]>
{/* 预设 */}
window.api.llmConfig.getProviderPresets(): Promise<Preset[]>
window.api.llmConfig.addFromPreset(payload: { presetId: string; apiKey?: string }): Promise<Provider>
{/* 模型参数 */}
window.api.llmConfig.getAgentDefaultModels(): Promise<DefaultModels>
window.api.llmConfig.setAgentDefaultModels(payload: DefaultModels): Promise<void>
window.api.llmConfig.getGlobalModelParameters(): Promise<GlobalModelParameters>
window.api.llmConfig.setGlobalModelParameters(payload: GlobalModelParameters): Promise<void>
{/* API 密钥池 */}
window.api.llmConfig.getApiKeys(providerId: string): Promise<ApiKeyEntry[]>
window.api.llmConfig.addApiKey(input: ApiKeyInput): Promise<ApiKeyEntry>
window.api.llmConfig.updateApiKey(id: string, updates: ApiKeyUpdate): Promise<ApiKeyEntry>
window.api.llmConfig.deleteApiKey(id: string): Promise<void>
window.api.llmConfig.toggleApiKey(id: string, enabled: boolean): Promise<void>
{/* 导入/导出 */}
window.api.llmConfig.exportConfig(): Promise<ExportedConfig>
window.api.llmConfig.importConfig(payload: ExportedConfig): Promise<void>
settings
window.api.settings.get(key: string): Promise<any>
window.api.settings.set(key: string, value: any): Promise<void>
window.api.settings.getExperimentalFeatures(): Promise<ExperimentalFeatures>
window.api.settings.setExperimentalFeatures(payload: ExperimentalFeatures): Promise<void>
appPreferences
window.api.appPreferences.get(): Promise<AppPreferences>
window.api.appPreferences.update(payload: Partial<AppPreferences>): Promise<void>
config
window.api.config.get(key: string): Promise<any>
window.api.config.getAll(): Promise<Record<string, any>>
window.api.config.getPath(): Promise<string>
window.api.config.set(key: string, value: any): Promise<void>
window.api.config.merge(key: string, patch: any): Promise<void>
window.api.config.reset(key: string): Promise<void>
window.api.config.onChange(cb: (event: ConfigChangeEvent) => void): () => void
theme
window.api.theme.getState(): Promise<ThemeState>
window.api.theme.setMode(mode: 'light' | 'dark' | 'system'): Promise<void>
window.api.theme.updateUserTheme(payload: UserThemeUpdate): Promise<void>
window.api.theme.setCustomCss(css: string): Promise<void>
window.api.theme.setWallpaper(payload: WallpaperConfig): Promise<void>
window.api.theme.setWallpaperPreferences(payload: WallpaperPreferences): Promise<void>
window.api.theme.setRemoteAssetsPolicy(payload: RemoteAssetsPolicy): Promise<void>
window.api.theme.exportProfile(): Promise<ThemeProfile>
window.api.theme.importProfile(payload: ThemeProfile): Promise<void>
window.api.theme.resetProfile(): Promise<void>
window.api.theme.onUpdated(cb: (state: ThemeState) => void): () => void
mcp
window.api.mcp.list(): Promise<McpServer[]>
window.api.mcp.add(payload: AddMcpInput): Promise<McpServer>
window.api.mcp.addJson(payload: JsonMcpConfig): Promise<McpServer>
window.api.mcp.remove(payload: { id: string }): Promise<void>
window.api.mcp.test(payload: { id: string }): Promise<TestResult>
window.api.mcp.discover(payload: { id: string }): Promise<DiscoveryResult>
window.api.mcp.update(payload: { id: string; updates: McpUpdate }): Promise<void>
window.api.mcp.listServerTools(serverId: string): Promise<Tool[]>
window.api.mcp.listAllTools(): Promise<Tool[]>
window.api.mcp.callTool(payload: CallToolInput): Promise<ToolResult>
window.api.mcp.checkDependency(command: string): Promise<boolean>
window.api.mcp.installDependency(command: string): Promise<void>
agent
window.api.agent.checkAvailability(): Promise<boolean>
window.api.agent.getBackends(): Promise<BackendInfo[]>
window.api.agent.createSession(options: CreateSessionOptions): Promise<{ sessionId: string }>
window.api.agent.resumeSession(params: ResumeParams): Promise<void>
window.api.agent.interrupt(sessionId: string): Promise<void>
window.api.agent.respondPermission(params: { requestId: string; result: any }): Promise<void>
window.api.agent.respondAskUserQuestion(params: { requestId: string; result: { answers: Record<string, string>; annotations?: Record<string, { notes?: string }>; cancelled?: boolean } }): Promise<{ success: boolean }>
window.api.agent.getActiveSessions(): Promise<ActiveSession[]>
window.api.agent.isSessionActive(sessionId: string): Promise<boolean>
window.api.agent.selectFolder(): Promise<{ canceled: boolean; path: string | null }>
window.api.agent.onEvent(cb: (data: AgentEvent) => void): () => void
window.api.agent.onPermissionRequest(cb: (data: PermissionRequest) => void): () => void
window.api.agent.onAskUserQuestion(cb: (data: AskUserQuestionRequest) => void): () => void
window.api.agent.onA2UIRender(cb: (data: A2UIEvent) => void): () => void
window.api.agent.onDevPreview(cb: (data: PreviewStatus) => void): () => void
{/* 子命名空间 */}
window.api.agent.customAgents.list/get/create/update/delete/run/export/import(...)
window.api.agent.mcpRefs.list/attach/detach/toggleEnabled(...)
window.api.agent.agentSessions.create/get/list/update/delete(...)
window.api.agent.sharedComponents.create/get/list/update/delete(...)
window.api.agent.personas.list/get/create/update/delete(...)
image
window.api.image.generate(payload: ImageGeneratePayload): Promise<ImageResult>
window.api.image.generateInSession(payload: SessionImagePayload): Promise<void>
window.api.image.onGenerationCompleted(cb: (data: GenerationCompletedEvent) => void): () => void
video
window.api.video.generate(payload: VideoGeneratePayload): Promise<VideoResult>
window.api.video.generateInSession(payload: SessionVideoPayload): Promise<void>
window.api.video.onGenerationCompleted(cb: (data: GenerationCompletedEvent) => void): () => void
music
window.api.music.generateInSession(payload: SessionMusicPayload): Promise<void>
sessions
window.api.sessions.list(projectId: string, query?: any): Promise<Session[]>
window.api.sessions.delete(projectId: string, sessionId: string): Promise<void>
window.api.sessions.getTokenUsage(projectId: string, sessionId: string): Promise<TokenUsage>
magi
window.api.magi.getStatus(): Promise<MagiStatus>
window.api.magi.getConfig(): Promise<MagiConfig>
window.api.magi.updateConfig(payload: Partial<MagiConfig>): Promise<void>
window.api.magi.resetSession(): Promise<void>
elfi
window.api.elfi.ask(payload: { question: string; context?: string }): Promise<ElfiResponse>
window.api.elfi.getKnowledge(path: string): Promise<string>
window.api.elfi.searchKnowledge(query: string): Promise<KnowledgeResult[]>
media
window.api.media.migrateBase64ToFiles(): Promise<MigrationResult>
window.api.media.getMigrationStatus(): Promise<MigrationStatus>
window.api.media.onMigrationProgress(cb: (data: ProgressEvent) => void): () => void
window.api.media.generateMissingThumbnails(): Promise<MigrationResult>
window.api.media.onThumbnailProgress(cb: (data: ProgressEvent) => void): () => void
window.api.media.compressImage(payload: { base64: string; mimeType: string }): Promise<CompressResult>
window.api.media.compressDataUrl(dataUrl: string): Promise<CompressResult>
window.api.media.compressMany(payload: CompressInput[]): Promise<CompressResult[]>
window.api.media.migrateAttachmentsToFiles(): Promise<MigrationResult>
window.api.media.getAttachmentMigrationStatus(): Promise<MigrationStatus>
env
window.api.env.checkAll(options?: { force?: boolean }): Promise<EnvCheckResult>
window.api.env.installTool(name: string): Promise<void>
window.api.env.repairAll(): Promise<void>
window.api.env.getLastResult(): Promise<EnvCheckResult>
window.api.env.onProgress(cb: (data: ProgressEvent) => void): () => void
git
window.api.git.status(projectId: string): Promise<GitStatus>
window.api.git.diff(projectId: string, filePath: string, options?: { staged?: boolean; isUntracked?: boolean }): Promise<string>
prompts
window.api.prompts.list(query?: ListQuery): Promise<Prompt[]>
window.api.prompts.get(id: string): Promise<Prompt>
window.api.prompts.create(input: CreatePromptInput): Promise<Prompt>
window.api.prompts.update(id: string, input: UpdatePromptInput): Promise<Prompt>
window.api.prompts.delete(id: string): Promise<void>
window.api.prompts.reorder(ids: string[], sortOrders: number[]): Promise<void>
window.api.prompts.incrementUsage(id: string): Promise<void>
window.api.prompts.search(query: string, limit?: number): Promise<Prompt[]>
window.api.prompts.quickList(): Promise<Prompt[]>
export
window.api.export.sessions(input: ExportSessionsInput): Promise<ExportResult[]>
window.api.export.messages(input: ExportMessagesInput): Promise<ExportResult>
channelPlugins
window.api.channelPlugins.listPlugins(): Promise<ChannelPlugin[]>
window.api.channelPlugins.listInstances(): Promise<ChannelInstance[]>
window.api.channelPlugins.add(payload: AddChannelInput): Promise<ChannelInstance>
window.api.channelPlugins.remove(id: string): Promise<void>
window.api.channelPlugins.update(payload: UpdateChannelInput): Promise<void>
window.api.channelPlugins.changeStatus(payload: { id: string; status: ChannelStatus }): Promise<void>
webSearch
window.api.webSearch.search(query: string, providerId: string, options?: SearchOptions): Promise<SearchResult[]>
window.api.webSearch.configureProvider(config: ProviderConfig): Promise<void>
window.api.webSearch.configureProviders(configs: ProviderConfig[]): Promise<void>
window.api.webSearch.isProviderEnabled(providerId: string): Promise<boolean>
window.api.webSearch.getProviderConfig(providerId: string): Promise<ProviderConfig>
window.api.webSearch.getProviders(): Promise<Provider[]>
window.api.webSearch.jinaReader(url: string, options?: { timeout?: number }): Promise<string>
window.api.webSearch.isAvailable(): Promise<boolean>
windowControls
window.api.windowControls.minimize(): Promise<void>
window.api.windowControls.toggleMaximize(): Promise<void>
window.api.windowControls.close(): Promise<void>
window.api.windowControls.toggleDevTools(): Promise<void>
window.api.windowControls.getDeveloperMode(): Promise<boolean>
window.api.windowControls.enableDeveloperMode(): Promise<void>
window.api.windowControls.disableDeveloperMode(): Promise<void>
diagnostics
window.api.diagnostics.dump(): Promise<DiagnosticsData>
window.api.diagnostics.export(options: ExportOptions): Promise<string>
window.api.diagnostics.bundle(options: BundleOptions): Promise<string>
window.api.diagnostics.clearCaches(): Promise<void>
window.api.diagnostics.dbVacuum(): Promise<void>
window.api.diagnostics.dbGetSize(): Promise<number>
事件订阅模式
所有 onXxx 方法都返回一个取消订阅函数,典型用法:
useEffect(() => {
const unsubscribe = window.api.chat.onEvent((data) => {
handleChatEvent(data);
});
return unsubscribe; // 组件卸载时自动取消订阅
}, []);
主要事件通道汇总
| 方法 | 推送通道 | 事件内容 |
|---|---|---|
authSession.subscribe | authSession:state | 认证状态变更 |
chat.onEvent | chat:event | 聊天流式事件 |
completion.onStreamEvent | completion:stream:{id} | 补全流式事件 |
completion.onChatCompleted | chat:completed | 聊天完成 |
image.onGenerationCompleted | generation:completed | 图片生成完成 |
video.onGenerationCompleted | video:generation:completed | 视频生成完成 |
agent.onEvent | agent:event | Agent 事件 |
agent.onPermissionRequest | agent:permissionRequest | 权限请求 |
agent.onAskUserQuestion | agent:askUserQuestion | Agent 提问(ask_user_question MCP) |
theme.onUpdated | theme:updated | 主题变更 |
config.onChange | config:changed | 配置变更 |
files.subscribe | files:patch:{projectId} | 文件变更补丁 |
env.onProgress | env:progress | 环境检测进度 |