# AI Agent 平台 v1（把 Wolai 当成“Web 版 VSCode + Cline”来做）

> 目标：不只在思维导图里，而是在**主编辑区（BlockNote）**、**OnlyOffice**、**思维导图**三处都能使用同一套“会用工具做事”的 AI。
>  
> 我们把当前项目类比为 VSCode：  
> - UI 里有一个统一的 Chat 面板（像 VSCode Chat / Cline Webview）  
> - AI 不是“输出一段文本”，而是能调用工具（像 Cline 的工具 + VSCode 的 languageModelTools）  
> - 工具调用可追溯、可控（权限/确认/日志），且可扩展（MCP / 内置工具 / 用户自定义）

---

## 0. 现状与痛点（为什么现在“不智能”）

当前项目的 AI 主要集中在 mindmap 相关 Next Route + 面板：

- `wolai-frontend/src/app/api/mindmap-ai/*`：PDF 大纲生成导图、补完节点、agent 路由等。
- `wolai-frontend/src/components/editor/blocks/MindmapAiAgentPanel.tsx`：对话 UI + 在线/本地模型切换 +（有限）工具选择。

痛点（用户反馈的核心）：

1) AI 常变成“对话 + 兜底链接”，看起来没真正**调用工具**完成“写入/修改/跳转/补全”。  
2) 缺少跨区域能力：主编辑区、OnlyOffice 没有统一的 AI 工具体系。  
3) 缺少可观测性：用户看不到 AI 做了哪些步骤、调用了哪些工具、产生了哪些改动。  
4) 工具调用协议不稳定：不同模型/网关对 JSON tool-calling 的支持差异大，容易进入循环/步数耗尽。

---

## 1. 设计目标（对齐 Cline / VSCode Chat 的能力）

### 1.1 统一入口：一个 AI 面板，多处可用

- 右侧/浮层 AI 面板：所有区域共用（思维导图、BlockNote、OnlyOffice）。
- 支持“快速对话”与“任务模式”（像 Cline：可以多步执行、展示步骤与工具日志）。
- 支持 `@` 选择文件树资产/上传文件/引用当前选区。

### 1.2 统一协议：工具调用必须稳定、可解析、可追溯

参考 cankao/cline-main：

- 使用**XML-like 工具标签协议**（而不是依赖模型原生 function-calling）：
  - 优点：更跨模型、可流式解析、可用“严格 parser”保证可靠性。
  - 核心点：模型输出 `<tool_name>...</tool_name>`，服务端解析后执行工具，再把 `<tool_result>...</tool_result>` 回喂模型。

### 1.3 统一工具模型：Tool / ToolSet / 权限 / 确认

参考 cankao/vscode 的 chat tools：

- Tool 定义包含：id、展示名、modelDescription、inputSchema、来源、是否需要确认、是否可在 prompt 中被引用等。
- ToolSet：工具集合（方便“手动勾选一组工具”或“按场景启用”）。
- 权限策略：读操作默认允许；写操作可配置为“自动/需确认/禁止”。

### 1.4 统一上下文模型：Attachments / Variables（@ 引用）

参考 VSCode chat 的 attachments / variables：

- `@file`/`@folder`/`@selection`/`@mindmap`/`@onlyoffice` 统一变成“上下文条目”。
- 每个条目可计算 token 预算，必要时“省略/压缩/摘要”。

---

## 2. 总体架构（分层 + 运行时）

### 2.1 模块拆分（建议新增）

在 `wolai-frontend/src/lib` 下新增统一平台包（后续逐步迁移 mindmap AI 逻辑）：

- `src/lib/ai-agent/protocol/`
  - 工具标签协议（解析/序列化/流式切分）
  - 参考：`cankao/cline-main/src/core/assistant-message/*`
- `src/lib/ai-agent/tools/`
  - 工具注册表（Tool、ToolSet、schema）
  - 参考：VSCode `languageModelTools*`
- `src/lib/ai-agent/runtime/`
  - Agent 循环（step budget、工具执行、结果回喂、压缩/续写）
  - 参考：Cline “tool use + new_task + context management”
- `src/lib/ai-agent/context/`
  - Attachments/Variables（@ 引用）
  - token 预算与省略策略
- `src/lib/ai-agent/providers/`
  - 在线/本地模型统一适配（复用现有 `openaiCompatibleChat`）

### 2.2 服务端编排（主入口 API）

新增统一入口（示例）：

