Files
mnote/design/07-ai/done/7-8-page-ai-hermes-runtime-bff-next-v1.md
T

405 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 7-8 [process] 页面 AI Hermes Runtime BFF 下一阶段设计 v1
> 更新时间:2026-05-15
>
> 当前状态:`PROCESS`。本文承接 `7-3`、`7-4`、`7-5`、`7-6`、`7-7` 已完成的 Hermes 页面内客户端主线,写入对 `hermes-web-ui-0.5.18` Chat Runtime 架构的吸收结论。
>
> 上位依据:
> - `/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/reference-code/hermes-web-ui-0.5.18`
> - `/mnt/Data1T/mnote/design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md`
> - `/mnt/Data1T/mnote/design/07-ai/done/7-4-page-ai-hermes-panel-execution-checklist-v1.md`
> - `/mnt/Data1T/mnote/design/07-ai/done/7-5-hermes-client-proxy-contract-v1.md`
> - `/mnt/Data1T/mnote/design/07-ai/done/7-6-mnote-hermes-plugin-tool-contract-v1.md`
> - `/mnt/Data1T/mnote/design/07-ai/done/7-7-page-ai-mini-hermes-control-surface-v1.md`
---
## 1. 结论
`hermes-web-ui-0.5.18` 对 mnote 有用,但不能原样照搬。
可吸收的是:
- Web 端应采用 `Browser -> BFF -> Hermes gateway`,不是浏览器直接 ACP。
- BFF 应承担 runtime 管理:active run registry、resume、queue、abort、event normalization、gateway manager、错误规整。
- 前端只展示 message、tool event、状态和输入,不持有 AI 编排真相。
不可吸收的是:
- 不把 mnote 的页面 AI 聊天真相改为 Convex、SQLite 或 mnote 自建 chat DB。
- 不把 Hermes 降级成 `/v1/responses store=false` 的纯模型执行器。
- 不让 mnote-web 根据自有数据库长期组装完整 `conversation_history`
当前冻结方向:
> **mnote 学 `hermes-web-ui` 的 BFF/runtime 架构思想,但会话真相继续归 Hermes;mnote 只保存业务事实、audit、artifact、edge、page/body/title/options 结果。**
---
## 2. 当前实现定位
当前页面 AI 接入是:
```text
Leptos 页面 AI 面板
-> mnote-web /api/hermes/client/*
-> Hermes gateway /v1/runs
-> Hermes gateway /v1/runs/{run_id}/events
```
同时:
- `profiles / skills / memory` 等设置能力由 `mnote-web` 本地 BFF 通过 Hermes CLI 或 `~/.hermes` 文件读写补齐。
- `mnote.*` 工具由 mnote Rust runtime 承接,Hermes 只通过 skill/plugin/tool 调用。
- 页面 AI 不再走旧 `/api/ai-agent/run`
这已经满足最小闭环,但仍只是“最小 runtime 接入”,缺少 `hermes-web-ui` 已经具备的完整 Chat Runtime 能力。
---
## 3. ACP、gateway、responses 的取舍
### 3.1 ACP
ACP 适合:
- VSCode 插件
- Tauri / Electron 桌面端
- 本地 IDE host
- 需要由宿主启动 `hermes acp` 并通过 stdio JSON-RPC 深度交互的场景
ACP 不适合作为 mnote 页面 AI 第一主链:
- 浏览器不能直接 `spawn hermes acp`
- 若 Web 使用 ACP,仍需 mnote-web 作为 ACP bridge 管理 stdio 子进程。
- 这会引入长期进程、session、backpressure、并发、恢复和崩溃清理复杂度。
- 当前 Hermes gateway 已提供 Web 更自然的 `/v1/*` 与 stream 能力。
结论:
> **ACP 后续只作为桌面端或高级 host bridge 候选,不作为页面 AI Web 主链。**
### 3.2 `/v1/runs`
`/v1/runs` 适合当前 mnote 主线:
- Hermes 持有 run / session / event 语义。
- mnote 页面 AI 只是 Hermes client。
- mnote 不需要长期组装 `conversation_history`
- 与“AI 会话归 Hermesmnote 能力归 Rust kernel”一致。
风险:
- mnote-web 需要补 runtime 状态管理,否则刷新、断线、队列、abort 体验弱。
- Hermes gateway 的非 `/v1/*` 管理面不足,需要 BFF 补 profiles/skills/memory/gateway manager。
结论:
> **短期继续以 `/v1/runs` 为默认页面 AI 主链,并在 mnote-web 上补 Runtime BFF。**
### 3.3 `/v1/responses`
`hermes-web-ui` 的产品化 Chat Runtime 使用 `/v1/responses stream=true`,典型形态是:
```text
Browser Vue UI
-> Socket.IO /chat-run
-> hermes-web-ui server
-> /v1/responses stream=true
-> server 从本地 DB 组装 conversation_history
-> server 把 response.* 事件转成 run/message/tool 事件
-> server 写入 SQLite session/messages
```
它适合“自建 Chat Runtime”:
- 后端自有 session/messages 数据库。
- 后端自行压缩上下文。
- 后端自行映射 tool event。
- `store=false` 时 Hermes 不再是会话真相。
这与 mnote 当前页面 AI 方向有冲突。除非后续明确改变设计,把“AI 会话真相”从 Hermes 迁到 mnote,否则不能把 `/v1/responses store=false + mnote conversation_history` 写成默认主链。
允许使用 `/v1/responses` 的条件:
- 只作为特定 runtime 实验或 fallback。
- 必须证明 Hermes session 仍能作为用户可见会话真相,或者另开设计稿明确改变会话真相。
- 不得把 mnote page aggregate / Convex 页面数据变成聊天消息数据库。
结论:
> **`/v1/responses` 先作为参考实现和可评估候选,不作为当前页面 AI 默认主链。**
---
## 4. 目标架构
下一阶段目标不是改成 ACP,也不是直接改成 `/v1/responses`,而是在当前 gateway 主线上补一个 mnote-web Runtime BFF
```text
Leptos 页面 AI 面板
-> mnote-web Hermes Runtime BFF
- active run registry
- session/run resume
- queue
- abort
- event normalization
- gateway/profile/skill/memory BFF
- trace/audit 串联
-> Hermes gateway /v1/runs
-> Hermes session storage
-> mnote skill/plugin/tool
-> Rust runtime / kernel
```
真相边界:
- HermesAI session、message、run、tool event、usage、model、profile。
- mnote:页面、树、正文、artifact、edge、projection、audit、权限、idempotency。
- mnote-web Runtime BFF:运行时连接和事件编排,不保存长期聊天真相。
---
## 5. Hermes Web UI 参考索引
参考根目录:
```text
/mnt/Data1T/mnote/design/05-editor-mainline/reference-code/hermes-web-ui-0.5.18
```
只参考下表,不整站搬运:
| 参考主题 | 文件 | 搜索点 | mnote 中吸收什么 | mnote 中不采用什么 |
| --- | --- | --- | --- | --- |
| Socket runtime 主链 | `packages/server/src/services/hermes/chat-run-socket.ts` | `ChatRunSocket``onConnection``resumeSession``handleRun``dequeueNextQueuedRun``handleAbort` | active run registry、resume、queue、abort、前端刷新不丢运行态 | 不照搬 Socket.IOmnote 可用 SSE / WebSocket / HTTP 状态轮询 |
| `/v1/responses` 事件映射 | `packages/server/src/services/hermes/chat-run-socket.ts` | `/v1/responses``applyResponseStreamEvent``response.output_text.delta``response.output_item.done``response.completed` | 学习如何把上游事件标准化为 `message.delta``tool.started``tool.completed``run.completed` | 不把 `/v1/responses store=false` 写成默认主链 |
| 后端 session store | `packages/server/src/db/hermes/session-store.ts` | `HermesSessionRow``HermesMessageRow``createSession``addMessage``getSessionDetail` | 理解 Hermes Web UI 如何建完整 chat DB,以及字段形态 | 不在 mnote 建第二套 chat DB;不把 Convex 当 AI 会话真相 |
| 前端 chat store | `packages/client/src/stores/hermes/chat.ts` | `resumeServerWorkingRun``queueLengths``abortState``case 'message.delta'``case 'tool.started'``case 'run.completed'` | 前端状态机、队列提示、abort UI、tool event 归并 | 不复用 Vue/Pinia;不把前端 state 当真相 |
| 前端 API | `packages/client/src/api/hermes/chat.ts` | `startRunViaSocket``resumeSession``registerSessionHandlers``RunEvent` | 客户端事件合同与 runtime event 类型 | 不让浏览器绕过 mnote-web 直连 Hermes |
| VSCode ACP tool UI | `design/05-editor-mainline/reference-code/hermes-vscode-main/src/sessionManager.ts``src/protocol.ts``src/chatPanel.ts``src/webview/main.ts` | `tool_call``tool_call_update``parseToolCall``parseToolCallUpdate``case 'toolCall'``data-tool-id` | 学习按 `toolCallId` 追加工具行、再用后续 update 原地更新状态的 UI 模型 | 不采用 ACP 作为 Web 主链;只参考 tool event UI 状态机 |
| gateway 管理 | `packages/server/src/services/hermes/gateway-manager.ts``packages/server/src/services/gateway-bootstrap.ts` | `getUpstream``start``stop``health` | profile 对应 gateway 的发现、启动、健康检查、错误提示 | 不让页面 AI 抽屉变成完整 gateway 管理台 |
| proxy handler | `packages/server/src/routes/hermes/proxy-handler.ts` | `resolveUpstream``SSE_EVENTS_PATH``streamSSE``/v1/runs` | 路由改写、SSE 拦截、upstream 错误规整 | 不把全量 proxy catch-all 暴露给浏览器 |
| skills 来源 | `packages/server/src/controllers/hermes/skills.ts` | `.bundled_manifest``.hub/lock.json``.usage.json``source``modified` | skill 来源与生成/安装/本地分类 | 不复制完整 skill 管理台 |
快速定位命令:
```bash
cd /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/hermes-web-ui-0.5.18
rg -n "ChatRunSocket|resumeSession|handleRun|dequeueNextQueuedRun|handleAbort|/v1/responses|applyResponseStreamEvent|response\\.output_text\\.delta|response\\.output_item\\.done|response\\.completed|HermesSessionRow|startRunViaSocket|gateway-manager" packages/server/src packages/client/src
```
---
## 6. RuntimeEvent 合同
mnote-web BFF 对前端暴露的事件应稳定为 `mnote.hermes_runtime_event.v1`
最小事件集:
```json
{ "event": "run.started", "sessionId": "mnote_doc_1_trace_1", "runId": "run_1", "traceId": "trace_1" }
```
```json
{ "event": "message.delta", "sessionId": "mnote_doc_1_trace_1", "runId": "run_1", "delta": "当前页", "traceId": "trace_1" }
```
```json
{ "event": "tool.started", "sessionId": "mnote_doc_1_trace_1", "runId": "run_1", "toolCallId": "call_1", "toolName": "mnote.page.get", "traceId": "trace_1" }
```
```json
{ "event": "tool.completed", "sessionId": "mnote_doc_1_trace_1", "runId": "run_1", "toolCallId": "call_1", "toolName": "mnote.page.get", "summary": "读取当前页面", "auditId": "audit_1", "traceId": "trace_1" }
```
```json
{ "event": "run.completed", "sessionId": "mnote_doc_1_trace_1", "runId": "run_1", "output": "总结文本", "usage": { "inputTokens": 0, "outputTokens": 0 }, "traceId": "trace_1" }
```
```json
{ "event": "run.failed", "sessionId": "mnote_doc_1_trace_1", "runId": "run_1", "code": "hermes_client_upstream_error", "message": "Hermes upstream 返回错误", "traceId": "trace_1" }
```
```json
{ "event": "abort.started", "sessionId": "mnote_doc_1_trace_1", "runId": "run_1", "traceId": "trace_1" }
```
```json
{ "event": "abort.completed", "sessionId": "mnote_doc_1_trace_1", "runId": "run_1", "synced": true, "traceId": "trace_1" }
```
如果上游是 `/v1/runs/{run_id}/events`BFF 只做字段规整;如果后续试验 `/v1/responses`BFF 负责把 `response.*` 映射为上述 RuntimeEvent。前端不直接依赖上游原始事件格式。
---
## 7. 下一阶段 checklist
### A. Runtime 状态注册表
- [x]`mnote-web` 建立内存级 `sessionId -> active run state` registry。
- [x] 记录 `sessionId``runId``profile``documentId``traceId``status``startedAt``lastEventAt`
- [x] registry 只保存运行态和最近事件摘要,不保存完整聊天历史。
- [x] 服务重启后允许 registry 丢失,但页面必须能从 Hermes session detail 恢复已完成消息。
验收标准:
- [x] 页面刷新时,若 run 仍在 registry 中,前端能看到 `running/tool_calling` 状态。
- [x] 关闭页面再打开,不会把 mnote local storage 当作聊天真相。
### B. Resume
- [x] 增加 `POST /api/hermes/client/sessions/{session_id}/resume` 或等价同源接口。
- [x] 返回 Hermes session detail 中的 messages,并附带 registry 中当前运行态。
- [x] 若 session 不在 registry 中,只返回 Hermes 已持久化状态。
验收标准:
- [x] run 过程中刷新页面,UI 能恢复 run 状态或明确显示“正在同步 Hermes 状态”。
- [x] run 完成后刷新页面,消息来自 Hermes session detail / export,不来自 mnote 自建聊天表。
验证证据:
- `cargo test -p mnote-web hermes_client_ -- --nocapture`:通过 9 个 Hermes client 单测,覆盖 registry 不保存 `messages`、tool event 摘要和 `/resume` 返回 runtime。
- `MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-smoke.js`:通过。13000 是本轮临时启动的新 `mnote-web`,用于避免打断当前 3000;验证后已关闭。
- 当前 3000 运行的是本轮修改前的旧 `mnote-web` 二进制,`POST /api/hermes/client/sessions/{id}/resume` 返回 404;需要重启 3000 后再用同一 smoke 复验主入口。
### C. Queue
- [x] 同一 session 已有 active run 时,后续输入进入后端 queue。
- [x] queue item 只保存待发送 input、profile、context snapshot 摘要和 trace,不保存长期聊天真相。
- [x] 当前 run 结束后自动触发下一条。
- [x] 前端显示 queue length 和可取消项。
验收标准:
- [x] 连续发送两条消息时,第二条显示 queued,而不是并发打到同一 Hermes session。
- [x] 取消 queued item 后,不触发 Hermes run。
验证证据:
- `cargo test -p mnote-web hermes_client_ -- --nocapture`:通过 12 个 Hermes client 单测,新增覆盖 active run 时第二条入队、queue item 不返回完整 `messages/pageContext`、后端取消 queued item、终态后用 mock Hermes upstream 自动启动下一条 queued run。
- `MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-queue-smoke.js`:通过。验证连续发送两条消息时第二条走 `queued` 响应,UI 显示队列长度,并能从 Runtime 面板取消 queued item。
- `MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-smoke.js`:通过。确认 resume / tool / 完成态基础链路未被 queue 改动破坏。
- 13000 是本轮临时启动的新 `mnote-web`,验证后已关闭;当前 3000 仍需重启后复验。
### D. Abort
- [x] abort 由 BFF 统一执行,调用 Hermes `/v1/runs/{run_id}/stop` 或中断当前 upstream request。
- [x] abort 前后发出 `abort.started``abort.completed`
- [x] abort 后清理 registry 状态,并处理队列后续项。
验收标准:
- [x] 点击停止后,UI 不再继续追加该 run 的 assistant delta。
- [x] 若 abort 后有队列项,后端按顺序继续处理或明确要求用户确认。
验证证据:
- `cargo test -p mnote-web hermes_client_ -- --nocapture`:通过 13 个 Hermes client 单测,新增覆盖 abort 响应返回 `abort.started/abort.completed`,并在 abort 后继续处理 queued run。
- 临时 `mnote-web``MNOTE_WEB_HERMES_UPSTREAM_URL=http://127.0.0.1:3999` 启动后,执行 `MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-runtime-controls-smoke.js`:通过。验证停止 run 后 UI 状态进入 `aborted`,并且后续 `message.delta` 不再追加到聊天区。
- `MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-queue-smoke.js``MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-smoke.js`:通过。确认 queue / resume 基础链路未被 abort 改动破坏。
- 13000 是本轮临时启动的新 `mnote-web`,验证后已关闭;当前 3000 仍需重启后复验。
### E. Event normalization
- [x] mnote-web 将 Hermes 上游事件规整为 `mnote.hermes_runtime_event.v1`
- [x] 前端只消费标准事件,不直接分支处理多套 Hermes 原始事件。
- [x] tool event 展示独立于 assistant 文本。
- [x] 当前 UI 已能在聊天区输出 `工具` 消息并显示工具名,例如 `mnote.page.get`;下一阶段必须升级为按 `toolCallId` 合并的 tool event card。
- [x] `tool.started` 创建或更新同一个工具卡,显示工具名、运行中状态、参数摘要。
- [x] `tool.completed` 原地更新同一个工具卡,显示完成状态、结果摘要、audit/trace id。
- [x] `tool.failed` 原地更新同一个工具卡,显示失败状态、错误码和可复制详情。
- [x] Runtime 页的最近 tool call 摘要继续保留,但不能替代聊天区内联工具卡。
验收标准:
- [x] `message.delta``tool.started``tool.completed``run.completed``run.failed` 均有 smoke 覆盖。
- [x] `tool.started -> tool.completed` 不产生两条互不关联的纯文本工具消息;同一 `toolCallId` 在 UI 中表现为同一张工具卡状态变化。
- [x] 工具卡至少展示 `toolName``toolCallId`、状态、参数摘要、结果摘要、`traceId/auditId`
- [x] tool result 不混入正文编辑器,不写入 page body,除非 Hermes 明确调用 `mnote.page.save` 等写工具。
验证证据:
- `MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-smoke.js`:通过。smoke 发送同一 `toolCallId=call_smoke_page_get``tool.started -> tool.completed`,断言聊天区只有 1 张 completed 工具卡;同时发送 `toolCallId=call_smoke_page_save``tool.started -> tool.failed`,断言 failed 工具卡显示 `permission_denied`
- `MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-runtime-controls-smoke.js``MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-queue-smoke.js`:通过。确认工具卡改动未破坏 abort / queue。
- `cargo test -p mnote-web hermes_client_ -- --nocapture`:通过 14 个 Hermes client 单测,新增覆盖 `assistant_message``tool.failed` 等上游事件被规整为 `mnote.hermes_runtime_event.v1`
- mnote-web `/client/events/{run_id}` 输出 `event: <canonical>``schemaVersion: "mnote.hermes_runtime_event.v1"`;前端消费路径只处理 `message.delta``run.completed``run.failed``run.aborted``tool.*` 标准事件名。
### F. Gateway manager
- [x] BFF 能检查当前 Hermes gateway health。
- [x] BFF 能识别 profile 对应 gateway / model 状态。
- [x] 缺 model/default 或 API key 时,错误提示指向 Hermes 设置,而不是只显示 502。
验收标准:
- [x] `hermes_client_upstream_error` 场景能显示具体修复建议,例如“当前 profile 缺 model.default”。
- [x] profile/skill/settings API 不再错误代理到 Hermes gateway 非 `/v1/*` 路径。
验证证据:
- `mnote-web` 新增 `GET /api/hermes/client/gateway/health?profile=<name>`,只做只读探测,不启动/停止 gateway;返回 `gateway.configured/upstream/status/httpStatus``profile.modelDefault/provider/apiKeyConfigured``suggestions`
- `profile_detail_payload()` 与 fallback profiles 会从 Hermes profile `config.yaml` 读取 `model.default``model.provider`、provider `api_key/key_env` 摘要,但不返回 API key 原文。
- `upstream_error()``hermes_client_upstream_error` 增加 Hermes 设置修复建议;当上游错误正文包含 `model.default``API key``profile/provider` 等线索时,错误 message 会指向 Hermes 设置。
- Runtime 面板增加 gateway/profile 状态区;页面请求失败时前端显示后端 `message`,不再只显示错误 code。
- `cargo test -p mnote-web hermes_client_ -- --nocapture`:通过 17 个 Hermes client 单测,新增覆盖 gateway 未配置、profile 缺 model/API key、`hermes_client_upstream_error` 错误建议。
- 临时 `mnote-web``MNOTE_WEB_HERMES_UPSTREAM_URL=http://127.0.0.1:3999` 启动到 `127.0.0.1:13000` 后,`task-hermes-page-ai-smoke.js``task-hermes-page-ai-runtime-controls-smoke.js``task-hermes-page-ai-queue-smoke.js` 均通过;验证后已关闭 13000。
- `MNOTE_UI_BASE_URL=http://127.0.0.1:13000 node scripts/task-hermes-page-ai-agent-skill-smoke.js`:通过。确认新增 gateway health 请求不影响 agent/profile 选择、SOUL.md 保存、skill toggle 与 run profile 透传。
### G. `/v1/responses` 评估,不默认切换
- [x] 增加只读 spike 文档或测试,验证当前 Hermes gateway 的 `/v1/responses stream=true` 事件格式。
- [x] 明确 `/v1/responses` 是否能在不迁移会话真相的前提下复用 Hermes session。
- [x] 若不能保持 Hermes session 真相,则不得进入默认页面 AI 主链。
验收标准:
- [x] 有明确结论:继续 `/v1/runs`,或另开设计稿说明为什么改变会话真相。
- [x] 任何 `/v1/responses` 实验都不得把 mnote Convex / page aggregate 变成聊天消息真相。
只读 spike 结论:
- 参考 `hermes-web-ui-0.5.18/packages/server/src/services/hermes/chat-run-socket.ts`,其 `/v1/responses` 主链在发送前从后端 DB 组装 `conversation_history`,随后设置 `body.stream = true``body.store = false`,再请求 `${upstream}/v1/responses`
- 同一文件的 `applyResponseStreamEvent()` 表明 responses 事件格式主要是 `response.created``response.output_text.delta``response.output_item.added``response.output_item.done``response.completed``response.failed`,由上层 BFF 映射为 `run.started``message.delta``tool.started``tool.completed``run.completed``run.failed`
- `response.output_item.done``function_call` 会被映射为 `tool.started``function_call_output` 会被映射为 `tool.completed`。这对 mnote 的 tool card 状态机有参考价值,但不改变主链。
- 本机只读探测 `http://127.0.0.1:3999/health``/v1/models``OPTIONS /v1/responses` 时,当前没有 gateway 监听,无法取得 live `/v1/responses stream=true` 事件样本;因此本轮不把 live event capture 写成验收依据。
- 基于参考实现,`/v1/responses store=false + conversation_history` 的顺滑体验依赖上层 BFF/SQLite 自建 chat session 真相。除非后续确认 Hermes gateway 支持把 `/v1/responses` 直接绑定到 Hermes session storage,否则 mnote 不应把它切成默认主链。
当前决策:
> **继续 `/v1/runs` 作为页面 AI 默认主链;`/v1/responses` 只作为事件标准化与 tool card 的参考实现。若未来要切换,必须另开设计稿证明 Hermes session 仍是 AI 会话真相,或明确批准迁移会话真相。**
---
## 8. 非目标
- 不在本阶段引入 ACP 主链。
- 不在本阶段把页面 AI 主链切到 `/v1/responses store=false`
- 不在 mnote 建 Hermes Web UI 那样的 SQLite chat DB。
- 不把 Convex 作为 AI 会话真相。
- 不把页面 AI 抽屉扩成完整 Hermes 管理台。
- 不让 mnote plugin 直接写 Convex;写入仍回到 Rust runtime / kernel。
---
## 9. 最终验收口径
本稿完成时,应能同时成立:
- [x] 页面 AI 仍是 Hermes 页面内客户端。
- [x] Hermes 仍是 AI session/message/tool event/usage/model/profile 真相。
- [x] mnote-web 有 Runtime BFF 能力,支持 run resume、queue、abort 和事件标准化。
- [x] 页面刷新或断线不导致 active run UI 状态丢失;完成后的消息从 Hermes 恢复。
- [x] mnote 不保存完整聊天历史,只保存 mnote 业务写入结果和 audit。
- [x] `/v1/responses` 是否进入主链已有单独评估结论,且没有绕过 Hermes session 真相。
一句话:
> **补齐 Web Chat Runtime 的工程能力,但不改变“AI 会话归 Hermesmnote 事实归 Rust kernel”的长期边界。**