- 归档 OnlyOffice live bridge、Page AI、mindmap、design governance 与相关 bug 条目 - 补齐 MinerU OCR 后端 runtime 合同与 smoke/test 基线 - 收口 ChatOnly/Doubao、ObjectIdentity、Page Aggregate compat 与 runtime owner 文档口径 验证: - cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1 - cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_bridge -- --test-threads=1 - git diff --check - git diff --cached --check - codegraph index . --force && codegraph status . - codegraph sync . && codegraph status .
408 lines
14 KiB
Markdown
408 lines
14 KiB
Markdown
# 7-42 Page AI mindmap skill and resource generation v1
|
||
|
||
> 创建时间:2026-05-30
|
||
> 状态:`done`
|
||
> owner:`07-ai`
|
||
> 上位参考:
|
||
> - `design/07-ai/reference/7-28-resource-ai-tool-contract-v1.md`
|
||
> - `design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md`
|
||
> - `design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md`
|
||
> - `design/04-tree-domain/done/4-24-resource-tree-filetree-pagetree-source-contract-checklist-v1.md`
|
||
|
||
## 1. 背景
|
||
|
||
当前 Page AI 的 MNote 内置技能只有:
|
||
|
||
- `mnote-current-page`
|
||
- `mnote-local-file`
|
||
- `mnote-chat-only`
|
||
|
||
但 Rust Hermes tool manifest 已经暴露了资源工具雏形:
|
||
|
||
- `mnote.mindmap.fetch`
|
||
- `mnote.mindmap.apply_ops`
|
||
|
||
这说明底层 resource tool 方向已经存在,缺口不在“完全没有工具”,而在 Page AI 缺少一个明确的 `mnote-mindmap` 内置 skill 来指导 agent 何时读取、何时写入、如何生成新的思维导图资源,以及如何把 PDF / Office / Markdown 等材料整理成新的 `.mindmap.json`。
|
||
|
||
用户明确的长期目标是:
|
||
|
||
> AI 能总结 PDF,并整理新建出思维导图。
|
||
|
||
因此本设计不能只覆盖“编辑已有导图节点”,还必须覆盖“从外部材料生成新导图资源”的闭环。
|
||
|
||
## 2. 原型观察
|
||
|
||
### 2.1 KMind plugin
|
||
|
||
`reference-code/kmind-plugin` 体现的关键点:
|
||
|
||
- 以 `simple-mind-map` 风格树结构为核心。
|
||
- 支持多根、MOC、文档树导图、节点超链接、TODO、主题、布局、导入导出。
|
||
- 节点可以携带思源块/文档引用,说明 mindmap 节点不只是纯文本,还可能是资源引用容器。
|
||
- 导入导出会处理 markdown、Freemind、XMind 等格式,但最终仍要落回 mindmap runtime 可消费的数据结构。
|
||
|
||
对 MNote 的启发:
|
||
|
||
- AI 不能把思维导图降级为普通 Markdown 大纲后直接覆盖文件。
|
||
- AI 写入必须尽量保留未知扩展字段,如节点样式、引用、视图状态、主题配置。
|
||
- 从 PDF 生成导图时,应先生成结构化 outline,再转换成 mindmap tree,而不是让模型手写完整 runtime JSON。
|
||
|
||
### 2.2 lx-doc mind-map
|
||
|
||
`reference-code/lx-doc/mind-map` 体现的关键点:
|
||
|
||
- 思维导图项目独立部署,工作台只负责文件/资源管理。
|
||
- 文件内容是完整对象,典型形态为:
|
||
- `root`
|
||
- `theme`
|
||
- `layout`
|
||
- `config`
|
||
- `view`
|
||
- runtime 使用 `setFullData` 恢复完整文件,用 `getData(true)` 保存全量配置。
|
||
- `root` 是 `simple-mind-map` 树:`{ data: { text, uid, ... }, children: [...] }`。
|
||
|
||
对 MNote 的启发:
|
||
|
||
- mindmap 是 Resource Tree 对象,不是 Markdown 正文的一部分。
|
||
- Markdown 页面只保留占位、链接或嵌入引用。
|
||
- AI 读写 mindmap 时应围绕 resource 文件、object identity 和 resource capability 工作。
|
||
|
||
## 3. 当前 MNote 数据合同
|
||
|
||
当前默认 `.mindmap.json` 不是裸树,而是 envelope:
|
||
|
||
```json
|
||
{
|
||
"data": {
|
||
"children": [],
|
||
"data": {
|
||
"expand": true,
|
||
"isActive": false,
|
||
"text": "KMIND",
|
||
"uid": "root"
|
||
}
|
||
},
|
||
"view": {
|
||
"state": {
|
||
"scale": 1,
|
||
"sx": 0,
|
||
"sy": 0,
|
||
"x": -44.99991989135742,
|
||
"y": -15.500006675720217
|
||
},
|
||
"transform": {
|
||
"a": 1,
|
||
"b": 0,
|
||
"c": 0,
|
||
"d": 1,
|
||
"e": -44.99991989135742,
|
||
"f": -15.500006675720217,
|
||
"originX": 0,
|
||
"originY": 0,
|
||
"rotate": 0,
|
||
"scaleX": 1,
|
||
"scaleY": 1,
|
||
"shear": 0,
|
||
"translateX": -44.99991989135742,
|
||
"translateY": -15.500006675720217
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
设计约束:
|
||
|
||
- 最终写入文件必须保持 envelope。
|
||
- 根节点位于 `data.data`。
|
||
- 子节点位于 `data.children`。
|
||
- 新建导图默认 `data.data.uid` 为 `root`。
|
||
- 新建导图默认 `data.data.text` 可由用户材料标题覆盖;没有标题时使用 `KMIND`。
|
||
- `view` 默认使用上述稳定模板;AI 不应自行发明缩放和位移。
|
||
- 修改已有导图时必须保留未知字段,包括 `view`、节点样式、节点引用、主题和未来扩展字段。
|
||
|
||
## 4. 目标
|
||
|
||
- 新增 Page AI MNote 内置 skill:`mnote-mindmap`。
|
||
- 让 Hermes / Reasonix 在 Page AI 中知道如何读写当前页面或当前资源 tab 的 mindmap。
|
||
- 让 AI 能从 PDF、Office、Markdown、当前页内容或用户粘贴文本生成层级 outline,再创建新的 mindmap resource。
|
||
- 让新建导图进入 Resource Tree / File Tree / Page Tree 的正确边界,而不是写进 Markdown 正文。
|
||
- 保留 local-first 主线:本地 `.mindmap.json` 是本地导图资源真相;Rust control-plane 负责授权、审计和 resource identity。
|
||
|
||
## 5. 非目标
|
||
|
||
- 不在本批实现 PDF OCR / MinerU / Office 文本抽取本身。
|
||
- 不把 mindmap 正文存进 Markdown 页面。
|
||
- 不让 Page AI 前端私有拼第二套 mindmap 真相。
|
||
- 不让 agent 直接大段重写完整 JSON 作为默认写入方式。
|
||
- 不引入轮询刷新链路;写入后的 UI 同步应走已有 watcher、resource session 或命令结果驱动刷新。
|
||
|
||
## 6. Skill 设计
|
||
|
||
新增内置 skill:
|
||
|
||
```text
|
||
id: mnote-mindmap
|
||
title: MNote mindmap editing
|
||
description: Read, update, summarize, or create MNote mindmap resources, including generating a new mindmap from PDF or document outlines.
|
||
agentIds: hermes, reasonix
|
||
readOnly: false
|
||
requiresContextRefs: current_page, file, folder, resource
|
||
toolNames:
|
||
- mnote.context.snapshot
|
||
- mnote.context.resolve_target
|
||
- mnote.mindmap.fetch
|
||
- mnote.mindmap.apply_ops
|
||
- mnote.mindmap.create_from_outline
|
||
```
|
||
|
||
Skill 正文规则:
|
||
|
||
- 只有用户明确要求“思维导图 / mindmap / KMind / 脑图 / 从材料生成导图”时启用。
|
||
- 先解析目标资源,再读取内容。
|
||
- 若当前 Page AI target 是 mindmap resource tab,优先使用该资源。
|
||
- 若当前页面包含 mindmap embed,占位中的 `mindmapId` / `sourcePath` 是候选资源。
|
||
- 若用户要求“从 PDF 生成导图”,先读取或请求 PDF 摘要/outline,再调用 mindmap 创建工具。
|
||
- 写前必须确认 `permissionLevel=read_write`,并确认 `allowedResourceIds` 覆盖目标资源。
|
||
- 写后必须回读,并报告新建或变更的 `.mindmap.json`。
|
||
- 生成 outline 时必须使用“中心主题 + 一级分类 + 短语化节点”的导图结构;禁止把 PDF/文档摘要以长段落塞进节点文本。
|
||
- 节点文本优先使用关键词或短语,一个节点只表达一个概念;层级必须用 `children` 表达,引用/页码/来源信息优先放入 `sourceRefs` 或 metadata。
|
||
|
||
## 7. Tool 面设计
|
||
|
||
### 7.1 `mnote.mindmap.fetch`
|
||
|
||
保留现有命名,增强返回结构。
|
||
|
||
输入:
|
||
|
||
- `workspaceId`
|
||
- `documentId`
|
||
- `mindmapId`
|
||
- `rootUri`
|
||
- `resourcePath`
|
||
- `scope`: `tree | subtree | markdown_summary | full_envelope`
|
||
- `nodeId`
|
||
- `aiAccessScope`
|
||
|
||
输出:
|
||
|
||
- `objectIdentity`
|
||
- `resourceKind=mindmap`
|
||
- `mindmapId`
|
||
- `resourcePath`
|
||
- `revision`
|
||
- `envelope`,仅 `full_envelope` 返回
|
||
- `root`
|
||
- `nodes`
|
||
- `edges`
|
||
- `markdownSummary`
|
||
- `source=local_folder`
|
||
|
||
约束:
|
||
|
||
- `tree` / `markdown_summary` 默认不返回完整 envelope,避免 prompt 被视图和样式噪音污染。
|
||
- `full_envelope` 只在需要保留或精确 patch 文件时使用。
|
||
|
||
### 7.2 `mnote.mindmap.apply_ops`
|
||
|
||
当前该工具已存在,但 local resource 非 dry-run 仍提示 agent 用原生 patch。后续应收口为真正结构化写入工具。
|
||
|
||
输入:
|
||
|
||
- `workspaceId`
|
||
- `documentId`
|
||
- `mindmapId`
|
||
- `rootUri`
|
||
- `resourcePath`
|
||
- `expectedRevision`
|
||
- `ops`
|
||
- `aiAccessScope`
|
||
|
||
建议 ops:
|
||
|
||
- `updateText`
|
||
- `insertChild`
|
||
- `insertSiblingAfter`
|
||
- `deleteNode`
|
||
- `setHyperlink`
|
||
- `setRefs`
|
||
- `appendNote`
|
||
- `patchView`
|
||
- `setLayout`
|
||
- `setTheme`
|
||
|
||
约束:
|
||
|
||
- 默认只改 `data` 树和指定 metadata。
|
||
- 未知字段必须透传。
|
||
- `expectedRevision` 不匹配时拒写或返回 conflict。
|
||
- 写入后返回 `revision`、`changedFiles`、`markdownSummary`。
|
||
|
||
### 7.3 `mnote.mindmap.create_from_outline`
|
||
|
||
新增工具,用于“从材料生成新导图”。
|
||
|
||
输入:
|
||
|
||
- `workspaceId`
|
||
- `documentId`
|
||
- `rootUri`
|
||
- `targetPageId` 或 `targetDocumentId`
|
||
- `resourcePath`,可选;缺省由服务端生成唯一 `.mindmap.json`
|
||
- `title`
|
||
- `outline`
|
||
- `sourceRefs`
|
||
- `aiAccessScope`
|
||
- `embedIntoPage`,默认 `true`
|
||
|
||
`outline` 建议格式:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"text": "一级主题",
|
||
"children": [
|
||
{
|
||
"text": "二级主题",
|
||
"children": []
|
||
}
|
||
]
|
||
}
|
||
]
|
||
```
|
||
|
||
输出:
|
||
|
||
- `objectIdentity`
|
||
- `mindmapId`
|
||
- `resourcePath`
|
||
- `envelope`
|
||
- `revision`
|
||
- `changedFiles`
|
||
- `embedResult`
|
||
- `markdownSummary`
|
||
|
||
写入规则:
|
||
|
||
- 服务端负责把 outline 转换为默认 envelope。
|
||
- 根节点文本使用 `title`,没有标题时使用 `KMIND`。
|
||
- 子节点 uid 由服务端稳定生成,避免模型生成重复 uid。
|
||
- 默认 view 使用当前稳定模板。
|
||
- 若 `embedIntoPage=true`,通过 Resource Tree / Markdown embed 合同把资源绑定到当前页面。
|
||
|
||
## 8. PDF 到导图闭环
|
||
|
||
长期目标链路:
|
||
|
||
```text
|
||
PDF resource
|
||
-> 文本/OCR/章节提取
|
||
-> AI 生成层级 outline
|
||
-> mnote.mindmap.create_from_outline
|
||
-> 写入 .mindmap.json
|
||
-> Resource Tree 绑定当前页面
|
||
-> 打开 mindmap resource tab
|
||
```
|
||
|
||
本设计只冻结后半段合同:
|
||
|
||
- PDF 摘要工具输出应是 `title + outline + sourceRefs`。
|
||
- `sourceRefs` 可以记录 PDF 文件、页码、章节、引用片段。
|
||
- mindmap 节点可把 `sourceRefs` 保存到节点 `refs` 或 `note`,但第一版只要求保留到工具审计和 root metadata。
|
||
|
||
后续可接入:
|
||
|
||
- `mnote.office.fetch_summary`
|
||
- `mnote.pdf.extract_outline`
|
||
- MinerU markdown 识别结果
|
||
- 本地 Markdown / 当前页正文
|
||
|
||
## 9. 权限与审计
|
||
|
||
读写 mindmap resource 必须同时满足:
|
||
|
||
- 当前 actor 拥有 root 的 read 或 write grant。
|
||
- `aiAccessScope.permissionLevel` 覆盖目标操作。
|
||
- `allowedResourceIds` 包含 `mindmapId`、`resourcePath` 或 `objectIdentity`。
|
||
- 写入只能落在授权 root 内。
|
||
|
||
审计必须记录:
|
||
|
||
- tool name
|
||
- sessionId / runId / traceId
|
||
- actorId
|
||
- documentId
|
||
- mindmapId
|
||
- resourcePath
|
||
- sourceRefs
|
||
- changedFiles
|
||
- before / after revision
|
||
|
||
## 10. Page AI 上下文
|
||
|
||
Page AI run payload 应能携带当前 mindmap target:
|
||
|
||
```json
|
||
{
|
||
"contextRefs": [
|
||
{
|
||
"kind": "resource",
|
||
"resourceKind": "mindmap",
|
||
"objectIdentity": "resource:mindmap:{documentId}:{mindmapId}",
|
||
"documentId": "{documentId}",
|
||
"mindmapId": "{mindmapId}",
|
||
"resourcePath": "{relativePath}",
|
||
"rootUri": "{rootUri}"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
来源优先级:
|
||
|
||
1. 当前打开的 mindmap resource tab。
|
||
2. 当前页面选中的 mindmap block/embed。
|
||
3. 当前页面中唯一 mindmap embed。
|
||
4. 用户明确给出的资源文件路径。
|
||
5. 创建新导图时,当前页面作为目标页面。
|
||
|
||
## 11. 验收清单
|
||
|
||
- [x] MNote 内置技能面板出现 `MNote mindmap editing`。
|
||
- [x] `mnote-mindmap` 开关能进入 `skillPreferences.mnote`。
|
||
- [x] `mnote.skill.read` 能读取 `mnote-mindmap` 正文。
|
||
- [x] `mnote-mindmap` 正文说明导图 outline 格式:中心主题、一级分类、短语化节点、避免长段落。
|
||
- [x] `mnote.mindmap.fetch` 可读取默认 envelope 并返回 root/nodes/summary。
|
||
- [x] `mnote.mindmap.create_from_outline` 可生成符合默认 envelope 的 `.mindmap.json`。
|
||
- [x] `mnote.mindmap.create_from_outline` 在显式 `embedIntoPage=true` 时可把新导图链接写入当前 local-md 页面。
|
||
- [x] `task503-mindmap-skill-capability-smoke` 可直接读取 skill、创建能力导图、fetch 回读、绑定当前页面,并用真实登录浏览器截图验证。
|
||
- [x] 新建导图能绑定当前页面并在 File Tree / Resource Tab 可见。
|
||
- [x] `mnote.mindmap.apply_ops` 写入后保留 `view` 和未知字段。
|
||
- [x] shared/read-only scope 下写工具拒绝。
|
||
- [x] revision 不匹配时拒写或返回 conflict。
|
||
- [x] PDF outline fixture 可生成 mindmap resource。
|
||
- [x] 真实 mindmap resource tab 能注入 Page AI `active_editor` contextRef / `targetPackage`。
|
||
|
||
当前第一批已完成 Page AI skill 发现、skill 正文读取、默认 envelope fetch、`create_from_outline` 写入、显式 `embedIntoPage=true` 页面链接绑定、`task502` Page AI skill payload smoke,以及 `task503` 直接 tool 创建导图 + 页面绑定 + 浏览器截图 smoke。第二批已完成 `apply_ops` 最小结构化写入、`view` / 未知字段保留、revision conflict 和 shared/read-only 拒写单测;2026-06-01 已修复 `task455` 暴露的 local-folder embedded mindmap 刷新后 id 退化,根因是 `blockDocument.blocks[].attrs` 未保留 `mindmapId/sourcePath/rootNodeId` 且浏览器 conversion 未读取 blockDocument attrs;新增 `task525` 覆盖真实 mindmap resource tab 的 Page AI `active_editor` contextRef / `targetPackage`。
|
||
|
||
2026-06-01 复核:`mnote.mindmap.apply_ops` 已从 native patch 提示收口到最小结构化写入,当前支持 `updateText` / `updateNode`、`insertChild` / `addChild`、`deleteNode`,并由 `hermes_tools_mindmap_apply_ops_writes_and_preserves_envelope_fields`、`hermes_tools_mindmap_apply_ops_rejects_stale_revision`、`hermes_tools_mindmap_apply_ops_shared_read_is_forbidden` 覆盖。resource tab / File Tree 可见性和 Page AI mindmap contextRefs 已由 `task455`、`task524`、`task525` 验收。后续若继续扩展 `moveNode`、`insertSiblingAfter`、`setHyperlink`、`setRefs`、`appendNote`、`patchView`,应另拆 P2 follow-up,不阻塞本轮最小闭环。
|
||
|
||
## 12. 第一批执行建议
|
||
|
||
第一批只做可控闭环:
|
||
|
||
1. 新增 `skills/mnote-mindmap/SKILL.md`。
|
||
2. 在 `hermes_tools::skill` 注册 `mnote-mindmap`。
|
||
3. 补 Page AI skill 面板 smoke。
|
||
4. 补 `mnote.skill.read` 单测。
|
||
5. 增强 `mnote.mindmap.fetch` 输出,识别当前默认 envelope。
|
||
6. 新增 `mnote.mindmap.create_from_outline` dry-run 与真实写入。
|
||
7. 用 fixture 模拟 PDF 摘要,不接真实 PDF OCR。
|
||
|
||
第二批再做:
|
||
|
||
1. 补浏览器 smoke,验证新建或修改后的 mindmap 能在 File Tree / Resource Tab 可见。
|
||
2. 接入真实 PDF / Office / MinerU 结果。
|
||
3. 在资源 tab 中把当前 mindmap 自动注入 Page AI contextRefs。
|
||
4. 按真实编辑需求继续扩展 `apply_ops`,例如 `moveNode`、`insertSiblingAfter`、`setHyperlink`、`setRefs`、`appendNote`、`patchView`。
|