- `POST /api/ai-agent/run`
  - 输入：会话信息 + 用户输入 + attachments + 工具允许集（auto 或手动）
  - 输出：SSE 流（推荐）或 JSON：
    - assistant 文本流
    - tool_call / tool_result 事件流
    - 最终 completion（包含“做了什么/改了什么/引用来源/失败原因”）

为什么需要 SSE：
- 让 UI 像 Cline 一样逐步显示：正在检索/正在读取文档/正在写入导图/已保存等。

### 2.3 客户端工具宿主（可选但很关键）

很多能力必须在浏览器侧执行（例如读取当前选区、定位 OnlyOffice 页码、获取思维导图当前选中节点）。

设计为两类工具：

1) **Server Tools**（在 Next Route 执行）
   - searxng 检索、LightRAG 查询、读写 mindmap JSON、生成导图 ops、读写 BlockNote 文档存储等。
2) **Client Tools**（在浏览器执行）
   - 读取当前编辑器选区、读取 OnlyOffice 当前页/选中区域、读当前 mindmap 选中节点等。

执行方式（v1 推荐）：
- `/api/ai-agent/run` 只执行 Server Tools；
- Client Tools 先不做“由 AI 主动触发”，而是通过 attachments 提前把必要上下文注入（@selection、@currentFile、@mindmapSelection）。

执行方式（v2 目标）：
- 引入“前端工具宿主”：当服务端需要执行 Client Tool 时，通过 SSE 向前端发起请求，前端执行后再回传结果（类似 VSCode extension host / Cline host provider）。
- 现状：已在 OnlyOffice 场景落地（SSE 事件 `client_tool_call` → 前端调用 OnlyOffice 插件 API → 回调 `/api/ai-agent/client-tool-result`）。
- 后续：把该机制抽象成通用 Client Tool Host，复用到 BlockNote/思维导图的“选区/选中节点”等能力。

---

## 3. 协议：工具调用（建议采用 Cline 风格 XML 标签）

### 3.1 为什么不用纯 JSON tool-calling

- 不同在线网关/模型对 `response_format=json_object`、function-calling 支持不一致。
- 一旦输出不符合 schema，容易进入循环（步数耗尽），用户只看到“兜底链接”。

### 3.2 v1 工具标签协议（最小可用）

模型输出只能出现以下块之一：

- `<tool_name>...</tool_name>`：请求执行工具
- `<attempt_completion>...</attempt_completion>`：结束并输出最终结果

工具参数采用子标签：

```xml
<search_web>
  <query>gemini 3 tokens price</query>
  <count>5</count>
</search_web>
```

工具结果回喂：

```xml
<tool_result>
  <tool_name>search_web</tool_name>
  <result>{"results":[...]}</result>
</tool_result>
```

解析器参考：
- `cankao/cline-main/src/core/assistant-message/parse-assistant-message.ts`

---

## 4. 工具体系（跨 Mindmap / BlockNote / OnlyOffice）

### 4.1 核心内置工具（v1 必做）

#### A. 检索与证据

- `search_web`：通过 searxng 搜索，返回 title/url/snippet（必须可追溯）
- `rag_query`：通过 LightRAG 查询（文档内检索）

#### B. 思维导图（Mindmap）

（复用并升级 `design/mindmap-ai-agent-api.md` 的 ops 思路）

- `mindmap_get`：读取某个 mindmap JSON（documentId + mindmapId）
- `mindmap_apply_ops`：应用 ops 并落盘（增量修改，禁止全量覆盖）
- `mindmap_expand_node`：检索→生成 ops→apply（服务端组合工具）

#### C. 主编辑区（BlockNote 文档）

> 目标：让 AI 像“写代码”一样能对文档做结构化编辑，而不是生成一段文本让用户复制粘贴。

- `doc_get_selection`（v1 先做成 attachment 注入；v2 再做成 client tool）
- `doc_insert_blocks`：在某个 block 前/后插入 blocks
- `doc_replace_range`：替换某个选区（或某 block 的内容）
- `doc_find`：在文档内查找某段文本/标题定位位置

#### D. OnlyOffice（文档阅读/编辑）

v1（先做最基础的增/删/改/查 + 可落地的“文档驱动导图”）：
- `oo_get_selection`：读取当前选区（查）
- `oo_replace_selection`：替换当前选区（改/删；删=传空字符串）
- `oo_insert_text` / `oo_insert_html`：插入内容（增）
- `oo_insert_image`：插入图片（增）
- `asset_extract_outline`：附件（PDF 优先）→结构化大纲（含页码）
- `asset_to_mindmap`：附件大纲→思维导图落盘（含 refs/hyperlink）

