feat: land page aggregate and phase7 document ai mainline

- 收口 page aggregate 读取、本地状态与命令客户端\n- 接入 phase7 document ai sidecar 与前端编排入口\n- 更新 architecture 与 design 状态迁移
This commit is contained in:
lix-2026
2026-04-23 07:38:34 +08:00
parent 8353aea2f9
commit 41e958769e
93 changed files with 8778 additions and 2222 deletions
@@ -0,0 +1,108 @@
# 7-1 [done] Phase 7 文档页 AI 最小闭环执行清单 v1
> 更新时间:2026-04-22
>
> 上位依据:
> - `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v2.md`
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md`
>
> 状态说明:
> - 本稿对应 `Phase 7 v2` 的“文档页 AI 最小闭环”已完成,故迁入 `done/`
> - 本稿完成不等于整个 `Phase 7 v2` 已完成;结构化知识写链仍以后续阶段继续推进
---
## 1. 本轮范围
本轮只执行 `Phase 7 v2` 的第一轮最小闭环:
- 文档页 AI 读取当前页 page aggregate 上下文
- 编排层切入 `openai-agents-python`
- 正文插入 / 改写继续沿 `page.body.save` 回写
- 标题改名继续沿 `page.head.updateTitle` 回写
- 前端默认在线主路径先走新 sidecar,失败时 fallback 到 Hermes
- 页面 AI 配置开始收口到 `model_key / profile / tool registry`
本轮明确不做:
- `summary node`
- `ai_note node`
- `reference edge`
- `PDF / Book -> kernel index`
- mindmap / OnlyOffice AI 主链
---
## 2. 当前基线
- [x] 文档页主编辑区已经是页面内 `leptos-tiptap` island
- [x] 文档页 AI 已开始消费 page aggregate snapshot
- [x] 页面写命令面已开始收口到 `page.head.updateTitle` / `page.body.save`
- [x] 前端 `/api/ai-agent/run` 已承载 `online -> sidecar / fallback -> Hermes` 分流
- [x] `openai-agents-python` sidecar 已接入
- [x] 前端在线主路径已切到新 sidecar
---
## 3. 执行项
### A. 语义面冻结
- [x] 第一批正式写动作只覆盖:改标题 / 插入正文 / 改写正文
- [x] 正式命令语义固定为:`page.head.updateTitle` / `page.body.save`
- [x] 过渡工具面固定为:`doc_get` / `doc_find` / `doc_insert_blocks` / `doc_replace_range` / `slash_run`
- [x] 不新增第三套 AI 专用产品命名面
### B. 上下文装配冻结
- [x] sidecar 请求体固定包含:`documentId` / `documentBlocks` / `pageOptions` / `subtree` / `outline` / `evidence`
- [x] 不再新增新的 AI 私有页面 getter
- [x] 会话上下文裁剪规则先冻结到文档页最小字段集
### C. `openai-agents-python` sidecar
- [x]`wolai-backend` 新增文档页 AI sidecar route
- [x] 接入 `openai-agents-python`
- [x] 接入 OpenAI `Responses API`
- [x] 最小 tools 只注册:`doc_get` / `doc_find` / `doc_insert_blocks` / `doc_replace_range` / `slash_run`
- [x] tool 执行统一桥接到 `mnote-web /api/hermes/bridge`
- [x] 建立最小 session / tracing
- [x] 建立最小 guardrail / fallback 边界
### D. 前端主路径接线
- [x] `/api/ai-agent/run` 新增 sidecar adapter
- [x] `online` provider 默认先走 `openai-agents-python`
- [x] 新 sidecar 失败时自动 fallback Hermes
- [x] 继续输出兼容当前 panel 的 SSE 事件:`assistant_message` / `tool_call` / `tool_result` / `completion` / `error`
- [x] 文档页 AI 回写链继续复用 `page.head.updateTitle` / `page.body.save`
### E. 配置真源与可见性
- [x] 页面 AI 模型配置真源切到 `model_key`
- [x] `model_key -> resolved_combo -> resolved_runtime_model` 分层可见
- [x] 页面 AI 不再把 combo 名或 provider model 作为产品主键
- [x] `profile` 前端可设,但由后端 registry 持有真源
- [x] 页面 AI 设置页能显示当前 `profile`
- [x] 后端提供当前 scope 的真实 tool registry
- [x] 页面 AI 设置页能显示当前 scope 的已注册工具
### F. 验证
- [x] route 测试覆盖 sidecar 主路径与 Hermes fallback
- [x] 后端最小 smoke / 单测覆盖文档页 run route
- [x] 验证在线主路径下标题改名与正文改写都能完成结构化回写
说明:`task111-phase7-document-ai-online-smoke.js` 已验证 `doc_insert_blocks -> slash_run -> doc_replace_range` 在线主路径闭环
---
## 4. 本轮完成判定
当以下条件同时成立,才可以宣称本轮完成:
- [x] 文档页 AI 在线主路径不再默认依赖 Hermes 主编排
- [x] 文档页 AI 仍只围绕当前页主编辑区最小闭环工作
- [x] 标题改名与正文改写仍沿正式页面命令语义回写
- [x] Hermes 已退回 fallback / 对照链
- [x] 页面 AI 的模型 / 设定 / 工具状态已进入正式可见配置面
@@ -0,0 +1,528 @@
# 7-2 [process] Phase 7 结构化 Artifact 写链最小落地方案 v1
> 更新时间:2026-04-23
>
> 上位依据:
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-tree-first-graph-kernel-v1.md`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md`
> - `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v2.md`
> - `/mnt/Data1T/mnote/design/07-ai/done/7-1-phase7-document-ai-minimum-loop-checklist-v1.md`
---
## 1. 文档目的
这份稿只回答一个问题:
> **在文档页 AI 最小闭环已经完成之后,`summary node / ai_note node / reference edge` 这三条结构化知识写链,第一版到底如何落地,才能既进入 kernel,又不重新污染页面树、文件树和页面主链。**
当前不写这份稿,后续最容易出现两类跑偏:
-`summary / ai_note` 继续做成 AI 面板里的临时聊天产物,而不是 kernel node
- 为了让文件树看见它们,额外发明一个 `AI Artifacts` 真容器节点,重新污染树真相
因此本稿的目标不是“做完整 AI 平台”,而是:
> **只把 `summary node / ai_note node / reference edge` 这三条结构化写链,收口成第一版可执行、可验证、可继续扩展的最小实现。**
---
## 2. 当前结论
第一版固定采用下面这组边界,不再开放:
1. 只做三类结构对象:
- `summary node`
- `ai_note node`
- `reference edge`
2. 只允许围绕**当前文档页**创建,不做跨页、跨工作区写链
3. 触发方式不是自然语言,不做自动推断,只允许页面 AI 面板里的固定按钮触发
4. 点击按钮后直接创建,不走“先预览再确认”的两阶段流
5. `summary node` 默认单例覆盖更新;`ai_note node` 每次新建
6. 两者都落成**可编辑的页面型节点**
7. 文件树可见,页面树默认不可见
8. 文件树中的 `AI Artifacts` 只是 projection-only 的虚拟分组,不是新的真实 kernel node
9. 每次创建 `summary node``ai_note node` 时,自动连一条指向当前页的 `reference edge`
一句话收口:
> **第一版不是让 AI 自由生长“知识图谱”,而是让当前页能够稳定产出两类正式 artifact node,并带上一条最小来源边。**
---
## 3. 为什么第一版只做这三条
### 3.1 这是从“正文写链”走向“结构写链”的最小跨越
当前 `7-1` 已经完成的是:
- AI 读取当前页 page aggregate 上下文
- AI 通过 `page.head.updateTitle / page.body.save` 回写标题和正文
但这仍然只是在“改当前页”。
如果要让 AI 真正进入 `tree-first graph kernel`,第一步不应该直接跳到:
- 跨页知识网
- PDF / Book 结构化摄取
- 完整 index node / retrieval 主线
而应先从三条最小结构写链开始:
- 为当前页生成一个 `summary node`
- 为当前页生成一个 `ai_note node`
- 把它们用 `reference edge` 连回当前页
### 3.2 这三条最适合当前主线边界
这三者同时满足:
- 与当前页 AI 主链直接相邻
- 不要求跨页权限扩展
- 不要求额外引入新的树真相层
- 能直接复用当前的 page aggregate 上下文
- 能验证 `typed node / typed edge` 进入产品主线,而不是继续只停在文档里
### 3.3 `PDF / Book -> kernel index` 当前必须继续后置
`kernel index` 第一版不并入本稿,原因很明确:
- 它依赖更稳定的摄取边界
- 它会引入更重的异步任务与检索协议
- 它不是当前页 AI 面板的最小邻接能力
所以本稿故意不把阶段 5 全写成一个“大包”,而是只切出:
> **当前页 -> artifact node / reference edge**
---
## 4. 对象模型
第一版真正进入 kernel 的对象只有三类。
### 4.1 `summary node`
`summary node` 是一个真实的 `KernelNode``node_type = summary`
它的产品语义固定为:
- 它代表“当前页的最新摘要页”
- 它不是聊天消息
- 它不是页面内一段临时 block
- 它是可编辑页面型节点,但语义上属于 artifact
它的最小数据要求:
- `node_type = summary`
- `workspace_id = 当前页 workspace`
- `metadata.title = 当前页标题 + Summary`
- `content = 可被页面主编辑区消费的正文载荷`
- `refs.reference_node_ids` 至少包含当前页 `pageId`
- `refs.source_node_ids` 至少包含当前页 `pageId`
- `audit` 带最小 request / trace / actor 信息
### 4.2 `ai_note node`
`ai_note node` 也是一个真实的 `KernelNode``node_type = ai_note`
它的产品语义固定为:
- 它代表“围绕当前页生成的一份 AI 工作笔记页”
- 它不是摘要快照
- 它允许后续继续人工编辑
- 它是页面型节点,但语义上属于 artifact
它的最小数据要求:
- `node_type = ai_note`
- `workspace_id = 当前页 workspace`
- `metadata.title = 当前页标题 + AI Note + 时间戳/序号`
- `content = 可被页面主编辑区消费的正文载荷`
- `refs.reference_node_ids` 至少包含当前页 `pageId`
- `refs.source_node_ids` 至少包含当前页 `pageId`
- `audit` 带最小 request / trace / actor 信息
### 4.3 `reference edge`
`reference edge` 在第一版里不新增新的 edge type 名字,先收口到现有 `KernelEdgeType::References`
它的产品语义固定为:
- 表示 artifact node 引用了当前页
- 它不是父子边
- 它不进入页面树 / 文件树
- 它只进入关系层 / 引用层 /后续 graph traversal
第一版边方向固定为:
- `from_node_id = artifact node`
- `to_node_id = 当前页 node`
- `edge_type = references`
这样可以稳定表达:
> **这个 summary / ai_note 是围绕当前页生成的。**
### 4.4 `AI Artifacts` 不是对象,只是投影分组
第一版明确禁止把 `AI Artifacts` 做成真实 node。
它只允许存在于:
- 文件树 projection
- 可能的 Inspector / artifact 列表 projection
它不允许存在于:
- kernel node truth
- tree command truth
- page aggregate truth
理由很简单:
- 它只是展示分组
- 它不是用户真正的知识对象
- 它不应反向塑造树真相
---
## 5. 写入语义
### 5.1 统一动作面
第一版只开放两个显式动作:
- `create_summary_artifact_for_current_page`
- `create_ai_note_artifact_for_current_page`
这里先用产品动作名描述,不在本稿中强行冻结底层最终 route/path 名。
长期原则固定为:
- 它们必须进入 Rust runtime / bridge-runtime 主写链
- 不允许绕过 kernel 直接只写前端本地状态
- 不允许只停留在 AI 面板会话日志里
### 5.2 `summary node` 的写入策略
`summary node` 第一版采用**单例覆盖更新**。
固定规则:
1. 先按“当前页 -> artifact node_type = summary”查询是否已有 summary node
2. 若已存在:
- 复用该节点 `node_id`
- 覆盖其 `content`
- 更新其 `metadata.updated_at`
- 保留其页面型身份
3. 若不存在:
- 新建一个 `summary node`
- 自动附加到当前页的 artifact projection 分组下
- 自动创建一条 `reference edge`
为什么 `summary` 采用单例:
- 它更像“当前页最新摘要”
- 否则文件树下会快速积累多份摘要页
- 第一版要先控制 artifact 数量,而不是先保留完整历史
### 5.3 `ai_note node` 的写入策略
`ai_note node` 第一版采用**每次新建**。
固定规则:
1. 每次点击 `创建 AI Note` 都新建一个 `ai_note node`
2. 标题默认带时间戳或递增序号
3. 创建后自动创建一条 `reference edge`
4. 不尝试合并、覆盖旧 `ai_note`
为什么 `ai_note` 采用多实例:
- 它更像工作产物
- 一次次 AI 分析、本轮整理、本轮方案,本来就可能并存
- 如果也做成单例,会过早丢失工作过程
### 5.4 来源边写入策略
创建 `summary node``ai_note node` 时,自动写一条 `reference edge`
第一版不要求用户再单独确认,也不要求额外按钮。
这条边的作用不是“展示炫酷图谱”,而是保证两个基本能力:
1. 后续能追溯这个 artifact 来源于哪一页
2. 后续文件树/关系面板/graph traversal 不需要重新猜测来源
### 5.5 第一版不做的写入动作
第一版明确不做:
- artifact -> 多来源页面的复合引用
- artifact -> 块级 evidence 的精细挂接
- 跨页创建 summary / ai_note
- 人工拖拽 artifact 重新挂到别的页面
- artifact 自动进页面树
这些都属于第二版以后再做的能力。
---
## 6. 触发方式与产品入口
### 6.1 只允许固定按钮触发
第一版不走自然语言触发。
不支持:
- “帮我顺手创建一个摘要节点”
- “看起来像摘要就自动生成”
- “只要语义明确就直接落库”
只支持页面 AI 面板里的两个固定按钮:
- `创建 Summary`
- `创建 AI Note`
### 6.2 点击后直接创建
第一版点击按钮后,直接创建,不走预览确认。
这是一个非常明确的产品取舍:
- 优点:动作和结果一一对应,最容易验证主写链
- 缺点:产物质量控制不如“先预览再落库”
当前优先级里,第一版更重视:
- 正式写链成立
- kernel node / edge 成立
- 文件树 projection 成立
而不是先做复杂的人机审核流。
### 6.3 内容来源固定为当前页全文
第一版两个按钮的内容来源都固定为:
- 当前页全文
不做:
- 仅选区生成
- 仅当前可见块生成
- 混入会话消息做额外上下文真相
这能确保第一版边界足够清楚:
> **artifact 是围绕当前页全文生成,而不是围绕聊天面板局部状态生成。**
---
## 7. 文件树 projection 与页面树隐藏规则
### 7.1 页面树默认不可见
`summary node``ai_note node` 第一版默认不进入页面树 projection。
原因:
- 页面树是日常导航主链
- artifact 进入页面树会明显污染日常使用
- 它们虽然是页面型节点,但不是“用户正常页面层级”的一部分
### 7.2 文件树可见
`summary node``ai_note node` 第一版可以在文件树 projection 中可见。
这样做的目的不是把文件树变成第二个知识图谱,而是保留一个“必要时可管理”的管理入口。
### 7.3 `AI Artifacts` 虚拟分组规则
在文件树 projection 中,为每个当前页生成一个 projection-only 分组:
- `AI Artifacts`
固定规则如下:
1. 它不是真实 node
2. 它不持久化到 kernel
3. 它只存在于 `file_tree` projection 结果中
4. 它的 children 由“当前页关联的 artifact nodes”动态投影得出
### 7.4 文件树中的相对位置
第一版推荐把 `AI Artifacts` 放在当前页下面,但与普通子页面分区显示。
不是:
- artifact 混在普通子页面列表里
而是:
- 当前页
- 普通文件/子页
- `AI Artifacts`
- `Summary`
- `AI Note 2026-04-23 10:31`
- `AI Note 2026-04-23 10:46`
这样既满足“文件树可管理”,又最大限度避免污染普通导航。
### 7.5 `reference edge` 不进树
`reference edge` 永远不是树项。
它应只进入:
- 关系面板
- 引用面板
- graph traversal
- 后续结构阅读态
它不允许伪装成页面树 / 文件树节点。
---
## 8. 与当前主链的关系
### 8.1 不改变当前页主编辑区真相
第一版 artifact 写链不会改变:
- 当前页正文依然走 `page.body.save`
- 当前页标题依然走 `page.head.updateTitle`
- 当前页页面设置依然走 `page.layout.updateOptions`
artifact 写链是新增的结构写链,不是对当前页主链的替代。
### 8.2 与 page aggregate 的关系
第一版 artifact 生成必须依赖当前 page aggregate 上下文,但不把 artifact 自身并入当前页的 page aggregate truth。
也就是说:
- page aggregate 提供生成材料
- artifact 是新的 kernel node
- artifact 不是当前页 `page_body` 的附属字段
这是必须守住的边界,否则又会回到“把结构对象塞进页面壳状态”的旧路。
### 8.3 与 tree command 的关系
artifact node 虽然默认不进页面树,但它们仍然是 tree-first graph kernel 的真实 node。
因此长期上仍应可复用:
- `kernel.node.get`
- `kernel.subtree.get`
- `kernel.edges.list`
- `kernel.edge.attach`
但第一版不要求把 artifact 的全部树命令交互一次做完。
---
## 9. 最小实现分层
### 9.1 Kernel / Rust runtime 层
需要补的最小能力:
1. 创建 `summary node`
2. 更新现有 `summary node`
3. 创建 `ai_note node`
4. 创建 `references` edge
5. 按当前页查找其关联 artifact nodes
第一版不要求完整 artifact 生命周期,只要求:
- create
- update summary
- list by current page relation
### 9.2 Projection 层
需要补的最小能力:
1. `file_tree` projection 能识别“当前页关联的 artifact nodes”
2. 在 projection 里注入一个虚拟 `AI Artifacts` 分组
3. 页面树 projection 不注入该分组
### 9.3 前端文档页层
需要补的最小能力:
1. 页面 AI 面板显示两个固定按钮
2. 点击按钮后触发相应写入动作
3. 创建完成后,文件树对应 projection 刷新
4. 若新建了 `ai_note node`,允许点击进入该页面
5. 若更新了 `summary node`,允许点击进入摘要页
---
## 10. 验证口径
第一版完成,至少要满足以下验证。
### 10.1 Summary 链
- 当前页点击 `创建 Summary`
- 若不存在 summary node,则新建
- 若已存在,则覆盖更新
- 文件树中当前页下出现或保留 `AI Artifacts / Summary`
- 页面树中不出现该节点
- 可打开该 `summary node`
- kernel 中存在从 `summary node -> 当前页``references` edge
### 10.2 AI Note 链
- 当前页点击 `创建 AI Note`
- 每次都新建一个新的 `ai_note node`
- 文件树中当前页下 `AI Artifacts` 分组内累积出现新节点
- 页面树中不出现这些节点
- 可打开新建的 `ai_note node`
- kernel 中存在从 `ai_note node -> 当前页``references` edge
### 10.3 真相边界
- `AI Artifacts` 不出现在真实 kernel node 列表中
- `AI Artifacts` 只存在于文件树 projection 结果中
- 当前页 page aggregate 不被额外塞入 artifact truth
- artifact 不混入普通页面树导航主链
---
## 11. 明确不做什么
第一版明确不做:
- 自然语言隐式触发 artifact 创建
- 跨页 summary / ai_note 写链
- artifact 多来源引用
- block 级 evidence 精细挂接
- `AI Artifacts` 真实容器节点化
- artifact 进入页面树默认主链
- artifact 复杂权限模型
- artifact 预览确认流
- artifact 版本历史产品壳
---
## 12. 最终冻结口径
当前冻结如下:
> **阶段 5 的第一版,只把 `summary node / ai_note node / reference edge` 作为最小结构化知识写链落到 kernel。**
> **`summary node / ai_note node` 都是真实页面型 kernel node`reference edge` 使用现有 `references` typed edge`AI Artifacts` 只是文件树 projection 下的虚拟分组,不是真实对象。**
> **第一版只允许围绕当前页,通过页面 AI 面板固定按钮直接触发;`summary node` 单例覆盖更新,`ai_note node` 每次新建;创建节点时自动连一条指向当前页的 `reference edge`。**
一句话收口:
> **第一版的目标不是做“大而全 AI 知识层”,而是让当前页第一次稳定地产出正式 artifact node,并且能在不污染页面树真相的前提下进入文件树管理视图。**
@@ -0,0 +1,779 @@
# 7 [process] mnote Kernel Phase 7 AI 编排与 Kernel Projection 实施计划 v2
> 更新时间:2026-04-22
>
> 当前主线依据:
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
> - `/mnt/Data1T/mnote/design/01-05-current-priority-overview.md`
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-tree-first-graph-kernel-v1.md`
> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md`
> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md`
> - `/mnt/Data1T/mnote/design/04-tree-domain/process/4-6-tree-command-protocol-cutover-stage2-v1.md`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md`
>
> 本稿与 `v1` 的关系:
> - `/mnt/Data1T/mnote/design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v1.md` 已降级为上一轮判断稿
> - 当前如要真正执行 `Phase 7`,应以本 `v2` 为执行口径
>
> 当前状态补充:
> - `/mnt/Data1T/mnote/design/07-ai/done/7-1-phase7-document-ai-minimum-loop-checklist-v1.md` 对应的“文档页 AI 最小闭环”已完成
> - 但本 `v2` 的后续阶段,尤其 `summary node / ai_note node / reference edge / kernel index` 仍未完成,因此本稿继续保留在 `process/`
> - 2026-04-23 验证补充:
> - `cd /mnt/Data1T/mnote/wolai-backend && ./.venv/bin/python -m pytest -q tests/test_ai_document_agent.py` -> `15 passed`
> - `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- --runInBand src/app/api/ai-agent/run/route.test.ts src/app/api/ai-agent/document/config/route.test.ts src/components/editor/DocumentAiAgentPanel.runtime.test.tsx src/components/ai-agent/panelShared.test.ts` -> `202 passed`
---
## 1. 文档目的
这份 `v2` 只做一件事:
> **把 `Phase 7` 从“抽象地谈 AI 最终形态”改写成“能接在当前 page aggregate / tree command / realtime 主线之后执行的现实方案”。**
当前不再适合继续直接沿用 `v1` 的原因,不是方向完全错了,而是:
- `v1` 更像长期判断稿
- 它对当前真实工具面、命令面、依赖顺序仍然写得过于理想化
- 它没有充分吸收 `Page Aggregate` 这几天已经形成的收口事实
因此本稿要解决的不是“要不要做 Phase 7”,而是:
1. 如果现在开始做 `Phase 7`,第一交付物到底是什么
2. `Phase 7` 应该接在哪条现有主线之后,而不是另起一套理想结构
3. `openai-agents-python` 到底如何接入当前文档页 AI 主链
4. 哪些 `v1` 里的目标继续保留,哪些必须降级到后续阶段
一句话收口:
> **`Phase 7` 当前第一目标不是“做完整 AI 平台”,而是让文档页 AI 先沿着 `page aggregate command family` 进入主编辑区正式主链。**
---
## 2. 当前结论
当前推荐口径固定如下:
> **`mnote` 的长期 AI 主线仍然采用“Rust kernel / Rust runtime 做唯一事实源与真执行面,`openai-agents-python` 作为 `mnote` 专用编排层,`Hermes` 退回过渡与实验平台”的结构。**
但如果按真实执行顺序来排,当前 `Phase 7` 必须服从下面这个前置条件:
1. `Page Aggregate` 继续作为文档页真相收口主线
2. `tree command cutover` 继续作为页面生命周期正式命名面主线
3. `tree realtime event stream` 继续作为工作区树实时主线
4. `Phase 7` 只在这三条主线已形成可接入的最小面之后,切入文档页 AI 最小闭环
因此当前不能把 `Phase 7` 表述成:
- 先做一套完整 AI 产品平台
- 先把所有 AI 工具都切到全新命名
- 先把 `summary node / ai_note node / reference edge / kernel index` 全部一口气打通
当前正确表述应是:
> **`Phase 7` 的第一闭环,是“文档页 AI 读取 page aggregate 上下文,并通过 `page.head.updateTitle / page.body.save / tree.*` 正式命令面回写主编辑区”。**
---
## 3. 当前真实基线
`v2` 必须建立在当前已经真实成立的代码事实之上。
### 3.1 文档页主编辑器已经切到正式 island
当前默认主编辑区已经是页面内 `leptos-tiptap` island,不再是 `iframe bridge``BlockNote` 只保留为 fallback / 对照链。
这意味着 `Phase 7` 的文档页 AI 主写链,默认目标已经不是旧编辑器壳,而是当前正式主编辑区。
### 3.2 文档页已经开始消费统一 page aggregate
当前文档页首屏与客户端补拉已经围绕 `PageAggregateProjection` 收口,页面本地状态也开始收口到统一 client aggregate state。
这意味着:
- AI 上下文已经不必继续只围绕零散 `title / content / options / pageSubtree` getter 组织
- 文档页 AI 可以以 page aggregate snapshot 作为第一上下文来源
### 3.3 页面命令面已经开始收口到 `page.*`
当前前端与 route 执行面已经开始统一到下面三组页面命令:
- `page.head.updateTitle`
- `page.layout.updateOptions`
- `page.body.save`
这组命令面已经成为文档页 AI 后续接入的第一正式写入口。
这也是本稿与 `v1` 的关键差异之一:
> **`Phase 7` 第一阶段不再直接凭空引入一套全新的 `editor.*` 产品命名面,而是优先挂接已经开始收口的 `page aggregate command family`。**
### 3.4 树域命令面正在切到 `tree.*`
当前页面新建、重命名、移动、归档、恢复、嵌入等生命周期命令,长期正式命名已固定为:
- `tree.node.create`
- `tree.node.rename`
- `tree.subtree.move`
- `tree.node.archive`
- `tree.node.restore`
- `tree.node.purge`
- `tree.node.embed`
- `tree.subtree.copy`
这意味着:
- AI 若需要跨页面生命周期操作,不应继续以 `documents.*` 作为长期契约
-`Phase 7` 第一闭环仍以当前页正文编写为先,不先扩大全树操作面
### 3.5 当前 AI runtime 仍以 Hermes 兼容桥为主
当前文档页 AI 面板仍主要通过 `Hermes bridge` 工作,前端默认工具面仍以这些运行时工具为主:
- `slash_run`
- `doc_get`
- `doc_find`
- `doc_insert_blocks`
- `doc_replace_range`
- `docs_search`
- `docs_read`
- `image_read`
并且当前结构化结果恢复,明确只对以下文档页写工具做了正式回接:
- `slash_run`
- `doc_insert_blocks`
- `doc_replace_range`
这意味着当前现实不是:
- 已有一套完整 `mnote-native` agent 编排层
而是:
- 已有一个可工作的文档页 AI 过渡链
- 这条链已经开始向 `page aggregate command family` 回接
- `Phase 7` 的第一任务,应是把这条链从 Hermes 兼容桥迁到正式 `openai-agents-python` 编排层
---
## 4. 为什么 `v1` 不能直接当执行稿
`v1` 里最需要修正的不是方向,而是以下四个执行偏差。
### 4.1 工具命名过于理想化
`v1` 直接把第一批工具写成:
- `editor.insert_block_after`
- `editor.replace_block`
- `editor.delete_block`
- `kernel.summary.create`
- `kernel.ai_note.create`
这在长期上未必错,但它跳过了当前已经开始成形的两层真实命名:
- 页面命令面:`page.head.* / page.layout.* / page.body.*`
- 树域命令面:`tree.*`
如果现在按 `v1` 直接执行,容易在现有 `page.*` / `tree.*` 之外,再长出第三套 AI 专用命名面。
### 4.2 没有明确把 Phase 7 锚定到 Page Aggregate
`v1` 虽然提到了 `Page Aggregate`,但没有把它明确设为 `Phase 7` 的第一依赖。
而当前真实主线已经很明确:
> **文档页 AI 若不先对齐 `Page Aggregate`,后面很容易再次绕回“前端局部快照 + 兼容副作用链”的旧路。**
### 4.3 第一阶段战线铺得过宽
`v1` 把下面这些目标放得过于靠前:
- `summary node`
- `ai_note node`
- `reference edge`
- `PDF / Book -> kernel index`
这些目标仍然重要,但当前如果要先做 `Phase 7`,第一交付物不应是它们。
当前第一交付物应是:
> **文档页 AI 直接编写主编辑区,人审核后应用,且整个过程沿 `page aggregate` 正式命令面回写。**
### 4.4 没有充分吸收当前 Hermes 兼容桥已形成的过渡事实
当前已经存在一条可运行的 Hermes 文档页 AI 过渡链,且它已经开始把结果恢复成:
- `page.body.save` 语义
- `page.head.updateTitle` 语义
所以 `Phase 7` 的正确做法不是假装这条链不存在,而是:
1. 明确它是过渡链
2. 冻结它的保留边界
3.`openai-agents-python` 替换它的编排层,而不是推翻整条文档页 AI 回写链
---
## 5. 架构边界冻结
### 5.1 长期推荐结构
```text
Document Page / Read View / AI Panel
|
v
AI Gateway / SSE Event Adapter
|
+---- current fallback: Hermes bridge
|
+---- target mainline: openai-agents-python
| |
| +---- provider: OpenAI Responses API
| +---- mnote page tools
| +---- mnote tree tools
|
v
Rust runtime / mnote-web / bridge-runtime
|
+---- page aggregate command family
| - page.head.updateTitle
| - page.layout.updateOptions
| - page.body.save
|
+---- tree command family
| - tree.node.*
| - tree.subtree.*
|
v
Rust kernel truth
```
### 5.2 各层职责
#### Rust kernel / Rust runtime
负责:
- 对象真相
- projection / query / command
- page aggregate 命令面
- tree command 命令面
- 审计、trace、失败回放与回滚基线
不负责:
- 通用 agent 编排框架
- 通用聊天产品壳
#### `openai-agents-python`
负责:
- 文档页 AI 会话编排
- tools / handoffs / tracing / guardrails / HITL
- 调用 OpenAI `Responses API`
- 组织 `mnote` 的文档页 AI 工具合同
不负责:
- 保存产品真相
- 绕过 Rust runtime 直接写产品数据
- 自己持有第二套页面真相
#### Hermes
负责:
- 过渡期 fallback
- 回归对照
- 试验非主链场景
不负责:
- 文档页 AI 长期主编排
- 产品正式工具契约
#### 前端 AI Host / Panel
负责:
- 会话 UI
- 流式事件渲染
- 审核与应用入口
- 挂接当前页面的 page aggregate snapshot
- 展示当前页面 AI 的正式配置真源与运行时能力面
不负责:
- 私下拼出第二份页面真相
- 私下定义长期 AI 工具协议
- 私下持有 `profile` 真源
- 私下硬编码一份长期工具注册表
### 5.3 页面 AI 配置真源冻结
当前页面 AI 的配置真源,必须额外冻结为下面三层。
#### 模型层:前端保存 `model_key`,不保存底层 provider model
页面 AI 的模型配置真源,不应是:
- `slow / fast / codex` 这类 combo 内部路由名
- `ju/gpt-5.4` 这类底层 provider model id
页面 AI 应保存的是**产品层可识别的 `model_key`**,例如:
- `gpt-5.4`
- `gpt-5.4-mini`
- `gpt-5.3-codex`
- `gemini-3.1-pro-preview`
- `third`
其长期原则固定如下:
- `model_key` 是前端设置与产品语义真源
- `resolved_combo` 是运行时解析结果,例如 `slow / fast / codex`
- `resolved_runtime_model` 是最终底层节点 / provider model,仅用于调试、trace 与排障
也就是说:
> **页面 AI 配置真源固定为 `model_key -> resolved_combo -> resolved_runtime_model`,而不是直接把 combo 名或底层 provider model 暴露成产品配置键。**
#### 设定层:前端可设 `profile`,后端持有真源
当前 `Soul / Profile` 的正确落点不是前端自由文本壳,也不是 `openai-agents-python` 自己的长期真相层,而是:
- 前端可以选择与查看 `profile`
- 后端持有正式 `profile registry`
- 编排层把 `profile` 编译成最终 instructions / policy / defaults
固定原则如下:
- 前端只提交 `profileId`
- `profile` 内容、版本、默认值、升级策略由后端持有
- 前端可显示 profile 说明、用途、默认工具集、session 策略
- 不允许前端静态硬编码出第二份长期 `profile` 真相
#### 工具层:工具注册表必须前端可见
当前页面 AI 的正式工具面,不允许只在后端注册、前端不可见。
必须固定为:
- 后端持有正式 tool registry
- 前端设置页可以看见当前 scope 已注册工具
- 工具显示至少包含:
- `name`
- `description`
- `scope`
- `read/write`
- `status`
- `version`(如有)
这样后续若新增 `mindmap`、阅读态、搜索态等工具,前端设置页会直接反映真实能力面,而不是继续依赖人工记忆。
---
## 6. `Phase 7` 的当前目标重写
本稿把 `Phase 7` 当前目标重写为两层。
### 6.1 第一层目标:文档页 AI 最小闭环
这是当前必须优先完成的唯一第一闭环。
完成口径如下:
- AI 读取当前文档页 page aggregate 上下文
- AI 能对当前页正文执行插入、改写、重命名
- AI 回写沿正式 `page aggregate command family`
- 主编辑区 island 能正式回显结果
- 人可以作为审核者决定是否应用或继续编辑
- 人可以在页面 AI 设置中看见当前 `model_key / profile / tool registry` 的正式状态
一句话说:
> **先让 AI 真正进入当前页主编辑区主链,而不是先做大而全的 AI 能力矩阵。**
### 6.2 第二层目标:结构化知识写链
下面这些目标保留,但降到文档页最小闭环之后:
- `summary node`
- `ai_note node`
- `reference edge`
- `PDF / Book -> kernel index`
它们属于 `Phase 7` 的后续扩展,不再作为第一交付物。
---
## 7. 第一闭环的冻结验收口径
当前如要宣称 `Phase 7` 进入执行,应只以以下验收口径作为第一阶段成功标准。
### 7.1 读侧
AI 至少能稳定拿到:
- `documentId`
- 当前页 `blocks`
- 当前页 `pageSubtree`
- `pageOptions`
- `editorRuntimePageOptions`
- 必要时的 `outline / evidence`
说明:
- 当前不要求所有上下文都来自 Rust 原生 `Page Aggregate route`
- 允许过渡期继续使用当前文档页已经收口出的 page aggregate loader 与 client aggregate snapshot
- 但不再允许继续围绕零散页面壳对象拼装新的 AI 私有上下文
### 7.2 写侧
AI 第一批正式写能力只冻结为:
- 当前页标题改名
- 当前页正文插入
- 当前页正文改写
其长期命令语义分别锚定为:
- 标题改名 -> `page.head.updateTitle`
- 正文插入 / 改写 -> `page.body.save`
说明:
- 过渡期运行时仍可继续通过 `slash_run / doc_insert_blocks / doc_replace_range` 承接
- 但这些运行时工具必须被视为过渡工具,不得继续上升为长期产品契约
### 7.3 审核侧
当前文档页 AI 的产品定位固定为:
> **AI 直接接入主编辑区编写,人负责审核、继续编辑、确认结果。**
因此第一闭环里必须明确:
- AI 输出不是单纯聊天文本
- AI 输出必须能映射到页面正式写链
- 人能在主编辑区中继续接手与修订
### 7.4 不在第一闭环内的项
当前不纳入第一闭环:
- 页面设置类 AI 写工具
- 跨页大规模树操作
- mindmap AI 主链
- PDF / Book 结构化摄取
- `summary node / ai_note node / reference edge`
### 7.5 配置侧
第一闭环内,页面 AI 的配置面至少要有可冻结的正式口径:
- 模型真源为 `model_key`
- `resolved_combo / resolved_runtime_model` 只作为运行时调试信息
- `profile` 前端可设,但由后端 registry 持有真源
- 当前 scope 的 tool registry 必须前端可见
说明:
- 第一闭环不要求一开始就做完整 AI 设置产品壳
- 但必须把“谁是配置真源、哪些信息必须可见”冻结下来
- 否则后续模型、profile、工具会继续散落在前端本地状态、后端环境变量和隐式注册代码里
---
## 8. 正式工具面与过渡工具面的双层口径
为避免混乱,本稿把工具合同拆成两层。
### 8.1 长期正式命令面
这是产品长期应围绕的正式语义面:
#### 页面命令面
- `page.head.updateTitle`
- `page.layout.updateOptions`
- `page.body.save`
#### 树域命令面
- `tree.node.create`
- `tree.node.rename`
- `tree.node.archive`
- `tree.node.restore`
- `tree.node.purge`
- `tree.node.embed`
- `tree.subtree.move`
- `tree.subtree.copy`
### 8.2 过渡运行时工具面
这是当前 Hermes 兼容链与 bridge-runtime 已经真实承接的工具面:
- `slash_run`
- `doc_get`
- `doc_find`
- `doc_insert_blocks`
- `doc_replace_range`
- `docs_search`
- `docs_read`
- `image_read`
固定原则如下:
> **`Phase 7` 不删除过渡工具面,但也不把过渡工具名继续写成长期产品契约。**
### 8.3 `openai-agents-python` 的接入原则
`openai-agents-python` 接入时,优先接的不是抽象理想工具名,而是:
1. 当前页最小闭环所需的正式命令语义
2. 当前已真实存在的过渡运行时工具能力
3. 两者之间的明确映射关系
也就是说:
- 对外长期文档写正式命令语义
- 对内迁移期允许 adapter 调用当前 bridge-runtime 能跑通的过渡工具
### 8.4 工具注册表可见原则
文档页 AI 长期不能只做到“后端注册工具”,还必须做到“前端能看见当前真正注册了哪些工具”。
因此冻结如下:
1. 后端需要提供正式能力面 / 注册表接口
2. 前端页面 AI 设置页默认展示当前 scope 的真实工具注册表
3. 前端手动工具选择只允许在真实注册工具集合内进行
4. 新增 `mindmap`、阅读态、搜索态工具时,必须同步进入注册表可见面
一句话收口:
> **工具不是隐藏在编排层里的实现细节,而是页面 AI 产品能力面的一部分。**
---
## 9. 分阶段实施计划
## 阶段 0:冻结 `Phase 7` 依赖关系
### 目标
明确 `Phase 7` 是文档页主线的下一层,而不是脱离 `Page Aggregate` 单独启动的平行工程。
### 需要完成
- [x] 明确 `Phase 7` 第一依赖是 `5-6 Phase J`
- [x] 明确当前第一闭环只覆盖文档页 AI 主写链
- [x] 明确 `summary / ai_note / reference / index` 降为后续扩展
- [x] 明确 `Hermes` 只保留为 fallback / 对照链
- [x] 明确 `openai-agents-python` 为长期推荐编排层
- [x] 明确页面 AI 模型配置真源是 `model_key`,不是 combo 名或 provider model
- [x] 明确 `profile` 前端可设、后端持有真源
- [x] 明确 tool registry 必须前端可见
### 完成判定
- [ ] 团队口径统一为“先文档页最小闭环,再扩结构化知识写链”
- [ ] 团队口径统一为“`model_key / profile / tool registry` 都有正式真源,不再散落在隐式实现里”
---
## 阶段 1:冻结文档页 AI 正式语义面
### 目标
先把文档页 AI 到底面向哪一组正式语义面写清楚。
### 需要完成
- [x] 冻结当前页 AI 写入第一批正式动作:
- 改标题
- 插入正文
- 改写正文
- [x] 冻结这些动作对应的长期正式命令语义:
- `page.head.updateTitle`
- `page.body.save`
- [x] 冻结树域相关动作的长期正式命令语义为 `tree.*`
- [x] 写清 `过渡工具面 -> 正式命令面` 的映射关系
- [x] 禁止新增第三套 AI 专用产品命名面
- [x] 冻结页面 AI 模型配置真源为 `model_key`
- [x] 冻结 `model_key -> resolved_combo -> resolved_runtime_model` 的分层关系
- [x] 冻结 `profile` 前端可设、后端 registry 持有真源
- [x] 冻结当前 scope tool registry 必须前端可见
### 完成判定
- [x] 文档页 AI 已有一套与 `page aggregate command family` 对齐的稳定语义面
- [x] 文档页 AI 已有一套与 `model_key / profile / tool registry` 对齐的稳定配置语义面
---
## 阶段 2:冻结文档页 AI 上下文装配
### 目标
让 AI 输入上下文显式锚定到 page aggregate,而不是继续围绕零散页面壳字段。
### 需要完成
- [x] 固定当前页 AI 最小上下文字段:
- `documentId`
- `blocks`
- `pageSubtree`
- `pageOptions`
- `editorRuntimePageOptions`
- `outline`
- `evidence`
- [x] 明确上下文优先级:
- page aggregate snapshot
- page subtree / outline / evidence
- 必要的兼容页面壳快照
- [x] 不再继续扩散新的 AI 私有页面 getter
- [x] 为 AI 会话定义上下文裁剪规则
### 完成判定
- [x] 文档页 AI 读侧可以被明确描述为“消费 page aggregate 上下文”
---
## 阶段 3:引入 `openai-agents-python` 文档页编排层
### 目标
在不推翻现有文档页 AI 回写链的前提下,用 `openai-agents-python` 替换 Hermes 作为长期文档页编排层。
### 需要完成
- [x] 建立独立的 `mnote-ai-orchestrator` Python 服务或 sidecar
- [x] 接入 OpenAI `Responses API`
- [x] 先只注册文档页第一闭环所需工具
- [ ] 打通 session / tracing / guardrails / HITL 最小能力
- [x] 对齐当前前端 SSE 协议,或提供新的稳定 event adapter
- [x] 前端 provider 切换具备 `Hermes fallback`
- [x] 建立页面 AI capability/config route,至少返回:
- `model_key` 列表
- 默认 `profile`
- 当前 scope tool registry
- `resolved_combo / resolved_runtime_model` 调试字段
- [x] 让 online provider 也能稳定进入正式 session 模式,而不只是在 codex provider 下启用
### 完成判定
- [x] 在不依赖 Hermes 主编排的情况下,文档页 AI 已能跑通第一闭环
- [x] 新编排层已具备“模型 / profile / 工具”统一能力面出口
---
## 阶段 4:切文档页 AI 默认主路径
### 目标
让文档页 AI 在产品可见行为上真正从 Hermes 过渡到新编排层。
### 需要完成
- [x] 文档页 AI panel 默认走 `openai-agents-python`
- [x] 标题改名沿 `page.head.updateTitle` 回写
- [x] 正文改写沿 `page.body.save` 回写
- [x] 主编辑区 island 稳定回显 AI 结果
- [x] 审核与继续编辑行为维持在主编辑区内完成
- [x] Hermes 仅保留 fallback 开关
- [x] 页面 AI 设置页显示正式 `model_key` 下拉,而不是自由文本底层 model
- [x] 页面 AI 设置页显示当前 `profile`
- [x] 页面 AI 设置页显示当前 scope 已注册工具列表
- [x] 页面 AI 设置页显示当前 `resolved_combo / resolved_runtime_model` 作为调试信息,而不是产品主键
### 完成判定
- [x] 可以明确说“AI 已正式进入当前页主编辑区主链”
- [x] 可以明确说“页面 AI 的模型 / 设定 / 工具状态对用户是可见且可解释的”
---
## 阶段 5:扩展结构化知识写链
### 目标
在文档页最小闭环稳定后,再向更完整的 `Phase 7` 目标扩展。
### 需要完成
- [ ] `summary node`
- [ ] `ai_note node`
- [ ] `reference edge`
- [ ] `PDF / Book -> kernel index`
- [ ] 对这些写链补齐 trace / audit / rollback / evidence
### 完成判定
- [ ] `Phase 7` 才能开始被描述为“进入结构化知识写链阶段”
---
## 10. Hermes 的过渡策略重写
当前不建议立刻删除 Hermes,但必须缩边界。
### 10.1 继续保留的价值
- 承接现有文档页 AI 运行链
- 作为 `openai-agents-python` 的回归对照
- 作为 fallback 开关
- 承接非主链实验场景
### 10.2 明确禁止的事情
- 不让 Hermes 成为文档页长期主编排
- 不让 Hermes memory 取代 page aggregate / kernel-aware retrieval
- 不让 Hermes 工具名继续成为长期产品契约
- 不让 Hermes 默认 shell/fs 能力绕过 Rust runtime 写业务数据
### 10.3 最终可接受状态
最终可接受状态有两种:
1. Hermes 退化为非主链实验平台
2. Hermes 完全下线,只保留 `openai-agents-python + Rust runtime`
---
## 11. 非目标
本稿当前不覆盖:
- 完整 AI 平台产品化
- 完整 suggestion review 产品壳
- 多平台消息网关
- 通用桌面 agent / shell agent
- mindmap AI 主线
- OnlyOffice AI 主线
- 完整长期记忆产品壳
这些都不是当前 `Phase 7` 的第一任务。
---
## 12. 当前冻结口径
当前冻结如下:
> **`Phase 7` 仍然以 `openai-agents-python` 作为长期推荐编排层,以 Rust runtime 作为唯一事实源与真执行面。**
> **但当前 `Phase 7` 的第一交付物不再定义为“完整 AI 平台”或“完整结构化知识写链”,而是“文档页 AI 直接进入主编辑区,并沿 `page aggregate command family` 正式回写”。**
> **`Hermes` 可以继续作为过渡平台与实验平台存在,但不再作为文档页 AI 的长期语义中心。**
> **页面 AI 的模型真源固定为 `model_key``resolved_combo / resolved_runtime_model` 只作为运行时调试信息;`profile` 前端可设但由后端持有真源;tool registry 必须前端可见。**
一句话收口:
> **当前如要先做 `Phase 7`,正确起点不是继续抽象谈 kernel-aware AI,而是先让 AI 真正沿 `page aggregate -> 主编辑区 island` 这条当前主线闭环。**
@@ -0,0 +1,549 @@
# 7 [process][recycle] mnote Kernel Phase 7 AI 编排与 Kernel Projection 实施计划 v1
> 更新时间:2026-04-22
>
> 状态说明:
> - 本稿已被 `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v2.md` 覆盖
> - 保留在 `design/old/` 仅作为上一轮判断稿与历史参考,不再作为当前执行口径
>
> 当前主线依据:
> - `/mnt/Data1T/mnote/design/01-05-current-priority-overview.md`
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-tree-first-graph-kernel-v1.md`
> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md`
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md`
> - `/mnt/Data1T/mnote/design/04-tree-domain/process/4-6-tree-command-protocol-cutover-stage2-v1.md`
> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md`
>
> 历史参考:
> - [tree-first-graph-kernel-checklist-v2.md](/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-1-tree-first-graph-kernel-checklist-v2.md)
> - [rust-web-long-term-checklist-v2.md](/mnt/Data1T/mnote/design/03-rust-web/process/3-1-rust-web-long-term-checklist-v2.md)
> - [ai-first-rust-block-editor-baseline-v1.md](/mnt/Data1T/mnote/design/old/05-editor-mainline/process/ai-first-rust-block-editor-baseline-v1.md)
> - [rust-block-editor-ai-tool-contract-v0.md](/mnt/Data1T/mnote/design/old/05-editor-mainline/done/rust-block-editor-ai-tool-contract-v0.md)
---
## 1. 文档目的
本文用于冻结 `mnote``Kernel Phase 7` 中与 AI 相关的实施口径。
这里仍沿用 `Phase 7` 命名,是为了保留与旧阶段拆分的一致性;当前执行依据应以 `design/01-05-current-priority-overview.md``3-rust-web-long-term-architecture-v1.md``5-5 / 5-6``4-6``3-3` 这些仍在推进的主线文档为准,不再把 `1-1``3-1` 视为唯一推进入口。
这份计划只回答下面四件事:
1. `Phase 7` 中 AI 子系统到底要落什么
2. 为什么当前更适合采用 `openai-agents-python``mnote` 专用编排层,而不是继续把 `Hermes` 当长期主线,也不是直接从零手写完整 agent 平台
3. Rust kernel / Rust runtime / OpenAI Agents / Hermes 各自的边界是什么
4. 如何分阶段把当前 AI 面板切到真正的 `kernel projection + kernel command` 主链
一句话说:
> **在 `Phase 7` 中,AI 的核心任务不是“换一个聊天框架”,而是让 AI 真正直接面向 `node / subtree / edge / editor command / kernel command` 工作。**
---
## 2. 对齐当前 AI 主线验收口径
当前 AI 主线的验收口径,应综合以下现行主线来理解:
- `tree-first graph kernel` 的对象真相边界
- `Page Aggregate` 对标题 / 正文 / 页面设置的单一真源收口
- `tree command cutover` 对正式命令面的统一
- `tree realtime event stream` 对 projection + delta 主链的统一
结合历史 `Kernel Phase 7` 清单中已经写明的目标,当前 AI 仍需满足下面这些验收要求:
- AI tool 直接面向 `node / subtree / edge`
- AI 不再默认面向“页面前端壳”
- AI 能创建 `summary node / ai_note node / reference edge`
- AI 能把 PDF / Book 解析结果落进 `kernel index`
因此本计划不把目标定义为:
- 再做一套前端 AI runtime
- 继续围绕页面对象和编辑器壳拼 prompt
- 继续把 `Hermes` 或某个 SDK 本身当事实中心
本计划把目标定义为:
> **让 AI 变成 `kernel-aware` 的业务执行者,而不是围绕旧页面壳工作的聊天插件。**
---
## 3. 当前结论
当前推荐口径固定如下:
> **`mnote` 的长期主线应采用“Rust kernel / Rust runtime 做唯一事实源与真执行面,`openai-agents-python` 作为 `mnote` 专用 AI 编排层”的结构。`Hermes` 继续保留为过渡期外置 agent 平台或实验平台,但不再作为长期主链的语义中心。**
再展开就是:
- **事实源**:只有 Rust kernel 的 `node / edge / subtree / projection / command`
- **业务真执行面**:只有 Rust runtime / Rust Web / Rust editor command
- **AI 编排层**:优先采用 `openai-agents-python`
- **模型底座**:优先采用 OpenAI `Responses API`
- **过渡平台**:当前 `Hermes` 可继续承接已有会话、流式事件和部分工具桥接
- **浏览器前端**:只保留 host / island / stream 渲染,不再承担主 AI 编排
一句话总结:
> **不是把 OpenAI Agents SDK 当事实源,而是把它当“比纯自建更省力、比 Hermes 更可塑”的编排层。**
---
## 4. 为什么这次主线更适合 `openai-agents-python`
### 4.1 不是从零手写整套 agent 平台
如果纯自建,就必须自己补:
- agent run loop
- session/history
- tool orchestration
- tracing
- guardrails
- handoff
- human in the loop
这条路线长期最干净,但在 `Phase 7` 并不是最优先的工作。
`Phase 7` 更应该把时间投到:
- `kernel-aware context assembly`
- Rust tool contract
- summary / ai_note / reference edge 写链
- PDF / Book -> kernel index 写链
- 阅读页与 AI 共用 `pageSubtree / outline / evidence`
因此当前不值得先把 agent 平台从头再造一遍。
### 4.2 也不继续把 Hermes 当长期主线
`Hermes` 的优势很明显:
- skills
- memory
- cron
- gateway
- 多后端模型
- 现成 agent 平台能力
但对 `mnote` 来说,它的问题也很明确:
- 它是通用 agent 平台,不是 `mnote-native` AI 架构
- 它自己的 memory / search / skill 体系,容易和 `kernel-aware retrieval` 冲突
- 它自己的工具心智模型,不适合作为 `node / subtree / edge / command` 的长期事实入口
- 它更适合做外置大脑壳,不适合做产品内核
所以当前口径不是“彻底弃用 Hermes”,而是:
> **让 Hermes 退回到过渡平台与实验平台的位置。**
### 4.3 `openai-agents-python` 正好卡在中间层
`openai-agents-python` 当前已经提供:
- agent primitives
- tools
- handoffs
- guardrails
- sessions
- tracing
- human in the loop
- sandbox agents
这意味着:
- 不必从零重写 agent orchestration
- 也不必接受 Hermes 整个平台的产品壳
- 可以把 `mnote` 自己的 Rust tools / kernel retrieval / audit 规则深度塞进去
这条路线更符合当前项目的长期方向:
- AI-first
- CLI-first
- Rust-native
- 工具直达 Rust command
- UI 只剩薄壳
---
## 5. 架构边界冻结
### 5.1 长期推荐结构
```text
UI Host / AI Panel / Document Read View
|
v
AI Gateway / Stream Adapter
|
v
openai-agents-python Orchestrator
|
+---- provider: OpenAI Responses API
|
+---- mnote tools:
| - kernel.node.*
| - kernel.subtree.*
| - kernel.edge.*
| - editor.command.*
| - search.kernel_aware.*
| - import_export.*
|
v
Rust runtime / mnote-web / bridge-runtime
|
v
Rust kernel truth
```
### 5.2 每层职责
#### Rust kernel / Rust runtime
负责:
- 统一对象真相
- projection/query/command
- editor command
- audit / rollback / policy
- summary node / ai_note node / reference edge / kernel index 的真写链
不负责:
- 多 agent handoff 框架
- 通用聊天 session UI
- 通用 agent 记忆产品壳
#### `openai-agents-python` 编排层
负责:
- prompt / instructions / tool routing
- session orchestration
- tracing / guardrails
- handoff / background agent / HITL
- 与 OpenAI `Responses API` 的 agent 级编排
不负责:
- 定义产品事实源
- 保存 `mnote` 的结构真相
- 直接写产品数据库
- 绕过 Rust runtime 调产品数据
#### Hermes
负责:
- 过渡期运行现有链路
- 保留实验平台和已有运营场景
- 提供短期 fallback
不负责:
- 长期 AI 主线语义中心
- `Phase 7` 的最终实现基线
---
## 6. Phase 7 中 AI 的实施目标
本计划只覆盖 `Phase 7` 所需 AI 主链,不扩展到完整长期 AI 平台。
### 6.1 目标一:AI 输入上下文改成 `kernel-aware`
AI 读取上下文不再默认基于:
- 页面前端对象
- BlockNote 临时结构
- 页面壳里拼出来的二次真相
AI 输入上下文统一改成:
- `node`
- `subtree`
- `outline`
- `evidence`
- `edges`
- 可选的 `pageSubtree projection`
### 6.2 目标二:AI 工具改成 Rust tool contract
第一批 AI tools 固定围绕下面几类:
- `kernel.node.get`
- `kernel.subtree.get`
- `kernel.edges.list`
- `kernel.project_view`
- `editor.insert_block_after`
- `editor.replace_block`
- `editor.delete_block`
- `editor.move_block`
- `editor.indent_block`
- `editor.outdent_block`
- `editor.toggle_heading_collapse`
- `kernel.summary.create`
- `kernel.ai_note.create`
- `kernel.reference.attach`
- `kernel.index.ingest_pdf`
- `kernel.index.ingest_book`
原则固定为:
> **AI 不操作 UI,不操作 DOM,不操作页面壳;AI 只操作 Rust 暴露出来的真工具面。**
### 6.3 目标三:先打通三条主写链
`Phase 7` 中优先打通下面三条链:
1. 文档页 AI -> summary node / ai_note node / reference edge
2. 文档页 AI -> block editor Rust command
3. PDF / Book AI 解析 -> kernel index
### 6.4 目标四:阅读页与 AI 共用一套 projection 口径
阅读页与 AI 共用:
- `pageSubtree`
- `outline`
- `evidence`
- `edges`
这样阅读页与 AI 才能真正围绕同一套真相工作。
---
## 7. 分阶段实施计划
## 阶段 0:边界冻结与过渡口径确认
### 目标
把 AI 主线从“继续围绕 Hermes 与前端 runtime 打补丁”改成“为 Rust kernel 准备长期编排层”。
### 需要完成
- [ ] 冻结 `Phase 7` 的 AI 主线目标,不再把“继续增强前端 AI runtime”当主任务
- [ ] 明确 `openai-agents-python` 为当前推荐编排层
- [ ] 明确 Hermes 只保留为过渡 fallback / 实验平台
- [ ] 明确 Rust runtime 才是唯一真执行面
- [ ] 明确前端 AI host 只负责会话壳与流式渲染
### 完成判定
- [ ] 团队口径统一为“AI 编排层可替换,但 Rust truth layer 不可替换”
---
## 阶段 1:定义 `mnote` 专用 AI tool surface
### 目标
先把 AI 能做什么冻结成稳定工具合同。
### 需要完成
- [ ] 基于 `node / subtree / edge / editor command` 定义第一批 tool schema
- [ ] 为所有写工具补齐审计字段:
- actor
- target node ids / block ids
- command list
- trace id
- rollback token
- [ ] 把现有前端临时工具名收口到统一命名
- [ ] 区分:
- read tools
- write tools
- index tools
- retrieval tools
- [ ]`summary node / ai_note node / reference edge` 定义稳定写协议
### 完成判定
- [ ] `mnote` 已有一套不依赖前端 UI 的 AI 工具合同
---
## 阶段 2:做 `kernel-aware context assembly`
### 目标
让 AI 的输入上下文改成以 kernel projection 为主。
### 需要完成
- [ ] 把文档页 AI 上下文切到:
- `node`
- `subtree`
- `outline`
- `evidence`
- `edges`
- [ ] 明确上下文优先级:
- page subtree > outline > evidence > page shell snapshots
- [ ] 移除或降级旧页面对象快照在主链中的权重
- [ ] 为 AI 会话定义可重复的上下文裁剪规则
- [ ] 让阅读页与 AI 共用同一套 projection 获取接口
### 完成判定
- [ ] AI 已经不再默认围绕旧页面壳工作
---
## 阶段 3:引入 `openai-agents-python` 编排层
### 目标
用官方 agent primitives 取代当前以 Hermes 为中心的长期编排口径,但不触碰 Rust truth layer。
### 需要完成
- [ ] 建立独立的 `mnote-ai-orchestrator` Python 服务或 sidecar
- [ ] 接入 OpenAI `Responses API`
- [ ]`mnote` Rust tools 注册到 `openai-agents-python`
- [ ] 打通 session / tracing / guardrails / handoff 基础设施
- [ ] 对齐当前前端 SSE 协议或定义新的稳定 event adapter
- [ ] 明确前端如何在 Hermes / Agents Python 之间切换
- [ ] 保留 Hermes fallback 开关,便于过渡期回退
### 完成判定
- [ ] 在不依赖 Hermes 的情况下,AI 已能跑通至少一条 `mnote-native` 主链
---
## 阶段 4:打通三条主写链
### 目标
`Phase 7` 的 AI 写能力真正落到 kernel。
### 需要完成
- [ ] AI -> `summary node` 写链
- [ ] AI -> `ai_note node` 写链
- [ ] AI -> `reference edge` 写链
- [ ] AI -> Rust block editor command 写链
- [ ] PDF / Book -> AI 结构化解析 -> kernel index 写链
- [ ] 对所有写操作补齐:
- trace
- audit
- target evidence
- rollback
### 完成判定
- [ ] AI 能稳定创建 `summary node / ai_note node / reference edge`
- [ ] AI 能把 PDF / Book 解析结果落进 `kernel index`
---
## 阶段 5:切文档页与阅读页主路径
### 目标
`Phase 7` 在产品可见行为上成立。
### 需要完成
- [ ] 文档页 AI 面板默认走 `kernel-aware` 上下文
- [ ] 阅读页大纲来自 kernel subtree
- [ ] 回链 / 引用 / 结构信息来自 kernel edge
- [ ] AI 输出的结构节点能在阅读页中被稳定消费
- [ ] 至少保留一条兼容 fallback,但不再是默认主链
### 完成判定
- [ ] 阅读页与 AI 至少各有一条主路径已经直接消费 kernel projection
---
## 8. Hermes 的过渡策略
当前不建议立刻删除 Hermes。
### 8.1 Hermes 在过渡期继续保留的价值
- 承接现有运行链
- 作为 agent 行为回归对照
- 作为短期 fallback
- 承接不属于 `mnote-native` 主链的实验场景
### 8.2 需要限制的边界
- 不让 Hermes 直接成为产品事实源
- 不让 Hermes memory 取代 `kernel-aware retrieval`
- 不让 Hermes 默认 shell/fs 能力直接改业务数据
- 不让 Hermes 工具名继续成为长期产品契约
### 8.3 最终状态
最终可接受的状态有两种:
1. Hermes 退化为非主链实验平台
2. Hermes 完全下线,只保留 `openai-agents-python + Rust runtime`
---
## 9. 非目标
这份计划当前不覆盖:
- 完整 AI suggestion review UI
- 完整协作评论体系
- 多平台消息网关
- 完整长期记忆产品壳
- 通用桌面 agent / shell agent 平台
- 把前端页面壳继续增强成 AI 主执行面
这些都不是 `Phase 7` 的核心目标。
---
## 10. 风险与取舍
### 风险一:`openai-agents-python` 仍然不是 Rust
这是现实限制,但当前可接受,因为它只做编排层,不做事实层。
### 风险二:Hermes 与新编排层会短期并存
这是过渡期复杂度,但能换来更平滑的切换与回退能力。
### 风险三:如果先把“agent 平台能力”做太重,会挤压 `Phase 7` 主任务
因此必须坚持:
> **`Phase 7` 先做 kernel-aware tools 与写链,不先做通用 AI 平台产品化。**
---
## 11. 最终冻结口径
当前冻结如下:
> **`Kernel Phase 7` 的 AI 主任务,是把 AI 从“页面壳上的聊天插件”升级为“直接围绕 Rust kernel / Rust editor command 工作的业务执行者”。**
> **当前推荐采用 `openai-agents-python` 作为 `mnote` 专用编排层,以减少从零自建 agent 平台的成本;同时继续让 Rust runtime 保持唯一事实源和真执行面。**
> **Hermes 可以继续作为过渡平台与实验平台存在,但不再应作为长期主线的语义中心。**
---
## 12. 对应当前 AI 主线的落地映射
本计划与历史 `Kernel Phase 7` 检查项以及当前主线收口目标的一一对应如下:
| `Phase 7` 检查项 | 本计划对应 |
| --- | --- |
| AI tool 直接面向 `node / subtree / edge` | 阶段 1、阶段 2 |
| AI 不再默认面向“页面前端壳” | 阶段 2、阶段 5 |
| AI 能创建 `summary node / ai_note node / reference edge` | 阶段 1、阶段 4 |
| AI 能把 PDF / Book 解析结果落进 `kernel index` | 阶段 4 |
| 阅读页与 AI 至少有一条主路径直接消费 kernel projection | 阶段 5 |
一句话收口:
> **如果这份计划执行完成,那么 `Phase 7` 中 AI 这一半就不再只是“接了个 agent”,而是第一次真正进入 `tree-first graph kernel` 主链。**