主进程设计
主进程(Main Process)是 Elftia 的核心,负责所有业务逻辑、外部 API 调用、数据库操作和安全管控。入口文件为 packages/desktop/app/main/index.ts。
服务模块总览
主进程包含 45+ 服务模块,按职能领域组织在 packages/desktop/app/main/services/ 目录下:
graph LR
subgraph "核心基础设施"
Core[core/]
Config[config/]
Settings[settings/]
end
subgraph "认证与账户"
Auth[auth/]
Account[account/]
OAuth[oauth/]
end
subgraph "AI 引擎"
Engine[engine/]
Completion[completion/]
LLM[llm/]
Prompt[prompt/]
end
subgraph "智能体编排"
Magi[magi/]
Agent[agent/]
Plugin[plugin/]
end
subgraph "通信渠道"
Channel[channel/]
Security[security/]
end
subgraph "媒体与内容"
Media[media/]
Project[project/]
Search[search/]
end
Core --> Engine
Core --> Channel
Engine --> Magi
LLM --> Completion
Completion --> Engine
Magi --> Agent
Channel --> Security
按领域分类的服务清单
| 领域 | 服务 | 说明 |
|---|---|---|
| 核心 (core/) | LoggerService | Winston + daily-rotate-file 日志 |
AppPaths | 应用路径解析 (userData, dbPath, configDir 等) | |
RuntimeService | 运行时信息 (版本, 渠道, 平台) | |
CacheService | 通用缓存 (TTL 过期清理) | |
ConfigManager | 配置文件管理 | |
SecurityService | AES-256-GCM 加密服务 | |
CryptoService | PBKDF2 密钥派生 + 加解密 | |
PerformanceMonitor | 性能监控与告警 | |
ErrorHandler | 全局错误处理 | |
PluginManager | 插件生命周期管理 | |
DatabaseOptimizer | SQLite 优化 (VACUUM, ANALYZE) | |
CommandService | 命令执行服务 | |
| 认证 (auth/) | AuthService | IPC 认证 token 验证 |
AuthSessionService | 登录会话 + Deep Link 处理 | |
AuthTokenStore | 认证 token 持久化 | |
TokenRefreshService | 自动 token 刷新 | |
| 账户 (account/) | AccountService | 用户凭证管理 |
AccountTokensService | OAuth Token 管理 | |
LimitsService | 会员限制检查 | |
| LLM (llm/) | LLMConfigService | 提供商/模型配置 CRUD |
TransformerService | 请求格式转换链 | |
| 补全 (completion/) | CompletionService | LLM API 调用入口 |
ApiKeyPoolService | 多密钥轮询 + 会话亲和 | |
| 引擎 (engine/) | EngineDispatcher | 引擎注册和路由 |
ApiEngine | 媒体 API 引擎 | |
ChatEngine | 通用聊天引擎 | |
ClaudeSdkEngine | Claude Agent SDK 引擎 | |
TinyElfEngine | 内置 Agent 引擎 | |
CliRunnerEngine | CLI 子进程引擎 | |
STChatEngine | RP 聊天管线引擎 | |
| Magi 编排 (magi/) | MagiService | 核心消息处理服务(含 assembleMagiMcps 走 services/capabilities/tools/mcp-builtin/ 注册表收集 Clawia 的 MCP set;buildTinyElfDirectMcpServers 是 TinyElf 入口) |
MagiSessionService | 会话持久化管理 | |
MagiWorkspaceService | 工作空间目录管理 | |
MagiSdkOptionsBuilder | Prompt 构建 (V1-V4) + 用户 MCP 注入(setUserMcpServers / getMcpServers(allowedUserMcpNames) / getDirectMcpServers)+ Channel probe;内置 MCP 装配自 Phase 5.9 起迁出至 mcp-providers/ | |
AgentOrchestrator | Agent 调度编排 | |
AgentDiscovery | Agent 可调度清单 | |
MessageRouter | 双模式消息路由 | |
ChannelMagiBridge | Channel 到 Magi 的桥接 | |
SessionEventBus | 会话事件总线 | |
SessionDispatcherImpl | 跨会话调度实现 | |
SubagentRegistry | 子智能体状态追踪 | |
| 内置 MCP 注册表 (mcp-providers/) | McpProviderRegistry | 12 个内置 Provider + 动态 ScriptPlugin Provider 工厂。所有内置 MCP handler 都在主进程内运行(in-process);SDK 直接调用 / TinyElf 注册为 ITool / CLI 通过中央 BuiltinMcpHttpServer HTTP 桥访问。DispatchServer / ChannelServer / VisionAssistServer 三个 HTTP 桥在 cleanup-legacy-mcp(2026-05-19)删除 |
BuiltinMcpHttpServer | 中央 HTTP MCP 桥(per-session scope),所有 in-process MCP 通过它对 CLI 引擎暴露 | |
assembleMcpForSession(ctx) | 统一装配入口(SDK + TinyElf;返回 McpAssembly 含 sdkServers / tinyElfServers / promptFragments / allowedTools / cleanups) | |
applyAssembly.ts | applyAssemblyToSdkOptions / applyAssemblyToTinyElfConfig — 把 McpAssembly 合到 engine options | |
contextBuilders.ts | buildAssemblyContextFor{Clawia,Agent} — 从 caller 视角构造 AssemblyContext | |
registerBuiltinMcpProviders.ts | 一次性 boot 装配点(含 ScriptPlugin 同名 alias 处理) | |
builtin/<Name>Provider.ts | 每个内置 MCP 一个 Provider 模块(12 个静态 + 动态 ScriptPlugin 工厂) | |
| Channel (channel/) | ChannelPluginLoader | 插件发现与加载 |
ChannelPluginRegistry | 插件注册与实例管理 | |
ChannelMessageRouter | 消息触发路由 | |
ChannelMarketplaceService | 插件市场 | |
| 安全 (security/) | ExecutionFirewall | 文件路径防火墙 |
GuardianAgent | AI 工具调用审查 | |
PromptGuardian | 提示注入检测 | |
RateLimiter | 速率限制 | |
InputSanitizer | 输入消毒 | |
UserPermissionService | 用户权限管理 | |
ChannelPermissionGate | 渠道权限确认 | |
AuditLogger | 安全审计日志 | |
| 媒体 (media/) | ImageGenerationService | 图片生成 |
MusicGenerationService | 音乐生成 | |
MediaStorageService | 媒体文件存储 | |
MediaResourceService | 内容寻址资源存储 | |
MediaConfigService | 媒体提供商配置 | |
AsrService / TtsService | 语音识别/合成 | |
| 项目 (project/) | ProjectService | 项目 CRUD |
FileIndexService | 文件索引服务 | |
GitService | Git 操作 | |
| 搜索 (search/) | WebSearchService | 统一搜索入口 |
JinaProvider / TavilyProvider / SearxngProvider | 搜索引擎适配器 | |
| UI (ui/) | ThemeService | 主题管理 |
WindowControlsService | 窗口控制 | |
TrayService | 系统托盘 | |
NotificationService | 桌面通知 | |
| 配置 (config/) | ConfigStore | electron-store + fs.watch 热重载 |
| 定时任务 (cron/) | CronService | Cron 定时任务调度 |
| MCP (mcp/) | McpService | MCP 服务器管理 |
| 插件 (plugin/) | ScriptPluginLoader | Script 插件加载 |
ScriptPluginRegistry | Script 插件注册表 | |
ScriptPluginBridgeManager | 插件桥接管理 |
IPC Router 架构
所有前端到后端的通信通过 IPC Router 层进行,当前注册了 68+ 个路由模块。
secureHandle 模式
每个 IPC 通道都使用 secureHandle 包装,强制认证 token 验证:
{/* packages/desktop/app/main/ipc/safe-handle.ts */}
function secureHandle(
channel: string,
handler: (event: IpcMainInvokeEvent, params: unknown) => Promise<unknown>,
validateToken: (token: string) => boolean,
): void;
流程:
sequenceDiagram
participant R as Renderer
participant P as Preload
participant S as secureHandle
participant H as Router Handler
R->>P: window.api.someMethod(params)
P->>S: ipcRenderer.invoke(channel, {token, ...params})
S->>S: validateToken(token)
alt token 无效
S-->>P: throw AuthError
else token 有效
S->>H: handler(event, params)
H-->>S: result
S-->>P: result
P-->>R: result
end
路由注册
所有路由在 registerAllRouters() 中集中注册。每个 Router 类继承 BaseRouter 并在 register() 方法中注册通道:
{/* 简化的 Router 结构 */}
class SomeRouter extends BaseRouter {
register() {
secureHandle('domain:action', async (_event, params) => {
const validated = SomeSchema.parse(params);
return this.service.doSomething(validated);
}, this.validate);
}
}
路由分类与数量
| 路由目录/文件 | 通道前缀 | 主要通道数 |
|---|---|---|
auth/ | auth:* | 5+ |
account/ | accounts:*, accountTokens:* | 8+ |
session/ | sessions:*, sessionOrganizer:* | 10+ |
chat/ | chatMessages:*, chatAssistants:*, chatControl:*, mediaSession:* | 15+ |
completion/ | completion:* | 5+ |
capabilities/llm/ | llmProviders:*, llmModels:*, apiKeys:*, transformers:* | 15+ |
project/ | projects:*, files:*, git:* | 10+ |
media/ | media:*, imageProviders:*, musicProviders:*, videoProviders:*, asr:*, tts:* | 20+ |
settings/ | settings:*, appPreferences:* | 8+ |
ui/ | theme:*, window:* | 6+ |
MagiRouter | magi:* | 10+ |
ChannelPluginRouter | channels:* | 8+ |
sillytavern/ | characterCards:*, worldInfo:*, regexScripts:*, groupChat:* 等 | 25+ |
| 其他 | mcp:*, webSearch:*, todo:*, tasks:*, notes:*, tags:*, cron:*, elfi:* 等 | 30+ |
Worker 线程模式
耗时的 I/O 操作通过 Worker Thread 执行,避免阻塞主线程。
DbClient — 数据库 Worker
DbClient 是最核心的 Worker,封装了与 SQLite 数据库的所有交互:
sequenceDiagram
participant S as Service
participant C as DbClient
participant W as db.worker.ts
participant D as SQLite (WAL)
S->>C: db.someMethod(params)
C->>C: seq++, 创建 Promise
C->>W: postMessage({id: seq, method, params})
W->>D: 执行 SQL 查询
D-->>W: 结果
W-->>C: postMessage({id: seq, result})
C->>C: resolve(pending[seq])
C-->>S: Promise<result>
{/* 简化的 DbClient RPC 模式 */}
class DbClient extends EventEmitter implements DbRpc {
private worker: Worker;
private seq = 0;
private pending = Map<number, {resolve, reject}>;
async send(method: string, params: unknown): Promise<unknown> {
const id = ++this.seq;
return new Promise((resolve, reject) => {
this.pending.set(id, { resolve, reject });
this.worker.postMessage({ id, method, params });
});
}
async ready(): Promise<void>;
}
关键设计:
- 异步 RPC: 每次调用分配唯一序列号,通过
postMessage发送请求 - 就绪等待:
await db.ready()确保 Worker 初始化(Schema 创建)完成后再使用 - 错误转发: Worker 错误通过 EventEmitter 冒泡
Worker 线程清单
| Worker 文件 | 用途 | 通信方式 |
|---|---|---|
db.worker.ts | SQLite 数据库读写 (100+ RPC 方法) | DbClient RPC |
fileSearch.worker.ts | 文件搜索(fuzzy match) | MessagePort |
fileWatcher.worker.ts | 文件系统监听 (chokidar) | MessagePort |
mcp.worker.ts | MCP 服务器进程管理 | MessagePort |
diagnostics.worker.ts | 系统诊断数据收集 | MessagePort |
project.worker.ts | 项目文件索引构建 | MessagePort |
fileSnapshot.worker.ts | 文件快照对比 | MessagePort |
关键基础设施
LoggerService
基于 Winston,支持日志分级和日志文件自动轮转:
{/* 简化的 LoggerService 接口 */}
class LoggerService {
info(message: string, meta?: Record<string, unknown>): void;
warn(message: string, err?: Error, meta?: Record<string, unknown>): void;
error(message: string, err?: unknown, meta?: Record<string, unknown>): void;
debug(message: string, meta?: Record<string, unknown>): void;
}
- 日志位置:
{userData}/logs/ - 轮转策略: daily-rotate-file,保留 14 天
- 格式: JSON + timestamp
SecurityService / CryptoService
{/* 加密服务核心接口 */}
class SecurityService {
encrypt(plaintext: string): string;
decrypt(ciphertext: string): string;
}
class CryptoService {
deriveKey(password: string, salt: Buffer): Buffer;
encrypt(data: string, key: Buffer): EncryptedData;
decrypt(data: EncryptedData, key: Buffer): string;
}
AppPaths
统一管理所有应用目录路径:
| 属性 | 路径 | 用途 |
|---|---|---|
userData | {appData}/elftia/ | 应用数据根目录 |
dbPath | {userData}/elftia.db | SQLite 数据库 |
configDir | {userData}/config/ | 配置文件目录 |
resourcesDir | {userData}/resources/ | 媒体资源 |
diagnosticsDir | {userData}/diagnostics/ | 诊断数据 |
logsDir | {userData}/logs/ | 日志文件 |
相关文件
| 文件 | 说明 |
|---|---|
packages/desktop/app/main/index.ts | 主进程入口,全部服务创建和启动 |
packages/desktop/app/main/services/routers/index.ts | 路由注册中心,registerAllRouters() |
packages/desktop/app/main/services/routers/BaseRouter.ts | 路由基类 |
packages/desktop/app/main/ipc/safe-handle.ts | secureHandle IPC 安全包装 |
packages/desktop/app/main/workers/DbClient.ts | 数据库 Worker 客户端 |
packages/desktop/app/main/workers/db.worker.ts | 数据库 Worker 实现 |
packages/desktop/app/main/workers/types.ts | Worker RPC 类型定义 |
packages/desktop/app/main/services/infra/logger/LoggerService.ts | 日志服务 |
packages/desktop/app/main/services/platform/security/SecurityService.ts | 加密服务 |
packages/desktop/app/main/services/infra/paths/paths.ts | 路径管理 |
packages/desktop/app/main/services/agent-core/engine/EngineDispatcher.ts | 引擎调度器 |