v2 再做：
- `onlyoffice_jump`：跳转到某页/某段（依赖 OnlyOffice API 能力）
- `onlyoffice_insert_comment`：插入批注/引用锚点
- `onlyoffice_forcesave`：强制保存/落盘（用于“编辑中→解析/索引→生成”闭环）

### 4.2 ToolSet（便于 UI 一键勾选）

建议默认提供：

- `toolset.readonly`：search_web、rag_query、asset_get、mindmap_get（只读）
- `toolset.mindmap_write`：mindmap_apply_ops、mindmap_expand_node
- `toolset.doc_write`：doc_insert_blocks、doc_replace_range
- `toolset.onlyoffice_editor`：oo_get_selection、oo_replace_selection、oo_insert_*（选区增删改查）
- `toolset.onlyoffice_read`/`toolset.onlyoffice_write`：asset_extract_outline / asset_to_mindmap（文档驱动导图）

---

## 5. UI/交互（对齐“像 Cline 一样智能”）

### 5.1 一个统一的 AI 面板（简洁）

参考你给的 CherryStudio 截图：保持简洁，但必须有三块：

1) 顶部：会话标题 + 模型选择（在线/本地 + model）
2) 中部：对话历史 + 工具执行日志（可折叠）
3) 底部：输入框 + `@` 选择附件 + 工具选择（自动/手动、多选 ToolSet/Tool）

关键交互规则：
- 焦点在输入框：Enter = 发送；Shift+Enter = 换行；不触发思维导图/编辑器快捷键。
- 焦点不在输入框：Enter/Tab 等交由当前编辑器（mindmap 节点快捷键、BlockNote 等）。

### 5.2 可观测性：必须展示“AI 做了什么”

每条消息可附：
- 计划（可选）
- 调用过的工具列表（工具名 + 输入 + 输出摘要 + 耗时 + 是否保存）
- 改动摘要（例如：对 mindmap 增加了 7 个子节点；对文档插入了 3 个段落）

### 5.3 “自动 vs 手动”的真正含义

- 自动：AI 在允许的 ToolSet 范围内自行调用工具。
- 手动：只允许用户勾选的工具/ToolSet；AI 只能在这个集合内调用。

---

## 6. 里程碑计划（慢慢实现，但每一步都可验收）

### 完成进度（截至 2026-01-12）

> 说明：本节用于记录“已经落地到代码”的进度，避免只停留在规划层。  
> ✅=已完成；🟡=部分完成/已打通但仍需扩展；⬜=未开始

