179 lines
6.6 KiB
Markdown
179 lines
6.6 KiB
Markdown
# 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`:
|
||
|
||
```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 加载时自动过滤 |
|
||
|
||
### 关键类型
|
||
|
||
```typescript
|
||
// 消息
|
||
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>;
|
||
```
|