Agent 引擎概览
Elftia 的 Agent 系统基于多引擎分发架构。EngineDispatcher 作为统一的请求分发器,根据 EngineType 将请求路由到对应的引擎实现。每个引擎实现 IEngine 接口,封装不同的后端服务。
架构图
graph TB
Router["AgentRouter / MagiService"] --> Dispatcher["EngineDispatcher"]
Dispatcher --> TinyElf["TinyElfEngine<br/>tinyelf"]
Dispatcher --> ClaudeSdk["ClaudeSdkEngine<br/>claude-sdk"]
Dispatcher --> CliRunner["CliRunnerEngine<br/>cli"]
Dispatcher --> Chat["ChatEngine<br/>chat"]
Dispatcher --> STChat["STChatEngine<br/>st-chat"]
Dispatcher --> Api["ApiEngine<br/>api"]
TinyElf --> TinyLoop["TinyElfAgentLoop<br/>工具调用循环"]
TinyElf --> ToolReg["ToolRegistry<br/>工具注册表"]
TinyElf --> LLMAdapter["TinyElfLLMAdapter<br/>LLM 适配器"]
ClaudeSdk --> AgentSvc["AgentService<br/>Claude Agent SDK"]
ClaudeSdk --> Proxy["AgentProxyServer<br/>HTTP 代理"]
CliRunner --> Supervisor["ProcessSupervisor<br/>进程管理"]
Chat --> Pipeline["ChatCompletionPipeline<br/>聊天管线"]
IEngine 接口
所有引擎必须实现 IEngine 接口:
interface IEngine {
readonly engineType: EngineType;
startSession(ctx: EngineSessionContext): Promise<void>;
resumeSession(ctx: EngineSessionContext): Promise<void>;
interrupt(dbSessionId: string): Promise<boolean>;
isActive(dbSessionId: string): boolean;
reloadMcpForAllActive?(): Promise<void>;
}
| 方法 | 说明 |
|---|---|
startSession | 启动新会话(保存用户消息,运行引擎循环) |
resumeSession | 在已有会话上继续对话 |
interrupt | 中断活跃会话,返回是否成功 |
isActive | 检查会话是否正在运行 |
reloadMcpForAllActive | 热重载所有活跃会话的 MCP 工具(可选) |
EngineSessionContext
所有引擎共享同一个会话上下文结构体。每个引擎按需使用其中的字段:
interface EngineSessionContext {
dbSessionId: string; // 数据库会话 ID
session: ChatSession; // 完整会话记录
sender: WebContents; // Electron IPC 发送器
prompt: string; // 用户消息
attachments?: Array<...>; // 多模态附件
providerId?: string; // LLM 提供商 ID
model?: string; // 模型 ID(v89+ 为裸 SDK id)
/**
* v89+:CLI 后端绑定(来自 chat_sessions.cliBackend 列)。
* 'claude-code' 走 ClaudeSdkEngine + AgentProxyServer.passThrough;
* 'codex' / 'gemini-cli' 走 CliRunnerEngine。
*/
cliBackend?: 'claude-code' | 'codex' | 'gemini-cli' | null;
/**
* v89+:1M-context 偏好(来自 chat_sessions.useExtendedContext 列)。
* Engines / AgentProxyServer / TransformerChainExecutor 据此决定
* 是否注入 'context-1m-2025-08-07' 到 anthropic_beta。
*/
useExtendedContext?: boolean;
engineConfig?: EngineConfig; // 引擎特定配置
projectPath?: string; // 项目路径
agentId?: string; // Agent ID
// Chat 引擎专用
systemPrompt?: string;
parentId?: string | null;
thinkingLevel?: string;
searchOrchestration?: PipelineSearchConfig;
mcpConfig?: PipelineMcpConfig;
// Magi/Agent 引擎专用
providerEnv?: Record<string, string>;
onSessionEnd?: () => void;
isOfficialProvider?: boolean;
customAgentOptions?: { ... };
permissionMode?: string;
channelSource?: string;
channelId?: string;
channelSenderId?: string;
channelUserPermissions?: { canUseTool: boolean; requireConfirmation: boolean };
}
EngineDispatcher
EngineDispatcher 是引擎注册和分发的核心:
class EngineDispatcher {
private engines = new Map<EngineType, IEngine>();
registerEngine(engine: IEngine): void;
getEngine(type: EngineType): IEngine;
hasEngine(type: EngineType): boolean;
dispatch(type: EngineType, ctx: EngineSessionContext): Promise<void>;
resume(type: EngineType, ctx: EngineSessionContext): Promise<void>;
interrupt(dbSessionId: string): Promise<boolean>;
reloadMcpForAllActive(): Promise<void>;
getEngineInfos(): EngineInfo[];
}
引擎注册
引擎在 packages/desktop/app/main/index.ts 中注册:
const dispatcher = new EngineDispatcher();
dispatcher.registerEngine(new TinyElfEngine(...));
dispatcher.registerEngine(new ClaudeSdkEngine(...));
dispatcher.registerEngine(new CliRunnerEngine(getProcessSupervisor(), db, logger));
dispatcher.registerEngine(new ChatEngine(...));
dispatcher.registerEngine(new STChatEngine(...));
dispatcher.registerEngine(new ApiEngine(...));
中断机制
interrupt() 方法遍历所有引擎,找到拥有目标会话的引擎并中断:
async interrupt(dbSessionId: string): Promise<boolean> {
for (const engine of this.engines.values()) {
if (engine.isActive(dbSessionId)) {
return engine.interrupt(dbSessionId);
}
}
return false;
}
引擎类型注册表
| EngineType | 类 | 后端服务 | 活跃会话追踪 |
|---|---|---|---|
tinyelf | TinyElfEngine | 内置 Agent 循环 | Map<string, ActiveTinyElfSession> |
claude-sdk | ClaudeSdkEngine | AgentService (SDK) | AgentService 内部管理 |
cli | CliRunnerEngine | ProcessSupervisor | Map<string, ActiveCliSession> |
chat | ChatEngine | ChatCompletionPipeline | 内部 Map |
st-chat | STChatEngine | CompletionService | 内部 Map |
api | ApiEngine | CompletionService | 无状态 |
活跃会话追踪
TinyElf 引擎使用 ActiveTinyElfSession 追踪每个活跃会话的状态:
interface ActiveTinyElfSession {
dbSessionId: string;
projectPath: string;
abortController: AbortController;
parentMessageId?: string;
lastAssistantMessageId?: string;
directMcpConnections?: Array<...>;
hookExecutor?: HookExecutor;
sdkDualWrite?: {
sdkSessionId: string;
lastUuid: string;
seqNum: number;
};
subagentManager?: SubagentManager;
}
IPC 事件
引擎通过 sender.send('agent:event', ...) 向渲染进程发送事件:
| 事件类型 | 载荷 | 说明 |
|---|---|---|
init | { sessionId, systemInfo } | 会话初始化 |
sessionCreated | { sessionId } | 会话创建完成 |
userMessage | { sessionId, message } | 用户消息已保存 |
streamDelta | { sessionId, delta } | 流式文本/思维增量 |
toolCallStart | { sessionId, block } | 工具调用开始 |
toolCallEnd | { sessionId, block, status } | 工具调用完成 |
assistantMessage | { sessionId, message } | 助手消息已保存 |
permissionRequest | { sessionId, requestId, toolName, input } | 权限确认请求 |
result | { sessionId, stats } | 执行统计结果 |
complete | { sessionId } | 会话完成 |
error | { sessionId, error } | 错误事件 |
retry | { sessionId, retry } | API 重试通知 |
processing | { sessionId, message } | 处理中状态 |
关键文件
| 文件 | 路径 | 说明 |
|---|---|---|
| IEngine 接口 | services/agent-core/engine/types.ts | 引擎接口和上下文定义 |
| EngineDispatcher | services/agent-core/engine/EngineDispatcher.ts | 引擎注册和分发 |
| 模块入口 | services/agent-core/engine/index.ts | 所有引擎的导出 |
| TinyElfEngine | services/agent-core/engine/tinyelf/TinyElfEngine.ts | TinyElf 引擎实现 |
| ClaudeSdkEngine | services/agent-core/engine/ClaudeSdkEngine.ts | Claude SDK 引擎 |
| CliRunnerEngine | services/agent-core/engine/cli/CliRunnerEngine.ts | CLI 引擎 |
| ChatEngine | services/agent-core/engine/ChatEngine.ts | 聊天引擎 |
| STChatEngine | services/agent-core/engine/STChatEngine.ts | 单轮聊天引擎 |
| ApiEngine | services/agent-core/engine/ApiEngine.ts | API 引擎 |
| EngineType 定义 | @shared/contracts/elftia-agent-types.ts | 类型定义 |
所有路径相对于 packages/desktop/app/main/。
扩展点
- 新增引擎:实现
IEngine接口 + 在EngineDispatcher注册 + 添加EngineType - 新增 IPC 事件:在引擎的回调中通过
sender.send()发送 - MCP 热重载:实现
reloadMcpForAllActive()方法
相关模块
| 模块 | 路径 | 关系 |
|---|---|---|
| AgentRouter | services/routers/AgentRouter.ts | 接收 IPC 调用 dispatcher |
| MagiService | services/agent-core/magi/MagiService.ts | 高层编排,选择引擎 |
| CompletionService | services/capabilities/llm/completion/CompletionService.ts | LLM API 调用 |
| AgentService | services/agent-core/agent/AgentService.ts | Claude SDK 会话管理 |