Files
mnote/design/07-ai/process/7-12-page-ai-hermes-tool-routing-and-review-surface-v1.md
T
lix-2026 f292c6710a feat: EditorRuntimeActor - 三层缓存/delta/事件架构
Phase A — EditorRuntimeActor 内存缓存层
- 新增 editor_actor.rs: EditorBlockDocument 内存态 + apply_command + load_or_init
- block.rs 四个写工具(replace/insert/delete/move)接入 actor 路径
- editor_actor feature flag(MNOTE_WEB_ENABLE_EDITOR_ACTOR=true 默认开启)
- bridge-runtime 三个核心函数公开化
- rust-toolchain: 1.89 → stable(修复 spike WASM 编译阻塞)

Phase B — 编辑器增量 delta channel
- BlockDelta/DeltaOperation 类型 + actor.build_block_delta()
- leptos-tiptap spike: mnote:editor:block-delta CustomEvent 监听 + JSON patch
- DocumentAiAgentPanel: 拦截 blockDelta → window dispatchEvent
- 工具响应含 blockDelta 字段供前端消费

Phase C — 事件 stream delta
- broadcast channel 在 AppState/actor/SSE 三层贯通
- tree_events SSE 端点发 block.delta 事件
- 旧客户端降级兼容

环境修复
- rustc recursion_limit = 1024(修复 Leptos SSR 类型深度溢出)
- run-convex-deploy.js(封装 Convex function 部署到本地后端 3210)

ref: design/07-ai/process/7-13-page-block-editor-runtime-actor-v1.md
2026-05-16 22:03:30 +08:00

18 KiB
Raw Blame History

7-12 [process] 页面 AI Hermes 工具路由与编辑审阅面设计 v1

更新时间:2026-05-16

当前状态:PROCESS

本稿目的:修正“页面 AI 快速块编辑”后续方向,明确 mnote 不再建设独立 AI agent runtimemnote 只建设 Hermes 可消费的编辑工具路由、工具 manifest、上下文冻结、dry-run/review 和 Rust 写入安全边界。

关联文档:

  • /mnt/Data1T/mnote/design/10-review/process/09-page-ai-fast-block-edit-runtime-review.md
  • /mnt/Data1T/mnote/design/07-ai/process/7-10-page-block-ai-tooling-execution-checklist-v1.md
  • /mnt/Data1T/mnote/design/07-ai/done/7-9-page-block-ai-tooling-roadmap-v1.md
  • /mnt/Data1T/mnote/design/07-ai/done/7-6-mnote-hermes-plugin-tool-contract-v1.md
  • /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/cli-main
  • /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/blocknote-ai
  • /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/tiptap-apcore

1. 本轮结论

页面 AI 编辑卡顿的根因不是“Rust apply 慢”,而是模型和工具之间缺少稳定、低歧义、可审计的编辑命令面:

用户说一句自然语言
  -> Hermes/模型需要猜:读哪个范围、改哪个块、调用哪个工具、如何传参
  -> 如果猜错 blockId 或工具参数,mnote 再 fallback / 重跑 / 整页写入
  -> 用户感知为慢、卡、偶发失败

正确方向不是再造一个 mnote 自有 AI runtime,而是:

Hermes 继续作为唯一页面 AI agent runtimemnote 提供 Agent-native editor command layer。

因此,本地意图解析 + Rust apply 必须被重新定义为:

  • Hermes 的工具路由提示层。
  • 低风险确定性编辑的本地 shortcut。
  • Rust 写工具的参数校验和执行面。
  • review/dry-run/session 的安全边界。

它不是:

  • 第二套对话 runtime。
  • 第二套 agent tool loop。
  • 绕过 Hermes profile/tool toggle/audit 的长期写入口。
  • 让模型直接产 operations 并立刻写入的通用方案。

2. 现有问题

2.1 /api/page-ai/block-edit-workflow 方向需要收口

当前 route 已证明低歧义中文块编辑可以很快完成:

local_rule -> mnote.doc.apply_block_ops -> Rust apply -> page readback

但如果把这个 route 继续扩成 PageAIIntentParser / OperationPlanner / ApplyController,它会自然变成第二套 runtime

  • 自己判断意图。
  • 自己调用模型。
  • 自己解析模型输出。
  • 自己决定 fallback。
  • 自己写入并展示结果。

