chore: 收口 review 执行清单与 runtime 验证
- 补齐 design/10-review 执行清单、验收标准与相关设计治理记录 - 迁移已完成的 tree、mindmap、runtime fallback、AI kernel 等设计和缺陷条目 - 推进 Rust Web runtime、tree/sidebar、page aggregate、mindmap 与 OnlyOffice 路由侧验证支撑 - 增加 task177-task180 smoke/audit 脚本及前端相关测试覆盖
This commit is contained in:
@@ -10,7 +10,8 @@
|
||||
> 状态说明:
|
||||
> - 本稿对应 `Phase 7 v2` 的“文档页 AI 最小闭环”已完成,故迁入 `done/`
|
||||
> - 本稿完成不等于整个 `Phase 7 v2` 已完成;结构化知识写链仍以后续阶段继续推进
|
||||
> - 2026-05-05 追加说明:本稿记录的是 `openai-agents-python` sidecar 作为过渡主链的完成状态,不代表当前长期方向;长期口径已由 `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md` 收口为 `mnote-cli` 是唯一长期 agent 执行面
|
||||
> - 2026-05-05 追加说明:本稿记录的是 `openai-agents-python` sidecar 作为过渡主链的完成状态,不代表当前长期方向;当时长期口径曾由 `/mnt/Data1T/mnote/design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md` 收口为 `mnote-cli` 是唯一长期 agent 执行面
|
||||
> - 2026-05-13 追加说明:`mnote-cli` 唯一长期 agent 执行面口径已被 `/mnt/Data1T/mnote/design/07-ai/process/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md` 覆盖;新的长期方向是页面 AI 面板仅作为 Hermes 页面内客户端,Hermes 持有 AI 会话真相,mnote 通过 Hermes skill/plugin 暴露业务工具
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -12,8 +12,14 @@
|
||||
>
|
||||
> 2026-05-05 追加说明:
|
||||
> - 本稿的对象模型、artifact 写链与 kernel 边界仍然有效
|
||||
> - 但触发与执行口径已被 `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md` 覆盖
|
||||
> - 当前凡是提到“页面 AI 面板触发”的位置,都应理解为“页面 AI 面板作为 `mnote-cli` host 触发”,而不是独立内置编排主线
|
||||
> - 当时触发与执行口径曾被 `/mnt/Data1T/mnote/design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md` 覆盖
|
||||
> - 该 `mnote-cli` host 口径现已被 2026-05-13 的 Hermes 面板主线覆盖
|
||||
>
|
||||
> 2026-05-13 追加说明:
|
||||
> - 本稿的对象模型、artifact 写链、projection-only `AI Artifacts` 分组与 kernel 边界继续有效
|
||||
> - 触发与执行口径改由 `/mnt/Data1T/mnote/design/07-ai/process/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md` 覆盖
|
||||
> - 当前凡是提到“页面 AI 面板触发”或“页面 AI host 固定动作”的位置,都应理解为:
|
||||
> 页面 AI 面板作为 Hermes 页面内客户端发起意图,Hermes 通过 mnote skill/plugin 调用正式 artifact 工具,最终写入仍回到 Rust runtime / kernel
|
||||
|
||||
---
|
||||
|
||||
@@ -43,7 +49,7 @@
|
||||
- `ai_note node`
|
||||
- `reference edge`
|
||||
2. 只允许围绕**当前文档页**创建,不做跨页、跨工作区写链
|
||||
3. 触发方式不是自然语言,不做自动推断,只允许页面 AI host 暴露的固定动作触发;当前页面 AI 面板只是 `mnote-cli` host 的一个页面内入口
|
||||
3. 第一版允许页面 AI 面板提供固定快捷入口,但快捷入口本质是向 Hermes 发送意图;Hermes 通过 mnote skill/plugin 调用 artifact 工具,不再由页面 AI host 或 `mnote-cli` host 私有触发
|
||||
4. 点击按钮后直接创建,不走“先预览再确认”的两阶段流
|
||||
5. `summary node` 默认单例覆盖更新;`ai_note node` 每次新建
|
||||
6. 两者都落成**可编辑的页面型节点**
|
||||
@@ -278,21 +284,25 @@
|
||||
|
||||
## 6. 触发方式与产品入口
|
||||
|
||||
### 6.1 只允许固定按钮触发
|
||||
### 6.1 允许固定按钮触发,但必须经过 Hermes
|
||||
|
||||
第一版不走自然语言触发。
|
||||
|
||||
不支持:
|
||||
|
||||
- “帮我顺手创建一个摘要节点”
|
||||
- “看起来像摘要就自动生成”
|
||||
- “只要语义明确就直接落库”
|
||||
|
||||
只支持页面 AI host 面板里的两个固定按钮:
|
||||
第一版允许页面 AI 面板提供两个固定快捷按钮:
|
||||
|
||||
- `创建 Summary`
|
||||
- `创建 AI Note`
|
||||
|
||||
但按钮不得绕过 Hermes 或 mnote plugin 直接写入。正确链路是:
|
||||
|
||||
```text
|
||||
Leptos 页面 AI 面板
|
||||
-> Hermes session/run
|
||||
-> mnote Hermes skill/plugin
|
||||
-> Rust runtime / kernel
|
||||
-> artifact node / reference edge
|
||||
```
|
||||
|
||||
自然语言触发可以作为后续能力加入,但第一版验收仍以固定按钮或固定 tool intent 为准,避免 artifact 写链质量和权限边界同时失控。
|
||||
|
||||
### 6.2 点击后直接创建
|
||||
|
||||
第一版点击按钮后,直接创建,不走预览确认。
|
||||
@@ -307,6 +317,7 @@
|
||||
- 正式写链成立
|
||||
- kernel node / edge 成立
|
||||
- 文件树 projection 成立
|
||||
- Hermes tool call -> mnote plugin -> Rust kernel 的边界成立
|
||||
|
||||
而不是先做复杂的人机审核流。
|
||||
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
# 7-3 [process] 页面 AI Hermes 面板与 mnote Plugin 主线方案 v1
|
||||
|
||||
> 更新时间:2026-05-13
|
||||
>
|
||||
> 上位依据:
|
||||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||||
> - `/mnt/Data1T/mnote/design/01-05-current-priority-overview.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/05-editor-mainline/done/5-10-wolai-page-settings-and-ai-surface-alignment-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/reference-code/hermes-web-ui-0.5.18`
|
||||
> - `/mnt/Data1T/mnote/design/07-ai/process/7-2-phase7-structured-artifact-write-chain-v1.md`
|
||||
>
|
||||
> 覆盖关系:
|
||||
> - 覆盖 `/mnt/Data1T/mnote/design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md`
|
||||
> 中“`mnote-cli` 是唯一长期 agent 执行面”的口径。
|
||||
> - 保留 `v4` 中“Web 不应拥有第二套工具注册表、结构化写入必须回到 Rust runtime / kernel”的判断。
|
||||
> - 保留 `7-2` 中 `summary node / ai_note node / reference edge` 的对象模型和写入边界,
|
||||
> 但触发方改为 Hermes tool call,而不是页面 AI host 私有按钮或 `mnote-cli` host。
|
||||
|
||||
---
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
这份稿只回答一个问题:
|
||||
|
||||
> **未来页面 AI 的长期主语到底是谁。**
|
||||
|
||||
当前冻结答案是:
|
||||
|
||||
> **页面 AI 面板只是 Hermes 的页面内客户端;Hermes session/message/tool event/usage/model 才是会话真相;mnote 通过 Hermes skill/plugin 暴露业务能力。**
|
||||
|
||||
这不是把 mnote 的业务真相交给 Hermes。长期边界必须分清:
|
||||
|
||||
- Hermes 负责 AI 编排、会话、模型、tool call 调度和聊天历史。
|
||||
- mnote 负责页面、树、正文、artifact、edge、projection 和审计事实。
|
||||
- 页面 AI 面板只负责在文档页里打开一个 Hermes 客户端。
|
||||
|
||||
一句话收口:
|
||||
|
||||
> **AI 会话归 Hermes,mnote 能力归 Rust kernel;页面 AI 面板只连接两者。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 为什么要从 CLI-first 改为 Hermes-first
|
||||
|
||||
`CLI-first` 解决了一个真实问题:避免 Web 前端继续拥有私有 AI 编排、私有工具注册表和私有写链。
|
||||
|
||||
但它也带来了新的错位:
|
||||
|
||||
- 页面 AI 面板开始伪装成 `mnote-cli` 图形客户端。
|
||||
- Hermes、Codex、`openai-agents-python` 被统一压成“外置 agent”,但实际用户希望页面 AI 就是 Hermes 面板。
|
||||
- 真实会话能力、模型选择、tool event、thinking、usage、历史搜索这些已经是 Hermes 的强项,mnote 自己再做一套会重复。
|
||||
- 当前运行态已经出现冲突:页面壳默认发送 `provider=hermes`,而 `/api/ai-agent/run` 又按旧退场口径返回 `ai_provider_bridge_unavailable`。
|
||||
|
||||
因此新的主线不是恢复旧的 Web 私有 AI 编排,而是:
|
||||
|
||||
> **把页面 AI 从 `mnote-cli host` 改成 Hermes client,把 mnote 能力从 Web 私有 tool 改成 Hermes 可发现、可调用的 skill/plugin。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 长期分层
|
||||
|
||||
### 3.1 Hermes
|
||||
|
||||
Hermes 负责:
|
||||
|
||||
- session 创建、恢复、重命名、删除、搜索
|
||||
- message 存储与 conversation history
|
||||
- model / provider / profile 选择
|
||||
- streaming 事件、thinking / reasoning、usage
|
||||
- tool call 调度、排队、取消、恢复
|
||||
- skill / plugin 的发现和启停
|
||||
|
||||
Hermes 不负责:
|
||||
|
||||
- 直接写 mnote 的 Convex 表
|
||||
- 直接构造第二套 page aggregate
|
||||
- 直接决定页面树、文件树、artifact、edge 的事实结构
|
||||
|
||||
### 3.2 mnote Rust kernel / runtime
|
||||
|
||||
mnote Rust 负责:
|
||||
|
||||
- `Page Aggregate`
|
||||
- `page.*` command
|
||||
- `tree.*` command
|
||||
- `kernel.*` query / edge
|
||||
- `summary node / ai_note node / reference edge`
|
||||
- projection、audit、idempotency、workspace / actor scope
|
||||
|
||||
Rust 不负责:
|
||||
|
||||
- 存储 Hermes 聊天历史
|
||||
- 维护 Hermes session 列表
|
||||
- 重做 Hermes 模型、profile、usage 管理
|
||||
|
||||
### 3.3 页面 AI Leptos 面板
|
||||
|
||||
页面 AI 面板负责:
|
||||
|
||||
- 右下角入口与右侧抽屉壳层继续服从 Wolai 对齐结果
|
||||
- 用 Leptos 实现 Hermes chat 的页面内子集
|
||||
- 调用 Hermes session / run / stream API
|
||||
- 把当前页面上下文作为 Hermes run 的输入或 session workspace context
|
||||
- 展示 Hermes 返回的 message、reasoning、tool event、error、usage
|
||||
|
||||
页面 AI 面板不负责:
|
||||
|
||||
- 自己保存聊天真相
|
||||
- 自己维护工具注册表
|
||||
- 自己执行页面写入
|
||||
- 自己 fallback 到 `mnote-cli` 或旧 sidecar
|
||||
|
||||
### 3.4 mnote Hermes skill/plugin
|
||||
|
||||
mnote 需要作为 Hermes skill/plugin 暴露能力。
|
||||
|
||||
第一版建议能力分组:
|
||||
|
||||
- `mnote.page.get`
|
||||
- `mnote.page.save`
|
||||
- `mnote.page.update_title`
|
||||
- `mnote.page.update_options`
|
||||
- `mnote.tree.create`
|
||||
- `mnote.tree.move`
|
||||
- `mnote.search.documents`
|
||||
- `mnote.artifact.create_summary`
|
||||
- `mnote.artifact.create_ai_note`
|
||||
- `mnote.kernel.attach_reference`
|
||||
|
||||
这些工具可以由 plugin 内部调用:
|
||||
|
||||
- Rust Web 同源 tool bridge
|
||||
- `mnote-cli` JSON adapter
|
||||
- 或后续更稳定的 Rust plugin bridge
|
||||
|
||||
但对 Hermes 来说,它们必须表现为一组稳定 Hermes tools,而不是页面前端私有函数。
|
||||
|
||||
---
|
||||
|
||||
## 4. 会话真相
|
||||
|
||||
页面 AI 的会话真相固定在 Hermes。
|
||||
|
||||
mnote 不保存:
|
||||
|
||||
- 聊天消息列表
|
||||
- assistant 文本历史
|
||||
- thinking / reasoning 历史
|
||||
- tool event 完整展开状态
|
||||
- session 标题、分组、usage
|
||||
|
||||
mnote 可以保存:
|
||||
|
||||
- 结构化写入产生的 audit
|
||||
- artifact node
|
||||
- reference edge
|
||||
- page/body/title/options 的正式变更
|
||||
- 与一次 Hermes tool call 对应的 request / trace / actor / reason
|
||||
|
||||
也就是说,mnote 只保存“对 mnote 事实源造成影响的结果”,不复制 Hermes 的聊天数据库。
|
||||
|
||||
---
|
||||
|
||||
## 5. 页面上下文进入 Hermes 的方式
|
||||
|
||||
页面 AI 面板打开时,mnote 应提供最小上下文包:
|
||||
|
||||
- `workspaceId`
|
||||
- `documentId`
|
||||
- 页面标题
|
||||
- `pageAggregate` 摘要
|
||||
- 当前选区 / blockId / selected text
|
||||
- 页面设置
|
||||
- 当前用户 actor / capability 摘要
|
||||
|
||||
上下文传入 Hermes 有两种可接受方式:
|
||||
|
||||
1. 作为 run input / instructions 的结构化上下文。
|
||||
2. 作为 Hermes session workspace context,由 mnote panel 在创建或恢复 session 时设置。
|
||||
|
||||
第一版优先采用简单方式:
|
||||
|
||||
> 页面 AI 面板每次发起 run 时附带当前页面上下文摘要;Hermes 如需读取最新正文,再通过 `mnote.page.get` 工具回读。
|
||||
|
||||
这样可以避免把 page aggregate 大对象长期塞进 Hermes session,也避免 stale context 变成事实源。
|
||||
|
||||
---
|
||||
|
||||
## 6. API 与路由边界
|
||||
|
||||
### 6.1 退役 `/api/ai-agent/run` 主路径
|
||||
|
||||
`/api/ai-agent/run` 不再作为页面 AI 的长期主入口。
|
||||
|
||||
允许状态:
|
||||
|
||||
- 暂时保留为 legacy compat,明确返回旧接口退场信息
|
||||
- 或只用于旧 smoke / 对照验证
|
||||
|
||||
禁止状态:
|
||||
|
||||
- 页面 AI 新实现继续向它发送 `provider=hermes`
|
||||
- `/api/ai-agent/run` 继续作为 Hermes 面板的主代理
|
||||
- 它继续持有 mnote 私有工具注册表或执行编排
|
||||
|
||||
### 6.2 新增 Hermes client proxy
|
||||
|
||||
浏览器不应直接暴露 Hermes API key。
|
||||
|
||||
建议在 `mnote-web` 中提供同源薄代理:
|
||||
|
||||
- `/api/hermes/client/sessions`
|
||||
- `/api/hermes/client/runs`
|
||||
- `/api/hermes/client/events`
|
||||
- `/api/hermes/client/models`
|
||||
- `/api/hermes/client/tools`
|
||||
|
||||
这层只做:
|
||||
|
||||
- auth / cookie / token 转发
|
||||
- 同源安全边界
|
||||
- 页面上下文最小注入
|
||||
- 错误码标准化
|
||||
|
||||
这层不做:
|
||||
|
||||
- session 真相存储
|
||||
- message 真相存储
|
||||
- tool 执行编排
|
||||
- 旧 provider fallback
|
||||
|
||||
### 6.3 mnote tool bridge
|
||||
|
||||
Hermes 调用 mnote 工具时,应进入窄桥:
|
||||
|
||||
```text
|
||||
Hermes tool call
|
||||
-> mnote Hermes plugin
|
||||
-> mnote-web /api/hermes/tools/mnote/*
|
||||
-> Rust runtime / kernel command/query
|
||||
-> Hermes tool result
|
||||
```
|
||||
|
||||
第一版不要求一次性冻结最终 URL,但要求协议字段稳定:
|
||||
|
||||
- `toolName`
|
||||
- `arguments`
|
||||
- `workspaceId`
|
||||
- `documentId`
|
||||
- `actor`
|
||||
- `sessionId`
|
||||
- `traceId`
|
||||
- `idempotencyKey`
|
||||
- `dryRun`
|
||||
- `capabilityScope`
|
||||
|
||||
---
|
||||
|
||||
## 7. Leptos 面板参考范围
|
||||
|
||||
参考 `hermes-web-ui-0.5.18`,但只采用页面内必要子集。
|
||||
|
||||
第一版采用:
|
||||
|
||||
- Chat session list
|
||||
- Message list
|
||||
- Chat input
|
||||
- streaming delta
|
||||
- thinking / reasoning 展开
|
||||
- tool started / tool completed 展开
|
||||
- model selector
|
||||
- error / retry / abort
|
||||
- session search 可后置
|
||||
|
||||
第一版不采用:
|
||||
|
||||
- 平台 Channels 管理
|
||||
- Jobs / Cron 管理
|
||||
- Profiles 管理全页面
|
||||
- Logs 全页面
|
||||
- Files 全浏览器
|
||||
- Terminal
|
||||
- Group Chat
|
||||
- Hermes 全局 Settings
|
||||
|
||||
这些能力属于 Hermes 管理台,不属于 mnote 页面 AI 抽屉。
|
||||
|
||||
实现要求:
|
||||
|
||||
- 使用 Leptos island 实现,不引入 Vue / Naive UI。
|
||||
- 保留 Wolai 对齐的右下角入口和右侧 drawer 容器。
|
||||
- 文案和视觉以 mnote 文档页密度为准,不照搬 Hermes Web UI 的整站导航。
|
||||
|
||||
---
|
||||
|
||||
## 8. 结构化 Artifact 写链
|
||||
|
||||
`7-2` 的对象模型继续成立:
|
||||
|
||||
- `summary node`
|
||||
- `ai_note node`
|
||||
- `reference edge`
|
||||
- `AI Artifacts` projection-only 分组
|
||||
|
||||
但触发方改为 Hermes tool call:
|
||||
|
||||
- 用户可以在 Hermes 面板中自然语言要求总结当前页。
|
||||
- Hermes 决定调用 `mnote.artifact.create_summary`。
|
||||
- 或页面面板提供快捷按钮,但按钮本质也是向 Hermes 发送意图,不是绕过 Hermes 直接写 mnote。
|
||||
|
||||
第一版允许两个快捷入口:
|
||||
|
||||
- `创建 Summary`
|
||||
- `创建 AI Note`
|
||||
|
||||
但它们必须走:
|
||||
|
||||
```text
|
||||
Leptos panel -> Hermes session/run -> mnote plugin tool call -> Rust kernel
|
||||
```
|
||||
|
||||
不得走:
|
||||
|
||||
```text
|
||||
Leptos panel -> /api/documents/* 直接写 artifact
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 权限与安全
|
||||
|
||||
Hermes 可以调度工具,但 mnote 必须做最终授权。
|
||||
|
||||
每个 mnote tool call 至少校验:
|
||||
|
||||
- 当前 actor 是否登录
|
||||
- actor 是否属于 workspace
|
||||
- 当前页面是否允许 AI 读取
|
||||
- 当前页面是否允许 AI 写入
|
||||
- 当前工具是否允许写入页面 / 树 / artifact
|
||||
- 是否需要 `dryRun` 或确认
|
||||
|
||||
默认第一版:
|
||||
|
||||
- 读当前页:允许
|
||||
- 写当前页:按页面 capability
|
||||
- 创建 summary / ai_note:按当前页 artifact capability
|
||||
- 跨页写入:默认禁止
|
||||
- 跨 workspace:禁止
|
||||
|
||||
---
|
||||
|
||||
## 10. 迁移步骤
|
||||
|
||||
### Phase A:设计口径统一
|
||||
|
||||
- 新增本稿作为 07-ai 当前主线。
|
||||
- 将 `7-v4 CLI-first` 移入 `design/old/07-ai/process/` 并标记 `[recycle]`。
|
||||
- 更新仍引用 `mnote-cli` 唯一长期 agent 执行面的活跃设计稿。
|
||||
|
||||
### Phase B:薄 Hermes client proxy
|
||||
|
||||
- 在 `mnote-web` 补 Hermes client proxy。
|
||||
- 页面 AI 面板不再调用 `/api/ai-agent/run`。
|
||||
- 浏览器不直接持有 Hermes API key。
|
||||
|
||||
### Phase C:Leptos Hermes 面板最小子集
|
||||
|
||||
- 实现 session 创建 / 恢复。
|
||||
- 实现 run / stream / abort。
|
||||
- 实现 message / reasoning / tool event 展示。
|
||||
- 保留 Wolai 右侧抽屉壳。
|
||||
|
||||
### Phase D:mnote Hermes plugin
|
||||
|
||||
- 暴露 mnote tool manifest。
|
||||
- 先接 `mnote.page.get`、`mnote.page.save`、`mnote.artifact.create_summary`、`mnote.artifact.create_ai_note`。
|
||||
- 工具结果回到 Hermes tool event。
|
||||
|
||||
### Phase E:退役旧面板执行链
|
||||
|
||||
- `/api/ai-agent/run` 从主路径移除。
|
||||
- 旧 React `DocumentAiAgentPanel.runtime` 降为历史参考或 compat。
|
||||
- `provider=hermes/codex/claudecode` 502 不再出现在新页面 AI 主链。
|
||||
|
||||
---
|
||||
|
||||
## 11. 验收标准
|
||||
|
||||
第一版完成时必须满足:
|
||||
|
||||
- 页面 AI 抽屉打开后可创建或恢复 Hermes session。
|
||||
- Hermes session 存储中能看到页面 AI 的消息历史。
|
||||
- mnote 本地不复制聊天消息真相。
|
||||
- 发送消息后,事件流来自 Hermes run。
|
||||
- tool call 展示使用 Hermes tool event。
|
||||
- Hermes 可调用至少一个只读 mnote 工具读取当前页面。
|
||||
- Hermes 可调用至少一个写入工具,经 Rust runtime 写回当前页或创建 artifact。
|
||||
- 页面刷新后,AI 会话从 Hermes 恢复,而不是从 mnote 本地 state 恢复。
|
||||
- 结构化写入产生的 artifact / edge 能在 mnote projection 中验证。
|
||||
|
||||
---
|
||||
|
||||
## 12. 禁止项
|
||||
|
||||
- 不再新增 Web 私有 AI tool registry。
|
||||
- 不再把 `mnote-cli` 写成页面 AI 唯一长期执行面。
|
||||
- 不把 Hermes 聊天历史复制进 mnote page aggregate。
|
||||
- 不让 Hermes plugin 直接写 Convex。
|
||||
- 不在 Leptos 面板里重做 Hermes 后台管理台。
|
||||
- 不把 `AI Artifacts` 做成真实 kernel node。
|
||||
- 不绕过 Rust runtime 创建 artifact / edge。
|
||||
|
||||
---
|
||||
|
||||
## 13. 最终冻结口径
|
||||
|
||||
> **页面 AI 是 Hermes 面板,不是 mnote-cli 面板。**
|
||||
|
||||
> **Hermes 持有 AI 会话真相,mnote 持有业务对象真相。**
|
||||
|
||||
> **mnote 通过 Hermes skill/plugin 暴露工具,工具最终回到 Rust runtime / kernel。**
|
||||
|
||||
> **Leptos 负责页面内 Hermes 客户端体验,不负责 AI 编排。**
|
||||
@@ -1,702 +0,0 @@
|
||||
# 7 [process] mnote Kernel Phase 7 CLI-First 外置 Agent 统一执行面方案 v4
|
||||
|
||||
> 更新时间:2026-05-09
|
||||
>
|
||||
> 上位依据:
|
||||
> - `/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/04-tree-domain/done/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`
|
||||
> - `/mnt/Data1T/mnote/design/07-ai/done/7-1-phase7-document-ai-minimum-loop-checklist-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v2.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v3.md`
|
||||
>
|
||||
> 本稿与前稿的关系:
|
||||
> - `v2` 的价值仍然成立:它记录了文档页 AI 最小闭环已经真实完成
|
||||
> - `v3` 把 CLI 抬到了重要位置,但仍保留了“产品内 AI 主链”和“CLI 外置层”双中心
|
||||
> - 本稿进一步收口,明确长期只保留一个执行方向:`CLI-first`
|
||||
>
|
||||
> 当前判断修正:
|
||||
> - 文档页 AI 面板不再被视为独立 AI 编排主线
|
||||
> - `openai-agents-python` 不再被视为长期默认主编排,而是一个可插拔外置 agent
|
||||
> - Hermes、Codex、后续其他 agent,应统一通过 `mnote-cli` 接入
|
||||
> - `3000` 上的页面内 AI host 已属于 Rust `mnote-web` 主壳;`/api/ai-agent/run` 只保留 CLI host / adapter 口径
|
||||
> - 文档页 AI 上下文读取已优先消费 Rust `page aggregate` snapshot,旧 TS builder / 旧 sidecar 只保留 fallback / 对照语义
|
||||
|
||||
---
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
这份稿只回答一个问题:
|
||||
|
||||
> **`mnote` 的长期 AI 执行面,到底要不要收口成一个唯一方向。**
|
||||
|
||||
当前答案是:
|
||||
|
||||
> **要。长期只保留一个 AI 执行方向:`Rust kernel + mnote-cli`。**
|
||||
|
||||
这里的关键不是“要不要有 AI UI”,而是:
|
||||
|
||||
- UI 可以存在
|
||||
- 外置 agent 可以很多
|
||||
- 但执行面只能有一个
|
||||
|
||||
一句话收口:
|
||||
|
||||
> **`mnote` 的长期主线不是“内置 AI + CLI 两套长期并存”,而是“CLI 作为唯一 agent 执行面,Web 面板只是其中一个客户端”。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 为什么要改成 CLI-first
|
||||
|
||||
当前如果继续保留两套长期方向:
|
||||
|
||||
1. 产品内一套 AI 编排
|
||||
2. 外置 agent 一套 CLI / 脚本 / Hermes / Codex 编排
|
||||
|
||||
那么后面一定会出现这些重复维护成本:
|
||||
|
||||
- 两套工具注册表
|
||||
- 两套上下文装配逻辑
|
||||
- 两套 session / trace / audit 语义
|
||||
- 两套能力开关和权限边界
|
||||
- 两套“哪些命令是真执行、哪些只是兼容层”的判断
|
||||
|
||||
这不是“体验和平台分层”,而是“长期双轨维护”。
|
||||
|
||||
如果改成 CLI-first:
|
||||
|
||||
- Web AI 面板调用 CLI
|
||||
- Hermes 调用 CLI
|
||||
- Codex 调用 CLI
|
||||
- 批处理脚本调用 CLI
|
||||
- 定时任务调用 CLI
|
||||
|
||||
那么系统只维护:
|
||||
|
||||
1. 一个真执行方向:`mnote-cli`
|
||||
2. 多个调用方:UI / agent / script / job
|
||||
|
||||
这才是真正减少长期维护成本。
|
||||
|
||||
---
|
||||
|
||||
## 3. 当前完成情况如何解释
|
||||
|
||||
### 3.1 `7-1` 已完成,但不代表它必须成为长期方向
|
||||
|
||||
当前文档页 AI 最小闭环已经完成,这个事实不变:
|
||||
|
||||
- Rust `mnote.page_aggregate.v1` snapshot 优先的页面上下文读取
|
||||
- 标题改名与正文改写
|
||||
- `openai-agents-python` sidecar
|
||||
- `Hermes` fallback / 对照链
|
||||
|
||||
但这个完成状态只能说明:
|
||||
|
||||
> **我们已经验证过一条可工作的过渡主链。**
|
||||
|
||||
不能自动推出:
|
||||
|
||||
> **这条链就应该变成长期唯一主线。**
|
||||
|
||||
所以 `v2` 记录的工作不是白做,而是:
|
||||
|
||||
- 它证明了产品内写链需求真实存在
|
||||
- 它帮助我们冻结了最小工具面和页面语义面
|
||||
- 它可以作为 CLI-first 迁移时的行为基线
|
||||
|
||||
### 3.2 `mnote-cli` 已经足够接近长期入口
|
||||
|
||||
当前 `mnote-cli` 已经不是空壳,已有:
|
||||
|
||||
- `page`
|
||||
- `block`
|
||||
- `mindmap`
|
||||
- `search`
|
||||
- `sidebar`
|
||||
- `editor`
|
||||
- `tool`
|
||||
|
||||
同时还有这些关键参数:
|
||||
|
||||
- `--json`
|
||||
- `--execute`
|
||||
- `--session-id`
|
||||
- `--reason`
|
||||
- `--idempotency-key`
|
||||
- `--validate-only`
|
||||
- `--dry-run`
|
||||
|
||||
这说明真正应该继续投入的,不是再扩一条新的 Web 内 AI 主编排,而是把 CLI 补成稳定统一入口。
|
||||
|
||||
---
|
||||
|
||||
## 4. 新的长期架构边界
|
||||
|
||||
### 4.1 Rust kernel / Rust runtime
|
||||
|
||||
负责:
|
||||
|
||||
- 唯一事实源
|
||||
- query / command / projection
|
||||
- page / tree / graph / artifact 的正式语义
|
||||
- 审计、回放、恢复、trace 基线
|
||||
|
||||
不负责:
|
||||
|
||||
- 直接承担 agent 编排
|
||||
- 直接承担产品聊天壳
|
||||
|
||||
### 4.2 `mnote-cli`
|
||||
|
||||
负责:
|
||||
|
||||
- 唯一长期 agent 执行入口
|
||||
- 人类、脚本、外置 agent、Web 面板的统一命令面
|
||||
- 统一能力发现、统一参数面、统一输出结构
|
||||
|
||||
必须成为:
|
||||
|
||||
- CLI for humans
|
||||
- CLI for agents
|
||||
- CLI for jobs
|
||||
- CLI for UI host
|
||||
|
||||
### 4.3 Web AI 面板
|
||||
|
||||
负责:
|
||||
|
||||
- 当前页面里的交互壳
|
||||
- 流式展示
|
||||
- 输入与审核
|
||||
- 把页面上下文转成 CLI 可消费的标准输入
|
||||
- 接收 CLI 事件并映射到 UI
|
||||
|
||||
不负责:
|
||||
|
||||
- 自己维护独立 agent 编排层
|
||||
- 自己维护独立工具注册表
|
||||
- 自己定义长期 AI 契约
|
||||
|
||||
### 4.4 外置 agent
|
||||
|
||||
包括但不限于:
|
||||
|
||||
- Hermes
|
||||
- Codex
|
||||
- `openai-agents-python`
|
||||
- 后续任何别的 agent runtime
|
||||
|
||||
它们都负责:
|
||||
|
||||
- 决策
|
||||
- 推理
|
||||
- 工具调用策略
|
||||
- 会话层 orchestration
|
||||
|
||||
但它们不应再直接拥有产品内部执行面。它们都应该统一调用 `mnote-cli`。
|
||||
|
||||
---
|
||||
|
||||
## 5. `openai-agents-python` 的新定位
|
||||
|
||||
### 5.1 不再是默认主线
|
||||
|
||||
从本稿开始,`openai-agents-python` 不再被定义为:
|
||||
|
||||
- `mnote` 的长期默认主编排
|
||||
- 产品内文档页 AI 的唯一推荐底座
|
||||
|
||||
### 5.2 改为可插拔外置 agent
|
||||
|
||||
它的新定位是:
|
||||
|
||||
> **一个可插拔外置 agent runtime。**
|
||||
|
||||
也就是说,它和 Hermes、Codex 的区别不再是“谁是产品内主线”,而只是:
|
||||
|
||||
- 不同的 agent 实现
|
||||
- 不同的模型接法
|
||||
- 不同的 orchestration 风格
|
||||
|
||||
是否继续保留它,取决于后续真实效果,而不是当前历史惯性。
|
||||
|
||||
### 5.3 可接受的长期状态
|
||||
|
||||
未来允许的状态有三种:
|
||||
|
||||
1. `openai-agents-python` 继续保留,作为可选外置 agent
|
||||
2. `openai-agents-python` 仅保留在测试 / 回归 / 对照场景
|
||||
3. `openai-agents-python` 完全移除
|
||||
|
||||
这三种都不影响长期主架构,只要唯一执行面还是 `mnote-cli`。
|
||||
|
||||
---
|
||||
|
||||
## 6. CLI-first 下的产品口径
|
||||
|
||||
### 6.1 UI 仍然可以有 AI 面板
|
||||
|
||||
CLI-first 不等于没有产品内 AI UI。
|
||||
|
||||
允许继续有:
|
||||
|
||||
- 文档页 AI 面板
|
||||
- mindmap AI 面板
|
||||
- OnlyOffice AI 面板
|
||||
|
||||
但这些都只是:
|
||||
|
||||
> **CLI 的图形客户端。**
|
||||
|
||||
并且当前这些客户端默认都挂在 `3000` 的 Rust `mnote-web` 主壳里,而不是重新长出第二套产品内执行面。
|
||||
|
||||
### 6.2 页面语义仍然保留
|
||||
|
||||
虽然主执行面转到 CLI,但下面这些产品语义仍要保留:
|
||||
|
||||
- `model_key`
|
||||
- `profile`
|
||||
- `tool registry`
|
||||
- `page aggregate`
|
||||
- `page.head.updateTitle`
|
||||
- `page.body.save`
|
||||
- `tree.*`
|
||||
|
||||
区别只在于:
|
||||
|
||||
- 这些不再由 Web 内独立 AI service 主导
|
||||
- 而是由 CLI 和 Rust runtime 共同定义
|
||||
|
||||
### 6.3 Web 不应再拥有第二套工具面
|
||||
|
||||
当前过渡工具面:
|
||||
|
||||
- `doc_get`
|
||||
- `doc_find`
|
||||
- `doc_insert_blocks`
|
||||
- `doc_replace_range`
|
||||
- `slash_run`
|
||||
|
||||
如果继续保留,后续也应通过 CLI 暴露,而不是继续作为 Web 内 service 的私有 tool surface。
|
||||
|
||||
---
|
||||
|
||||
## 7. CLI 必须补齐的能力
|
||||
|
||||
CLI-first 成立的前提,不是“已有命令很多”,而是这些能力必须补齐。
|
||||
|
||||
### 7.1 能力发现
|
||||
|
||||
至少要能稳定输出:
|
||||
|
||||
- 当前有哪些 command / query / job
|
||||
- 每个能力属于哪个 scope
|
||||
- 哪些可读,哪些可写
|
||||
- 哪些是 plan-only
|
||||
- 哪些是真执行
|
||||
|
||||
建议提供:
|
||||
|
||||
- `mnote-cli capabilities --json`
|
||||
|
||||
### 7.2 标准上下文输入
|
||||
|
||||
CLI 需要能接住标准化页面上下文,而不是让每个 agent 自己拼:
|
||||
|
||||
- `documentId`
|
||||
- `blocks`
|
||||
- `pageOptions`
|
||||
- `editorRuntimePageOptions`
|
||||
- `subtree`
|
||||
- `outline`
|
||||
- `evidence`
|
||||
|
||||
也就是说,页面上下文装配逻辑要从 Web 内 agent service 迁到 CLI 兼容输入协议。
|
||||
|
||||
### 7.3 标准事件输出
|
||||
|
||||
如果 Web 面板要流式显示,CLI 需要输出标准事件流,例如:
|
||||
|
||||
- `assistant_message`
|
||||
- `tool_call`
|
||||
- `tool_result`
|
||||
- `completion`
|
||||
- `error`
|
||||
|
||||
否则 UI 最后还是会倒逼出第二套 Web 内编排逻辑。
|
||||
|
||||
### 7.4 标准 session / trace / audit
|
||||
|
||||
CLI 必须把这些变成一等能力:
|
||||
|
||||
- `session_id`
|
||||
- `trace_id`
|
||||
- `request_id`
|
||||
- `actor_id`
|
||||
- `actor_type`
|
||||
- `reason`
|
||||
- `idempotency_key`
|
||||
|
||||
### 7.5 权限与 scope
|
||||
|
||||
CLI 要能明确限制:
|
||||
|
||||
- 当前只能改当前页
|
||||
- 当前允许跨页还是不允许
|
||||
- 当前允许树命令还是只允许页面命令
|
||||
- 当前是只读、写入还是后台 job
|
||||
|
||||
---
|
||||
|
||||
## 8. 顺序执行 checklist
|
||||
|
||||
本节是后续实施时的主 checklist。执行时从上到下推进,完成一项后把对应 `- [ ]` 改成 `- [x]`,并在该项下补充实际命令输出摘要或截图路径。
|
||||
|
||||
### 8.1 冻结 CLI 基座
|
||||
|
||||
- [x] 确认 `mnote-cli` 顶层命令存在。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --help
|
||||
```
|
||||
- 通过标准:输出包含 `page`、`block`、`mindmap`、`search`、`sidebar`、`editor`、`tool`。
|
||||
|
||||
- [x] 确认 agent 必需的全局参数存在。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --help
|
||||
```
|
||||
- 通过标准:输出包含 `--json`、`--execute`、`--session-id`、`--reason`、`--idempotency-key`、`--validate-only`、`--dry-run`。
|
||||
|
||||
- [x] 确认 `mnote-cli` 当前单测全通过。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli
|
||||
```
|
||||
- 通过标准:所有 `mnote-cli` 测试通过;当前基线应覆盖 CLI JSON contract、tool registry、page/save/sidebar 等最小面。
|
||||
|
||||
### 8.2 冻结页面命令面
|
||||
|
||||
- [x] 验证页面读取命令。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json page get --page-id page_demo --workspace-id ws_demo
|
||||
```
|
||||
- 通过标准:输出包含 `domain: page`、`action: get`、`context.requestId`、`context.traceId`,并且 `operation.transport.functionName` 指向页面查询。
|
||||
|
||||
- [x] 验证页面标题更新命令。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json page title --page-id page_demo --workspace-id ws_demo --title "新标题"
|
||||
```
|
||||
- 通过标准:输出包含 `domain: page`、`action: title`、`operation.kind: command`,并且写入仍通过 Rust runtime / transport 计划表达。
|
||||
|
||||
- [x] 验证页面正文保存命令。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json page save --page-id page_demo --workspace-id ws_demo --content-json '[{"id":"block_1"}]'
|
||||
```
|
||||
- 通过标准:输出包含 `domain: page`、`action: save`、`operation.kind: command`,并且能看到正文写回 payload。
|
||||
|
||||
### 8.3 冻结块命令面
|
||||
|
||||
- [x] 验证块插入命令。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json block insert --page-id page_demo --workspace-id ws_demo --block-type paragraph --content "hello"
|
||||
```
|
||||
- 通过标准:输出包含 `domain: block`、`action: insert`、`operation.kind: command`、`operation.name: insert_block`。
|
||||
|
||||
- [x] 验证块 patch 命令。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json block patch --page-id page_demo --workspace-id ws_demo --block-id block_demo --snapshot-json '{"id":"block_demo","type":"paragraph","text":"updated"}'
|
||||
```
|
||||
- 通过标准:输出包含 `domain: block`、`action: patch`、`operation.kind: command`、`operation.name: blocks.patch`。
|
||||
|
||||
- [x] 第 1 步:固定块写链仍然存在的入口证据。
|
||||
- 结果:`/api/ai-agent/run` 已不再直接恢复 `slash_run` / `doc_insert_blocks` / `doc_replace_range`,`DocumentAiAgentPanel.runtime.tsx` 也已不再声明 Web 内独立 agent owner。
|
||||
- 验证命令:
|
||||
```bash
|
||||
rg -n "doc_insert_blocks|doc_replace_range|slash_run|startHermesRun|startDocumentAiOrchestratorRun|runCodexBridge" \
|
||||
/mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts \
|
||||
/mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx
|
||||
```
|
||||
|
||||
- [x] 第 2 步:把块写链收口为 `mnote-cli` host / adapter。
|
||||
- 结果:`/api/ai-agent/run` 已收口为薄 host route,块写链不再由 Web 私有 service 直接拥有。
|
||||
- 依赖检查:`DocumentAiAgentPanel.runtime.tsx` 与 `/api/ai-agent/run/route.ts` 的 contract 说明已同步改成 `mnote-cli`。
|
||||
|
||||
- [x] 第 3 步:补块写链回归测试。
|
||||
- 结果:`pnpm vitest run src/components/editor/DocumentAiAgentPanel.runtime.test.tsx` 与 `pnpm vitest run src/app/api/ai-agent/run/route.test.ts` 通过。
|
||||
- 验证命令:
|
||||
```bash
|
||||
pnpm vitest run /mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.test.tsx
|
||||
pnpm vitest run /mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.test.ts
|
||||
```
|
||||
- 通过标准:测试明确约束块写链不再暴露 Web 私有 tool surface,并且 route 只保留 CLI host / adapter 语义。
|
||||
|
||||
### 8.4 冻结搜索与侧栏投影
|
||||
|
||||
- [x] 验证文档搜索命令。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json search documents --workspace-id ws_demo --query "Hermes"
|
||||
```
|
||||
- 通过标准:输出包含 `domain: search`、`action: documents`,并且查询计划可由 Web host 消费。
|
||||
|
||||
- [x] 验证块搜索命令。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json search blocks --page-id page_demo --query "Hermes"
|
||||
```
|
||||
- 通过标准:输出包含 `domain: search`、`action: blocks`、`operation.name: search_blocks`。
|
||||
|
||||
- [x] 验证侧栏数据集命令。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json sidebar dataset --workspace-id ws_demo
|
||||
```
|
||||
- 通过标准:输出包含 `domain: sidebar`、`action: dataset`、`operation.name: sidebar.dataset.list`。
|
||||
|
||||
### 8.5 冻结 tool runtime 与安全模式
|
||||
|
||||
- [x] 验证 `tool run` 的只读 explain-plan。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --json --validate-only --dry-run --session-id ai-checklist-smoke --reason phase7-cli-first --idempotency-key phase7-cli-first-001 tool run --tool-name doc_get --kind query --mode explain-plan --args-json '{"pageId":"page_demo"}'
|
||||
```
|
||||
- 通过标准:输出包含 `domain: tool`、`action: run`、`context.sessionId: ai-checklist-smoke`、`context.idempotencyKey: phase7-cli-first-001`、`context.validateOnly: true`、`context.dryRun: true`。
|
||||
|
||||
- [x] 验证 tool registry 会拒绝未知工具。
|
||||
- 命令:
|
||||
```bash
|
||||
cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli tool_run_rejects_unknown_tool
|
||||
```
|
||||
- 通过标准:测试通过,未知 tool 不会绕过 registry 进入执行链。
|
||||
|
||||
- [x] 确认 `--reason` 进入后续 audit / trace 输出规划。
|
||||
- 当前状态:CLI 参数面已接住 `--reason`,并已在标准 JSON 输出的 `context.reason` 中展开。
|
||||
- 通过标准:`cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli output_context_keeps_reason_for_audit_trace` 通过,断言 `reason` 出现在标准 audit / trace 输出上下文里。
|
||||
|
||||
### 8.6 将 Web AI 面板降为 CLI host
|
||||
|
||||
- [x] 检查 Rust Web checklist 的 Phase 5 口径。
|
||||
- 文件:`/mnt/Data1T/mnote/design/03-rust-web/process/3-1-rust-web-long-term-checklist-v2.md`
|
||||
- 通过标准:AI 面板只能写成 `mnote-cli` host/client 收口,不得写成 Hermes 或 `openai-agents-python` 长期主编排。
|
||||
- 已核对:该文件明确写入“长期执行面应收口到 `mnote-cli`,Web 只作为 CLI host / client,`openai-agents-python` / Hermes / Codex 只作为可插拔外置 agent”。
|
||||
|
||||
- [x] 检查 legacy Next retirement gate 的 AI route 口径。
|
||||
- 文件:`/mnt/Data1T/mnote/design/03-rust-web/done/3-11-rust-web-legacy-next-retirement-gates-v1.md`
|
||||
- 通过标准:`/api/ai-agent/run` 只能写成 CLI host / adapter 兼容层,结构化写入必须经 Rust runtime。
|
||||
- 已核对:该文件明确写入 `/api/ai-agent/run` 长期应降为 `mnote-cli` host / adapter,结构化写入必须经 Rust runtime,外置 agent 不得拥有第二执行面。
|
||||
|
||||
- [x] 检查 Wolai-aline E27 的 AI 编辑口径。
|
||||
- 文件:`/mnt/Data1T/mnote/design/05-editor-mainline/process/5-9-wolai-aline-continuous-checklist-v1.md`
|
||||
- 通过标准:E27 只能把 `openai-agents-python` sidecar / Hermes fallback 当作过渡基线,不得写成长期主线。
|
||||
- 已核对:E27 明确写入 `/api/ai-agent/run` 后续应收口为 `mnote-cli` 唯一长期 agent 执行面上的 host / adapter,`Hermes`、`Codex`、`openai-agents-python` 仅为可插拔外置 agent;当前 sidecar / fallback 只保留为过渡行为基线。
|
||||
|
||||
### 8.7 外置 agent 接入顺序
|
||||
|
||||
- [x] 第 1 步:冻结 Codex 接入方式。
|
||||
- 结果:`/api/ai-agent/run` 已不再保留 `provider=codex` 默认系统入口;请求会明确失败,默认主链只保留 `mnote-cli` host。
|
||||
- 验证命令:
|
||||
```bash
|
||||
rg -n "provider === \"codex\"|runCodexBridge" /mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts
|
||||
```
|
||||
|
||||
- [x] 第 2 步:冻结 Hermes 接入方式。
|
||||
- 结果:`/api/ai-agent/run` 已不再直接调用 `startHermesRun` / `streamHermesRunEvents`,Hermes 不再是长期主链入口。
|
||||
- 验证命令:
|
||||
```bash
|
||||
rg -n "startHermesRun|streamHermesRunEvents|/api/hermes/bridge" /mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts
|
||||
```
|
||||
|
||||
- [x] 第 3 步:冻结 `openai-agents-python` 接入方式。
|
||||
- 结果:`DocumentAiAgentPanel.runtime.tsx` 已不再声明 `bridgeOwner: "openai-agents-python"`,`provider=online` 也不再直连 orchestrator。
|
||||
- 验证命令:
|
||||
```bash
|
||||
rg -n "bridgeOwner: \"openai-agents-python\"|startDocumentAiOrchestratorRun|/api/v1/ai-agent/document/run" /mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx /mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts
|
||||
```
|
||||
|
||||
- [x] 第 4 步:统一复核外置 agent 只剩 CLI host / adapter 口径。
|
||||
- 结果:已通过全局复核,`/api/ai-agent/run` 与面板 contract 都只保留 `mnote-cli` host / adapter 口径。
|
||||
- 验证命令:
|
||||
```bash
|
||||
rg -n "provider === \"codex\"|runCodexBridge|startHermesRun|streamHermesRunEvents|bridgeOwner: \"openai-agents-python\"|startDocumentAiOrchestratorRun|/api/v1/ai-agent/document/run" \
|
||||
/mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts \
|
||||
/mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx
|
||||
```
|
||||
|
||||
### 8.8 完成判定
|
||||
|
||||
- [x] `mnote-cli` 的最小命令面在仓库内可复跑。
|
||||
- 已验证:`cargo run --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -- --help` 与 `cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli` 可复跑。
|
||||
- [x] `--json`、`--execute`、`--validate-only`、`--dry-run` 的输出语义稳定。
|
||||
- 已验证:`--help` 暴露这些全局参数;`tool run --validate-only --dry-run --json` 输出包含 `context.validateOnly: true`、`context.dryRun: true`、`context.reason`、`context.sessionId` 与 `context.idempotencyKey`。
|
||||
- [x] `page / block / search / sidebar / tool` 都能用 CLI 直接验证。
|
||||
- 已验证:8.2 到 8.5 已分别覆盖 `page get/title/save`、`block insert/patch`、`search documents/blocks`、`sidebar dataset`、`tool run`。
|
||||
- [x] 第 1 步:确认 Web AI 面板的 contract 已收口为 `mnote-cli` host / client。
|
||||
- 结果:面板 contract 已改为 `bridgeOwner: "mnote-cli"`,`runtimeRole: "mnote_cli_host_client"`。
|
||||
- 验证命令:
|
||||
```bash
|
||||
rg -n "bridgeOwner: \"openai-agents-python\"|startDocumentAiOrchestratorRun|startHermesRun|runCodexBridge" /mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx /mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts
|
||||
```
|
||||
|
||||
- [x] 第 2 步:确认三类外置 agent 都只作为可插拔 runtime。
|
||||
- 结果:`route.ts` 已收口为统一 host route,不再按 provider 分叉到三套执行实现。
|
||||
- 验证命令:
|
||||
```bash
|
||||
rg -n "provider === \"codex\"|runCodexBridge|startHermesRun|startDocumentAiOrchestratorRun|bridgeOwner: \"openai-agents-python\"" /mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts /mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx
|
||||
```
|
||||
|
||||
- [x] 第 3 步:补完成判定的最终回归。
|
||||
- 结果:`cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli`、`pnpm vitest run src/components/editor/DocumentAiAgentPanel.runtime.test.tsx`、`pnpm vitest run src/app/api/ai-agent/run/route.test.ts` 均通过。
|
||||
- 验证命令:
|
||||
```bash
|
||||
cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli
|
||||
pnpm vitest run /mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.test.tsx
|
||||
pnpm vitest run /mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.test.ts
|
||||
```
|
||||
- [x] 结构化写入仍然只能回到 Rust runtime / Rust kernel。
|
||||
- 已核对:本稿 4.1、6.2、6.3 明确 Rust kernel / Rust runtime 负责事实源、query / command / projection 与结构化写入语义;`3-11` 与 Wolai-aline E27 均要求结构化写入经 Rust runtime 或 Rust tool / `page.body.save`。
|
||||
|
||||
### 8.9 当前测试账号写入验收
|
||||
|
||||
- [x] 确认当前测试账号默认允许 CLI 新建与编辑页面。
|
||||
- 命令:
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/server/mnote-cli-agent-host.test.ts
|
||||
```
|
||||
- 通过标准:`mnote-cli` host 默认下发 `MNOTE_CLI_ALLOW_CREATE_PAGE=1` 与 `MNOTE_CLI_ALLOW_EDIT=1`,并把当前 Web 用户身份透传给 CLI 子进程。
|
||||
|
||||
- [x] 确认当前测试账号的真实 workspace。
|
||||
- 当前测试账号:
|
||||
- `userId`: `a4b72c17-49e3-46d3-8456-24a0a7044d64`
|
||||
- `email`: `dev@mnote.local`
|
||||
- `name`: `开发用户`
|
||||
- 当前真实 workspace:
|
||||
- `workspaceId`: `ws_req_1778035004501_15`
|
||||
- `workspaceName`: `开发用户 的空间`
|
||||
- 首个页面:`tree_1778036320856_1` / `新页面`
|
||||
- 通过标准:`/api/sidebar?workspaceId=ws_req_1778035004501_15` 返回的 `documents` 至少包含 `tree_1778036320856_1`。
|
||||
|
||||
- [x] 确认旧的 CLI 直连 Convex identity 不能作为长期用户写入面。
|
||||
- 事实:曾经写入 `tree_1777430834634_3` / `anonymous 的空间` 的页面不会出现在当前测试账号的 `ws_req_1778035004501_15`。
|
||||
- 结论:CLI 不能长期依赖伪造 `DEV_USER_ID` 直连 Convex 来代表用户写入;需要由 Web host / mnote-web 持有当前会话、当前 workspace 与 capability 后再执行写入。
|
||||
|
||||
- [x] 确认 CLI host 会把当前页面 workspaceId 传入 CLI 输入。
|
||||
- 命令:
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/server/mnote-cli-agent-host.test.ts
|
||||
```
|
||||
- 通过标准:`--args-json` 包含 `workspaceId: "ws_req_1778035004501_15"`,避免 agent 在缺省 workspace 或错误 workspace 下创建页面。
|
||||
|
||||
- [x] 用当前浏览器会话创建当前账号可见页面。
|
||||
- 执行动作:在已登录测试账号的浏览器会话中调用 `/api/tree/commands` 创建:
|
||||
- `CLI 可见测试 A 1778057564`
|
||||
- `CLI 可见测试 B 1778057564`
|
||||
- 通过标准:创建响应的 `result.workspaceId` 必须是 `ws_req_1778035004501_15`。
|
||||
- 当前验证结果:
|
||||
- `tree_1778048047020_3` / `CLI 可见测试 A 1778057564`
|
||||
- `tree_1778048047047_4` / `CLI 可见测试 B 1778057564`
|
||||
|
||||
- [x] 用当前浏览器会话读取 sidebar 确认可见。
|
||||
- 命令等价动作:
|
||||
```js
|
||||
await fetch('/api/sidebar?workspaceId=ws_req_1778035004501_15', { credentials: 'include' })
|
||||
```
|
||||
- 通过标准:返回的 `documents`、`kernelSidebarProjection.items` 与 `kernelSidebarTree` 都包含 `CLI 可见测试 A 1778057564` 与 `CLI 可见测试 B 1778057564`。
|
||||
- 当前验证结果:已在浏览器会话 API 返回中看到上述两个页面;同一返回还显示早先创建的 `cli_visible_ws_req_a_17780471` 与 `cli_visible_ws_req_b_17780471`。
|
||||
|
||||
- [ ] 后续权限收口:补“禁止/允许 CLI 编辑、允许 CLI 新建页面”的 capability 开关。
|
||||
- 目标:默认测试账号允许 CLI 新建与编辑;后续真实用户可在设置中关闭关键页面的 CLI 编辑或新建权限。
|
||||
- 通过标准:CLI 写操作必须能读到当前用户、当前 workspace、当前页面 capability;未授权时返回明确拒绝,不得 fallback 到 anonymous / dev identity 写入。
|
||||
|
||||
- [x] 确认 Web host 会把当前会话用户透传给 `mnote-cli` 作为默认执行身份。
|
||||
- 命令:
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/server/mnote-cli-agent-host.test.ts src/app/api/ai-agent/run/route.test.ts
|
||||
```
|
||||
- 通过标准:`spawn("cargo", ...)` 的环境变量包含 `DEV_USER_ID`、`DEV_USER_EMAIL`、`DEV_USER_NAME`,并默认下发 `MNOTE_CLI_ALLOW_CREATE_PAGE=1` 与 `MNOTE_CLI_ALLOW_EDIT=1`。
|
||||
|
||||
---
|
||||
|
||||
## 9. 迁移策略
|
||||
|
||||
### 阶段 0:口径冻结
|
||||
|
||||
先冻结新的长期判断:
|
||||
|
||||
- CLI 是唯一长期执行面
|
||||
- Web 面板只是 CLI 客户端
|
||||
- `openai-agents-python` 是可插拔外置 agent
|
||||
- Hermes / Codex / 后续 agent 不再拥有默认产品内入口;是否保留仅通过显式接线决定
|
||||
|
||||
### 阶段 1:CLI 能力补齐
|
||||
|
||||
优先补:
|
||||
|
||||
- capability manifest
|
||||
- 标准 JSON 输出
|
||||
- 事件流输出
|
||||
- 标准上下文输入
|
||||
- 标准 trace / session 参数
|
||||
|
||||
### 阶段 2:Web 面板降为 CLI host
|
||||
|
||||
把当前文档页 AI 面板从:
|
||||
|
||||
- “调用内置 sidecar 主编排”
|
||||
|
||||
改成:
|
||||
|
||||
- “调用 CLI host / CLI adapter”
|
||||
|
||||
### 阶段 3:外置 agent 接入统一化
|
||||
|
||||
统一支持:
|
||||
|
||||
- Hermes -> 显式外置接线或停用
|
||||
- Codex -> 显式外置接线或停用
|
||||
- `openai-agents-python` -> `mnote-cli`
|
||||
|
||||
### 阶段 4:裁剪过渡层
|
||||
|
||||
当 CLI-first 成熟后,逐步评估:
|
||||
|
||||
- 是否保留 `openai-agents-python`
|
||||
- 是否保留当前 Web 内 sidecar
|
||||
- 是否完全移除旧过渡桥接
|
||||
|
||||
---
|
||||
|
||||
## 10. 非目标
|
||||
|
||||
本稿不做:
|
||||
|
||||
- 再造一套新的 agent 平台
|
||||
- 让 Web 直接失去 AI UI
|
||||
- 把所有 UX 都退回终端
|
||||
- 让 Hermes 或 `openai-agents-python` 重新变成产品内部唯一中心
|
||||
|
||||
---
|
||||
|
||||
## 11. 完成判定
|
||||
|
||||
满足下面几项时,才算 CLI-first 真正成立:
|
||||
|
||||
- `mnote-cli` 是唯一长期 agent 执行入口
|
||||
- Web AI 面板只是 CLI host,不再持有独立主编排
|
||||
- Hermes / Codex / `openai-agents-python` 都通过 CLI 接入
|
||||
- Rust kernel 仍然是唯一事实源
|
||||
- 是否保留 `openai-agents-python` 不影响整体架构
|
||||
|
||||
一句话收口:
|
||||
|
||||
> **`mnote` 的长期 AI 方向应当收口成“Rust kernel 负责真相,`mnote-cli` 负责唯一执行面,外置 agent 全部可插拔,Web 只做交互壳”。**
|
||||
Reference in New Issue
Block a user