| 里程碑 | 条目 | 状态 | 备注（对应实现） |
| --- | --- | --- | --- |
| M0 | `POST /api/ai-agent/run` | ✅ | `wolai-frontend/src/app/api/ai-agent/run/route.ts` |
| M0 | XML-like 工具标签协议解析器 | ✅ | `wolai-frontend/src/lib/ai-agent/protocol/toolTagProtocol.ts` |
| M0 | Tool Registry（Tool/ToolSet） | ✅ | `wolai-frontend/src/lib/ai-agent/tools/registry.ts` + `wolai-frontend/src/lib/ai-agent/tools/builtins/registryBuiltins.ts` |
| M0 | Agent Runtime（step budget + 工具日志） | ✅ | `wolai-frontend/src/lib/ai-agent/runtime/runAgent.ts` |
| M0 | SSE 输出（assistant/tool_call/tool_result/completion） | ✅ | `/api/ai-agent/run` 已支持 SSE |
| Infra | 公共环境文件（服务域名统一配置） | ✅ | `wolai-frontend/public/mnote-env.json`（Supabase/Backend/OnlyOffice Web/Desktop） |
| Infra | 桌面端默认远程客户端行为（启动不再走 127.0.0.1 登录） | ✅ | `desktop-electron/main.js`（networkMode=remote-client + 强制 Supabase/Backend 走 Tunnel） |
| Infra | OnlyOffice 构建兼容（useSearchParams + Suspense） | ✅ | `wolai-frontend/src/app/onlyoffice/page.tsx` + `wolai-frontend/src/app/onlyoffice/OnlyOfficeClientPage.tsx` |
| M0 | 前端 AI 面板（可复用） | 🟡 | 已在 dev + 思维导图 + OnlyOffice 接入；BlockNote 仍需继续推进 |
| M1 | mindmap 读写工具（增量 ops + 细粒度工具） | ✅ | `wolai-frontend/src/lib/ai-agent/tools/builtins/mindmap/mindmapServerTools.ts` |
| M1 | `mindmap_expand_node`（检索→生成→落盘） | ✅ | 同上（支持可选 `search_web` 证据） |
| M1 | UI：选中节点上下文注入（给 AI） | ✅ | 思维导图面板通过 `context.selectedUids` 注入；并对用户显示纯文本节点内容 |
| M1 | UI：最大步数可配置（不再固定 6） | ✅ | 思维导图面板/Dev 面板支持 1~24，默认 10 |
| M2 | ToolSet 按位置隔离（避免工具混淆） | ✅ | `/api/ai-agent/run` 按 `scope` 强制过滤；各面板按场景传不同 toolSets |
| M2 | BlockNote 文档工具（doc_*） | 🟡 | 已实现 doc_get/doc_find/doc_insert_blocks/doc_replace_range + 文档侧边 AI 面板；`@selection`/更丰富块类型仍需扩展 |
| M2 | LightRAG 检索工具（rag_*） | ✅ | `rag_lightrag_query`（调用 `LIGHTRAG_URL` 的 `/query`） |
| M2 | 跨页面文档工具（docs_*） | ✅ | `docs_search` + `docs_read`（按 title/raw_text） |
| M2 | 图片读取工具（OCR） | ✅ | `image_read`（读取 `media_assets.ocr_text`） |
| M2 | 斜杠命令工具 | ✅ | `slash_run`（/new 创建文档、/rename 重命名） |
| M2 | UI：Cline 风格工具栏 + 侧边栏内切页 | ✅ | 文档/思维导图 AI 面板统一顶部工具栏（工具/历史/账户/设置），不再使用居中弹窗 |
| M2 | UI：工具日志可折叠 | ✅ | tool_call/tool_result 支持折叠展开，便于长日志查看 |
| M3 | OnlyOffice 作用域（scope=onlyoffice）+ ToolSet | ✅ | `/api/ai-agent/run/route.ts` 支持 onlyoffice scope，并允许 `toolset.onlyoffice_*`（含 `toolset.onlyoffice_editor`） |
| M3 | OnlyOffice 客户端工具桥接（SSE↔回调） | ✅ | `wolai-frontend/src/lib/ai-agent/runtime/clientToolBridge.ts` + `/api/ai-agent/client-tool-result` + SSE `client_tool_call` |
| M3 | oo_* 工具（选区增/删/改/查） | ✅ | `registryBuiltins.ts` 注册 + OnlyOffice 插件 `wolai-frontend/public/onlyoffice/plugins/agent-tools/*` |
| M3 | OnlyOffice AI 面板接入（浮层） | ✅ | `wolai-frontend/src/app/onlyoffice/page.tsx` + `wolai-frontend/src/components/onlyoffice/OnlyOfficeAiAgentPanel.tsx` |
| M3 | `asset_extract_outline`（PDF→大纲，含页码） | 🟡 | `wolai-frontend/src/lib/ai-agent/tools/builtins/onlyoffice/onlyofficeServerTools.ts`（MinerU content_list） |
| M3 | `asset_to_mindmap`（附件→导图落盘） | 🟡 | 同上（把大纲转成 mindmap ops + refs + hyperlink） |

### M0（基础设施）：统一 Agent Runtime + 工具协议 + 日志

- [x] 新增 `POST /api/ai-agent/run`（先不替换现有 mindmap-ai，做并行）
- [x] 实现 XML-like 工具协议解析器（参考 cline 的 parse-assistant-message）     
- [x] 实现 Tool Registry（Tool/ToolSet/inputSchema/权限标记）
- [ ] 前端统一 AI 面板（可嵌入 mindmap/sidebar、主编辑区、OnlyOffice 页面）（已在 dev + mindmap 接入，BlockNote/OnlyOffice 待推进）     
- [x] SSE 输出：assistant 文本 + tool_call + tool_result + completion

验收（pw-tests）：
- 输入“请给出 gemini-3 tokens 价格”，能看到工具日志（至少 search_web），并返回带来源的答案。

### M1（思维导图）：把 mindmap AI 从“对话”升级为“增量 ops 写入”

- [x] 复用 `design/mindmap-ai-agent-api.md`：完善 `mindmap_get`、`mindmap_apply_ops`
- [x] `mindmap_expand_node`：服务端检索→生成 ops→apply，并强制 refs
- [x] UI：在 mindmap 中选择节点后，@mindmapSelection 自动注入上下文（通过 `context.selectedUids` 注入）