这会和 Hermes 的 session、profile、tool toggle、tool event、usage、audit、abort/retry 产生重叠。

2.2 模型直接输出 operations 仍不可靠

09-page-ai-fast-block-edit-runtime-review.md 已记录失败案例:模型输出了 operations,但 block 定位没有命中 Page Aggregate projection,最终触发 fallback 并拉长耗时。

长期规则应改为:

  • 模型可以建议工具调用。
  • 模型可以输出候选 operations。
  • mnote 必须用 Page Aggregate projection 解析、校验、dry-run。
  • blockId、revisionRef、allowedTargetBlockIds、editable、scope 必须由 mnote 校验。
  • 未通过校验不能隐式 fallback 到整页写或另一次 agent run。

2.3 当前工具面还缺少 cli-main 式 agent 合同

cli-main 的关键价值是把平台能力压成 Agent 可靠调用的命令面:

  • shortcut / API / generic 三层调用。
  • --dry-run 预览真实请求。
  • Risk: high-risk-writeconfirmation_required
  • structured error / hint。
  • skill 文档指导 agent 何时调用什么。
  • event consume 的 schema、ready marker、bounded run。

mnote 当前已有 Hermes tool manifest,但还需要把 manifest 提升为 Hermes/model 可直接消费的编辑合同,而不是只做 UI 列表。


3. 设计原则

3.1 单一 agent runtime

Hermes owns:
  session / message / model / tool loop / streaming / usage / profile / memory / skill

mnote owns:
  Page Aggregate / tool manifest / context snapshot / validation / Rust command / audit / readback

页面 AI 面板只是 Hermes 的页面内客户端;mnote 不再新增独立 agent 编排中心。

3.2 本地层只做“路由和校验”

本地层可以做:

  • 判断是不是低歧义块编辑。
  • 生成 recommendedToolCall
  • 附带 confidenceriskrequiresReview
  • 生成 allowedTargetBlockIds
  • 做 dry-run、validate、readback。

本地层不能做:

  • 自己维护长期对话状态。
  • 自己成为默认模型调用链。
  • 自己绕过 Hermes tool manifest 和 profile 开关。
  • 自己吞掉工具错误并隐式改走其他写入口。

3.3 所有写入都通过 Rust-owned mnote tools

写工具必须满足:

  • dryRun 显式传入。
  • idempotencyKey 显式传入。
  • revision/conflictDetectionKey/revisionRef 或等价冲突键参与校验。
  • allowedTargetBlockIds 限制 selection / scoped run。
  • 返回 diff/warnings/risk/blocked/changedBlocks/audit
  • 写入后通过 Page Aggregate 和 mnote.doc.fetch 回读验证。

3.4 快路径是 shortcut,不是 runtime

低歧义场景可以保留快路径,但必须改口径:

PageAICommandRouter
  -> recommendedToolCall
  -> direct tool shortcut 或 Hermes run with tool hint
  -> shared mnote tool executor
  -> shared audit/readback

如果走 direct tool shortcut,也必须产生 Hermes-compatible tool event / audit 语义,避免 UI 与历史记录断裂。


4. 总体架构

Browser Page AI panel
  -> PageAIContextBuilder
  -> MnoteAIToolManifestProvider
  -> PageAICommandRouter
      -> deterministic shortcut? ---- yes -> MnoteToolExecutor
      |                                      -> PageAIReviewSession/readback
      no
      -> Hermes run request with:
           - frozen page context
           - tool manifest
           - recommendedToolCall hint
           - risk/review policy
         -> Hermes tool loop
         -> /api/hermes/tools/mnote/call
         -> Rust mnote tools
         -> PageAIReviewSession/readback

这里 PageAICommandRouter 不是 agent,只是类似 cli-main shortcut 的工具路由器。


5. 组件设计

5.1 PageAIContextBuilder

职责:

  • 从 Page Aggregate block projection 构建冻结上下文。
  • 支持 scope=full/outline/block/selection/keyword
  • 输出 text/page_xml/json 三种视图。
  • 生成 allowedTargetBlockIds
  • 记录 revision/conflictDetectionKey/revisionRef
  • 大页面默认裁剪,返回 truncated/warnings/continuation

输出示例:

