6.6 KiB
6.6 KiB
llm-to-agent 设计文档
架构设计
核心理念:微内核 + 事件驱动
Agent 的本质是一个循环:用户输入 → LLM 思考 → 工具调用 → LLM 再思考 → 最终回复。
本项目的答案是:内核只做一件事——驱动这个循环。LLM 调用、工具执行、日志输出等一切能力全部通过事件总线交给外部插件。
三层架构
┌──────────────────────────────────────────┐
│ Route 层 CLI / Desktop / Web │ ← 只决定 I/O 方式
├──────────────────────────────────────────┤
│ Plugin 层 provider / tool / hook │ ← 可替换的能力单元
├──────────────────────────────────────────┤
│ Core 层 Scheduler + HookBus │ ← 只做循环 + 事件路由
└──────────────────────────────────────────┘
事件总线
内核循环的每一步都通过 HookBus 发出事件,插件注册响应,形成“事件驱动 + 插件化”的架构。
插件类型
| 类型 | 职责 | 响应的事件 |
|---|---|---|
provider |
LLM 提供商适配 | llm:call、tool:select |
tool |
工具能力 | tool:schema、tool:execute |
hook |
生命周期副作用 | tool:before、tool:after、run:end |
prompt |
系统提示词 | 通过配置注入,不响应事件 |
每个插件通过 manifest.json 声明元信息(名称、类型、提供的能力、适用平台),由 PluginManager 统一加载。
三条产品线
┌── @llm-to-agent/core ──┐
│ MicroKernel + HookBus │
└────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
CLI Desktop Web
(readline) (Electron) (Browser HTTP)
│ │ │
┌───────┴────────┐ ┌──────┴───────┐ ┌──────┴───────┐
│ 本地工具全部 │ │ 同 CLI │ │ 仅远程工具 │
│ console 日志 │ │ IPC 日志 │ │ SSE 日志 │
└────────────────┘ └──────────────┘ └──────────────┘
CLI 与 Desktop 共享本地工具(文件读写、Shell 执行),Web 端通过 platforms 字段自动跳过本地工具。
项目目录设计
Monorepo 结构(pnpm workspace)
llm-to-agent/
├── pnpm-workspace.yaml
├── package.json ← 根(private,统一 dev/test 脚本)
├── tsconfig.json
│
├── docs/ ← 设计文档
│ └── design.md
│
├── packages/
│ │
│ ├── types/ ← @llm-to-agent/types
│ │ └── src/index.ts ← 所有共享类型(Message/ToolDef/PluginManifest/...)
│ │
│ ├── core/ ← @llm-to-agent/core
│ │ └── src/
│ │ ├── hook-bus.ts ← 事件总线(on/emit/request/collect)
│ │ ├── scheduler.ts ← Agent 循环(think→tool→think)
│ │ ├── context.ts ← 消息上下文管理器
│ │ ├── plugin-manager.ts← 插件加载 + 生命周期
│ │ └── kernel.ts ← MicroKernel 入口(组合以上模块)
│ │
│ ├── plugins-builtin/ ← @llm-to-agent/plugins-builtin
│ │ └── [xxxxx]/ ← 内置插件
│ │
│ ├── cli/ ← @llm-to-agent/cli(终端入口)
│ │ └── src/index.ts ← readline 循环 + kernel.init([...])
│ │
│ ├── desktop/ ← @llm-to-agent/desktop(桌面入口)
│ │ └── src/main.ts ← Electron 主进程
│ │
│ ├── server/ ← @llm-to-agent/server(Web 后端)
│ │ └── src/index.ts ← Express + SSE
│ │
│ ├── web/ ← @llm-to-agent/web(Web 前端)
│ │ └── index.html ← 待实现 React 聊天界面
│ │
│ ├── tests/ ← @llm-to-agent/tests
│ │ └── src/ ← *.test.ts(Node 原生 test runner)
│ │
│ └── old/ ← @llm-to-agent/old(旧代码归档)
│ └── src/ ← 重构前的 Agent 实现
包依赖关系
@llm-to-agent/types ← 零依赖,纯类型
↑ ↑
core plugins-builtin
↑ ↑
├───────────┴────────────┐
↓ ↓ ↓
cli desktop server
↑
web
插件清单规范
每个插件目录包含 manifest.json:
{
"name": "@agent/tool-file",
"version": "1.0.0",
"type": "tool",
"provides": ["file-read", "file-write"],
"entry": "./index.ts",
"platforms": ["cli", "desktop"]
}
| 字段 | 说明 |
|---|---|
type |
provider / tool / hook / prompt |
provides |
提供的能力标识 |
entry |
入口文件,默认导出 register(bus: HookBus) |
platforms |
可用平台,PluginManager 加载时自动过滤 |
关键类型
// 消息
interface Message {
role: 'system' | 'user' | 'assistant' | 'tool';
content: string;
tool_calls?: ToolCall[];
tool_call_id?: string;
}
// 工具定义(OpenAI 兼容)
interface ToolDef {
type: 'function';
function: {
name: string;
description: string;
parameters: Record<string, unknown>;
};
}
// 插件清单
interface PluginManifest {
name: string;
version: string;
type: 'provider' | 'tool' | 'hook' | 'prompt';
provides: string | string[];
entry: string;
platforms?: ('cli' | 'desktop' | 'web')[];
}
// 事件总线
type EventName = string;
type Listener = (data: any) => any | Promise<any>;