# Mindmap AI Agent API 设计(读写思维导图,类似 CLI 工具) ## 目标 让 AI 不再“只输出一段文本”,而是像 CLI 一样: 1. **读**:获取当前页面中某个 Mindmap 的完整数据(包含节点、链接、引用)。 2. **改**:以结构化的 `ops`(操作序列)形式修改导图(新增/删除/改名/加链接/加引用/加备注)。 3. **可追溯**:每次 AI 修改都能记录“为什么这样改/引用来自哪里”(refs 作为第一公民)。 4. **安全**:必须校验登录态 + document 权限;只能操作该 document 下的 mindmap 文件。 ## 现状(简述) - 目前 Mindmap 的保存/加载已经存在(按文件树保存,支持同页多个独立 mindmap)。 - AI v2 的 `/api/mindmap-ai/outline-to-mindmap` 能把 PDF 转成 mindmapData(节点带 `hyperlink` 与 `refs`)。 - 仍缺少:AI 直接对“已有导图”做增量修改的能力(例如“补完此节点”“根据搜索扩展子节点”)。 ## 设计原则 - **客户端只负责 UI/交互**:选择节点、展示进度、应用结果。 - **服务端负责权限与落盘**:验证用户、读写 mindmap JSON、生成 ops、应用 ops。 - **AI 输出必须是 ops**:避免 AI 直接吐一棵全量树造成覆盖/丢数据;也利于审计与回滚。 - **引用强制**:默认每个新增节点都要给 `refs`(至少页码/URL),没有引用则标记为 `待核验`。 ## 核心数据结构 ### 1) Mindmap 节点引用 `NodeRef`(已在实现中使用) ```ts export type NodeRef = { kind: "pdf" | "docx" | "pptx" | "url"; assetId?: string; fileUrl?: string; page?: number; // 1-based slide?: number; // 1-based title?: string; snippet?: string; }; ``` ### 2) 操作协议 `MindmapOp` > 说明:这里的 `uid` 指 simple-mind-map 节点 `data.uid`(当前实现已使用)。 ```ts export type MindmapOp = | { op: "addChild"; parentUid: string; node: { uid?: string; text: string; hyperlink?: string; refs?: NodeRef[]; note?: string } } | { op: "addSiblingAfter"; targetUid: string; node: { uid?: string; text: string; hyperlink?: string; refs?: NodeRef[]; note?: string } } | { op: "updateText"; uid: string; text: string } | { op: "setHyperlink"; uid: string; hyperlink: string | null } | { op: "setRefs"; uid: string; refs: NodeRef[] } | { op: "appendNote"; uid: string; markdown: string } | { op: "deleteNode"; uid: string }; ``` ### 3) 服务端应用 ops(纯 JSON 层) - 以“树遍历 + uid 索引”应用变更,保证: - 不依赖浏览器端实例; - 不依赖 simple-mind-map 内部状态; - 可在服务端记录变更日志。 ## API 设计(建议新增) ### 1) 读取导图 `GET /api/mindmap/[documentId]/[mindmapId]` 返回: ```json { "mindmapId": "xxx", "documentId": "xxx", "data": { "data": { "text": "...", "uid": "..." }, "children": [] }, "updatedAt": "2026-01-09T00:00:00.000Z" } ``` ### 2) 应用 ops(增量修改 + 自动保存) `POST /api/mindmap/[documentId]/[mindmapId]/ops` 入参: ```json { "ops": [ { "op": "addChild", "parentUid": "...", "node": { "text": "...", "hyperlink": "...", "refs": [] } } ], "actor": { "kind": "ai", "provider": "online", "model": "gemini-2.5-flash" }, "reason": "补完该节点:……(可选)" } ``` 出参: ```json { "ok": true, "applied": 7, "data": { "data": { "text": "...", "uid": "..." }, "children": [] } } ``` ### 3) AI 补完(服务端编排:检索 → 生成 ops → 应用 ops) `POST /api/mindmap-ai/expand-node` 入参(建议): ```json { "documentId": "xxx", "mindmapId": "xxx", "targetUid": "xxx", "instruction": "请补完该节点,要求每条必须带引用", "sources": { "rag": true, "searxng": true } } ``` 输出: ```json { "ok": true, "providerUsed": "online", "ops": [ ... ], "applied": 7 } ``` > 注意:该接口内部会调用 `/api/mindmap/[...]/ops` 做落盘,避免重复代码。 ## 与 SearxNG / RAG 的关系 - 对“搜索补完”:服务端先走检索(LightRAG + 可选 SearxNG),把证据(标题/URL/snippet)整理成短上下文,再让在线 AI 输出 `MindmapOp[]`。 - 必须要求:每个新增节点都附带 refs(url 或 pdf page),否则标记为“待核验”并限制输出量。 ## 验收建议(后续 pw-tests) 1. 选中某节点,点击“AI 补完”,等待生成。 2. 导图新增 ≥ 3 个子节点。 3. 每个新增节点包含可点击 `hyperlink` 或 `refs`。 4. 刷新页面后仍存在(说明落盘成功)。