架构概览
Elftia 是基于 Electron + React 的桌面 AI 聊天应用,采用严格的前后端分离架构。本文档描述系统的整体结构、核心设计原则和关键技术选型。
多进程模型
Electron 应用运行在三个进程中,外加多个 Worker 线程:
graph TB
subgraph "Renderer Process (React)"
UI[React UI 组件]
Ctx[Context / Zustand Store]
Hooks[Custom Hooks]
end
subgraph "Preload Script (contextBridge)"
Bridge[window.api / window.native]
end
subgraph "Main Process (Node.js)"
Services[45+ 服务模块]
Routers[68+ IPC Routers]
Engines[5 引擎: API / Chat / ClaudeSDK / TinyElf / CLI]
Security[安全管控层]
end
subgraph "Worker Threads"
DbWorker[db.worker — SQLite 读写]
FileSearch[fileSearch.worker — 文件搜索]
FileWatcher[fileWatcher.worker — 文件监听]
McpWorker[mcp.worker — MCP 服务器]
DiagWorker[diagnostics.worker — 诊断]
ProjWorker[project.worker — 项目索引]
end
subgraph "External APIs"
LLM[LLM 提供商 API]
Media[媒体生成 API]
Search[搜索引擎 API]
Channel[Channel 平台 API]
end
UI --> Bridge
Bridge --> Routers
Routers --> Services
Services --> Engines
Services --> Security
Services --> DbWorker
Services --> FileSearch
Services --> FileWatcher
Services --> McpWorker
Services --> DiagWorker
Services --> ProjWorker
Services --> LLM
Services --> Media
Services --> Search
Engines --> Channel
进程职责
| 进程 | 职责 | 关键文件 |
|---|---|---|
| Main Process | 所有业务逻辑、外部 API 调用、数据库操作、文件系统访问、安全管控 | packages/desktop/app/main/index.ts |
| Renderer Process | 纯 UI 渲染和用户交互,不直接访问外部 API 或文件系统 | packages/renderer/src/app/App.tsx |
| Preload Script | 通过 contextBridge 暴露安全的 IPC 接口给渲染进程 | packages/desktop/app/preload/index.ts |
| Worker Threads | 耗时的 I/O 操作(数据库、文件索引、MCP 进程管理) | packages/desktop/app/main/workers/ |
核心设计原则
1. 前后端严格分离
渲染进程只负责 UI,所有外部调用由主进程统一处理:
Renderer ──(IPC)──> Main Process ──> 外部 API / 文件系统 / 数据库
│
└──> 处理响应并返回最终结果
│
Renderer <──(IPC)──< Main Process
禁止在前端直接调用外部 API 或处理大量数据后再回传后端。
2. 安全优先
- Context Isolation: 渲染进程完全隔离,只能通过
contextBridge暴露的接口通信 - IPC Auth Token: 每次 IPC 调用携带认证 token,主进程
secureHandle验证 - API 密钥仅存主进程: 所有密钥由
SecurityService(AES-256-GCM)加密存储 - ExecutionFirewall: 阻止访问系统目录和凭据文件
- GuardianAgent: AI 审查工具调用的安全性
3. 插件化架构
系统支持多种插件类型:
| 插件类型 | 说明 | 加载位置 |
|---|---|---|
| Agent Packages | 预配置的 Agent 定义(MCP、Skill、Prompt) | agent-packages/ |
| Persona Packages | 预配置的 Persona(角色)定义 | persona-packages/ |
| Script Plugins | 热插拔 MCP 工具服务器 | script-plugins/ |
| Channel Plugins | 多平台消息渠道(Discord、Telegram 等) | elftia-channels/ |
| Extensions | SillyTavern 兼容扩展 | 动态加载 |
4. 多引擎调度
通过 EngineDispatcher 统一管理 5 种引擎,按 Agent 配置路由到对应引擎:
{/* 简化的引擎注册 */}
interface IEngine {
type: EngineType;
chat(session: EngineSession): Promise<EngineResult>;
cancel(sessionId: string): Promise<void>;
}
type EngineType = 'api' | 'chat' | 'claude-sdk' | 'tinyelf' | 'cli' | 'st-roleplay';
| 引擎 | 用途 | 实现文件 |
|---|---|---|
ApiEngine | 图片/音乐等媒体生成 API | services/agent-core/engine/ApiEngine.ts |
ChatEngine | 通用 LLM 聊天补全 | services/agent-core/engine/ChatEngine.ts |
ClaudeSdkEngine | Claude Agent SDK 会话 | services/agent-core/engine/ClaudeSdkEngine.ts |
TinyElfEngine | 内置轻量级 Agent 引擎 | services/agent-core/engine/tinyelf/ |
CliRunnerEngine | CLI 子进程 Agent(Claude CLI、Codex CLI) | services/agent-core/engine/cli/CliRunnerEngine.ts |
STChatEngine | SillyTavern 兼容 RP 管线 | services/agent-core/engine/STChatEngine.ts |
自定义协议
Electron 注册了 4 个自定义协议,用于安全地加载本地资源:
| 协议 | 用途 | 权限 |
|---|---|---|
elftia:// | Deep Link(OAuth 回调等) | 默认协议客户端 |
wallpaper:// | 壁纸图片加载 | secure, fetchAPI, stream, bypassCSP, CORS |
media:// | 媒体文件(图片、音频、视频) | secure, fetchAPI, stream, bypassCSP, CORS |
resource:// | 通用资源文件 | secure, fetchAPI, stream, bypassCSP, CORS |
数据库概览
- 引擎: better-sqlite3 + Drizzle ORM
- 模式: WAL(Write-Ahead Logging),支持并发读取
- 位置:
{userData}/elftia.db - 访问模式: 主进程通过 Worker Thread(
DbClient→db.worker.ts)异步 RPC
详细数据库设计参见 数据库。
Monorepo 包结构
elftia/
├── packages/
│ ├── desktop/ # Electron 主进程 + preload
│ │ └── app/
│ │ ├── main/ # 主进程代码
│ │ │ ├── services/ # 45+ 服务模块
│ │ │ ├── workers/ # Worker 线程
│ │ │ ├── db/ # Drizzle ORM schema
│ │ │ └── ipc/ # IPC 安全工具
│ │ ├── preload/ # contextBridge 定义
│ │ └── shared/ # 前后端共享类型
│ ├── renderer/ # React 前端 (Vite)
│ │ └── src/
│ │ ├── app/ # 应用入口、布局、Provider 宿主
│ │ ├── features/ # 按功能分域(components/hooks/state)
│ │ ├── pages/ # 页面级组件
│ │ ├── shared/ # 跨功能共享(state/Zustand、hooks、utils、components/ui)
│ │ ├── components/ # 遗留共享 UI 组件(含 components/ui)
│ │ ├── contexts/ # React Context(少量保留)
│ │ └── locales/ # i18n (en/zh/ja)
│ ├── server/ # Web 服务端 (Fastify) — 可选
│ ├── channel-sdk/ # Channel 插件 SDK
│ └── pack-cli/ # Agent 包管理 CLI
├── agent-packages/ # 内置 Agent 定义
├── persona-packages/ # 内置 Persona 定义
├── script-plugins/ # 内置 Script 插件
├── elftia-channels/ # 内置 Channel 插件
└── docs/ # 开发文档
路径别名
| 别名 | 指向 | 使用位置 |
|---|---|---|
@/* | packages/renderer/src/* | 渲染进程 |
@shared/* | packages/desktop/app/shared/* | 全局共享类型 |
@main/* | packages/desktop/app/main/* | 主进程内部 |
技术栈
| 层级 | 技术 | 版本 |
|---|---|---|
| 桌面框架 | Electron | 31.7 |
| 前端框架 | React + TypeScript | 18.2 / 5.6 |
| 构建工具 | Vite (renderer) / tsup (main) | 7.0 |
| 样式方案 | Tailwind CSS + CSS 变量 | 3.4 |
| 状态管理 | React Context + Zustand | — |
| 数据库 | better-sqlite3 + Drizzle ORM | — |
| 代码编辑器 | CodeMirror 6 | — |
| 终端模拟 | xterm 5.5 | — |
| AI SDK | @anthropic-ai/claude-agent-sdk | — |
相关文件
| 文件 | 说明 |
|---|---|
packages/desktop/app/main/index.ts | 主进程入口,服务初始化和启动阶段定义 |
packages/renderer/src/app/App.tsx | 渲染进程入口,Context Provider 层级 |
packages/desktop/app/preload/index.ts | Preload 脚本,contextBridge 接口暴露 |
packages/desktop/app/shared/contracts/ | 前后端共享类型契约 |
packages/desktop/app/main/services/agent-core/engine/EngineDispatcher.ts | 引擎调度器 |
packages/desktop/app/main/ipc/safe-handle.ts | IPC 安全句柄工具 |
vite.config.js | Vite 构建配置 |
tsconfig.base.json | TypeScript 基础配置 |