启动阶段
Elftia 主进程的启动流程分为 13 个阶段,每个阶段有明确的职责和依赖关系。所有阶段的代码位于 packages/desktop/app/main/index.ts 的 createServices() 函数中。
启动阶段总览
flowchart TB
P0[Phase 0: 协议注册 + Logger]
P1[Phase 1: 核心服务]
P2[Phase 2: 功能服务]
P25[Phase 2.5: 包加载]
P26[Phase 2.6: 包同步]
P27[Phase 2.7: 包管理服务]
PS1[Phase S1: Magi 调度]
PS2[Phase S2: MagiService]
PS25[Phase S2.5: CronService]
PC1[Phase C1: Channel 插件]
PS3[Phase S3: ChannelMagiBridge]
P3[Phase 3: IPC 路由注册]
PT[Phase T1-T3: Todo/Task/Notes]
PW1[Phase W1: 窗口创建]
PW2[Phase W2: WebSocket/协议]
P0 --> P1 --> P2 --> P25 --> P26 --> P27
P27 --> PS1 --> PS2 --> PS25
PS25 --> PC1 --> PS3
PS3 --> P3 --> PT --> PW1 --> PW2
Phase 0: 协议注册 + Logger
在 app.whenReady() 之前执行,注册自定义协议和核心日志服务。
flowchart LR
A[注册 elftia:// 协议] --> B[注册特权 schemes]
B --> C[wallpaper://]
B --> D[media://]
B --> E[resource://]
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | app.setAsDefaultProtocolClient('elftia') | 注册 Deep Link 协议 |
| 2 | protocol.registerSchemesAsPrivileged() | 注册 wallpaper/media/resource 特权协议 |
| 3 | new LoggerService() | 创建日志服务 (Winston + daily-rotate) |
| 4 | setIpcLogger(logger) | 设置 IPC 层日志记录 |
| 5 | new ErrorHandler(logger) | 创建全局错误处理 |
| 6 | setIpcErrorHandler(errorHandler) | 设置 IPC 层错误处理 |
| 7 | new AutoUpdateService(logger) | 创建自动更新服务 |
| 8 | new DownloadService(logger) | 创建下载服务 |
| 9 | new WebUpdateService(logger, downloadManager) | 创建 Web 更新服务 |
关键文件: packages/desktop/app/main/services/infra/logger/LoggerService.ts, packages/desktop/app/main/services/infra/error/ErrorHandler.ts
Phase 1: 核心服务
创建应用运行所需的基础服务,这些服务没有外部依赖。
flowchart LR
RT[RuntimeService] --> AP[AppPaths]
AP --> DB[DbClient + ready]
DB --> SS[SettingsService]
SS --> CS[ConfigStore]
CS --> Migrate[配置迁移]
Migrate --> Auth[Auth 服务链]
Auth --> WC[WindowControlsService]
| 步骤 | 服务 | 依赖 | 说明 |
|---|---|---|---|
| 1 | RuntimeService | 无 | 运行时信息 (版本、平台、渠道) |
| 2 | AppPaths | 无 | 路径解析 |
| 3 | DbClient | AppPaths | 数据库 Worker 创建 |
| 4 | await db.ready() | DbClient | 阻塞等待 Worker 初始化完成 |
| 5 | initDatabase() | db.ready | Drizzle ORM + WAL + migrate |
| 6 | SettingsService | AppPaths | 应用设置 |
| 7 | ConfigStore | AppPaths | electron-store 配置文件 |
| 8 | migrateSettingsToConfigStore() | Settings, ConfigStore | SQLite -> config.json 迁移 |
| 9 | settings.setConfigStore(configStore) | - | 委托模式连接 |
| 10 | configStore.startWatching() | - | fs.watch 配置热重载 |
| 11 | AccountService | AppPaths | 用户凭证 |
| 12 | AuthTokenStore | AccountService | Token 存储 |
| 13 | AuthSessionService | Runtime, AuthStore, AuthApi | 认证会话 |
| 14 | AppPreferencesService | ConfigStore | 应用偏好 |
| 15 | WindowControlsService | Settings | 窗口控制 |
关键: await db.ready() 是阻塞点,确保 SQLite Worker 完成 Schema 创建后再继续。这防止了第一次启动时两个连接同时写入导致的 SQLITE_BUSY。
Phase 2: 功能服务
创建轻量级功能服务,重初始化延迟到使用时执行。
| 服务 | 依赖 | 说明 |
|---|---|---|
ConfigManager | Logger, AppPaths | 配置文件管理 |
SecurityService | Logger | AES-256-GCM 加密 |
PerformanceMonitor | Logger | 性能监控 |
CacheService | Logger | 通用缓存 |
DatabaseOptimizer | Logger, DbClient | SQLite 优化 |
NotificationService | Logger | 桌面通知 |
PluginManager | Logger | 插件生命周期 |
ProjectService | DbClient, AccountService | 项目管理 |
DiagnosticsService | AppPaths, ProjectService | 诊断服务 |
ChatService | Logger | 聊天服务 |
McpService | Logger | MCP 服务器管理 |
LLMConfigService | AppPaths, DbClient | LLM 配置 |
CompletionService | AppPaths, LLMConfigService | LLM 补全 |
ApiKeyPoolService | DB, CompletionService | 多密钥轮询 |
ElfiService | ConfigStore, LLMConfig, Completion | Elfi 助手 |
MediaConfigService | AppPaths, DbClient | 媒体配置 |
ImageGenerationService | MediaConfig | 图片生成 |
ThemeService | Settings, AuthSession | 主题管理 |
AgentService | DbClient, Settings, Logger | Agent 服务 |
TransformerService | - | 请求转换 |
WebSearchService | - | 网络搜索 |
EngineDispatcher + 引擎注册 | 各引擎依赖 | 引擎调度 |
引擎注册顺序
{/* 引擎注册 */}
engineDispatcher.registerEngine(new ApiEngine(...));
engineDispatcher.registerEngine(new ChatEngine(...));
engineDispatcher.registerEngine(new ClaudeSdkEngine(...));
engineDispatcher.registerEngine(new CliRunnerEngine(...));
engineDispatcher.registerEngine(new TinyElfEngine(...));
engineDispatcher.registerEngine(new STChatEngine(...));
Phase 2.5: 包加载
从磁盘加载 Agent 包、Persona 包和 Script 插件到内存。
flowchart TB
subgraph "Phase 2.5a: Agent Packages"
AL[AgentPackageLoader] --> BP[加载 builtin 包]
BP --> UP[加载 user 包]
UP --> AR[AgentPackageRegistry]
end
subgraph "Phase 2.5b: Persona Packages"
PL[PersonaPackageLoader] --> BPP[加载 builtin 包]
BPP --> UPP[加载 user 包]
UPP --> PR[PersonaPackageRegistry]
end
subgraph "Phase 2.5c: Script Plugins"
SL[ScriptPluginLoader] --> BSP[加载 builtin 插件]
BSP --> USP[加载 user 插件]
USP --> SR[ScriptPluginRegistry]
end
加载路径(双目录模式):
| 包类型 | Builtin 路径 (打包) | Builtin 路径 (开发) | User 路径 |
|---|---|---|---|
| Agent | resources/agent-packages/ | ../../agent-packages/ | {userData}/agent-packages/ |
| Persona | resources/persona-packages/ | ../../persona-packages/ | {userData}/persona-packages/ |
| Script | resources/script-plugins/ | ../../script-plugins/ | {userData}/script-plugins/ |
Phase 2.6-2.7: 包同步与管理
| 阶段 | 操作 | 说明 |
|---|---|---|
| 2.6 | PackageSyncService.syncAll() | 将内存中的包定义同步到数据库 (upsert FK anchors + persona data) |
| 2.7 | new AgentPackageService(...) | 创建包管理服务,支持 install/uninstall |
Phase S1: Magi 调度
创建 Agent 编排和调度相关服务。
flowchart TB
AGM[AgentManagementService] --> EB[SessionEventBus]
EB --> AD[AgentDiscovery]
AD --> AO[AgentOrchestrator]
AO --> MR[MessageRouter]
MR --> SDI[SessionDispatcherImpl]
AO -.->|setEngineDispatcher| ED[EngineDispatcher]
AO -.->|setDbProvider| DB[DbClient]
SDI -.->|注入到| TE[TinyElfEngine]
| 步骤 | 服务 | 说明 |
|---|---|---|
| 1 | AgentManagementService | Agent CRUD + 包注册表查询 |
| 2 | InternalSessionEventBus | 会话事件发布/订阅 |
| 3 | AgentDiscovery | Agent 可调度清单(从 DB + 包注册表发现) |
| 4 | AgentOrchestrator | Agent 调度编排,API dispatch handler |
| 5 | MessageRouter | 双模式消息路由(直连 / 通过 Orchestrator) |
| 6 | SessionDispatcherImpl | 跨会话调度实现 |
| 7 | 注入到 TinyElfEngine | tinyElfEngine.setSessionDispatcher(sessionDispatcher) |
| 8 | SubagentRegistry.setDb(db) | 子智能体注册表写穿持久化 |
历史说明:
DispatchServerHTTP 调度服务器在cleanup-legacy-mcp(2026-05-19)删除。dispatch 工具现由MagiDispatchProvider+MagiDispatchHandlers(in-process)通过统一注册表装配,handler 直接调AgentOrchestrator/AgentDiscovery,不再走 HTTP。CLI 子进程通过中央services/capabilities/tools/mcp-builtin/BuiltinMcpHttpServer.ts访问。
Phase S2: MagiService
创建核心消息处理服务并注入所有依赖。
{/* MagiService 依赖注入链 */}
const magiService = new MagiService(
magiWorkspace, magiSession, magiOptionsBuilder,
magiOrchestrator, magiMessageRouter, magiEventBus,
llmConfig, logger, configStore,
);
// 延迟注入 (避免循环依赖)
magiService.setAgentService(agent);
magiService.setCompletionService(completion);
magiService.setAsrService(new AsrService(asrConfig));
magiService.setEngineDispatcher(engineDispatcher);
magiService.setDbProvider(db);
magiService.setMcpListProvider(() => mcp.list());
magiService.setDeveloperModeProvider(() => ...);
MCP 热重载: 当 MCP 服务器列表变化时,自动同步到 Magi 工作空间并热重载活动会话:
mcp.on('servers:changed', () => {
magiService.syncMcpServersToWorkspace();
magiService.notifyMcpChanged();
});
Phase S2.5: CronService
创建 Cron 定时任务调度服务:
| 注入 | 用途 |
|---|---|
setNotificationService(notification) | 桌面通知 |
setNotificationChecker(...) | 检查通知偏好 |
setAgentExecutor(...) | 通过 MagiService 执行定时任务 |
setStatusBroadcaster(...) | 向前端广播任务状态 |
Phase C1: Channel 插件
发现、加载和注册 Channel 插件。
flowchart TB
CL[ChannelPluginLoader] --> Discover[discover 发现插件]
Discover --> Load[load 加载每个插件]
Load --> CR[ChannelPluginRegistry.registerPlugin]
CR --> CM[ChannelMarketplaceService<br/>异步获取远程清单]
subgraph "安全服务连接"
UPS[UserPermissionService] --> CMR[ChannelMessageRouter]
CPG[ChannelPermissionGate] --> CMR
AL[AuditLogger] --> TE[TinyElfEngine]
RL[RateLimiter] --> CMR
IS[InputSanitizer] --> CMR
PG[PromptGuardian] --> CMR
end
CR --> CMR
加载路径(双目录模式):
| 来源 | 路径 (打包) | 路径 (开发) |
|---|---|---|
| Bundled (只读) | resources/bundled-channel-plugins/ | elftia-channels/dist-plugins/ |
| Marketplace (可写) | {userData}/channel-plugins/ | 同 |
安全服务连接顺序:
UserPermissionService-> ChannelMessageRouter(用户权限检查)ChannelPermissionGate-> ChannelMessageRouter + TinyElfEngine(权限确认)AuditLogger-> TinyElfEngine(审计日志)RateLimiter-> ChannelMessageRouter(速率限制)InputSanitizer-> ChannelMessageRouter(输入消毒)PromptGuardian-> ChannelMessageRouter(提示注入检测)
Phase S3: ChannelMagiBridge
桥接 Channel 事件到 MagiService:
const channelMagiBridge = new ChannelMagiBridge(
channelRegistry,
channelMessageRouter,
magiService,
logger,
);
历史说明:
ChannelServerHTTP 服务器在cleanup-legacy-mcp(2026-05-19)删除。channel_send/channel_list等工具现由MagiChannelProvider+MagiChannelHandlers(in-process)通过统一注册表装配,handler 直接调ChannelPluginRegistry/ChannelMessageRouter。
Phase 3: IPC 路由注册
在窗口创建之前注册所有 IPC 处理器。
const router = new Router(/* 60+ 服务依赖 */);
const { skillHubDownloadService } = router.register();
registerAllRouters() 内部创建并注册 68+ Router 实例:
| 路由类 | 通道前缀 |
|---|---|
AuthRouter | auth:* |
ProjectRouter | projects:* |
SessionRouter | sessions:* |
CompletionRouter | completion:* |
LLMRouter | llmProviders:*, llmModels:* |
MediaRouter | media:* |
MagiRouter | magi:* |
ChannelPluginRouter | channels:* |
SecurityRouter | security:* |
TodoRouter | todo:* |
TaskRouter | tasks:* |
NoteRouter | notes:* |
SubagentRouter | subagents:* |
ElfiRouter | elfi:* |
EnvironmentRouter | env:* |
| ... 等 50+ 其他路由 | ... |
Phase T1-T3: Todo/Task/Notes
flowchart LR
T1[Phase T1: TodoService] --> T1a[initialize 加载 TODO.md]
T2[Phase T2: TaskService] --> T2a[initialize 扫描任务]
T3[Phase T3: NoteFileService + NoteWatcher] --> T3a[ensureVaultDir]
T3a --> T3b[scanAllNotes + reindex]
T3b --> T3c[DB 笔记迁移检查]
| 阶段 | 服务 | 操作 |
|---|---|---|
| T1 | TodoService | 初始化 Markdown 待办系统 |
| T2 | TaskService | 初始化文件系统 + SQLite 任务管理 |
| T3 | NoteFileService | 确保 vault 目录存在 |
| T3 | NoteWatcher | 文件系统监听器 |
| T3 | 笔记迁移 | DB -> .md 文件一次性迁移 |
| T3 | 启动重索引 | 扫描所有笔记并更新 DB 索引 |
Phase W1: 窗口创建
在所有服务和 IPC 路由注册完成后创建 BrowserWindow:
mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
preload: preloadPath,
},
});
Phase W2: WebSocket/协议处理
窗口创建后的后续初始化:
| 步骤 | 操作 |
|---|---|
| 1 | 注册 wallpaper:// 协议处理器 |
| 2 | 注册 media:// 协议处理器 |
| 3 | 注册 resource:// 协议处理器 |
| 4 | 加载渲染进程 URL (dev server 或 file://) |
| 5 | 处理待处理的 Deep Link |
| 6 | 恢复 Channel 实例 (autoConnect) |
| 7 | Content Security Policy 配置 |
| 8 | 导航拦截 (isAllowedNavigation) |
启动耗时
createServices() 在关键阶段记录耗时:
[INFO] Core services initialized { duration: ~50ms }
[INFO] Feature services created { duration: ~200ms }
[INFO] Agent packages loaded { builtin: N, user: M }
[INFO] Persona packages loaded { builtin: N, user: M }
[INFO] Script plugins loaded { builtin: N, user: M }
[INFO] Magi dispatch services created (Phase S1)
[INFO] MagiService created (Phase S2)
[INFO] ChannelMagiBridge created (Phase S3)
[INFO] IPC handlers registered { duration: ~500ms }
相关文件
| 文件 | 说明 |
|---|---|
packages/desktop/app/main/index.ts | 主进程入口,createServices() 函数 |
packages/desktop/app/main/services/routers/index.ts | registerAllRouters() 路由注册 |
packages/desktop/app/main/db/index.ts | initDatabase() 数据库初始化 |
packages/desktop/app/main/workers/DbClient.ts | 数据库 Worker 客户端 |
packages/desktop/app/main/services/infra/logger/LoggerService.ts | 日志服务 |
packages/desktop/app/main/services/infra/paths/paths.ts | AppPaths 路径管理 |
packages/desktop/app/main/services/platform/config/store/ConfigStore.ts | 配置存储 + fs.watch |
packages/desktop/app/main/services/agent-core/agent/AgentPackageLoader.ts | Agent 包加载器 |
packages/desktop/app/main/services/agent-core/agent/PersonaPackageLoader.ts | Persona 包加载器 |
packages/desktop/app/main/services/capabilities/tools/script-plugin/ScriptPluginLoader.ts | Script 插件加载器 |
packages/desktop/app/main/services/capabilities/integrations/channel/ChannelPluginLoader.ts | Channel 插件加载器 |
packages/desktop/app/main/services/agent-core/magi/MagiService.ts | Magi 核心服务 |
packages/desktop/app/main/services/agent-core/magi/AgentOrchestrator.ts | Agent 调度编排 |
packages/desktop/app/main/services/platform/cron/CronService.ts | 定时任务服务 |
packages/desktop/app/main/services/content/workspace/todo/TodoService.ts | 待办事项服务 |
packages/desktop/app/main/services/content/workspace/tasks/TaskService.ts | 任务管理服务 |
packages/desktop/app/main/services/content/workspace/notes/NoteFileService.ts | 笔记文件服务 |