{
  "schema": "mnote.page_ai_context.v1",
  "workspaceId": "tree_workspace",
  "documentId": "tree_doc",
  "scope": "selection",
  "revision": 12,
  "conflictDetectionKey": "body:12:hash",
  "allowedTargetBlockIds": ["p_1", "p_2"],
  "selectedBlockIds": ["p_1", "p_2"],
  "pageText": "第一段\n第二段",
  "pageXml": "<page id=\"tree_doc\" revision=\"12\"><block id=\"p_1\">第一段</block></page>",
  "blocks": [
    {
      "blockId": "p_1",
      "type": "paragraph",
      "text": "第一段",
      "revisionRef": "body:12:p_1",
      "editable": true
    }
  ]
}

5.2 MnoteAIToolManifestProvider

职责:

  • 从 Rust Hermes tool manifest 输出当前页面可用工具。
  • 合并 profile tool toggle、capability、scope、document permissions。
  • 输出 Hermes/model 可直接使用的 tool schema。
  • 输出风险和审批语义。

工具 manifest 必须包含:

{
  "name": "mnote.doc.apply_block_ops",
  "description": "Apply validated block operations to the current mnote document.",
  "inputSchema": {
    "type": "object",
    "required": ["operations", "dryRun", "idempotencyKey"],
    "additionalProperties": false
  },
  "annotations": {
    "readonly": false,
    "destructive": false,
    "idempotent": false,
    "requiresApproval": true,
    "approvalMode": "review",
    "selectionEffect": "destroy",
    "runtimeOwner": "mnote-web",
    "writeOwner": "rust-runtime-kernel"
  },
  "availability": {
    "enabled": true,
    "unsupportedReason": ""
  }
}

5.3 PageAICommandRouter

替代当前继续扩大的 block-edit-workflow 概念。

输入:

  • 用户 prompt。
  • 冻结后的 mnote.page_ai_context.v1
  • 当前 tool manifest。
  • 当前 profile / approval mode。

输出:

{
  "schema": "mnote.page_ai_command_route.v1",
  "intent": "direct_block_edit",
  "confidence": 0.94,
  "recommendedToolCall": {
    "toolName": "mnote.doc.apply_block_ops",
    "args": {
      "operations": [
        {"op": "replace", "matchText": "A", "content": "B"}
      ],
      "dryRun": true
    }
  },
  "risk": "low",
  "requiresHermesRun": false,
  "requiresReview": false,
  "reason": "明确中文引号替换表达,目标文本唯一命中"
}

规则:

  • 只覆盖低歧义命令。
  • 不能为复杂改写、总结、跨页面、多块结构化编辑直接生成写入。
  • 不能调用第二套长链模型;如需模型,交给 Hermes run。
  • 输出必须可被 Hermes 当作 tool hint 消费。

5.4 Hermes run hint 注入

requiresHermesRun=true 或 router 不确定时,页面 AI 发起 Hermes run,并附带:

{
  "pageContext": "mnote.page_ai_context.v1",
  "toolManifest": "mnote.ai_tool_manifest.v1",
  "toolHint": "mnote.page_ai_command_route.v1",
  "reviewPolicy": {
    "mode": "yolo|review|required",
    "defaultDryRun": true
  }
}

Hermes 仍负责:

  • 选择模型。
  • 工具调用循环。
  • stream message / tool event。
  • abort/retry。
  • session persistence。

mnote 只负责工具结果和写入安全。

5.5 PageAIReviewSession

职责:

  • 承接所有写工具 dryRun=truerequiresApproval=true 的结果。
  • 保存 plan/diff/warnings/risk/blocked。
  • 提供 accept/reject/retry/abort。
  • accept 时二次读取 Page Aggregate 并校验 revision。

状态:

draft
planning
previewing
awaiting_user
accepted
rejected
applying
applied
failed
aborted
stale

第一阶段可以保留 yolo,但仍应让工具返回 review-compatible 数据结构,避免后续 UI 重写。


6. 关键流程

6.1 低歧义块替换

用户:把「第二段」替换为「第二段已修改」
  -> ContextBuilder 冻结页面与 block ids
  -> CommandRouter 命中 direct_block_edit
  -> recommendedToolCall=mnote.doc.apply_block_ops
  -> dryRun validate 唯一命中
  -> yolo 模式:direct tool shortcut 正式 apply
  -> 记录 tool event/audit
  -> Page Aggregate readback

