重构基线
This commit is contained in:
@@ -0,0 +1,439 @@
|
||||
# 7-62 [recycle] Page AI Board-first full rewrite v1
|
||||
|
||||
> 创建时间:2026-06-19
|
||||
>
|
||||
> 当前状态:`RECYCLE`
|
||||
>
|
||||
> Owner:07-ai / Agent Board bridge / Page AI shell / MNote capability plugins
|
||||
>
|
||||
> 上位依据:
|
||||
> - `ARCHITECTURE.md`
|
||||
> - `CURRENT_ARCHITECTURE.md`
|
||||
> - `design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md`
|
||||
> - `design/07-ai/done/7-38-page-ai-sidebar-runtime-owner-split-v1.md`
|
||||
> - `design/07-ai/done/7-39-page-ai-agent-selector-context-authorization-settings-v1.md`
|
||||
> - `design/07-ai/done/7-40-page-ai-context-envelope-and-run-receipt-v1.md`
|
||||
> - `design/07-ai/done/7-50-lightrag-knowledge-rag-provider-v1.md`
|
||||
> - `design/07-ai/done/7-60-page-ai-settings-ia-cleanup-v1.md`
|
||||
|
||||
> 过时原因:已由 `design/07-ai/process/7-65-opencode-webui-embed-page-ai-v1.md` 替代;Page AI 新主路径只接入 opencode 官方 runtime + 官方 WebUI。
|
||||
|
||||
## 1. 第一结论
|
||||
|
||||
当前 Page AI 继续维护 Hermes / Reasonix / Chat-only / ACP runtime / provider session / skill toggle / tool event 映射,会让 MNote 重复承担 Agent Board 已经承担的中介层职责。后续不应再“小修小补”当前 Page AI,而应完整重构为 **Board-first Page AI**:
|
||||
|
||||
```text
|
||||
MNote Page AI = 页面入口 + 上下文/权限/目标封装 + 运行态展示
|
||||
Agent Board = worker 选择 + provider 适配 + workflow 编排 + QA/review/失败回流
|
||||
ZCode/Reasonix/Codex/GenericAgent = Board worker,不直接成为 MNote Page AI provider
|
||||
```
|
||||
|
||||
重构目标不是“把 ZCode 接进 Page AI”,而是“让 Page AI 不再适配 provider”。ZCode 胜出只决定 Board 默认 worker,MNote 只调用 Board。
|
||||
|
||||
## 2. 当前问题
|
||||
|
||||
### 2.1 Page AI 责任过载
|
||||
|
||||
当前 Page AI 同时负责:
|
||||
|
||||
- agent/provider selector:Hermes / Reasonix / Chat-only。
|
||||
- ACP runtime lifecycle:session、resume、queue、event、permission。
|
||||
- provider 特化逻辑:Reasonix native-live、Hermes profile、Chat-only remote conversation。
|
||||
- skills/tools UI:MNote skills、Hermes skills、Reasonix skills 混合展示。
|
||||
- run history:MNote 本地 session、外部 provider conversation、runtime audit 混合展示。
|
||||
- 写入主路径:既有 MNote tool 写入,又有 agent 原生文件编辑。
|
||||
|
||||
这导致每新增一个 agent 或 provider 都要重复改 Page AI 前端、Rust route、session store、event parser、设置页和 smoke。
|
||||
|
||||
### 2.2 与 Agent Board 职责重复
|
||||
|
||||
Agent Board 已经具备:
|
||||
|
||||
- worker preset 与角色路由。
|
||||
- ZCode / Reasonix / Codex / GenericAgent / reviewer / QA browser worker。
|
||||
- workflow run、task group、review、QA、git gate。
|
||||
- provider event 映射、任务状态、summary、MemPalace 归档。
|
||||
- ZCode app-server / CLI fallback 链路。
|
||||
|
||||
MNote 再维护一套 provider 层会形成双中介,长期 bug 面大于收益。
|
||||
|
||||
## 3. 新系统边界
|
||||
|
||||
### 3.1 MNote Page AI 只保留四件事
|
||||
|
||||
1. **上下文采集**:当前页、选区、打开资源、页面标题、rootUri、workspaceId、sourceKind、Page Aggregate snapshot。
|
||||
2. **权限与目标**:allowed roots、write/read policy、当前目标文件、是否允许修改真实文件。
|
||||
3. **任务入口**:选择 worker / workflow / intent,提交 Board run。
|
||||
4. **可视化回放**:展示 Board run/task/group 状态、事件、summary、文件变更提示、QA 截图链接。
|
||||
|
||||
### 3.2 Agent Board 承担中介层
|
||||
|
||||
Board 负责:
|
||||
|
||||
- provider 适配:ZCode / Reasonix / Codex / future agents。
|
||||
- worker 选择:developer / reviewer / qa / designer / researcher / workflow。
|
||||
- workflow:快速编辑、问答、bug 修复、功能开发、QA 验证、review gate。
|
||||
- run 状态:running / blocked / failed / complete。
|
||||
- 事件:file_read / file_edit / command / command_output / screenshot / summary。
|
||||
- 失败回流与人工介入。
|
||||
|
||||
### 3.3 MNote skills / plugins 重新定义
|
||||
|
||||
MNote 的 skill/plugin 不再是 “Hermes/Reasonix profile 内的技能开关”,而是 Board 可消费的 **MNote capability manifest**:
|
||||
|
||||
```text
|
||||
mnote.current_page.read
|
||||
mnote.selection.read
|
||||
mnote.open_resources.snapshot
|
||||
mnote.allowed_roots.describe
|
||||
mnote.lightrag.query
|
||||
mnote.reference.open
|
||||
mnote.page_aggregate.snapshot
|
||||
mnote.local_file.receipt
|
||||
```
|
||||
|
||||
这些 capability 由 MNote 生成 manifest/envelope,Board worker 通过任务 prompt、MCP 或后续 bridge tool 使用。MNote 不再为每个 worker 维护单独 skill UI。
|
||||
|
||||
## 4. 新 Page AI 信息架构
|
||||
|
||||
### 4.1 顶层只保留四个页签
|
||||
|
||||
| 页签 | 作用 | Owner |
|
||||
| --- | --- | --- |
|
||||
| `对话/任务` | 用户输入、当前目标、提交 Board run | MNote |
|
||||
| `工作流` | worker / workflow 选择、执行策略 | Agent Board |
|
||||
| `运行` | Board run/task/group 状态、事件、summary | Agent Board |
|
||||
| `上下文` | 当前页、选区、资源、权限、LightRAG capability | MNote |
|
||||
|
||||
删除旧一级页签:
|
||||
|
||||
- `Hermes`
|
||||
- `Reasonix`
|
||||
- `Chat-only`
|
||||
- `Runtime`
|
||||
- `高级`
|
||||
- provider-specific skills 面板
|
||||
|
||||
如确需保留,只能放在 debug/legacy 折叠区,不作为默认主链。
|
||||
|
||||
### 4.2 默认入口
|
||||
|
||||
默认按钮不再是“发送给 Reasonix/Hermes”,而是:
|
||||
|
||||
```text
|
||||
交给 Agent Board
|
||||
```
|
||||
|
||||
默认配置:
|
||||
|
||||
```text
|
||||
projectId = mnote 项目
|
||||
workflow = builtin-page-ai-developer-direct
|
||||
worker = Board direct workflow developer(现为 zcode-deepseek-flash)
|
||||
writePolicy = 按 MNote allowed roots
|
||||
```
|
||||
|
||||
## 5. 接口契约
|
||||
|
||||
### 5.1 MNote → Board envelope
|
||||
|
||||
新增 `MNoteBoardTaskEnvelope`:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "mnote.page_ai.board_task.v1",
|
||||
"intent": "ask|edit|fix|feature|qa|review|custom_workflow",
|
||||
"message": "用户原始输入",
|
||||
"workspaceId": "...",
|
||||
"sourceKind": "local-folder",
|
||||
"rootUri": "file:///...",
|
||||
"documentId": "...",
|
||||
"pageTitle": "...",
|
||||
"primaryTarget": {
|
||||
"kind": "markdown_file",
|
||||
"relativePath": "docs/page.md",
|
||||
"absolutePath": "/.../docs/page.md"
|
||||
},
|
||||
"selection": {
|
||||
"text": "...",
|
||||
"range": null
|
||||
},
|
||||
"contextRefs": ["current_page", "selection", "active_editor", "folder"],
|
||||
"allowedRoots": [
|
||||
{ "rootUri": "file:///...", "permission": "write" }
|
||||
],
|
||||
"capabilities": [
|
||||
"mnote.current_page.read",
|
||||
"mnote.allowed_roots.describe",
|
||||
"mnote.lightrag.query"
|
||||
],
|
||||
"writePolicy": {
|
||||
"allowFileWrite": true,
|
||||
"requireHumanApproval": false,
|
||||
"forbidMnoteInternalStateWrite": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Board API 选择
|
||||
|
||||
MNote 服务端先封装 Board API,不让前端直连 `3901`。
|
||||
|
||||
新增 MNote routes:
|
||||
|
||||
```text
|
||||
GET /api/page-ai/board/status
|
||||
GET /api/page-ai/board/workers
|
||||
GET /api/page-ai/board/workflows
|
||||
POST /api/page-ai/board/runs
|
||||
GET /api/page-ai/board/runs/:id
|
||||
POST /api/page-ai/board/runs/:id/cancel
|
||||
```
|
||||
|
||||
内部对应 Board:
|
||||
|
||||
```text
|
||||
GET http://127.0.0.1:3901/api/health
|
||||
GET http://127.0.0.1:3901/api/workers/catalog?projectId=<mnote>
|
||||
GET http://127.0.0.1:3901/api/workflow-presets?projectId=<mnote>
|
||||
POST http://127.0.0.1:3901/api/workflow-runs
|
||||
GET http://127.0.0.1:3901/api/workflow-runs/:id
|
||||
```
|
||||
|
||||
优先使用 `/api/workflow-runs`,而不是 `/api/controller/message`,因为 Page AI 需要可预测的 workflow/worker 选择和 run id。
|
||||
|
||||
### 5.4 Board 需要补给 MNote 的接口
|
||||
|
||||
这不是单向的“ MNote 适配 Board ”,而是双向协议。为了让 Page AI 真正瘦身,Board 侧还需要补出一组面向 MNote 的稳定接口:
|
||||
|
||||
#### A. Page AI envelope 预检
|
||||
|
||||
```text
|
||||
POST /api/page-ai/envelopes/validate
|
||||
```
|
||||
|
||||
作用:在真正创建 run 前,校验 envelope 是否满足 workflow/worker 的最小要求,返回:
|
||||
|
||||
- 缺失的字段。
|
||||
- 是否需要 worker 具备 vision / browser / filesystem / multimodal。
|
||||
- 是否需要人工确认。
|
||||
- 推荐 workflowId / workerPresetId。
|
||||
|
||||
这样 MNote 可以在 UI 层先提示“当前上下文不够”或“建议切换到 QA workflow”,避免无效提交。
|
||||
|
||||
#### B. Page AI envelope 到 workflow 的映射
|
||||
|
||||
```text
|
||||
POST /api/page-ai/envelopes/route
|
||||
```
|
||||
|
||||
作用:Board 根据 envelope 自动选择 workflow / worker / reviewer / QA 路线,返回最终路由结果:
|
||||
|
||||
- workflowId。
|
||||
- workerPresetId。
|
||||
- groupId 或 runId。
|
||||
- 是否需要用户二次确认。
|
||||
- 预估阶段序列。
|
||||
|
||||
这能让 MNote 不再内置 worker 选择逻辑,只保留“意图 + 上下文”。
|
||||
|
||||
#### C. Run 级事件流
|
||||
|
||||
```text
|
||||
GET /api/workflow-runs/:id/events
|
||||
GET /api/workflow-runs/:id/node-runs/:nodeRunId/events
|
||||
```
|
||||
|
||||
作用:MNote 不只看最终 run summary,而是直接消费 Board 的结构化事件流,渲染:
|
||||
|
||||
- 当前节点。
|
||||
- 进度阶段。
|
||||
- file_read / file_edit / command / screenshot / artifact。
|
||||
- block / retry / resume 原因。
|
||||
|
||||
如果 Board 未来提供 WS/SSE,这两条可退化为 snapshot/polling 兼容层,但 MNote 默认应面向事件流抽象,而不是 provider 私有日志。
|
||||
|
||||
#### D. Run receipt / artifact receipt
|
||||
|
||||
```text
|
||||
GET /api/workflow-runs/:id/receipt
|
||||
```
|
||||
|
||||
作用:返回统一的运行收据,便于 MNote 做历史展示和刷新同步:
|
||||
|
||||
- `runId` / `projectId` / `workflowId`。
|
||||
- `workerPresetId` / `workerName`。
|
||||
- `summary` / `status` / `completedAt`。
|
||||
- `artifactRefs`。
|
||||
- `targetSnapshot` / `allowedRoots` / `capabilities`。
|
||||
|
||||
这会让 Page AI history 直接依赖 Board receipt,而不是再保留一套 Hermes session 语义。
|
||||
|
||||
#### E. Board 侧能力目录
|
||||
|
||||
```text
|
||||
GET /api/workers/catalog?projectId=<mnote>
|
||||
GET /api/workflow-presets?projectId=<mnote>
|
||||
GET /api/projects/:id/capabilities
|
||||
```
|
||||
|
||||
作用:让 MNote 能展示“Board 当前能做什么”,而不是自己猜 worker。尤其是:
|
||||
|
||||
- 默认 developer 是谁。
|
||||
- 哪些 worker 具备 vision/browser。
|
||||
- 哪些 workflow 可用于编辑、QA、review、research。
|
||||
|
||||
#### F. Board 侧回写钩子
|
||||
|
||||
```text
|
||||
POST /api/workflow-runs/:id/report
|
||||
POST /api/workflow-runs/:id/artifacts
|
||||
POST /api/workflow-runs/:id/feedback
|
||||
```
|
||||
|
||||
作用:让 MNote 能把 UI 侧额外信息回写给 Board:
|
||||
|
||||
- 浏览器截图。
|
||||
- 用户补充说明。
|
||||
- 失败后的重新定界信息。
|
||||
- 页面刷新后的 targetSnapshot 变化。
|
||||
|
||||
这样 Board 的 workflow 才能逐步成为真正的 Page AI 控制面,而不是一次性任务提交器。
|
||||
|
||||
### 5.5 Board → MNote 展示模型
|
||||
|
||||
MNote 只归一化 Board 状态,不解析 provider 私有事件:
|
||||
|
||||
```text
|
||||
Board run -> Page AI run card
|
||||
Workflow node -> stage timeline
|
||||
Task event -> visible event row
|
||||
Task summary -> assistant final message
|
||||
Artifact refs -> screenshot/link/file changed chips
|
||||
```
|
||||
|
||||
MNote 不再关心事件来自 ZCode、Reasonix 还是 Codex。
|
||||
|
||||
## 6. 删除与迁移边界
|
||||
|
||||
### 6.1 默认主链删除
|
||||
|
||||
以下能力退出默认主链:
|
||||
|
||||
- Page AI 前端 `pageAiAcpRuntime` 作为主选择器。
|
||||
- Reasonix quick controls 作为默认控件。
|
||||
- Hermes profile select 作为默认控件。
|
||||
- Chat-only provider conversation 作为默认路径。
|
||||
- MNote 内部 provider-specific run resume。
|
||||
- provider-specific skill source 切换。
|
||||
|
||||
### 6.2 Legacy 保留原则
|
||||
|
||||
旧链路只允许:
|
||||
|
||||
- debug/internal route。
|
||||
- 历史 session 读取/导出。
|
||||
- 明确 fallback:Board 不可用时提示用户,而不是自动静默切回 Reasonix。
|
||||
|
||||
不允许:
|
||||
|
||||
- 新功能继续写进 `sidebar-page-ai-runtime.js` 的 provider 分支。
|
||||
- 新增 Hermes/Reasonix 专属 UI 作为默认交互。
|
||||
- 新增 MNote 自己的 provider adapter。
|
||||
|
||||
## 7. 实施计划
|
||||
|
||||
### Phase A:Board bridge 与新 shell 并行上线(已完成)
|
||||
|
||||
- [x] 新增 `page_ai_board.rs`,封装 Board status/workers/workflows/runs。
|
||||
- [x] 前端默认路径已切为 Board-first run 提交和状态展示;当前以 `sidebar-page-ai-runtime.js` 内 Board-first 分支承接,后续可继续拆到独立 runtime 文件。
|
||||
- [x] Board 侧补齐 `envelopes/validate`、`envelopes/route`、`runs/:id/events`、`runs/:id/receipt`、`projects/:id/capabilities` 稳定接口。
|
||||
- [x] 当前 Page AI 默认入口切到 Board shell。
|
||||
- [x] 旧 provider 入口默认隐藏,仅通过 legacy/debug 边界保留。
|
||||
- [x] smoke:从页面提交任务,Board 创建 workflow run,Page AI 能显示 run id、complete、summary。
|
||||
|
||||
### Phase B:worker / workflow 选择(已完成默认链路)
|
||||
|
||||
- [x] MNote bridge 提供 Board workers/workflows catalog API,默认 UI 先收口为 Board direct workflow。
|
||||
- [x] 默认选中 Board direct workflow developer:`zcode-deepseek-flash`。
|
||||
- [ ] 后续增强:在工作流页开放更多 built-in workflow 选择。
|
||||
- [x] smoke:ZCode developer 执行最小文件编辑任务,MNote 页面通过 watcher 刷新。
|
||||
|
||||
### Phase C:MNote capability manifest(已完成默认 envelope)
|
||||
|
||||
- [x] 定义并随 `mnote.page_ai.board_task.v1` envelope 下发 MNote capabilities。
|
||||
- [x] 把当前页/选区/allowed roots/LightRAG/source registry 统一注入 Board input。
|
||||
- [x] 默认路径收口为 capability manifest;旧 provider skill 面板隐藏为 legacy/debug。
|
||||
- [x] smoke:Board worker 能看到 primary target 与 allowed roots,并只在授权目录内改文件。
|
||||
|
||||
### Phase D:事件与 artifact 回放(后续增强)
|
||||
|
||||
- [ ] Page AI 展示 Board node timeline。
|
||||
- [ ] 展示 task events:file read/edit、command、command output、QA screenshot。
|
||||
- [ ] 支持打开 Board project/run/task 链接。
|
||||
- [ ] smoke:功能开发 workflow 完成后,Page AI 能看到 QA 截图 artifact 和 final summary。
|
||||
|
||||
### Phase E:旧链路下线(默认主链已下线,代码删除后续)
|
||||
|
||||
- [x] 默认 UI 隐藏 Hermes/Reasonix/Chat-only provider 入口,Board-first shell 成为默认主链。
|
||||
- [ ] 后续清理:`hermes_client.rs` 中 Page AI provider-specific run 创建逻辑迁入 legacy/debug 边界。
|
||||
- [ ] 后续清理:更新旧设计归档默认主链说明为 legacy。
|
||||
- [x] smoke:默认 Page AI Board-first 代码路径不再依赖 Reasonix/Hermes provider 即可运行。
|
||||
|
||||
## 8. 验收标准
|
||||
|
||||
### 8.1 功能验收
|
||||
|
||||
- Page AI 默认提交创建 Board workflow run。
|
||||
- 默认 worker 来自 Board,而不是 MNote 写死 Reasonix/Hermes。
|
||||
- ZCode 作为 Board 默认 developer 时,Page AI 不需要任何 ZCode 专属代码即可使用。
|
||||
- Board 不可用时,Page AI 明确显示“Agent Board 不可用”,不伪装为 provider 失败。
|
||||
- 文件写入通过真实文件编辑完成,MNote watcher/Page Aggregate 刷新页面。
|
||||
|
||||
### 8.2 维护性验收
|
||||
|
||||
- 新 provider 只需要 Agent Board 适配,不改 MNote Page AI provider 分支。
|
||||
- Page AI 前端默认路径不再包含 `reasonix/hermes/chat_only` 三套选择逻辑。
|
||||
- MNote skills/plugins 只表达能力,不表达 provider。
|
||||
- Rust route 中 Board bridge 与 Hermes legacy route 分离。
|
||||
|
||||
### 8.3 浏览器 smoke
|
||||
|
||||
- 登录 `http://localhost:3000/auth` 测试账号。
|
||||
- 打开 local-folder Markdown 页面。
|
||||
- 打开 Page AI。
|
||||
- 选择默认 Board workflow。
|
||||
- 提交“总结当前页并提出一个最小改进建议”。
|
||||
- 页面显示 Board run id、worker、阶段、最终 summary。
|
||||
- 再提交“在当前文件末尾追加一行测试内容”,确认真实 `.md` 文件变化,页面刷新可见。
|
||||
|
||||
## 9. 风险与处理
|
||||
|
||||
| 风险 | 处理 |
|
||||
| --- | --- |
|
||||
| Board 服务不可用 | Page AI 显示 Board health 错误与启动提示,不自动回退旧 provider |
|
||||
| Board workflow 太重 | 默认使用 minimal workflow,完整 QA workflow 由用户选择 |
|
||||
| Page AI 历史 session 断裂 | 旧 session 只读保留,新增 run 以 Board run 为历史主键 |
|
||||
| Board 改文件后页面不同步 | 依赖现有 watcher/Page Aggregate;缺口作为 05-editor-mainline bug 处理 |
|
||||
| MNote capability 被 worker 忽略 | Board prompt/template 中明确 envelope schema 与 allowed roots,后续再补 MCP bridge |
|
||||
|
||||
## 10. 立即决策
|
||||
|
||||
本稿确认后,后续实现不再以“接入 ZCode provider”为任务拆分,而以“Page AI Board-first full rewrite”为主线拆分。第一批代码应直接新增 Board bridge 和新 Page AI shell,而不是继续在旧 `sidebar-page-ai-runtime.js` 中叠加 provider 分支。
|
||||
|
||||
|
||||
## 11. 完成记录(2026-06-19)
|
||||
|
||||
- MNote 新增 `/api/page-ai/board/*` bridge,浏览器不直连 Board `3901`。
|
||||
- Agent Board 新增 Page AI envelope validate/route/events/receipt/capabilities 接口,并新增 `builtin-page-ai-developer-direct` workflow。
|
||||
- Page AI 默认发送 `mnote.page_ai.board_task.v1` envelope,默认 workflow 为 `builtin-page-ai-developer-direct`,worker 为 ZCode developer。
|
||||
- MNote capability 默认随 envelope 下发:`mnote.current_page.read`、`mnote.selection.read`、`mnote.open_resources.snapshot`、`mnote.allowed_roots.describe`、`mnote.lightrag.query`、`mnote.reference.open`、`mnote.page_aggregate.snapshot`、`mnote.local_file.receipt`。
|
||||
- 浏览器 smoke `scripts/task762-page-ai-board-first-smoke.js` 已验证:Page AI 可创建 Board run、可见 shell 显示 Agent Board、capability 已加载、ZCode 真实编辑当前 Markdown 文件、磁盘与编辑器可见内容同步。
|
||||
|
||||
验证命令:
|
||||
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/rust && cargo check -p mnote-web
|
||||
cd /mnt/Data1T/ai-agent-board && npm run build:server
|
||||
cd /mnt/Data1T/mnote && node scripts/task762-page-ai-board-first-smoke.js
|
||||
```
|
||||
@@ -0,0 +1,403 @@
|
||||
# 7-63 [recycle] Page AI Board-first product shell v1
|
||||
|
||||
> 创建时间:2026-06-20
|
||||
>
|
||||
> 当前状态:`RECYCLE`
|
||||
>
|
||||
> Owner:07-ai / Page AI product shell / Agent Board MNote runtime / session history
|
||||
>
|
||||
> 上位依据:
|
||||
> - `design/07-ai/done/7-62-page-ai-board-first-full-rewrite-v1.md`
|
||||
> - `design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md`
|
||||
> - `design/07-ai/done/7-38-page-ai-sidebar-runtime-owner-split-v1.md`
|
||||
> - `design/07-ai/done/7-40-page-ai-context-envelope-and-run-receipt-v1.md`
|
||||
> - `design/07-ai/done/7-60-page-ai-settings-ia-cleanup-v1.md`
|
||||
|
||||
> 过时原因:已由 `design/07-ai/process/7-65-opencode-webui-embed-page-ai-v1.md` 替代;Page AI 新主路径只接入 opencode 官方 runtime + 官方 WebUI。
|
||||
|
||||
## 1. 当前结论
|
||||
|
||||
7-62 已经证明 Board-first 主链能跑:MNote Page AI 可以通过 Agent Board 创建 run,可以把 MNote capability/envelope 下发给 worker,`mnote-page-ai-zcode` 能回复,也能真实编辑当前 Markdown 文件并触发编辑器刷新。
|
||||
|
||||
但这还不是合格的页面 AI。当前问题不是“再给用户更多 Board 选择”,而是 **MNote 页面 AI 需要自己的产品壳**:
|
||||
|
||||
```text
|
||||
MNote Page AI Product Shell
|
||||
= 聊天体验 + 当前页上下文 + MNote 白名单 worker/workflow + worker 内模型选择 + session/history + run detail
|
||||
|
||||
Agent Board MNote Runtime
|
||||
= MNote 专用 worker + MNote 专用 workflow + provider/model 执行 + receipt/event 持久化
|
||||
```
|
||||
|
||||
Page AI 不是 Agent Board 控制台的缩小版。默认 UI 不应该暴露 Board 全量 worker、全量 workflow、provider adapter 或通用任务报告。用户只需要面对少量 MNote 语义清楚的选择。
|
||||
|
||||
## 2. 要解决的四个问题
|
||||
|
||||
### 2.1 Worker 怎么选
|
||||
|
||||
Page AI 只能选择 MNote Page AI 白名单 worker。当前默认只有:
|
||||
|
||||
```text
|
||||
workerPresetId = mnote-page-ai-zcode
|
||||
name = MNote 页面 AI · ZCode
|
||||
surface = mnote-page-ai
|
||||
capabilities = text, repo-edit, terminal, mnote-capability-envelope, local-markdown-edit
|
||||
```
|
||||
|
||||
不暴露 Board 全量 worker catalog。Reasonix、Codex、ZCode、QA worker 都是 Board 内部 worker 类型,不直接成为 MNote 页面用户的选择项。后续如果需要新增 worker,必须在代码中显式登记为 `surface=mnote-page-ai`,同时补齐:
|
||||
|
||||
- 用户可见名称。
|
||||
- 适合场景。
|
||||
- 允许模型档位。
|
||||
- 权限能力。
|
||||
- smoke 验收。
|
||||
|
||||
当白名单只有一个 worker 时,UI 不显示“可切换 worker”的伪入口,只显示当前 worker 和模型档位。
|
||||
|
||||
### 2.2 模型怎么改
|
||||
|
||||
模型选择挂在特定 MNote worker 下,不做 provider picker:
|
||||
|
||||
```text
|
||||
workerPresetId = mnote-page-ai-zcode
|
||||
modelOverride = zcode-default | zcode-fast | zcode-strong
|
||||
```
|
||||
|
||||
UI 展示为 worker chip 旁的 model chip,例如:
|
||||
|
||||
```text
|
||||
MNote 页面 AI · ZCode / 默认
|
||||
```
|
||||
|
||||
用户可以切换模型档位,但不能直接选择 provider。MNote 不重新维护 Hermes/Reasonix/Codex/ZCode provider adapter;provider 和 credential 仍归 Board。
|
||||
|
||||
### 2.3 Workflow 怎么选
|
||||
|
||||
Page AI 只能选择 MNote Page AI 白名单 workflow。当前默认只有:
|
||||
|
||||
```text
|
||||
workflowId = builtin-mnote-page-ai-chat
|
||||
name = MNote 页面 AI
|
||||
surface = mnote-page-ai
|
||||
```
|
||||
|
||||
该 workflow 覆盖默认聊天、当前页轻编辑、当前页总结、当前页问答。通用 Board workflow 不出现在 Page AI picker 中。
|
||||
|
||||
后续确实需要时,再通过代码加入特定 MNote workflow:
|
||||
|
||||
| Workflow | 加入条件 | 默认 UI |
|
||||
| --- | --- | --- |
|
||||
| `builtin-mnote-page-ai-chat` | 已有默认主链 | 默认启用 |
|
||||
| `builtin-mnote-page-ai-edit` | 需要更明确的编辑阶段和 diff/receipt | 加入白名单后显示 |
|
||||
| `builtin-mnote-page-ai-review` | 需要当前页审阅、总结、检查 | 加入白名单后显示 |
|
||||
|
||||
复杂开发、hotfix、QA/browser workflow 不作为默认页面 AI 能力。只有当它们被改造成 MNote 专用 workflow,并明确加入白名单后,才允许显示。
|
||||
|
||||
### 2.4 Session 怎么选、怎么看历史
|
||||
|
||||
Page AI session 迁移为 Board-first session。每条 assistant 消息必须知道它来自哪个 Board run,但主聊天只显示用户需要的回答。
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "mnote.page_ai.session.v2",
|
||||
"sessionId": "...",
|
||||
"workspaceId": "...",
|
||||
"documentId": "...",
|
||||
"rootUri": "file:///...",
|
||||
"messages": [
|
||||
{ "role": "user", "content": "hi,收到请回复收到。" },
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "收到。",
|
||||
"boardRunId": "...",
|
||||
"workflowId": "builtin-mnote-page-ai-chat",
|
||||
"workerPresetId": "mnote-page-ai-zcode",
|
||||
"modelOverride": "zcode-default",
|
||||
"receiptId": "..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
历史 UI 分三层:
|
||||
|
||||
1. 会话列表:标题、最后回答摘要、状态、时间。
|
||||
2. 会话详情:聊天消息、当前页上下文、关联 run。
|
||||
3. Run detail:worker、model、workflow、timeline、changed files、receipt、失败原因。
|
||||
|
||||
短期可继续 localStorage/sessionStorage;产品化阶段必须落到 SQLite control-plane,避免刷新、跨标签和权限变化导致历史丢失。
|
||||
|
||||
## 3. 源头输出合同
|
||||
|
||||
MNote 专用 worker/workflow 必须从源头产出页面 AI 风格回答,而不是先产出 Board 任务报告再让 MNote 截断。
|
||||
|
||||
### 3.1 用户回答
|
||||
|
||||
简单 ask 的 worker 最终回答应直接是:
|
||||
|
||||
```markdown
|
||||
收到。
|
||||
```
|
||||
|
||||
当前页编辑任务的最终回答应类似:
|
||||
|
||||
```markdown
|
||||
已把当前页面中的“A”替换为“B”。
|
||||
```
|
||||
|
||||
不允许把以下内容作为主回答:
|
||||
|
||||
- `Completed`
|
||||
- `Comments`
|
||||
- `Remaining`
|
||||
- `Agent Board run 已创建`
|
||||
- 命令日志
|
||||
- 工具调用过程
|
||||
- provider 内部推理或计划
|
||||
|
||||
### 3.2 运行记录
|
||||
|
||||
Board runtime/workflow 负责旁路写入结构化记录:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "agent_board.workflow_run_receipt.v2",
|
||||
"runId": "...",
|
||||
"surface": "mnote-page-ai",
|
||||
"workflowId": "builtin-mnote-page-ai-chat",
|
||||
"workerPresetId": "mnote-page-ai-zcode",
|
||||
"modelOverride": "zcode-default",
|
||||
"finalAnswer": "收到。",
|
||||
"changedFiles": [],
|
||||
"verification": [],
|
||||
"remaining": [],
|
||||
"eventsUrl": "/api/workflow-runs/:id/events",
|
||||
"createdAt": 0,
|
||||
"completedAt": 0
|
||||
}
|
||||
```
|
||||
|
||||
`## FINAL_ANSWER` 只作为旧 run 或非专用 workflow 的兼容保护,不是长期主路径。长期主路径是 worker 主回答自然、Board receipt 结构化。
|
||||
|
||||
## 4. Board 和 MNote 的双向接口
|
||||
|
||||
### 4.1 Board route result
|
||||
|
||||
Board 提供 MNote surface 的推荐结果:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "agent_board.page_ai_route.v2",
|
||||
"surface": "mnote-page-ai",
|
||||
"workflowId": "builtin-mnote-page-ai-chat",
|
||||
"workflowName": "MNote 页面 AI",
|
||||
"workerPresetId": "mnote-page-ai-zcode",
|
||||
"workerName": "MNote 页面 AI · ZCode",
|
||||
"modelOverride": "zcode-default",
|
||||
"allowedWorkerPresetIds": ["mnote-page-ai-zcode"],
|
||||
"allowedWorkflowIds": ["builtin-mnote-page-ai-chat"],
|
||||
"modelOptions": [
|
||||
{ "id": "zcode-default", "label": "默认", "default": true },
|
||||
{ "id": "zcode-fast", "label": "快速" },
|
||||
{ "id": "zcode-strong", "label": "强力" }
|
||||
],
|
||||
"requiresConfirmation": false,
|
||||
"requires": {
|
||||
"filesystem": true,
|
||||
"write": false,
|
||||
"browser": false,
|
||||
"vision": false
|
||||
},
|
||||
"stages": ["answer"]
|
||||
}
|
||||
```
|
||||
|
||||
MNote 消费 Board 推荐,但仍按本地白名单过滤。这样 Board 可以逐步提供更多能力,MNote 不会把控制台复杂度泄露给页面用户。
|
||||
|
||||
### 4.2 MNote run request
|
||||
|
||||
MNote 创建 run 时必须显式传入:
|
||||
|
||||
```json
|
||||
{
|
||||
"surface": "mnote-page-ai",
|
||||
"workflowId": "builtin-mnote-page-ai-chat",
|
||||
"workerPresetId": "mnote-page-ai-zcode",
|
||||
"modelOverride": "zcode-default",
|
||||
"capabilityEnvelope": {
|
||||
"primaryTarget": { "absolutePath": "/.../current.md" },
|
||||
"allowedRoots": ["/..."]
|
||||
},
|
||||
"sessionId": "..."
|
||||
}
|
||||
```
|
||||
|
||||
Board 必须拒绝不匹配 `surface=mnote-page-ai` 的 worker/workflow 组合,避免前端绕过白名单。
|
||||
|
||||
## 5. 标准页面 AI 最小体验
|
||||
|
||||
按 VSCode/Cursor 类页面 AI 衡量,第一阶段只补核心能力,不把 QA/browser/artifact 做成默认入口。
|
||||
|
||||
### 5.1 Chat
|
||||
|
||||
- [ ] 主聊天只显示用户消息和 assistant 自然回答。
|
||||
- [ ] pending skeleton 或流式 token。
|
||||
- [ ] stop 当前 run。
|
||||
- [x] retry 同一消息。
|
||||
- [ ] copy 回答。
|
||||
- [ ] Enter 发送,Shift+Enter 换行。
|
||||
|
||||
### 5.2 Context
|
||||
|
||||
- [ ] composer 上方显示上下文 pills:当前页、选区、打开资源、文件夹、知识库。
|
||||
- [ ] 当前 write target 单独显示。
|
||||
- [ ] 无写权限时,编辑类 prompt 发送前提示授权缺失。
|
||||
- [ ] `allowedRoots` 与 `primaryTarget` run 前可预检。
|
||||
|
||||
### 5.3 Worker / Model / Workflow
|
||||
|
||||
- [ ] 只展示 MNote Page AI 白名单 worker。
|
||||
- [ ] 当只有一个 worker 时,不显示伪切换入口。
|
||||
- [ ] 模型选择挂在当前 worker 下。
|
||||
- [ ] 只展示 MNote Page AI 白名单 workflow。
|
||||
- [ ] 切换 worker/model/workflow 后写入偏好和 session metadata。
|
||||
|
||||
### 5.4 Timeline / Diff / Receipt
|
||||
|
||||
- [ ] run detail 展示 Board event timeline。
|
||||
- [ ] changed files 从 receipt 读取。
|
||||
- [ ] Markdown 编辑后展示最小 diff 摘要。
|
||||
- [ ] 命令输出默认折叠,失败时展开。
|
||||
- [x] dirty/stale guard:编辑器未保存或文件外部变化时阻止自动写入。
|
||||
|
||||
### 5.5 Session / History
|
||||
|
||||
- [ ] 会话列表可见、可搜索、可恢复。
|
||||
- [ ] 每条 assistant 消息关联 run id、worker、model、workflow、receipt。
|
||||
- [ ] 历史详情可查看 final answer、timeline、changed files。
|
||||
- [ ] 支持删除本地 history,不删除 Board 原始 run。
|
||||
|
||||
## 6. 非默认扩展
|
||||
|
||||
QA、浏览器截图和 artifact 展示不属于页面 AI 第一阶段核心体验。它们只在用户显式选择已加入白名单的 QA/browser workflow,或 Board route 判断确实需要浏览器验证并得到 UI 提示时出现。
|
||||
|
||||
- 默认 Page AI 不显示 QA/browser 入口。
|
||||
- artifact screenshot 只从 run detail 打开,不进入主聊天。
|
||||
- QA run 失败时主聊天只显示一句可理解失败原因,详情里展示日志。
|
||||
|
||||
## 7. 实施计划
|
||||
|
||||
### Phase A:源头回答收敛
|
||||
|
||||
- [x] Board 默认 worker 已改为 `mnote-page-ai-zcode`。
|
||||
- [x] Board 默认 workflow 已改为 `builtin-mnote-page-ai-chat`。
|
||||
- [x] MNote UI 已能只展示 final answer,不展示 Board run 创建日志。
|
||||
- [x] smoke:`hi,收到请回复收到。` 最终 assistant 气泡只显示 `收到。`。
|
||||
- [x] `mnote-page-ai-zcode` / `builtin-mnote-page-ai-chat` 源头默认输出自然语言 final answer。
|
||||
- [x] 结构化记录写入 `receipt.finalAnswer / changedFiles / verification / remaining`。
|
||||
|
||||
### Phase B:白名单选择壳
|
||||
|
||||
- [x] MNote 定义 Page AI worker 白名单。
|
||||
- [x] MNote 定义 Page AI workflow 白名单。
|
||||
- [x] Worker picker 只展示白名单 worker。
|
||||
- [x] Workflow picker 只展示白名单 workflow。
|
||||
- [x] 当白名单只有一个 worker/workflow 时,不显示伪切换。
|
||||
|
||||
### Phase C:worker 内模型选择
|
||||
|
||||
- [x] Board route 返回 `modelOptions`。
|
||||
- [x] MNote 显示当前 model chip。
|
||||
- [x] Model picker 只展示当前 worker 允许的模型档位。
|
||||
- [x] run payload 包含 `modelOverride`。
|
||||
- [x] session metadata 记录 `modelOverride`。
|
||||
|
||||
### Phase D:Board-first session/history
|
||||
|
||||
- [x] 定义并落地 `mnote.page_ai.session.v2`。
|
||||
- [x] assistant message 记录 `boardRunId/workflowId/workerPresetId/modelOverride/receiptId`。
|
||||
- [x] 历史列表展示 Board-first session。
|
||||
- [x] Run detail 可从历史打开。
|
||||
- [x] 刷新页面后仍能恢复会话和 run 详情。
|
||||
|
||||
### Phase E:timeline / changed files / diff
|
||||
|
||||
- [x] 从 Board events 生成 timeline。
|
||||
- [x] 从 receipt 提取 changed files。
|
||||
- [x] Markdown 文件编辑后展示最小 diff / changed files 摘要。
|
||||
- [x] 命令输出和日志折叠。
|
||||
- [x] smoke:编辑当前页面后,主聊天是自然回复,详情里能看到 changed file 和验证命令。
|
||||
|
||||
### Phase F:标准页面 AI 体验补齐
|
||||
|
||||
- [ ] 上下文 pills 完整可交互。
|
||||
- [x] pending skeleton / streaming 状态。
|
||||
- [x] stop / retry / copy。
|
||||
- [x] dirty/stale guard。
|
||||
|
||||
## 8. 验收标准
|
||||
|
||||
### 8.1 简单问答
|
||||
|
||||
- 输入:`hi,收到请回复收到。`
|
||||
- 主聊天最新 assistant 气泡:`收到。`
|
||||
- worker 源头最终回答就是自然语言,不依赖 MNote 截断通用任务报告。
|
||||
- run detail 可查看 worker、model、workflow、run id、receipt。
|
||||
|
||||
### 8.2 Worker 与模型
|
||||
|
||||
- UI 只展示 MNote Page AI 白名单 worker。
|
||||
- 白名单只有一个 worker 时,不显示 worker 切换列表。
|
||||
- UI 能切换当前 worker 允许的模型档位。
|
||||
- 发送后 payload 包含 `workerPresetId` 和 `modelOverride`。
|
||||
- 不在白名单内的 worker 不显示。
|
||||
|
||||
### 8.3 Workflow
|
||||
|
||||
- UI 只展示 MNote Page AI 白名单 workflow。
|
||||
- 默认 workflow 为 `builtin-mnote-page-ai-chat`。
|
||||
- 不在白名单内的 Board workflow 不显示。
|
||||
- 发送后 payload 包含 `workflowId`。
|
||||
|
||||
### 8.4 Session/history
|
||||
|
||||
- 新建会话、恢复会话、搜索历史可用。
|
||||
- 历史项显示 final answer preview、状态、时间。
|
||||
- 点击历史项恢复聊天消息。
|
||||
- 点击 run detail 可查看 Board receipt。
|
||||
|
||||
### 8.5 页面编辑
|
||||
|
||||
- 输入“把当前页面中的 A 替换为 B”。
|
||||
- worker 只修改 `primaryTarget.absolutePath`。
|
||||
- 磁盘文件变化。
|
||||
- 编辑器 watcher 刷新可见。
|
||||
- 主聊天显示自然结果。
|
||||
- 详情显示 changed files / verification。
|
||||
|
||||
## 9. 非目标
|
||||
|
||||
- 不重新实现 provider adapter;provider/model 执行仍归 Board。
|
||||
- 不暴露 Board 全量 worker/workflow catalog。
|
||||
- 不把复杂开发、hotfix、QA/browser workflow 默认化。
|
||||
- 不删除 Hermes/Reasonix legacy 代码,只隐藏默认入口并防止污染默认主链。
|
||||
- 不实现完整撤销系统,只保留 diff/receipt 所需数据结构。
|
||||
|
||||
## 10. 风险与处理
|
||||
|
||||
| 风险 | 处理 |
|
||||
| --- | --- |
|
||||
| MNote 专用 worker 仍输出任务报告 | 从 worker/workflow prompt 和 receipt API 源头修正,MNote 截取只做兼容保护 |
|
||||
| Board 选择太多 | MNote 只展示白名单 worker/workflow,新增项必须代码登记 |
|
||||
| 模型选择重新变成 provider picker | 模型挂在特定 worker 下,只展示该 worker 允许的档位 |
|
||||
| Workflow 太重影响简单问答 | 默认只启用 `builtin-mnote-page-ai-chat`,复杂 workflow 需 MNote 白名单 |
|
||||
| 历史数据分裂 | 新 session v2 记录 Board run,旧 session 只读兼容 |
|
||||
| 文件编辑误伤 | primaryTarget + allowedRoots + dirty/stale guard + receipt |
|
||||
|
||||
## 11. 最小落地顺序
|
||||
|
||||
1. 先把 MNote 专用 worker/workflow 的源头输出改成自然回答。
|
||||
2. 再把 Page AI UI 收敛为白名单 worker/workflow,不显示 Board 全量选择。
|
||||
3. 然后补 worker 内模型选择。
|
||||
4. 再补 Board-first session/history。
|
||||
5. 最后补 timeline、diff、dirty/stale guard 和可选扩展。
|
||||
@@ -0,0 +1,341 @@
|
||||
# 7-64 [recycle] CodexMobile 嵌入 Page AI 方案 v1
|
||||
|
||||
> 创建时间:2026-06-23
|
||||
>
|
||||
> 当前状态:`RECYCLE`
|
||||
>
|
||||
> Owner:07-ai / Page AI / CodexMobile embed
|
||||
>
|
||||
> 上位依据:
|
||||
> - `design/07-ai/done/7-62-page-ai-board-first-full-rewrite-v1.md`
|
||||
> - `design/07-ai/process/7-63-page-ai-board-first-productization-v1.md`
|
||||
> - `design/07-ai/done/7-38-page-ai-sidebar-runtime-owner-split-v1.md`
|
||||
|
||||
> 过时原因:已由 `design/07-ai/process/7-65-opencode-webui-embed-page-ai-v1.md` 替代;Page AI 新主路径只接入 opencode 官方 runtime + 官方 WebUI。
|
||||
|
||||
## 1. 核心结论
|
||||
|
||||
放弃 Board-first 和自研聊天 UI 两条路,改为 **fork CodexMobile 开源代码 → 精简 → iframe 嵌入 MNote**。
|
||||
|
||||
```text
|
||||
MNote Page AI = MNote 原生上下文 pills + CodexMobile 精简版 iframe
|
||||
CodexMobile = Vue 3 SPA + Express server → Codex CLI app-server (RPC)
|
||||
```
|
||||
|
||||
理由:
|
||||
- CodexMobile(`friuns2/codex-mobile`,MIT,675⭐)已提供成熟的聊天 UI、流式渲染、session 管理、plan/tool 卡片
|
||||
- 当前 MNote Page AI runtime(4457 行 JS)+ Rust bridge(~20000 行)维护成本高,且聊天体验不如 CodexMobile
|
||||
- CodexMobile 直接对接 Codex CLI,CodexRelay 已解决 DeepSeek 兼容,不需要 Board 中介
|
||||
- 嵌入方案比自研省 90% 代码量,比 Board-first 少一层依赖
|
||||
|
||||
## 2. CodexMobile 现状
|
||||
|
||||
### 2.1 仓库信息
|
||||
|
||||
| 项目 | 值 |
|
||||
|---|---|
|
||||
| 仓库 | `friuns2/codex-mobile` |
|
||||
| 协议 | MIT |
|
||||
| 星数 | 675 |
|
||||
| 语言 | TypeScript (Vue 3 + Express) |
|
||||
| 本地版本 | v0.1.90 (`/home/lix/.local/lib/node_modules/codexapp/`) |
|
||||
| 当前运行 | `codexapp --no-login --no-tunnel --no-open --port 5900` |
|
||||
|
||||
### 2.2 架构
|
||||
|
||||
```
|
||||
浏览器 Vue SPA (hash router)
|
||||
↓ fetch /codex-api/rpc
|
||||
Express httpServer.ts
|
||||
↓ codexAppServerBridge.ts
|
||||
Codex CLI app-server (RPC over HTTP)
|
||||
↓
|
||||
Codex CLI (实际 agent 执行)
|
||||
```
|
||||
|
||||
### 2.3 核心模块
|
||||
|
||||
| 模块 | 文件 | 作用 |
|
||||
|---|---|---|
|
||||
| RPC 桥接 | `codexAppServerBridge.ts` (~2500行) | 代理所有 Codex RPC 调用 |
|
||||
| API 网关 | `codexGateway.ts` | 线程/消息/模型/账户等高层 API |
|
||||
| RPC 客户端 | `codexRpcClient.ts` | 底层 RPC 调用与错误处理 |
|
||||
| HTTP 服务 | `httpServer.ts` | Express + WebSocket + 静态文件 |
|
||||
| 聊天 UI | `ThreadConversation.vue` | 消息气泡、plan 卡片、工具卡片 |
|
||||
| 输入框 | `ThreadComposer.vue` | 消息输入、发送、模型选择 |
|
||||
| 侧边栏 | `SidebarThreadTree.vue` | 线程列表、搜索、切换 |
|
||||
| 布局 | `DesktopLayout.vue` | 整体布局框架 |
|
||||
|
||||
## 3. 精简方案
|
||||
|
||||
### 3.1 删除清单
|
||||
|
||||
| 删除模块 | 原因 |
|
||||
|---|---|
|
||||
| xterm 终端 (`terminalManager.ts`, `ThreadTerminalPanel.vue`) | MNote 不是终端 |
|
||||
| 文件浏览 (`localBrowseUi.ts`) | MNote 有 FileTree |
|
||||
| Firebase auth | MNote 用 SQLite control-plane |
|
||||
| Telegram bridge (`telegramThreadBridge.ts`) | 无关 |
|
||||
| Composio 集成 | 无关 |
|
||||
| OpenRouter proxy (`openRouterProxy.ts`) | 无关 |
|
||||
| Zen proxy (`zenProxy.ts`) | 无关 |
|
||||
| Custom endpoint proxy (`customEndpointProxy.ts`) | 无关 |
|
||||
| Free mode (`freeMode.ts`) | 无关 |
|
||||
| Skills routes/hub (`skillsRoutes.ts`, `SkillsHub.vue`, `SkillCard.vue`) | 无关 |
|
||||
| Review git (`reviewGit.ts`, `ReviewPane.vue`) | 无关 |
|
||||
| Automations (`AutomationsPanel.vue`) | 无关 |
|
||||
| Directory hub (`DirectoryHub.vue`) | 无关 |
|
||||
| Account menu (`AccountMenu.vue`) | 简化 |
|
||||
| Rate limit status (`RateLimitStatus.vue`) | 无关 |
|
||||
| Dictation (`useDictation.ts`) | 无关 |
|
||||
| GitHub skills sync (`useGithubSkillsSync.ts`) | 无关 |
|
||||
| API methods panel (`ApiMethodsPanel.vue`) | 调试工具 |
|
||||
| Pending request panel (`ThreadPendingRequestPanel.vue`) | 简化 |
|
||||
| Queued messages (`QueuedMessages.vue`) | 简化 |
|
||||
| Composer dropdowns (runtime/search/skill picker) | 简化 |
|
||||
| Header git branch dropdown | 无关 |
|
||||
|
||||
### 3.2 保留清单
|
||||
|
||||
| 保留模块 | 作用 |
|
||||
|---|---|
|
||||
| `codexAppServerBridge.ts` | 核心 RPC 桥接 |
|
||||
| `codexGateway.ts` | 高层 API |
|
||||
| `codexRpcClient.ts` | RPC 客户端 |
|
||||
| `httpServer.ts` | Express + WebSocket |
|
||||
| `authMiddleware.ts` | 简化为 MNote token 验证 |
|
||||
| `ThreadConversation.vue` | 聊天气泡 |
|
||||
| `ThreadComposer.vue` | 输入框 |
|
||||
| `SidebarThreadTree.vue` | 线程列表 |
|
||||
| `DesktopLayout.vue` | 布局 |
|
||||
| `ContentHeader.vue` | 顶部信息 |
|
||||
| `appServerDtos.ts` | 类型定义 |
|
||||
| `codexErrors.ts` | 错误处理 |
|
||||
| WebSocket 流式事件 | 实时消息 |
|
||||
|
||||
### 3.3 新增:postMessage Bridge
|
||||
|
||||
MNote 原生层与 CodexMobile iframe 之间的通信协议:
|
||||
|
||||
```typescript
|
||||
// MNote → CodexMobile
|
||||
interface MnoteContextMessage {
|
||||
type: 'mnote:context';
|
||||
payload: {
|
||||
workspaceId: string;
|
||||
documentId: string;
|
||||
pageTitle: string;
|
||||
rootUri: string; // file:///...
|
||||
primaryTarget: {
|
||||
absolutePath: string;
|
||||
relativePath: string;
|
||||
};
|
||||
selection?: {
|
||||
text: string;
|
||||
};
|
||||
allowedRoots: Array<{
|
||||
rootUri: string;
|
||||
permission: 'read' | 'write';
|
||||
}>;
|
||||
knowledgeContext?: string; // LightRAG 查询结果
|
||||
};
|
||||
}
|
||||
|
||||
// CodexMobile → MNote
|
||||
interface CodexMobileEvent {
|
||||
type: 'codex:file-changed' | 'codex:session-update' | 'codex:ready';
|
||||
payload: {
|
||||
changedFiles?: string[];
|
||||
sessionId?: string;
|
||||
threadId?: string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 集成架构
|
||||
|
||||
### 4.1 整体拓扑
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ MNote Rust SSR (localhost:3000) │
|
||||
│ │
|
||||
│ ┌─ Page AI Panel ──────────────────────────────┐ │
|
||||
│ │ ┌─ MNote 原生上下文 pills ──────────────────┐ │ │
|
||||
│ │ │ [当前页] [选区] [知识库] [allowed roots] │ │ │
|
||||
│ │ └────────────────────────────────────────────┘ │ │
|
||||
│ │ ┌─ iframe ───────────────────────────────────┐ │ │
|
||||
│ │ │ CodexMobile 精简版 SPA │ │ │
|
||||
│ │ │ (Vue 3, hash router, 独立端口 5900) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ThreadConversation + ThreadComposer │ │ │
|
||||
│ │ └────────────────────────────────────────────┘ │ │
|
||||
│ │ postMessage ↑↓ │ │
|
||||
│ └────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ /codex-mobile/* → reverse proxy → 127.0.0.1:5900 │
|
||||
└──────────────────────────────────────────────────┘
|
||||
↓
|
||||
CodexMobile Express (5900)
|
||||
↓
|
||||
Codex CLI app-server (RPC)
|
||||
↓
|
||||
Codex CLI + CodexRelay → DeepSeek
|
||||
```
|
||||
|
||||
### 4.2 Rust 侧改动
|
||||
|
||||
```rust
|
||||
// mnote-web routes/mod.rs 新增
|
||||
.route("/codex-mobile/{*path}", any(codex_mobile_proxy))
|
||||
|
||||
// codex_mobile_proxy: 反向代理到 127.0.0.1:5900
|
||||
// 仅对已认证 session 放行
|
||||
// 注入 X-Mnote-Workspace-Id / X-Mnote-Document-Id header
|
||||
```
|
||||
|
||||
### 4.3 前端侧改动
|
||||
|
||||
```javascript
|
||||
// sidebar-page-ai-runtime.js 精简为:
|
||||
// 1. 渲染上下文 pills(当前页、选区、知识库)
|
||||
// 2. 创建 iframe 指向 /codex-mobile/
|
||||
// 3. postMessage 监听与转发
|
||||
// 4. 文件变更事件 → watcher 刷新编辑器
|
||||
|
||||
// 删除:
|
||||
// - 所有 provider 选择逻辑 (Hermes/Reasonix/Chat-only)
|
||||
// - 所有 session/message/run 持久化逻辑
|
||||
// - 所有 Board bridge 调用
|
||||
// - 所有 workflow/worker 选择器
|
||||
// 预计从 4457 行精简到 ~300 行
|
||||
```
|
||||
|
||||
### 4.4 Rust 侧删除
|
||||
|
||||
```text
|
||||
删除文件:
|
||||
- routes/page_ai_board.rs (317 行)
|
||||
- routes/page_ai_workflow.rs (967 行)
|
||||
- routes/hermes_client.rs 中 Page AI 相关部分
|
||||
|
||||
保留:
|
||||
- hermes_tools/doc.rs 中的 mnote.doc.* tools(非 Page AI 路径仍需要)
|
||||
```
|
||||
|
||||
## 5. 上下文注入机制
|
||||
|
||||
### 5.1 注入时机
|
||||
|
||||
1. Page AI 面板打开时:注入当前页路径、workspaceId、documentId
|
||||
2. 用户选中文本时:注入 selection
|
||||
3. 用户切换页面时:更新 primaryTarget
|
||||
4. 用户触发知识库查询时:注入 knowledgeContext
|
||||
|
||||
### 5.2 注入方式
|
||||
|
||||
MNote 通过 `iframe.contentWindow.postMessage()` 发送 `mnote:context`,CodexMobile 内新增 `useMnoteBridge.ts` composable 接收并注入到 Codex CLI 的 system prompt 中。
|
||||
|
||||
```typescript
|
||||
// CodexMobile 侧新增 useMnoteBridge.ts
|
||||
// 监听 postMessage,将上下文追加到 thread/start 的 system prompt
|
||||
// ponytail: 最小实现,只做 system prompt 注入,不做 UI 展示
|
||||
```
|
||||
|
||||
### 5.3 文件编辑闭环
|
||||
|
||||
```
|
||||
用户输入 "把当前页的 A 替换为 B"
|
||||
→ Codex CLI 通过 CodexRelay 执行
|
||||
→ Codex CLI 直接编辑 primaryTarget.absolutePath
|
||||
→ 磁盘文件变化
|
||||
→ CodexMobile 检测文件变更 → postMessage 'codex:file-changed'
|
||||
→ MNote watcher 检测到文件变化 → 刷新 tiptap 编辑器
|
||||
```
|
||||
|
||||
## 6. 实施计划
|
||||
|
||||
### Phase A:Fork 与精简(1天)
|
||||
|
||||
- [ ] `git clone https://github.com/friuns2/codex-mobile` 到 `/mnt/Data1T/mnote/codex-mobile/`
|
||||
- [ ] 删除 3.1 清单中的所有模块
|
||||
- [ ] 简化 `authMiddleware.ts`:接受 MNote session token
|
||||
- [ ] 新增 `useMnoteBridge.ts`:postMessage 监听
|
||||
- [ ] 验证 `npm run build` 通过
|
||||
- [ ] 验证精简版可独立运行(`codexapp --port 5900`)
|
||||
|
||||
### Phase B:MNote 集成(1天)
|
||||
|
||||
- [ ] Rust 新增 `/codex-mobile/{*path}` 反向代理路由
|
||||
- [ ] `sidebar-page-ai-runtime.js` 精简为上下文 pills + iframe + postMessage
|
||||
- [ ] 删除 `page_ai_board.rs`、`page_ai_workflow.rs`
|
||||
- [ ] 上下文 pills 实现(当前页、选区、知识库引用)
|
||||
- [ ] postMessage bridge 双向通信验证
|
||||
|
||||
### Phase C:闭环验证(0.5天)
|
||||
|
||||
- [ ] smoke:打开 Page AI → 看到 CodexMobile 聊天界面
|
||||
- [ ] smoke:发送消息 → 流式回复可见
|
||||
- [ ] smoke:编辑当前页 → 文件变化 → 编辑器刷新
|
||||
- [ ] smoke:刷新页面 → 会话恢复
|
||||
- [ ] smoke:上下文 pills 正确显示当前页信息
|
||||
|
||||
### Phase D:旧代码清理(后续)
|
||||
|
||||
- [ ] 归档 `sidebar-page-ai-runtime.js` 旧代码
|
||||
- [ ] 归档 `hermes_client.rs` Page AI 相关代码
|
||||
- [ ] 更新 `ARCHITECTURE.md` 和 `CURRENT_ARCHITECTURE.md`
|
||||
|
||||
## 7. 验收标准
|
||||
|
||||
### 7.1 聊天体验
|
||||
|
||||
- 用户可在 Page AI 面板中与 Codex 对话
|
||||
- 流式回复实时可见
|
||||
- 支持 stop / retry / copy
|
||||
- 刷新页面后会话历史可恢复
|
||||
- plan 卡片和工具调用卡片可见(含 plan 持久化补丁)
|
||||
|
||||
### 7.2 上下文注入
|
||||
|
||||
- 上下文 pills 显示当前页标题和路径
|
||||
- 选区内容自动注入
|
||||
- Codex 能读取和编辑当前页文件
|
||||
- 文件编辑后 MNote 编辑器自动刷新
|
||||
|
||||
### 7.3 代码精简
|
||||
|
||||
- `sidebar-page-ai-runtime.js` 从 4457 行精简到 <500 行
|
||||
- 删除 `page_ai_board.rs` 和 `page_ai_workflow.rs`(~1300 行)
|
||||
- 不再依赖 Agent Board 服务
|
||||
|
||||
## 8. 风险与处理
|
||||
|
||||
| 风险 | 处理 |
|
||||
|---|---|
|
||||
| CodexMobile 上游更新导致 fork 过时 | 定期 rebase,只保留精简 diff |
|
||||
| Codex CLI 不可用 | 降级提示 "Codex CLI 未运行",不伪装可用 |
|
||||
| iframe 跨域问题 | 同源反向代理(`/codex-mobile/*`),无跨域 |
|
||||
| postMessage 安全 | 验证 origin,只接受已知消息类型 |
|
||||
| plan 卡片刷新消失 | 已有 `codexmobile-plan-persist.js` 补丁,合入 fork |
|
||||
| npm 升级清空 codexapp 目录 | fork 到 MNote 仓库内,不依赖 npm 全局安装 |
|
||||
|
||||
## 9. 与旧方案的对比
|
||||
|
||||
| | Board-first (7-62/7-63) | CodexMobile 嵌入 (本方案) |
|
||||
|---|---|---|
|
||||
| MNote 代码量 | ~4457 JS + ~20000 Rust | ~500 JS + ~50 Rust |
|
||||
| 聊天 UI 成熟度 | 自研,持续打磨 | 675⭐ 开源验证 |
|
||||
| 依赖服务 | Agent Board (必须) | Codex CLI (必须) |
|
||||
| Agent 选择 | 通过 Board 间接 | 直接使用 Codex CLI |
|
||||
| Provider 适配 | Board 负责 | CodexRelay 负责 |
|
||||
| 上下文注入 | 自研 pills | 自研 pills + system prompt |
|
||||
| 维护负担 | Board bridge + 聊天 UI | 追上游 + postMessage bridge |
|
||||
| 差异化 | 上下文 pills | 上下文 pills + 成熟聊天体验 |
|
||||
|
||||
## 10. 非目标
|
||||
|
||||
- 不把 CodexMobile 的终端、文件浏览、Skills、Review 等功能带入 MNote
|
||||
- 不替换 MNote 的 FileTree、编辑器、知识库等核心功能
|
||||
- 不要求 CodexMobile 支持 MNote 特有的资源类型(mindmap、OnlyOffice)
|
||||
- 不实现 CodexMobile 与 MNote auth 的 SSO 统一(短期独立 auth,长期可选)
|
||||
Reference in New Issue
Block a user