验收（pw-tests）：
- 选中节点“补完”，新增子节点≥3，刷新仍存在，且每个新增节点带 refs/可跳转链接。

### M2（主编辑区 BlockNote）：让 AI 能“读选区并结构化改写/插入”

- [x] 定义 BlockNote 文档操作 API（只允许增量，禁止覆盖整篇）（当前以“块级插入/替换”为最小可用）
- [x] 工具：`doc_insert_blocks`、`doc_replace_range`、`doc_find`（另含 `doc_get`）
- [ ] UI：输入框支持 `@selection`（或“引用当前选区”按钮）

验收（pw-tests）：
- 选中一段文本，让 AI “改写成更简洁版本并保留要点”，结果直接落入文档（不是生成一段文本）。

### M3（OnlyOffice）：插件端实时改文档 + 文档驱动导图

- [x] OnlyOffice 插件注入（autostart + pluginsData + CORS）
- [x] oo_* 工具（选区增/删/改/查）：`oo_get_selection` / `oo_replace_selection` / `oo_insert_*`
- [x] 前端工具宿主（OnlyOffice 版）：SSE `client_tool_call` ↔ 回调 `/api/ai-agent/client-tool-result`
- [x] `asset_extract_outline`：PDF 优先（基于 MinerU 的 content_list 提取 text_level + page_idx）
- [x] `asset_to_mindmap`：从文档大纲生成 mindmap（章→节→要点）并落盘
- [ ] 引用：节点 refs（page/slide）+ hyperlink（`#page=`）在 OnlyOffice/PDF 预览器中可稳定跳转（仍需实测与兼容）

补充说明（OnlyOffice “能否穿透拿到信息”）：

1) **常规集成（不做插件）**：OnlyOffice Docs 集成侧主要通过 `editorConfig.callbackUrl` 回传保存/状态；外部并不会天然得到“当前文档全文/选区文本”。
2) **要拿到编辑器内信息**：需要（A）保证文档已落盘（callback + 保存/forcesave）后从存储侧读取，或（B）开发 OnlyOffice 插件/宏（在编辑器内执行 Office API，再把结果回传到宿主）。
3) **M3 v1 策略（双通道）**：
   - **实时编辑（Word/PPT/Excel 的基础增删改查）**：走 OnlyOffice 插件（编辑器内执行）→ 通过前端工具宿主把结果回传给服务端 Agent。
   - **结构化理解/导图生成**：走“附件/存储→MinerU 结构化解析→导图写入”，不依赖编辑器能直接吐出全文/层级信息。
   - 后续再补：`onlyoffice_forcesave`（保证拿到最新落盘版本）+ 更强的“书签/页码/定位”跳转能力。

验收（pw-tests）：
- 对指定 PDF 生成“章→节→内容”层级导图，点击节点跳到对应页（至少 URL 含 `#page=`）。

### M4（v2）：前端工具宿主 + MCP 工具 + 类“技能”系统

- [ ] 前端工具宿主（通用版）：允许 AI 请求 client tool（读取 BlockNote 选区、思维导图当前选中节点、OnlyOffice 当前页等）
- [ ] MCP：把 supabase_local / searxng / 未来自定义 MCP 作为工具源（像 cline）
- [ ] skills：把“工作流说明”做成可加载的技能文件，AI 可按需激活（类似你现在的 Codex skills）

验收：
- AI 能在一个任务里自行组合：检索→读文档→写导图→在主编辑区插入总结→生成可跳转引用。

---

## 7. 风险与策略

1) **安全/误操作**：默认只允许增量 ops；涉及删除/覆盖需要二次确认或显式指令。  
2) **上下文过长**：引入“attachments 省略/摘要”，并在会话接近上限时自动 compact（参考 opencode/crush）。  
3) **模型差异**：工具协议用 XML-like，避免强依赖 function-calling；必要时提供 provider 特化 prompt。  
4) **性能/长任务**：PDF 解析/大纲生成走后端 job（可加队列/轮询），前端只显示进度与结果。

---

## 8. 与现有 design 的关系（不推倒重来）

- `design/mindmap-ai-v2.md`：保留“PDF/小结/RAG 补完”的业务目标与验收用例。  
- `design/mindmap-ai-agent-api.md`：保留“mindmap ops 增量协议”，作为 v1 中 Mindmap 工具的核心。  
- 本文档新增的是：**把 mindmap 的思路抽象成全站统一的 AI Agent 平台**，并且对齐 Cline/VSCode 的“工具 + 上下文 + 日志 + 权限”工程化形态。