验收:

  • 不进入通用 Hermes agent run 也可以,但必须复用 mnote tool/audit/readback 语义。
  • 若非 yolo 模式,则停在 review session。

6.2 复杂自然语言改写

用户:把这段整理得更专业,并保留原意
  -> Router 无法确定操作
  -> Hermes run with context + manifest + hint
  -> Hermes 调 mnote.doc.fetch / block.fetch
  -> Hermes 调 mnote.doc.plan_update(dryRun=true)
  -> mnote 返回 review session draft
  -> 用户 accept 后 Rust apply

验收:

  • 模型不能直接改正文。
  • dry-run 不改变 Page Aggregate。
  • accept 时校验 revision。

6.3 selection 编辑

用户选中块 A/B:改成列表
  -> ContextBuilder 冻结 selectedBlockIds
  -> allowedTargetBlockIds=[A,B]
  -> 所有写工具自动带 allowedTargetBlockIds
  -> 写工具尝试修改 C 时 blocked=true

验收:

  • 用户后续改变选区不影响当前 run。
  • selection 外写入被阻断。

6.4 工具禁用

profile disabled mnote.block.fetch
  -> ToolManifestProvider 输出 enabled=false 或不输出该工具
  -> Router 不推荐该工具
  -> Hermes 直接调用仍被 /api/hermes/tools/mnote/call 拦截

验收:

  • UI 工具列表、Hermes manifest、后端执行拦截一致。

7. 与参考代码的吸收边界

7.1 cli-main

吸收:

  • shortcut/API/generic 三层工具面。
  • dry-run 作为写入前置能力。
  • structured error/hint。
  • risk/confirmation_required。
  • skill 文档让 agent 不靠猜。
  • event/schema/ready marker 的 agent-friendly contract。

不吸收:

  • 不复制 Go CLI 框架。
  • 不把 CLI 作为页面 AI 唯一执行面。
  • 不用命令行 prompt 作为 Web 审批 UI。

7.2 blocknote-ai

吸收:

  • DocumentStateBuilder 的 selection/full context 分离。
  • StreamToolsProvider 的工具集合思想。
  • AI lifecyclethinking / ai-writing / user-reviewing / error。
  • accept/reject/retry/abort 的交互形态。

不吸收:

  • 不引入 @blocknote/xl-ai 运行时依赖。
  • 不复制 GPL/PROPRIETARY 代码。
  • 不让 BlockNote/ProseMirror suggestion 成为 mnote 事实源。

7.3 tiptap-apcore

吸收:

  • tool schema。
  • annotations。
  • ACL / role。
  • query/content/destructive/selection/history 分类。
  • executor 前置检查。

不吸收:

  • 不把 Tiptap command 作为长期写入事实源。
  • 不让浏览器 editor instance 直接持久化写入。

7.4 AI SDK / Context7 核验结论

可用方向:

  • 用 schema/structured output 约束模型输出。
  • 用 tool calling 让模型选择工具。
  • 用 repair/validation 处理无效参数。
  • 工具执行结果必须由 mnote 校验后返回。

不可用方向:

  • 不把 structured output 当最终写入结果。
  • 不让模型输出的 blockId 绕过 projection resolve。

8. 迁移计划

Phase A:设计治理

  • 新增本文作为当前口径。
  • 7-10 继续作为执行 checklist。
  • 7-11 作为旧“自有 AI runtime”口径移入 design/old/07-ai/process/

Phase BManifest 合同收口

  • mnote.doc.* / mnote.block.* manifest 输出完整 inputSchema/outputSchema/annotations/availability
  • profile toggle、capability、scope 共同影响 manifest。
  • manifest 可直接转换为 Hermes/model tools。
  • 禁用工具在 manifest、UI、执行拦截三处一致。

Phase Cblock-edit-workflow 改造成 router

  • 将 route 命名和返回 schema 改为 mnote.page_ai_command_route.v1 或新增等价 route。
  • 本地规则只输出 recommendedToolCall
  • 低风险 yolo shortcut 走共享 mnote tool executor。
  • 非低风险或低置信度任务发起 Hermes run with tool hint。
  • 删除“模型 fallback 后再 Hermes agent run”的重复链路。

Phase DReview session

  • 定义 mnote.page_ai_review_session.v1
  • mnote.doc.plan_updatemnote.doc.apply_block_ops dryRun=true 返回 review-compatible draft。
  • 页面 AI UI 展示 diff/warnings/risk/blocked。
  • accept/reject/retry/abort 可用。
  • stale revision 被阻断。

Phase E:状态与事件统一

  • direct shortcut 和 Hermes run 都产生统一 tool event 形态。
  • 页面 AI 面板按 runId/toolCallId/reviewSessionId 聚合展示。
  • abort 不留下半写入正文。
  • 刷新后未提交 review session 不自动写入。

Phase F:验收 smoke

  • 低歧义替换:可 <1s 可见,且有 tool audit。
  • 复杂改写:进入 Hermes run,先 dry-run/review。
  • selection 外写入:blocked。
  • 禁用工具:manifest 不推荐,后端仍拦截。
  • 旧 revision acceptstale。

2026-05-16 补充验收证据:

  • scripts/task-page-block-ai-context-format-smoke.js 已验证 mnote.doc.apply_block_ops dryRun=true 携带 allowedTargetBlockIds=["p_2"] 时,尝试 replace p_1 会被 Rust mnote tool 拒绝。
  • 证据:tmp/page-block-ai-context-format-smoke/mp8ddr4n.json;错误路径为 HTTP 400mnote_block_target_out_of_scope
  • 同一 smoke 还验证了 context / manifest 基础合同:mnote.doc.fetch scope=selection format=page_xml/textmnote.block.fetch format=page_xml/text、manifest annotations 与 mnote.page.save 粗粒度兜底定位。
  • 边界:本证据不代表完整 review session、旧 revision accept、复杂改写或单个 mnote.block.* selection guard 已完成。

9. 7-107-11 的处理结论

9.1 7-10 继续执行

7-10 是页面块 AI 工具执行 checklist,包含真实代码和 smoke 证据。它仍然有效,继续保留在:

design/07-ai/process/7-10-page-block-ai-tooling-execution-checklist-v1.md

但后续执行必须按本文修正口径:

  • PageAIIntentParser 读作 PageAICommandRouter
  • PageAIOperationPlanner 读作 recommendedToolCall 构造器。
  • PageAIOperationValidator 继续有效,但归属 mnote tool executor / Rust validation。
  • PageAIApplyController 不应成为独立 runtime,改为 review session / tool executor / readback controller。
  • “不进入 Hermes run”只能表示 deterministic shortcut,不表示 mnote 新建了 agent runtime。

9.2 7-11 移入 old

7-11 的参考资料价值仍然成立,但标题和核心分层写成了“mnote 自有 AI 工具 runtime”。这会误导后续实现继续扩出第二套 runtime。

因此本轮将其移入:

design/old/07-ai/process/7-11-blocknote-tiptap-ai-reference-and-mnote-ai-tool-runtime-v1.md

保留原因:

  • 记录 BlockNote / Tiptap 参考取证。
  • 保留 GPL/PROPRIETARY 许可证边界。
  • 保留 selection/context/review 的参考价值。

不再作为当前执行口径;当前执行口径以本文为准。


10. 禁止项

  • 不新增 mnote 自有 agent runtime。
  • 不把 /api/page-ai/block-edit-workflow 扩成通用 AI 编排中心。
  • 不让模型直接输出未经校验的 blockId 并写入。
  • 不绕过 Hermes profile/tool toggle/audit。
  • 不让前端 editor instance 直接执行正式持久化写入。
  • 不以 HTML / Tiptap JSON / ProseMirror position 作为长期 AI tool contract。
  • 不复制 BlockNote XL AI 或 GPL/PROPRIETARY 实现代码。
  • 不把 mnote.page.save 描述为精确块编辑主入口。

11. 成功标准

完成本文后,页面 AI 编辑应满足:

  • 简单明确块编辑有低延迟 shortcut。
  • 复杂编辑仍走 Hermes agent runtime。
  • Hermes 不再盲猜工具和参数,而是拿到 mnote 提供的 context、manifest、tool hint。
  • 所有写入都能 dry-run、review、audit、readback。
  • 工具禁用、权限、scope、selection 与后端执行一致。
  • 设计文档不再鼓励建设第二套 AI runtime。