收口 Rust Web 入口与 AI 写入链
- 将 3000 主入口继续收口到 mnote-web,补齐 /favicon.ico、/api/auth、session alias、AI run 等 Rust Web 路由边界。 - 更新登录页与 Convex Auth 代理,支持测试账号快速登录写入真实 Convex Auth cookie。 - 推进页面设置、Wolai 对齐、Phase 7 AI kernel/CLI-first 设计文档与相关 smoke 脚本。 - 更新 leptos-tiptap 生成资产、mnote-cli/bridge-runtime、前端依赖和 dev/prod 启动脚本。
This commit is contained in:
@@ -47,7 +47,7 @@
|
||||
- [x] `Phase 2` 文档阅读态分离已经有实质代码
|
||||
- [x] `Phase 3` 主 Sidebar 已出现 `kernelSidebarTree` 消费接缝
|
||||
- [x] `Phase 4` 搜索已做 host/runtime 拆分,并开始返回 `nodeId` / `subtreeRootId` / `evidence`
|
||||
- [x] `Phase 5` AI 面板已做 host/runtime 拆分,并开始向 Hermes bridge 传递 `node` / `subtree` / `outline` / `evidence`
|
||||
- [x] `Phase 5` AI 面板已做 host/runtime 拆分,并开始向 AI bridge 传递 `node` / `subtree` / `outline` / `evidence`;长期执行面应收口到 `mnote-cli`,Web 只作为 CLI host / client,`openai-agents-python` / Hermes / Codex 只作为可插拔外置 agent
|
||||
- [x] `Phase 6` Mindmap 独立页已去掉 `editorStub` 主入口
|
||||
- [x] `Phase 7` 阅读态已直接消费 `pageSubtree`,`BlockNote` 也已不是文档页默认唯一入口
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
| Phase 2 | 文档阅读页 server-first 化 | `PARTIAL` 接近 `DONE` | 阅读态/编辑态已明显分离,但仍有旧链回退和大量客户端状态集中在 `DocumentContent` |
|
||||
| Phase 3 | Sidebar / 树结构 Rust 化 | `PARTIAL` 偏早期 | 主 Sidebar 已以 `kernelSidebarTree` 作为主树来源,但整体仍是超大客户端组件 |
|
||||
| Phase 4 | 搜索 Rust 化与 island 化 | `PARTIAL` | host/runtime 懒加载拆分已做,结果形状也开始带 `nodeId` / `subtreeRootId` / `evidence`,但仍未完成 server-first 搜索页 |
|
||||
| Phase 5 | AI 面板 bridge island 化 | `PARTIAL` | host/runtime 拆分已做,且已开始把 `node` / `subtree` / `outline` / `evidence` 送入 Hermes,但 runtime 仍重,协议也未统一到真正“最小壳” |
|
||||
| Phase 5 | AI 面板 bridge island 化 | `PARTIAL` | host/runtime 拆分已做,且已开始把 `node` / `subtree` / `outline` / `evidence` 送入 AI bridge;长期执行统一落在 `mnote-cli`,Web 面板只做 host / adapter,但 runtime 仍重,协议也未统一到真正“最小壳” |
|
||||
| Phase 6 | Mindmap 独立对象化 | `PARTIAL` | 独立页脱离 editor stub 主入口,并补出 `standalone` / `documentBridge` 边界,但仍是客户端重壳 |
|
||||
| Phase 7 | BlockNote 孤岛化 | `PARTIAL` | 阅读态已直接消费 `pageSubtree`,编辑器按需挂载,但外围 drawer/panel 仍集中在同一内容组件 |
|
||||
| Phase 8 | 旧前端壳下线 | `PARTIAL` 接近 `DONE` | 3000 gateway / 文档 shell / tree realtime / Search / AI bridge / Mindmap object shell 已由 `mnote-web` 持有;Next App Router 降为 legacy compat / island bundle source,旧链彻底删除仍待后续 |
|
||||
@@ -154,7 +154,7 @@
|
||||
- [x] 已有 request context / middleware
|
||||
- [context.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/context.rs)
|
||||
- [request_context.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/middleware/request_context.rs)
|
||||
- [x] 已有最小 Hermes bridge route
|
||||
- [x] 已有最小 Hermes bridge route;当前仅按兼容 AI bridge 记录,不作为长期 agent 执行面
|
||||
- [hermes.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes.rs)
|
||||
- [x] 已有 SSE / WS / compat route 骨架
|
||||
- [x] 已有真实 bridge / compat 接缝
|
||||
@@ -290,7 +290,7 @@
|
||||
|
||||
---
|
||||
|
||||
## 10. Phase 5:AI 面板进一步收口为纯桥接 island
|
||||
## 10. Phase 5:AI 面板进一步收口为 `mnote-cli` host / 纯桥接 island
|
||||
|
||||
**当前状态:`PARTIAL`**
|
||||
|
||||
@@ -301,7 +301,7 @@
|
||||
- [DocumentAiAgentPanel.runtime.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx)
|
||||
- [x] Mindmap / OnlyOffice 也有类似 runtime 拆分
|
||||
- [x] `GlobalAiAgentHost` 已不在 `(app)/layout.tsx` 主布局中挂载
|
||||
- [x] 文档页 AI 已开始把 `node` / `subtree` / `outline` / `evidence` 传给 Hermes bridge
|
||||
- [x] 文档页 AI 已开始把 `node` / `subtree` / `outline` / `evidence` 传给 AI bridge;长期执行面应收口到 `mnote-cli`,页面 AI 只保留为 CLI host / client,`openai-agents-python` / Hermes / Codex 只作为可插拔外置 agent
|
||||
- [DocumentAiAgentPanel.runtime.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx)
|
||||
- [route.ts](/mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts)
|
||||
|
||||
@@ -311,7 +311,7 @@
|
||||
- [ ] “最小会话协议、统一流式协议、页面上下文协议”还更多体现在组件内部,不是系统级协议层
|
||||
- [ ] 还不能说 AI 面板已经变成“纯桥接壳”
|
||||
- [ ] 页面级 AI adapter 仍然很大,只是改成了懒加载
|
||||
- [ ] AI 已能消费 `node` / `subtree` / `outline` / `evidence` 上下文,但还不是统一的 kernel-first tool 协议
|
||||
- [ ] AI 已能消费 `node` / `subtree` / `outline` / `evidence` 上下文,但还不是统一的 `mnote-cli` kernel-first tool 协议;Web 面板也还没有彻底退成单纯 host / adapter
|
||||
|
||||
### 10.3 v2 后续任务
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 目标
|
||||
|
||||
将 Next App Router 从 3000 默认主链降级为显式 legacy/debug/internal 兼容边界。默认首页、文档页、搜索页、导图页、tree SSE 与 Hermes bridge 均由 `mnote-web` 承接。
|
||||
将 Next App Router 从 3000 默认主链降级为显式 legacy/debug/internal 兼容边界。默认首页、文档页、搜索页、导图页、tree SSE 与 AI bridge host 均由 `mnote-web` 承接;长期 agent 执行面收口到 `mnote-cli`。
|
||||
|
||||
## 当前 owner
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
- `/search`:Rust Web `search::shell`,Search projection owner `rust-kernel`。
|
||||
- `/mindmap/{doc_id}/{mindmap_id}`:Rust Web `mindmap_shell::mindmap_object_shell`,Mindmap projection owner `rust-kernel`。
|
||||
- `/api/tree/events`:Rust Web SSE,stream owner `rust-web`。
|
||||
- `/api/hermes/bridge`:Rust Web Hermes bridge,AI bridge owner `rust-web-hermes`。
|
||||
- `/api/hermes/bridge`:Rust Web 兼容 AI bridge;仅作为过渡边界,不是长期 agent 执行面。
|
||||
- `/api/compat/next/*`:legacy compat boundary,仅用于迁移期兼容与调试。
|
||||
|
||||
## Gate
|
||||
@@ -19,12 +19,12 @@
|
||||
- `MNOTE_WEB_ENABLE_LEGACY_NEXT_COMPAT` 默认关闭;只有显式设置为 `1/true/yes` 才允许 fallback proxy。
|
||||
- 默认主路径不得返回 `x-mnote-legacy-upstream: next-app-router`。
|
||||
- 导图、搜索、文档页 contract 不得再把 `next-app-router` 声明为主 runtime。
|
||||
- `/api/ai-agent/run` 仅声明 canonical route `/api/hermes/bridge`,结构化写入必须经 Hermes/Rust bridge。
|
||||
- `/api/ai-agent/run` 当前仍保留兼容 route,但长期应降为 `mnote-cli` host / adapter,结构化写入必须经 Rust runtime,外置 agent 不得拥有第二执行面。
|
||||
|
||||
## 删除条件
|
||||
|
||||
- 删除 `/api/compat/next/sidebar`:Sidebar、workspace shell、file tree smoke 均证明 Rust projection 可覆盖默认入口。
|
||||
- 删除 `/api/compat/next/ai-agent/run`:AI 面板默认请求 Hermes,task126 smoke 通过,并且 legacy 调用方清零。
|
||||
- 删除 `/api/compat/next/ai-agent/run`:AI 面板默认请求统一 CLI host,legacy 调用方清零;Hermes 仅保留为可插拔外置 agent。
|
||||
- 删除 fallback proxy:`task117` 默认关闭 legacy compat 后覆盖首页、文档页、搜索页、导图页与 tree SSE。
|
||||
|
||||
## 验收命令
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
- Rust 内核和 Web 承载层如何分工
|
||||
- 前端哪些部分应该退出当前重 React 壳
|
||||
- `axum`、`Leptos` 这类 Rust Web 方案是否值得采用
|
||||
- `mnote-cli` 应如何成为唯一长期 agent 执行面
|
||||
- `BlockNote` 应如何被隔离到最后处理
|
||||
|
||||
---
|
||||
@@ -56,7 +57,7 @@
|
||||
- **业务执行面:现有 Rust workspace 继续作为唯一业务真执行面**
|
||||
- **Web 承载层:`axum`**
|
||||
- **页面渲染模型:`Leptos Islands`**
|
||||
- **AI 运行时:Hermes**
|
||||
- **AI 执行面:`mnote-cli`**
|
||||
- **最后保留的重前端孤岛:`BlockNote`**
|
||||
|
||||
一句话概括:
|
||||
@@ -179,7 +180,7 @@
|
||||
- 文档查询与聚合层
|
||||
- 树结构装配层
|
||||
- 搜索服务层
|
||||
- AI bridge / Hermes bridge 层
|
||||
- AI bridge / CLI host 层;长期 agent 执行面只收口到 `mnote-cli`,Hermes 仅作为历史兼容 bridge / 外置 adapter
|
||||
- 页面 SSR 外壳承载层
|
||||
- 流式更新、通知、事件推送层
|
||||
|
||||
@@ -356,7 +357,7 @@ Leptos Islands 很适合承接下面这类长期目标:
|
||||
|
||||
到目前为止,长期路线里已经有几条可以被源码直接证明的最小里程碑:
|
||||
|
||||
- Rust Web 承载层已经有 `mnote-web` crate 骨架,`router / middleware / request context / SSE / WS / Hermes bridge` 的主接缝已立住。
|
||||
- Rust Web 承载层已经有 `mnote-web` crate 骨架,`router / middleware / request context / SSE / WS / AI bridge` 的主接缝已立住;历史上这条线曾经包含 Hermes bridge。
|
||||
- 文档页已经从“默认先进编辑器”改成“先阅读、后编辑”:服务端先读 `meta + content`,阅读态单独渲染,`BlockNote` 只在进入编辑态后挂载。
|
||||
- Sidebar 已形成“服务端首包 + 客户端局部 island”的最小边界,导航数据聚合契约不再散落在布局层。
|
||||
- SearchPalette 与页面级 AI 面板都已经收成轻 host + 按需 runtime island,重量运行态不再默认跟随主布局常驻。
|
||||
@@ -410,14 +411,14 @@ Leptos Islands 很适合承接下面这类长期目标:
|
||||
|
||||
目标:
|
||||
|
||||
- 继续桥接 Hermes
|
||||
- 继续桥接统一 CLI host
|
||||
- 不再承担前端本地 orchestration
|
||||
- 不再成为常驻大壳的一部分
|
||||
|
||||
归位:
|
||||
|
||||
- 面板只保留最小 UI 与上下文桥接
|
||||
- 工具执行全部走 Hermes + Rust tools
|
||||
- 工具执行全部走 `mnote-cli` + Rust tools
|
||||
- 面板按页面需要懒挂载成单独 island
|
||||
|
||||
### 9.5 Mindmap
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
+541
@@ -0,0 +1,541 @@
|
||||
# 5-10 [process] Wolai 页面设置与 AI 交互壳对齐方案 v1
|
||||
|
||||
> 更新时间:2026-05-06
|
||||
>
|
||||
> 关联文档:
|
||||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||||
> - `/mnt/Data1T/mnote/design/01-05-current-priority-overview.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/process/5-7-wolai-page-tree-main-editor-experience-restoration-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-9-wolai-aline-continuous-checklist-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md`
|
||||
> - `/mnt/Data1T/mnote/design/08-wolai-aline-test-flow/process/wolai-aline-test-flow-v1.md`
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
这份文档只回答一个问题:
|
||||
|
||||
> **在不制造第二份页面真相、不重开一条 AI 执行面的前提下,如何把 `3000` 文档页的“页面设置”和“AI 界面”收口成更接近 Wolai 的交互壳。**
|
||||
|
||||
这次不处理整条文档页体验复刻,也不把评论、协作、演示模式一起打包推进。
|
||||
|
||||
本轮优先级固定为:
|
||||
|
||||
1. 页面设置入口与面板形态
|
||||
2. 页面级 AI 入口与右侧抽屉
|
||||
3. 两者与现有 `Page Aggregate` / `mnote-cli` 主线的接线方式
|
||||
|
||||
一句话收口:
|
||||
|
||||
> **先把“入口和容器”做对,再逐项把内部动作接到现有正式命令链。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前判断
|
||||
|
||||
### 2.1 当前 `3000` 的问题不是“没有能力”,而是“能力挂错了壳”
|
||||
|
||||
当前仓库里已经有可复用能力:
|
||||
|
||||
- 页面设置 UI 已存在:`PageOptionsSidebar`
|
||||
- 页面设置写链已存在:`page.layout.updateOptions`
|
||||
- 页面 AI host 已存在:`DocumentAiAgentPanel`
|
||||
- AI 执行面已收口到 `mnote-cli` host / client
|
||||
- 评论 drawer、历史 drawer、分享 dialog 都已有各自最小实现
|
||||
|
||||
但当前现网文档页仍然存在两个明显错位:
|
||||
|
||||
- 页面设置还是“右侧整块 inspector”思路,不是 Wolai 的右上角 `...` 贴边 popover
|
||||
- 页面 AI 主要还是顶栏“页面AI”按钮思路,不是 Wolai 的右下角浮动入口 + 右侧抽屉
|
||||
|
||||
因此本轮不应重写一套新产品,而应优先做:
|
||||
|
||||
> **现有能力重新编排到正确交互壳。**
|
||||
|
||||
### 2.2 当前不该做的事
|
||||
|
||||
本轮明确不做:
|
||||
|
||||
- 不新造第二套页面设置数据结构
|
||||
- 不新造第二套页面 AI runtime
|
||||
- 不把 Web AI 面板重新升格成独立 AI 编排主线
|
||||
- 不为了像 Wolai 而把评论、协作、成员、演示模式一并拉进首批实现
|
||||
- 不在 Rust SSR 和 React compat 层同时各做一套相同按钮逻辑
|
||||
|
||||
---
|
||||
|
||||
## 3. Wolai 基线
|
||||
|
||||
2026-05-06 已通过 `wolai-aline` 基线取证得到当前 Wolai 行为证据,截图目录:
|
||||
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/`
|
||||
|
||||
关键结论如下。
|
||||
|
||||
### 3.1 页面设置
|
||||
|
||||
- 入口位于右上角 `...`
|
||||
- hover tooltip 为“页面选项和全局选项”
|
||||
- 点击后打开右侧贴边 `popover`,不是 modal,也不是新页面
|
||||
- URL 保持不变
|
||||
- 没有遮罩,不压暗背景
|
||||
- 关闭方式为:
|
||||
- `Esc`
|
||||
- 点击页面空白处
|
||||
- 再次点击同一入口
|
||||
- 顶部为 `页面选项 / 自定义页面 / 全局选项` 三个 tab
|
||||
- 可见开关为 checkbox 形态
|
||||
- 当前主 tab 内有:
|
||||
- `自适应宽度`
|
||||
- `小字体`
|
||||
- `标题目录`
|
||||
- `标题自动编号`
|
||||
- `编辑保护`
|
||||
- 下方还有动作项:
|
||||
- `删除页面`
|
||||
- `移动到...`
|
||||
- `嵌入到...`
|
||||
- `页面历史...`
|
||||
- `公开分享页面...`
|
||||
|
||||
### 3.2 AI 界面
|
||||
|
||||
- 入口位于右下角浮动 `AI` 按钮
|
||||
- 点击后打开右侧抽屉,不改 URL
|
||||
- 抽屉没有遮罩,不压暗背景
|
||||
- 当前关闭方式只有右上角 `X`
|
||||
- `Esc` 无效
|
||||
- 点击页面空白处无效
|
||||
- 入口按钮在抽屉打开后被覆盖,不承担 toggle 关闭语义
|
||||
- 抽屉标题为“智能问答”
|
||||
- 中部存在推荐问题/快捷入口
|
||||
- 底部存在会话区、模型入口、输入框和发送按钮
|
||||
|
||||
这说明本轮对齐的最小行为合同已经足够明确:
|
||||
|
||||
> **页面设置是“顶栏入口 + 贴边 popover”;页面 AI 是“右下角入口 + 右侧抽屉”。**
|
||||
|
||||
---
|
||||
|
||||
## 4. 设计原则
|
||||
|
||||
### 4.1 页面设置继续服从 `Page Aggregate`
|
||||
|
||||
页面设置只能是:
|
||||
|
||||
- `pageOptions`
|
||||
- `editorRuntimePageOptions`
|
||||
- 对应的 `page.layout.updateOptions`
|
||||
|
||||
不能变成:
|
||||
|
||||
- 某个单独 UI 组件内部维护的临时配置真相
|
||||
- 一套只在文档页壳层生效、却不进入主编辑器 runtime 的新设置体系
|
||||
|
||||
因此,页面设置改造的重点不是多做几个开关,而是:
|
||||
|
||||
> **把现有设置项放进更接近 Wolai 的容器,同时继续显式区分“已正式接通”和“仅保存字段/待接通”。**
|
||||
|
||||
### 4.2 页面 AI 继续服从 `CLI-first`
|
||||
|
||||
页面 AI 界面可以继续做产品壳,但它不能重新变成独立执行面。
|
||||
|
||||
当前长期方向已经明确:
|
||||
|
||||
- `mnote-cli` 是唯一长期 agent 执行面
|
||||
- Web AI 面板只是 host / client
|
||||
|
||||
因此本轮 AI 界面改造只处理:
|
||||
|
||||
- 入口位置
|
||||
- 抽屉壳形态
|
||||
- 页面级上下文绑定
|
||||
- 与现有 `DocumentAiAgentPanel` 的挂载方式
|
||||
|
||||
本轮不处理:
|
||||
|
||||
- AI runtime 重写
|
||||
- 新模型编排
|
||||
- 新工具协议
|
||||
- 第二套全局 AI 路由
|
||||
|
||||
### 4.3 先对齐容器语义,再推进动作项
|
||||
|
||||
Wolai 里页面设置和 AI 的第一感受,首先是:
|
||||
|
||||
- 从哪里打开
|
||||
- 打开成什么容器
|
||||
- URL 是否变化
|
||||
- 如何关闭
|
||||
|
||||
这四项比内部是否一开始就全部可用更重要。
|
||||
|
||||
因此本轮优先级必须是:
|
||||
|
||||
1. 入口位置和按钮密度对齐
|
||||
2. 容器形态和开关语义对齐
|
||||
3. 内部动作项逐项复用现有能力
|
||||
|
||||
---
|
||||
|
||||
## 5. 本轮范围
|
||||
|
||||
### 5.1 范围内
|
||||
|
||||
- 文档页 owner 态右上角 `...` 页面设置入口
|
||||
- 页面设置 `popover` 容器
|
||||
- 页面设置 `tablist` 和最小项分组
|
||||
- 页面设置最小动作项接线策略
|
||||
- 文档页右下角浮动 `AI` 入口
|
||||
- 页面 AI 右侧抽屉容器
|
||||
- 页面 AI 与现有 `DocumentAiAgentPanel` 的页面级绑定
|
||||
- 相应 smoke、截图和差异矩阵
|
||||
|
||||
### 5.2 暂不进入本轮
|
||||
|
||||
- 演示模式
|
||||
- 页面评论
|
||||
- 页面协作
|
||||
- 成员邀请
|
||||
- 完整公开分享体验重做
|
||||
- 全局 AI 面板收口
|
||||
- 帮助中心浮动入口的完整 Wolai 化
|
||||
- AI 内部推荐内容、模型文案、提示词体系大改
|
||||
|
||||
补充:
|
||||
|
||||
- `页面历史...` 和 `公开分享页面...` 因为当前已有最小能力,可以作为本轮页面设置动作项的优先复用对象
|
||||
- 评论、协作、成员这类能力虽然在 Wolai 顶栏可见,但当前不进入首批实现
|
||||
|
||||
---
|
||||
|
||||
## 6. 目标交互合同
|
||||
|
||||
## 6.1 页面设置
|
||||
|
||||
### 6.1.1 入口
|
||||
|
||||
- 入口继续位于文档页右上角操作区
|
||||
- 视觉上以 `...` 弱按钮承载
|
||||
- tooltip 调整为“页面选项和全局选项”
|
||||
- 不再把“页面设置”理解成常驻右侧栏
|
||||
|
||||
### 6.1.2 容器
|
||||
|
||||
- 使用右侧贴边 `popover`
|
||||
- 不使用全屏 modal
|
||||
- 不使用带遮罩的 `Sheet`
|
||||
- 打开后 URL 不变
|
||||
- 面板宽度以 Wolai 的紧凑设置面板为准,不沿用当前宽侧栏比例
|
||||
|
||||
### 6.1.3 关闭语义
|
||||
|
||||
- `Esc` 关闭
|
||||
- 点击空白关闭
|
||||
- 再次点击入口关闭
|
||||
|
||||
### 6.1.4 内容结构
|
||||
|
||||
顶部固定三 tab:
|
||||
|
||||
- `页面选项`
|
||||
- `自定义页面`
|
||||
- `全局选项`
|
||||
|
||||
页面选项首批保留并对齐的设置项:
|
||||
|
||||
- `wideLayout`
|
||||
- `smallText`
|
||||
- `showToc`
|
||||
- `showHeadingNumbers`
|
||||
- `protectEditing`
|
||||
|
||||
自定义页面首批保留:
|
||||
|
||||
- `pageFont`
|
||||
- `layoutDensity`
|
||||
- `collapseBacklinks`
|
||||
- `hideChildPages`
|
||||
- `showBlockRefCount`
|
||||
- `embedDefaultBlockId`
|
||||
|
||||
全局选项首批只保留当前已有全局偏好中与文档体验直接相关的最小项,不在本轮扩面。
|
||||
|
||||
### 6.1.5 动作项
|
||||
|
||||
页面设置面板中的动作项分三类:
|
||||
|
||||
1. 本轮直接接线
|
||||
- `页面历史...`
|
||||
- `公开分享页面...`
|
||||
|
||||
2. 本轮保留入口但延后落地
|
||||
- `移动到...`
|
||||
- `嵌入到...`
|
||||
- `删除页面`
|
||||
|
||||
3. 本轮不放入页面设置面板
|
||||
- 评论
|
||||
- 协作
|
||||
- 成员邀请
|
||||
- 演示模式
|
||||
|
||||
设计原因:
|
||||
|
||||
- `历史` 和 `分享` 当前已有组件可复用
|
||||
- `移动到 / 嵌入到 / 删除` 与树命令、确认流和 picker 交互更深,应拆成后续小任务
|
||||
- 评论/协作不在本轮优先级内
|
||||
|
||||
## 6.2 页面 AI
|
||||
|
||||
### 6.2.1 入口
|
||||
|
||||
- 文档页主入口改为右下角浮动 `AI` 按钮
|
||||
- 顶栏“页面AI”不再作为主入口
|
||||
- 首批可以先去掉顶栏 `页面AI`,或把它降为 debug/临时入口,不再作为默认视觉路径
|
||||
|
||||
### 6.2.2 容器
|
||||
|
||||
- 使用右侧抽屉
|
||||
- 不使用遮罩
|
||||
- 打开后 URL 不变
|
||||
- 抽屉属于“页面级 AI”,不是全局 AI
|
||||
|
||||
### 6.2.3 关闭语义
|
||||
|
||||
- 右上角 `X` 关闭
|
||||
- `Esc` 不关闭
|
||||
- 点击页面空白不关闭
|
||||
- 不要求入口按钮承担 toggle 关闭
|
||||
|
||||
### 6.2.4 内容结构
|
||||
|
||||
抽屉内部继续复用现有 `DocumentAiAgentPanel` 与其 runtime。
|
||||
|
||||
本轮只改:
|
||||
|
||||
- 外层 chrome
|
||||
- 标题区与关闭按钮
|
||||
- 页面级容器布局
|
||||
- 文档页入口位置和打开方式
|
||||
|
||||
本轮不改:
|
||||
|
||||
- `mnote-cli` 执行链
|
||||
- 工具注册表
|
||||
- 页面 AI 读写命令族
|
||||
- AI 输出协议
|
||||
|
||||
### 6.2.5 页面级与全局级边界
|
||||
|
||||
页面文档内优先展示“页面级 AI”。
|
||||
|
||||
全局 AI 继续保留其现有能力,但不在本轮文档页里抢主入口。长期关系应为:
|
||||
|
||||
- 文档页浮动 AI:页面上下文优先
|
||||
- 全局 AI:跨页面/全局工作区能力
|
||||
|
||||
---
|
||||
|
||||
## 7. 实现落点
|
||||
|
||||
## 7.1 顶栏与入口层
|
||||
|
||||
当前文档页右上角操作主入口仍由:
|
||||
|
||||
- `wolai-frontend/src/components/breadcrumb.tsx`
|
||||
|
||||
负责。
|
||||
|
||||
因此本轮入口层优先落在 React compat 主路径,而不是先去大改 Rust SSR 占位按钮。
|
||||
|
||||
首批调整建议:
|
||||
|
||||
- `Breadcrumb` 负责右上角 `...` 入口
|
||||
- `Breadcrumb` 不再突出“页面AI”主按钮
|
||||
- 浮动 AI 入口改由文档页内容壳或页面级 host 提供
|
||||
|
||||
理由:
|
||||
|
||||
- 当前现网入口真正在这里
|
||||
- 直接改这里可以最小改动验证体验
|
||||
- 先把交互壳对齐,再决定 Rust SSR 侧是否同步收口
|
||||
|
||||
## 7.2 页面设置面板组件
|
||||
|
||||
当前 `PageOptionsSidebar` 是一个“常驻侧栏”组件,形态上不适合直接复用为 Wolai popover。
|
||||
|
||||
建议拆成两层:
|
||||
|
||||
1. `PageOptionsPanelContent`
|
||||
- 只负责 tab、设置项、动作项内容
|
||||
- 不假设自己是 `aside`
|
||||
|
||||
2. `PageOptionsPopover`
|
||||
- 负责定位、宽度、开关语义、关闭语义
|
||||
- 作为文档页 owner 态页面设置入口的正式容器
|
||||
|
||||
同时保留:
|
||||
|
||||
- `PageOptionsSidebar`
|
||||
|
||||
作为兼容/开发容器,避免 dev playground 与旧测试全部失效。
|
||||
|
||||
### 7.2.1 页面设置状态
|
||||
|
||||
当前 `usePageLayoutStore.showInspector` 语义过于偏“右侧常驻 inspector”。
|
||||
|
||||
本轮建议把它改造成更接近“页面 chrome 状态”的命名,例如:
|
||||
|
||||
- `pageSettingsOpen`
|
||||
|
||||
或等价 surface state,但不要把 AI 和页面设置混成一个大 store。
|
||||
|
||||
最小原则:
|
||||
|
||||
- 页面设置开关状态独立
|
||||
- 不影响 AI drawer store
|
||||
- 不重新发明 `pageOptions` 数据真相
|
||||
|
||||
## 7.3 页面设置动作项接线
|
||||
|
||||
动作项接线优先复用现有能力:
|
||||
|
||||
- `页面历史...` -> `DocumentHistoryDrawer`
|
||||
- `公开分享页面...` -> `DocumentShareDialog`
|
||||
|
||||
本轮延后:
|
||||
|
||||
- `移动到...`
|
||||
- `嵌入到...`
|
||||
- `删除页面`
|
||||
|
||||
这些项可以先作为 disabled/coming soon,或只在 checklist 中保留为后续项,但不要假装完成。
|
||||
|
||||
## 7.4 页面 AI host
|
||||
|
||||
页面 AI 的正式 runtime 继续使用:
|
||||
|
||||
- `DocumentAiAgentPanel`
|
||||
- `DocumentAiAgentPanel.runtime`
|
||||
|
||||
本轮只需要把“谁来打开它、以什么容器打开它”改对。
|
||||
|
||||
建议:
|
||||
|
||||
- 页面级浮动 AI 入口挂在 `DocumentContent` 这一层
|
||||
- 页面 AI 打开状态继续用 `useAiAgentUiStore.documentAgentOpen`
|
||||
- 页面 AI 可用态继续由 `DocumentAiAgentPanel` mount 生命周期维护
|
||||
|
||||
需要避免:
|
||||
|
||||
- 再新增一份 `PageAiDrawer` 独立 runtime
|
||||
- 把页面 AI 又接回 `GlobalAiAgentHost`
|
||||
|
||||
## 7.5 与 Rust SSR 的关系
|
||||
|
||||
Rust `mnote-web` 当前在文档壳中已有顶栏占位按钮与右下角浮动按钮。
|
||||
|
||||
本轮不把 Rust SSR 作为首批真实交互 owner,原因是:
|
||||
|
||||
- 当前现网文档页真实入口仍由 React compat 壳主导
|
||||
- 先在 React compat 层做对入口与容器,风险更低
|
||||
- 等行为稳定后,再决定是否把 Rust SSR 占位按钮收口到同一 contract
|
||||
|
||||
这意味着本轮的正确做法是:
|
||||
|
||||
> **先统一产品行为合同,再决定是否让 Rust SSR 与 React compat 共用同一套入口渲染。**
|
||||
|
||||
---
|
||||
|
||||
## 8. 分阶段实施建议
|
||||
|
||||
## 8.1 Phase A:设计与基线冻结
|
||||
|
||||
- 固定 Wolai 页面设置和 AI 抽屉的动作链基线
|
||||
- 新增专属 checklist
|
||||
- 明确哪些页面设置项本轮保留、隐藏、降级
|
||||
- 明确页面 AI 与全局 AI 的入口边界
|
||||
|
||||
## 8.2 Phase B:页面设置交互壳
|
||||
|
||||
- 把 `PageOptionsSidebar` 抽成可复用内容组件
|
||||
- 文档页顶栏 `...` 接入 `PageOptionsPopover`
|
||||
- 对齐关闭语义、URL 不变、无遮罩
|
||||
- 最小接线 `历史` 与 `分享`
|
||||
|
||||
## 8.3 Phase C:页面 AI 交互壳
|
||||
|
||||
- 增加右下角浮动 `AI` 入口
|
||||
- 让页面 AI 通过右侧抽屉打开
|
||||
- 去掉顶栏“页面AI”主入口地位
|
||||
- 对齐 AI drawer 的关闭语义
|
||||
|
||||
## 8.4 Phase D:动作项与回归补齐
|
||||
|
||||
- 页面设置中逐步接通 `移动到 / 嵌入到 / 删除`
|
||||
- 评估是否追加帮助浮动入口对齐
|
||||
- 为 owner/published 两种状态补差异 smoke
|
||||
|
||||
---
|
||||
|
||||
## 9. 风险与约束
|
||||
|
||||
### 9.1 双 owner 风险
|
||||
|
||||
当前 `3000` 仍有:
|
||||
|
||||
- Rust SSR 产品壳
|
||||
- React compat 真正交互壳
|
||||
|
||||
如果同时在两边各自补交互,容易再次分裂。
|
||||
|
||||
本轮约束:
|
||||
|
||||
> **入口行为先只认一套真实 owner。**
|
||||
|
||||
### 9.2 页面设置“看起来能改,实际没生效”的风险
|
||||
|
||||
这仍是页面设置线的核心风险。
|
||||
|
||||
本轮约束:
|
||||
|
||||
- 未接通项继续显式降级
|
||||
- 不因为换成 Wolai 容器就把所有项都宣称正式可用
|
||||
|
||||
### 9.3 页面 AI 重复造轮子的风险
|
||||
|
||||
如果为了像 Wolai 而新做一层 AI drawer runtime,会直接偏离 `CLI-first`。
|
||||
|
||||
本轮约束:
|
||||
|
||||
> **页面 AI 只换壳,不换执行面。**
|
||||
|
||||
### 9.4 范围失控风险
|
||||
|
||||
页面设置一旦带上评论、成员、协作、演示模式,很容易从“交互壳对齐”膨胀成“整页顶栏重做”。
|
||||
|
||||
本轮约束:
|
||||
|
||||
- 优先做页面设置
|
||||
- 优先做页面 AI
|
||||
- 其他项延后
|
||||
|
||||
---
|
||||
|
||||
## 10. 验收标准
|
||||
|
||||
只有同时满足以下条件,才可以说这条线进入实现阶段:
|
||||
|
||||
- 页面设置入口、容器、关闭语义已和 Wolai 基线一致
|
||||
- 页面 AI 入口、容器、关闭语义已和 Wolai 基线一致
|
||||
- 页面设置仍继续走 `page.layout.updateOptions`
|
||||
- 页面 AI 仍继续走 `DocumentAiAgentPanel -> mnote-cli`
|
||||
- 没有新增第二套页面设置真相
|
||||
- 没有新增第二套页面 AI 执行面
|
||||
- 评论、协作、成员、演示模式没有被混入首批范围
|
||||
|
||||
本轮完成后的正确口径应是:
|
||||
|
||||
> **文档页“页面设置”和“AI 界面”的交互壳开始按 Wolai 收口,但页面域单一真源与 CLI-first AI 的主线保持不变。**
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
# 5-11 [process] Wolai 页面设置与 AI 交互壳连续执行 checklist v1
|
||||
|
||||
> 更新时间:2026-05-06
|
||||
>
|
||||
> 本清单服务于:
|
||||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-10-wolai-page-settings-and-ai-surface-alignment-v1.md`
|
||||
>
|
||||
> 执行口径继续统一服从:
|
||||
> - `/home/lix/.codex/skills/wolai-aline/SKILL.md`
|
||||
> - `/mnt/Data1T/mnote/design/08-wolai-aline-test-flow/process/wolai-aline-test-flow-v1.md`
|
||||
|
||||
## 1. 使用方式
|
||||
|
||||
每次只领取一个最小行为,按下面闭环推进:
|
||||
|
||||
1. 用一句话定义行为,例如“右上角 `...` 打开页面设置 popover 且 URL 不变”。
|
||||
2. 派 subagent 先取 Wolai 基线。
|
||||
3. 主线程复核截图并填写差异矩阵。
|
||||
4. 新增或更新本地 smoke,先让当前实现失败。
|
||||
5. 小范围实现,不新造第二份页面真相或 AI 执行面。
|
||||
6. 运行本地 smoke 和相关单测。
|
||||
7. 再派 subagent 对 Wolai 与本地复测。
|
||||
8. 主线程复核最终截图。
|
||||
9. 更新本清单状态、证据路径和剩余差异。
|
||||
|
||||
状态标记:
|
||||
|
||||
- `TODO`:未开始
|
||||
- `BASELINE`:Wolai 基线已取
|
||||
- `RED`:本地失败 smoke 已存在
|
||||
- `GREEN`:本地实现与 smoke 已通过
|
||||
- `PARITY`:subagent 复测和主线程截图复核通过
|
||||
- `BLOCKED`:存在阻塞
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前基线证据
|
||||
|
||||
2026-05-06 已完成 Wolai 页面设置与 AI 界面的只读基线取证,目录:
|
||||
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/`
|
||||
|
||||
当前已确认事实:
|
||||
|
||||
| 项 | Wolai 证据 | 当前结论 |
|
||||
| --- | --- | --- |
|
||||
| 页面设置入口 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/10-page-settings-open.png` | 右上角 `...` 打开右侧贴边 popover,URL 不变 |
|
||||
| 页面设置关闭 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/11-page-settings-after-esc.png` `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/13-page-settings-after-outside-click.png` `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/15-page-settings-after-reclick.png` | `Esc`、点击空白、再次点击入口都可关闭 |
|
||||
| 页面设置结构 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/10-page-settings-open.json` | 3 个 tab,内部主控件是 checkbox 形态 |
|
||||
| AI 入口 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/20-ai-open.png` | 右下角浮动 `AI` 按钮打开右侧抽屉,URL 不变 |
|
||||
| AI 关闭 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/21-ai-after-esc.png` `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/23-ai-after-outside-click.png` `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/27-ai-after-close-button.png` | `Esc` 和点击空白无效,只能点右上角 `X` |
|
||||
| AI 结构 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/20-ai-open.json` | 标题“智能问答”,有会话区、模型区、输入框和发送按钮 |
|
||||
|
||||
### 2.1 用户追加截图复核(2026-05-06)
|
||||
|
||||
用户追加的当前 `3000` 截图:
|
||||
|
||||
- `/mnt/Data1T/mnote/tmp/image copy 44.png`
|
||||
- `/mnt/Data1T/mnote/tmp/image copy 45.png`
|
||||
|
||||
当前补充判断:
|
||||
|
||||
- `image copy 44.png` 和 `image copy 45.png` 暴露的是三类真实问题:页面设置 tab-panel 混显、页面设置保存后回退、页面 AI 抽屉没有真实文本返回。
|
||||
- 这三类问题已经在本轮代码修复中逐项落地:
|
||||
- `styles.rs`:补 `[hidden]` surface 样式,修复 `页面选项 / 自定义页面 / 全局选项` 混显。
|
||||
- `documents.rs + bridge-runtime + document.rs + layout.rs`:修复页面设置写链、读链和 SSR 首屏注入,解决“闪一下又复原”。
|
||||
- `compat.rs + layout.rs`:修复真实 `/api/ai-agent/run` 返回文本,页面 AI 默认 provider 对齐为 `hermes`。
|
||||
|
||||
---
|
||||
|
||||
## 3. 通用证据矩阵
|
||||
|
||||
每项必须记录下列字段:
|
||||
|
||||
| 字段 | 要求 |
|
||||
| --- | --- |
|
||||
| Wolai 截图 | 绝对路径,保存在 `/mnt/Data1T/mnote/tmp/wolai-editor-parity/<task>/` |
|
||||
| 本地截图 | 同视口、同动作链截图 |
|
||||
| 入口 | 按钮、菜单、浮动入口、快捷键 |
|
||||
| 关闭路径 | `Esc`、点击空白、再次点击入口、关闭按钮 |
|
||||
| URL | 操作前后是否变化 |
|
||||
| 容器类型 | `popover`、`drawer`、`sheet`、`modal` |
|
||||
| 控件类型 | `checkbox`、`button`、`tab`、`textarea` 等 |
|
||||
| 控件状态 | `checked`、`selected`、`focused`、`disabled`、`active` |
|
||||
| DOM/ARIA | `role`、`aria-*`、`data-testid`、可聚焦性 |
|
||||
| smoke | 对应 `scripts/task*-smoke.js` 或测试文件 |
|
||||
| 剩余差异 | 不允许只写“基本一致” |
|
||||
|
||||
---
|
||||
|
||||
## 4. Phase A:页面设置基线与壳层
|
||||
|
||||
| ID | 状态 | 任务 | 验收要点 |
|
||||
| --- | --- | --- | --- |
|
||||
| A1 | BASELINE | Wolai 页面设置基线 | 已有 2026-05-06 Wolai 基线截图和 JSON |
|
||||
| A2 | GREEN | 本地页面设置入口现状基线 | `task160` 已记录并复测当前文档页右上角 `更多` 打开页面设置容器,URL 不变 |
|
||||
| A3 | GREEN | 页面设置入口 tooltip | `task160` 已断言入口 `title="页面选项和全局选项"` |
|
||||
| A4 | GREEN | 页面设置容器类型 | `task160` 已断言本地打开右侧贴边 `popover`,不再是空按钮 active |
|
||||
| A5 | GREEN | 页面设置 URL 合同 | `task160` 已断言打开和关闭页面设置时 URL 不变化 |
|
||||
| A6 | GREEN | 页面设置关闭语义 | `task160` 已断言 `Esc`、点击空白、再次点击入口全部有效 |
|
||||
| A7 | GREEN | 页面设置 3 tab | `task160` 已在真实后端端口上断言 `页面选项 / 自定义页面 / 全局选项` 的 tab-panel 隔离行为 |
|
||||
| A8 | GREEN | 页面选项主控件形态 | `task160` 已断言首 tab 使用 checkbox 行,而不是旧 inspector 大块按钮 |
|
||||
| A9 | GREEN | 最小设置项保留清单 | `task160` 已断言 `wideLayout / smallText / showToc / showHeadingNumbers / protectEditing` 出现在首 tab |
|
||||
| A10 | GREEN | 未接通项显式降级 | `task160` 已断言 `showToc / protectEditing` 当前 disabled 且带“待接线”说明 |
|
||||
|
||||
### 4.1 本阶段 smoke 建议
|
||||
|
||||
- `scripts/task160-wolai-page-settings-shell-smoke.js`
|
||||
|
||||
首轮最小断言建议:
|
||||
|
||||
- 点击右上角 `...` 后 URL 不变
|
||||
- 出现页面设置 `popover`
|
||||
- 出现三 tab
|
||||
- `Esc` 可关闭
|
||||
- 点击页面空白可关闭
|
||||
- 再次点击入口可关闭
|
||||
|
||||
### 4.2 task160 页面设置壳执行记录
|
||||
|
||||
2026-05-06 已新增并执行 `scripts/task160-wolai-page-settings-shell-smoke.js`,用于固化 A2-A7 的本地 RED 基线。
|
||||
|
||||
RED:
|
||||
|
||||
- 命令:`node scripts/task160-wolai-page-settings-shell-smoke.js`
|
||||
- 结果:失败
|
||||
- 失败信息:`页面设置入口必须打开右侧贴边 popover`
|
||||
- 当前本地状态:
|
||||
- 点击右上角 `更多` 后 URL 保持文档页不变
|
||||
- 顶栏 `更多` 获得焦点,但没有打开页面设置容器
|
||||
- 当前页面中未出现页面设置 popover;探测到的唯一 `tablist` 仍是左侧 `我的页面 / Explorer / +`
|
||||
|
||||
证据路径:
|
||||
|
||||
- 本地点击后截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/01-after-click-more.png`
|
||||
- 本地点击后状态:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/01-after-click-more.json`
|
||||
- 本地失败截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/failure.png`
|
||||
- 本地失败状态:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/failure-state.json`
|
||||
|
||||
当前判断:
|
||||
|
||||
- A2 已有本地基线
|
||||
- A4 已形成真实 RED
|
||||
- A5 目前从 failure-state 可见点击后 URL 未变化,但完整打开/关闭合同仍待容器实现后继续验证
|
||||
- A6-A7 仍待容器出现后继续验证
|
||||
|
||||
GREEN:
|
||||
|
||||
- 命令:`node scripts/task160-wolai-page-settings-shell-smoke.js`
|
||||
- 结果:通过
|
||||
- 当前通过行为:
|
||||
- 右上角 `更多` 打开页面设置 `popover`
|
||||
- URL 保持不变
|
||||
- `Esc`、点击空白、再次点击入口均可关闭
|
||||
- 顶部存在 `页面选项 / 自定义页面 / 全局选项`
|
||||
- 页面设置首 tab 使用 checkbox 行
|
||||
- `showToc / protectEditing` 当前显式降级
|
||||
|
||||
新增证据:
|
||||
|
||||
- `task160` 最终截图:
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/01-after-click-more.png`
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/02-after-esc.png`
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/03-after-outside-click.png`
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/04-after-reclick.png`
|
||||
|
||||
修复补充(2026-05-06):
|
||||
|
||||
- 在 `styles.rs` 中补了 `.wolai-page-settings-section[hidden] { display: none !important; }`
|
||||
- `task160` 随后已在真实后端端口 `41327` 上验证 `页面选项` 不再混出 `自定义页面` 字段,`自定义页面 / 全局选项` 的 panel 行为恢复正常
|
||||
|
||||
---
|
||||
|
||||
## 5. Phase B:页面设置动作项与现有能力接线
|
||||
|
||||
| ID | 状态 | 任务 | 验收要点 |
|
||||
| --- | --- | --- | --- |
|
||||
| B1 | GREEN | `页面历史...` 接线 | `task160` 已断言页面设置动作项可打开 Rust Web 页面历史抽屉 |
|
||||
| B2 | GREEN | `公开分享页面...` 接线 | `task160` 已断言页面设置动作项可打开 Rust Web 公开分享对话框 |
|
||||
| B3 | GREEN | `移动到...` 入口策略 | `task160` 已断言当前显式为 disabled/placeholder |
|
||||
| B4 | GREEN | `嵌入到...` 入口策略 | `task160` 已断言当前显式为 disabled/placeholder |
|
||||
| B5 | GREEN | `删除页面` 入口策略 | `task160` 已断言当前显式为 disabled/placeholder |
|
||||
| B6 | GREEN | 统计信息布局 | `task160` 已断言底部存在紧凑统计信息区 |
|
||||
| B7 | GREEN | 页面设置项真实生效 | `task160` 已在真实后端端口上断言 `wideLayout`、`layoutDensity` 持久化并在刷新后回读成功 |
|
||||
|
||||
### 5.1 本阶段 smoke 建议
|
||||
|
||||
- 在 `task160` 基础上扩展动作项断言
|
||||
- 新增针对已接通选项的可见结果断言
|
||||
|
||||
最低要求:
|
||||
|
||||
- 历史入口可打开现有历史抽屉
|
||||
- 分享入口可打开现有分享对话框
|
||||
- `wideLayout`、`smallText`、`layoutDensity` 这类已接通项能在页面可见变化中被捕获
|
||||
|
||||
### 5.2 task160 Phase B 执行记录
|
||||
|
||||
2026-05-06 `task160` 已继续覆盖 B1-B7,当前通过:
|
||||
|
||||
- `页面历史...` 可打开 `data-testid="wolai-page-history-drawer"`
|
||||
- `公开分享页面...` 可打开 `data-testid="wolai-page-share-dialog"`
|
||||
- `移动到... / 嵌入到... / 删除页面` 当前显式 disabled
|
||||
- 页面设置底部显示字数、字符、块数、待办统计
|
||||
- `wideLayout` 写链真实命中 `/api/documents/options`
|
||||
- `layoutDensity` 写链真实命中 `/api/documents/options`
|
||||
- `wideLayout` 打开后 `.document-shell` 宽度真实增大
|
||||
|
||||
修复补充(2026-05-06):
|
||||
|
||||
- 先修了 `mnote-web` 页面设置 route payload 与 `bridge-runtime` command plan:不再把 `workspaceId` 和一组 `null` 选项继续下发到 `documents:updateOptions`
|
||||
- 再修了 `DocumentPage` 的 SSR `data-page-*` 首屏注入,以及 `SIDEBAR_TREE_JS` 初始化顺序,避免在 `__MNOTE_PAGE_AGGREGATE__` 还未进入 DOM 时把默认 page options 缓存死
|
||||
- 之后通过真实后端端口 `41327` 验证:
|
||||
- `/api/documents/options` 返回 200
|
||||
- `/api/page-aggregate/:id` 能读回 `wideLayout=true`、`layoutDensity=compact`
|
||||
- `task160` 刷新后 checkbox 和壳层 attr 不再回退
|
||||
|
||||
---
|
||||
|
||||
## 6. Phase C:页面 AI 入口与抽屉壳
|
||||
|
||||
| ID | 状态 | 任务 | 验收要点 |
|
||||
| --- | --- | --- | --- |
|
||||
| C1 | BASELINE | Wolai 页面 AI 基线 | 已有 2026-05-06 Wolai 基线截图和 JSON |
|
||||
| C2 | GREEN | 本地页面 AI 入口现状基线 | `task161` 已记录并复测右下角 AI 可打开页面 AI 抽屉,URL 不变 |
|
||||
| C3 | GREEN | 页面 AI 主入口迁到右下角 | `task161` 已断言页面级 AI 主入口为右下角浮动按钮 |
|
||||
| C4 | GREEN | 顶栏 `页面AI` 降级 | `task161` 已断言顶栏不再保留 `页面AI` 主入口 |
|
||||
| C5 | GREEN | 页面 AI 容器类型 | `task161` 已断言页面 AI 以右侧抽屉打开、无遮罩、不跳新页面 |
|
||||
| C6 | GREEN | 页面 AI 关闭语义 | `task161` 已断言 `Esc`、点击空白无效,右上角 `X` 有效 |
|
||||
| C7 | GREEN | 页面 AI 页面级绑定 | `task161` 已断言 `/api/ai-agent/run` 请求体携带当前 `documentId` 与 `pageOptions` |
|
||||
| C8 | GREEN | 页面 AI 执行面不分裂 | 真实 `/api/ai-agent/run` 已改为 `Next 兼容优先 -> 本地 mnote-cli fallback -> 旧 orchestrator 兜底`;`task162` 已验证真实页面可返回文本结果 |
|
||||
| C9 | GREEN | AI chrome 与 Wolai 接近 | `task161` 已断言标题、输入区、`新会话 / 历史会话 / mnote-cli` chrome 可见 |
|
||||
|
||||
### 6.1 本阶段 smoke 建议
|
||||
|
||||
- `scripts/task161-wolai-page-ai-shell-smoke.js`
|
||||
|
||||
首轮最小断言建议:
|
||||
|
||||
- 点击右下角 AI 后 URL 不变
|
||||
- 打开右侧抽屉
|
||||
- 抽屉无遮罩
|
||||
- `Esc` 不关闭
|
||||
- 点击页面空白不关闭
|
||||
- 点右上角关闭按钮可关闭
|
||||
|
||||
### 6.2 task161 页面 AI 壳执行记录
|
||||
|
||||
2026-05-06 已新增并执行 `scripts/task161-wolai-page-ai-shell-smoke.js`,用于固化 C2-C6 的本地 RED 基线。
|
||||
|
||||
RED:
|
||||
|
||||
- 命令:`node scripts/task161-wolai-page-ai-shell-smoke.js`
|
||||
- 结果:失败
|
||||
- 失败信息:`页面 AI 入口必须打开右侧抽屉`
|
||||
- 当前本地状态:
|
||||
- 点击右下角 `AI 助手` 后 URL 保持文档页不变
|
||||
- 浮动 AI 按钮没有打开抽屉
|
||||
- 当前页面中未出现页面 AI 容器、关闭按钮、标题或输入框
|
||||
|
||||
证据路径:
|
||||
|
||||
- 本地点击后截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/01-after-click-ai.png`
|
||||
- 本地点击后状态:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/01-after-click-ai.json`
|
||||
- 本地失败截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/failure.png`
|
||||
- 本地失败状态:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/failure-state.json`
|
||||
|
||||
当前判断:
|
||||
|
||||
- C2 已有本地基线
|
||||
- C5 已形成真实 RED
|
||||
- C6 仍待抽屉出现后继续验证
|
||||
- C7-C8 仍待实现阶段继续验证
|
||||
|
||||
GREEN:
|
||||
|
||||
- 命令:`node scripts/task161-wolai-page-ai-shell-smoke.js`
|
||||
- 结果:通过
|
||||
- 当前通过行为:
|
||||
- 右下角 AI 入口打开页面级右侧抽屉
|
||||
- URL 保持不变
|
||||
- `Esc` 和点击空白不会关闭
|
||||
- 右上角关闭按钮可关闭
|
||||
- 抽屉标题、输入区、会话/模型 chrome 可见
|
||||
- 发送动作继续命中 `/api/ai-agent/run`
|
||||
- 请求体继续携带当前 `documentId` 与 `pageOptions`
|
||||
|
||||
新增证据:
|
||||
|
||||
- `task161` 最终截图:
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/01-after-click-ai.png`
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/02-after-esc.png`
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/03-after-outside-click.png`
|
||||
- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/04-after-close-button.png`
|
||||
|
||||
修复补充(2026-05-06):
|
||||
|
||||
- `compat.rs` 的 `/api/ai-agent/run` 已改为:
|
||||
- 先尝试代理到 Next 的 `/api/ai-agent/run`
|
||||
- 失败时本地直接 `mnote-cli` host fallback
|
||||
- 再失败才走旧 orchestrator
|
||||
- 同时补了认证头显式转发,避免被 Next 侧 307 `/auth` 拦截
|
||||
- 页面 AI drawer 默认 provider 改为 `hermes`
|
||||
- 新增 `task162-wolai-page-ai-real-response-smoke.js`,并在真实后端端口 `41327` 上验证:页面 AI 不再显示 `page_ai_failed_502` / “没有返回文本结果”,而是会回填真实文本
|
||||
|
||||
### 6.3 task162 页面 AI 真实返回执行记录
|
||||
|
||||
2026-05-06 已新增并执行 `scripts/task162-wolai-page-ai-real-response-smoke.js`,用于补齐 C8 的真实返回验证。
|
||||
|
||||
- 命令:`MNOTE_UI_BASE_URL=http://127.0.0.1:41327 node scripts/task162-wolai-page-ai-real-response-smoke.js`
|
||||
- 结果:通过
|
||||
- 当前通过行为:
|
||||
- 页面 AI 不再出现 `page_ai_failed_502`
|
||||
- 不再显示“当前页面 AI 已接通 \`mnote-cli\`,但这次没有返回文本结果。”
|
||||
- 页面 AI 会回填真实 `mnote-cli` 输出文本
|
||||
|
||||
---
|
||||
|
||||
## 7. Phase D:页面 AI 与页面设置的集成护栏
|
||||
|
||||
| ID | 状态 | 任务 | 验收要点 |
|
||||
| --- | --- | --- | --- |
|
||||
| D1 | GREEN | 不新造页面设置真相 | 页面设置继续围绕 `currentPageOptions -> /api/documents/options -> page.layout.updateOptions` |
|
||||
| D2 | GREEN | 不新造 AI 执行面 | 页面 AI 继续围绕 `/api/ai-agent/run -> mnote-cli` |
|
||||
| D3 | GREEN | 文档页 owner 行为合同固定 | `task160/task161` 已断言 owner 态页面设置和 AI 都不跳新页面、不改 URL |
|
||||
| D4 | GREEN | mobile / 窄屏退化 | `task160/task161` 已断言移动视口下 popover / drawer 不超出视口 |
|
||||
| D5 | GREEN | React compat 与 Rust SSR 边界 | 本轮实现仅落在 `mnote-web` Rust SSR 壳、脚本与样式;未再把入口回接 React compat |
|
||||
| D6 | GREEN | checklist 与失败模式回填 | 已向 `wolai-aline/references/failure-patterns.md` 新增“本地 3000 进程未重启,smoke 误打旧实现” |
|
||||
|
||||
---
|
||||
|
||||
## 8. Deferred 清单
|
||||
|
||||
以下项当前明确延后,不混入首批验收:
|
||||
|
||||
| ID | 状态 | 任务 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| X1 | TODO | 演示模式 | 不是本轮页面设置与 AI 壳的主线 |
|
||||
| X2 | TODO | 页面评论 | 用户已明确可延后 |
|
||||
| X3 | TODO | 页面协作 | 用户已明确可延后 |
|
||||
| X4 | TODO | 成员邀请 | 顶栏 owner 态能力,后续单拆 |
|
||||
| X5 | TODO | 全局 AI 入口重构 | 本轮只做页面级 AI |
|
||||
| X6 | TODO | 帮助浮动入口完全对齐 | 本轮优先 AI,不把帮助入口一起扩面 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 完成判定
|
||||
|
||||
本清单只有在以下条件同时成立时,才可以视为本轮设计进入可实现状态:
|
||||
|
||||
- 页面设置 `popover` 行为已通过本地 smoke 和 Wolai 基线复核
|
||||
- 页面 AI 抽屉行为已通过本地 smoke 和 Wolai 基线复核
|
||||
- 页面设置仍然围绕 `page.layout.updateOptions`
|
||||
- 页面 AI 仍然围绕 `/api/ai-agent/run -> mnote-cli`
|
||||
- deferred 项没有被误报为已完成
|
||||
|
||||
本轮完成后的正确口径:
|
||||
|
||||
> **页面设置与页面 AI 的交互壳已开始对齐 Wolai,但评论、协作、成员、演示模式仍是后续独立任务。**
|
||||
@@ -390,6 +390,16 @@ GREEN:
|
||||
- E24 图片最小真源闭环:2026-05-01 已按 Wolai E13 slash 基线确认 `媒体与附件` 分组存在 `图片 /tp` 与 `最近上传图片 /tp`;第一段实现 `图片 /tp` 最小切片,参考 `leptos-tiptap` 官方 `TiptapImageResource` / `set_image` bridge(`src/api/types/extensions/image.rs`、`src/api/commands.rs`、`tiptap/src/extensions/tiptap_image.ts`)与 template `components/tiptap-node/image-node/*`、`image-upload-node/*`,不手写 image JSON。当前本地 `SLASH_ACTIONS` 已补 `图片 /tp` 和 `媒体与附件` 分组,`p0_extensions()` 显式启用 `TiptapExtension::Image`,点击后调用 `editor.set_image(TiptapImageResource { ... })` 插入真实 Tiptap `image` 节点;`core-protocol` 新增 `EditorBlockType::Image` / `TiptapNode::Image`,`bridge-runtime` 保存为 legacy `image` 且保留 `props.tiptapImage`,`mnote-web` bootstrap 从 content API 恢复为 `<img>`;本地只读占位资源走 `/api/editor/image-placeholder.svg`,避免 smoke 依赖外网或破图。第二段补图片点击选中态与图片专用 floating toolbar,参考 `tiptap-notion-like-registry/materialized/tiptap-node/image-node/image-node-floating.tsx`、`image-node-extension.ts`、`tiptap-ui/image-align-button/use-image-align.ts`、`tiptap-ui/image-download-button/use-image-download.ts`:本地点击 `<img>` 后展示 `image-floating-toolbar`,提供左/中/右对齐和同源图片下载,删除入口本切片保持禁用;图片对齐通过 `Image.extend({ addAttributes: { "data-align" } })` 扩展官方 Image schema 后调用 `editor.update_attributes(TiptapSchemaTarget::Node(TiptapNodeName::Image), ...)`,不是 UI 伪样式;同源下载只读当前 NodeSelection 图片 DOM 的 `src/title/alt`,用隐藏 `<a download>` 触发,不触发保存链。`task152-e24-image-smoke.js` 覆盖 slash 入口、DOM `<img>`、图片实际加载、图片 toolbar、同源下载事件、删除入口禁用态、居中对齐 `data-align`、保存请求 `tiptapDocument`、`/api/documents/content` image 真源与 reload 恢复;通过截图目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task152-e24-image-download-green`。剩余:真实上传、最近上传图片、caption、resize、replace、跨源下载 fallback、删除保存链、移动端 toolbar、上传失败态另拆后续。
|
||||
|
||||
- E25 TOC 最小真源闭环:2026-05-01 已按 Wolai slash 基线确认 `页面目录 /toc`,并参考 `tiptap-notion-like-template/src/components/tiptap-node/toc-node/*`、`toc-show-title-button/*`、`toc-sidebar/*` 与 `notion-like-editor.tsx` 中 `TableOfContents.configure({ onUpdate })` 的数据链路。当前本地先完成第一段:`leptos-tiptap` 新增 `toc_node` bridge 扩展,真实 Tiptap schema 名为 `tocNode`,slash `页面目录 /toc` 调用 `editor.insert_toc_node(TiptapTocNodeAttrs { top_offset: 0, max_show_count: 20, show_title: true })`,不是普通 div 或手写 spike JSON;NodeView 从当前 Tiptap doc 的 heading 节点派生目录项,支持点击目录项定位并更新 hash,支持标题显示开关并通过 `updateAttributes("tocNode", { showTitle })` 持久化。保存链新增 `EditorBlockType::Toc` / `TiptapNode::TocNode`,`bridge-runtime` legacy content 保留 `props.tiptapTocNode`,`mnote-web` reload 恢复 `tocNode`;`task153-e25-toc-smoke.js` 覆盖 `/toc` 入口、真实 tocNode DOM、heading 列表派生、动态 heading 更新、点击定位、标题开关、保存请求、content API 和 reload 恢复。截图目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task153-e25-toc-local-smoke`。剩余:接入 Tiptap 官方 `@tiptap/extension-table-of-contents` v3 数据源或完成等价 bridge 评估、TOC sidebar、active heading 高亮、完整块菜单标题开关入口、Wolai 像素级视觉、移动端行为、UniqueID/anchor 统一化。
|
||||
- E26 执行前口径纠偏:2026-05-02 已按 `5-2`、`5-4`、`5-5`、`5-6` 和 `5-7` 设计确认,E26 不是“前端引入 Tiptap UniqueID 即完成”。正式块身份必须来自 Rust `EditorBlock.block_id`,经 Tiptap bridge 映射为 `data-block-id` 供浏览器 runtime 使用,再通过 `page.body.save` 写回 Convex-backed 持久化底座;复制锚点和 hash 定位只能消费这个真源 id。Tiptap `UniqueID` 可以参考其节点身份策略,但不得生成长期块 id、不得绕过 Rust `EditorBlockDocument`、不得绕过 Page Aggregate / `page.body.save`。
|
||||
- E26 执行边界:实现与 smoke 必须把 `EditorBlockDocument -> Tiptap attrs.blockId/data-block-id -> DOM 锚点 -> page.body.save -> /api/documents/content -> reload/hash 定位` 串成一条链。允许在浏览器 runtime 内用 `UniqueID` 或等价插件帮助定位节点,但只能读取/补齐已有 Rust block id;若某块缺少正式 id,应通过 Rust/保存适配链生成并持久化,而不是让前端临时 id 成为长期合同。Convex 只验证持久化结果可读可刷新,不作为语义真源。
|
||||
- E26 最小真源闭环:2026-05-02 已完成第一段 anchor 切片。`leptos-tiptap` paragraph/heading/blockquote/codeBlock/image/table 的 `blockId` 渲染同时输出 `data-block-id` 与 DOM `id`,浏览器 hash 命中走 `id=:blockId` + CSS `:target`,不是手工给 ProseMirror DOM 写临时 class;Rust runtime 复制链接和 hash 滚动继续只消费 `EditorBlock.block_id` 派生的 `attrs.blockId`。`mnote-web` 保存 payload 不再发送空 `content: []`,而是派生 `editorDocument`、legacy `content`、`tiptapDocument` 和 `blockCount` 写回 Convex-backed 持久化底座;reload 侧 legacy block 恢复继续补 `attrs.blockId`。本地 smoke `node scripts/task154-e26-anchor-smoke.js` 已覆盖保存请求、`/api/documents/content`、复制链接、DOM `id/:target` 和 reload/hash 定位,截图目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task154-e26-anchor-local-smoke`。剩余:列表项/分割线等更多块类型的统一 anchor attr 覆盖、Wolai 视觉细节、块引用/页面引用预览与移动端行为另拆后续。
|
||||
- E27 执行前口径纠偏:AI 编辑能力包不是“补 AI 菜单文案”或“点击后显示 feedback”。最小闭环必须从 `leptos-tiptap` 的 slash / 块菜单入口出发,携带当前 `documentId`、`workspaceId`、Rust `blockId`、selection 摘要和 Tiptap JSON 快照,调用 mnote 现有 AI 真源边界。2026-05-05 起长期口径进一步修正:`/api/ai-agent/run` 不应长期绑定 `openai-agents-python` sidecar,而应收口为 `mnote-cli` 唯一长期 agent 执行面上的 host / adapter;`openai-agents-python`、`Hermes`、`Codex` 只允许作为可插拔外置 agent。结构化写入仍必须回到 Rust tool / `page.body.save` / Convex-backed content 链。E27 第一刀已完成的 sidecar 路径只作为过渡基线,不宣称是长期主线。
|
||||
- E27 AI agent 入口与写入闭环:2026-05-02 已完成主路径纠偏,修正此前把 `/api/hermes/bridge` 当作 E27 主入口的误导口径。块菜单 `AI 助理` 现在从当前 `leptos-tiptap` editor 读取 `documentId`、`workspaceId`、Rust `blockId`、selection state、selected text 与 `tiptapDocument` 快照,发起 `/api/ai-agent/run` 请求,payload 固定 `scope=document`、`stream=true`、`options.ai.provider=online`,并显示 `mnote-leptos-tiptap-ai-status` 的 `idle/pending/ready/error` 状态;请求上下文标记 `source=leptos-tiptap-island`、`action=ask_ai`,Next sidecar adapter 已透传 `workspaceId / selectedBlockId / selection / tiptapDocument` 等 block 级上下文给 `openai-agents-python`。本地 smoke `node scripts/task155-e27-ai-edit-smoke.js` 已先 RED 于 Hermes 主入口,再 GREEN 覆盖请求 URL、payload 真源字段和 ready 状态;`node scripts/task156-e27-ai-writeback-smoke.js` 已先 RED 于只返回不写入,再 GREEN 覆盖 SSE `doc_replace_range` tool_result -> 编辑器改写 -> `/api/documents/save` -> `/api/documents/content` 真源读回 -> reload 后页面读回。截图目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task156-e27-ai-writeback-local-smoke`。剩余:Wolai AI 菜单视觉基线断流未完成、slash AI/selection toolbar AI、Improve/continue/regenerate/summarize/translate 子命令、SSE 分段 UI 状态、`doc_insert_blocks` 多块插入和标题 `slash_run` 应用另拆后续。
|
||||
- E27 Auth 真源纠偏:2026-05-02 补充确认,AI 编辑和在线 smoke 的用户身份必须以真实 Convex Auth 为主线;不同账号的数据隔离依赖 Convex `getAuthUserId(ctx)` 解析真实 identity subject,并由 workspace/member 权限链校验。`/auth` 复用既有 Convex Auth 页面和统一测试账号 `test@example.com` / `Test123456`;`/api/auth/session`、`/api/auth/whoami`、AI orchestrator 转发和 Convex transport 均应真实 token / forwarded actor 优先。`DEV_USER_ID` / admin acting identity 只允许作为本地底层 fallback 或显式 `MNOTE_DEV_AUTH=1` 联调模式,不能作为 E27 在线验收、多账号隔离或正式数据真源。
|
||||
- E27 当前推进备注:2026-05-03 主线程先切到 E28 Mention / Emoji,E27 暂停在 online smoke 模型网关层排障状态。当前已确认 `3000 -> 8000` orchestrator 主链可达,本地 `task155/task156` 通过;剩余在线阻塞点在 `20128 /v1/responses` 上游模型/渠道可用性,以及后续真实 actor 收口。恢复 E27 时应从这两点继续,不要回退成“主入口未迁完”。
|
||||
- E28/E29 暂停与 E30 先行口径:2026-05-03 主线程先暂停 E28 Mention / Emoji 与 E29 Comment / History,转入 E30 Menu / Floating 状态机能力包。E28 已有 Wolai Hermes baseline 显示正文输入 `@` 当前弹出提醒/会议/成员候选,并可插入成员 mention,不是页面引用搜索;证据目录为 `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task157-e28-wolai-mention-baseline/`,恢复 E28 时需先重新定 `@mention` 口径,不要按“页面引用第一刀”继续。E29 在评论/历史后端边界未重新确认前保持暂停。E30 第一刀只收敛已有 slash、块菜单、二级菜单、selection/image/table floating toolbar 的打开互斥、Esc、外部点击、方向键、Enter 与层级收起,不扩新业务命令。
|
||||
- E30 Menu / Floating 状态机第一刀:2026-05-03 已参考 `use-floating-element`、`use-menu-navigation`、`use-floating-toolbar-visibility` 的集中可见性/键盘/关闭模型,把本地已有 slash、块菜单、selection toolbar、image toolbar、table toolbar/options 的关闭与互斥收口到 `close_editor_floating_overlays*` 与 `open_*_overlay` 入口;`task158-e30-menu-state-smoke.js` 覆盖 slash `ArrowDown` active、Esc 关闭、块菜单二级菜单、selection color panel、image toolbar、table options、slash 打开关闭 selection toolbar、块菜单打开关闭 image toolbar。Wolai 基线目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task158-e30-wolai-baseline/`;本地主线程截图目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task158-e30-menu-state-local-smoke-main3`;本地 subagent 复测目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task158-e30-local-postfix-subagent`。剩余:Wolai slash / 块菜单二级菜单在只读条件下未稳定验证,Enter 选中、外部点击和更多三级菜单收起需后续 editable-test 小切片继续补。
|
||||
- E31 Auth 入口回收:2026-05-04 已把 `3000` 的 `/auth` 收回为本地 `mnote-web` SSR 登录页,不再代理 3100;未登录访问 `/` 现在 303 到 `/auth`,已登录(forwarded actor / Convex Auth cookie)才进入工作区。`task159-auth-entry-smoke.js` 覆盖 `/auth` 本地 200、`/` 未登录 303、已登录 200、无第三方快捷登录/隐私政策文案,`task114-rust-web-gateway-entry-smoke.js` 与 `task117-next-retirement-guard.js` 已同步更新。截图待复核:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task159-auth-entry-baseline/`。
|
||||
|
||||
|
||||
| ID | 状态 | 任务 | 验收要点 |
|
||||
@@ -409,11 +419,11 @@ GREEN:
|
||||
| E23 | PARTIAL | TableKit 能力包 | 已完成简单表格可验收切片:`leptos-tiptap` 增加 table/tableRow/tableCell/tableHeader schema,slash `简单表格 /jdbg` 按 Wolai 基线插入 `4x3` 真实 `<table>`,本地 table toolbar 支持下方插入行、右侧插入列、清空当前单元格、删除当前行/列/表格,并补 `选项` 菜单的标题行、标题列、隐藏边框线 switch;已补行侧/列顶 aux controls 和最小 TableSelectionOverlay,点击行/列 aux 会插入行/列并显示对应淡红选择覆盖层,toolbar 保持可用;`core-protocol`/`bridge-runtime`/`mnote-web` 保存与刷新恢复保留 `table` Tiptap 快照、`tableHeader` 和 `attrs.hiddenBorders`;本地 smoke `task151-e23-table-smoke.js` 覆盖入口、DOM、row/column aux 插入、selection overlay、列宽拖拽、switch 语义/状态、保存请求、content API、reload 和删除。剩余表格对齐、fit、数据表格入口,以及 Wolai 选项菜单图标/toolbar 视觉细节另拆后续 |
|
||||
| E24 | PARTIAL | Image / Media 能力包 | 已完成图片 `/tp` 最小真源闭环与图片 toolbar 小闭环:slash `媒体与附件` 分组入口调用 `leptos-tiptap` 官方 `set_image(TiptapImageResource)`,启用 `TiptapExtension::Image`,保存链新增 `EditorBlockType::Image` / `TiptapNode::Image` 并保留 `props.tiptapImage`,`mnote-web` reload 恢复 `<img>`;点击图片后出现 `image-floating-toolbar`,删除入口本切片保持禁用,左/中/右对齐通过官方 Image 扩展 `addAttributes("data-align")` + `updateAttributes("image")` 持久化,同源下载通过隐藏 `<a download>` 触发且不改文档;`task152-e24-image-smoke.js` 覆盖入口、实际图片加载、toolbar、同源下载、删除入口禁用态、居中对齐、保存请求、content API 和刷新恢复;剩余上传、最近上传、caption、resize、replace、跨源下载 fallback、删除保存链、移动端 toolbar、失败态 |
|
||||
| E25 | PARTIAL | TOC 能力包 | 已完成 `/toc` 最小真源闭环:`leptos-tiptap` 新增真实 `tocNode` schema/command,slash `页面目录 /toc` 插入真实节点,NodeView 从当前 headings 派生目录项,支持点击定位、标题显示开关、保存请求、content API 与 reload 恢复;`task153-e25-toc-smoke.js` 覆盖入口、动态 heading 更新、hash 定位和 `props.tiptapTocNode`。剩余 TOC sidebar、active heading 高亮、完整块菜单入口、官方 TableOfContents v3 数据源评估、移动端与像素级视觉 |
|
||||
| E26 | TODO | UniqueID / Anchor 能力包 | 参考 UniqueID/anchor/copy anchor link 相关实现;每个块需要稳定 id,复制链接应指向可恢复的页面/块锚点,刷新后仍可定位 |
|
||||
| E27 | TODO | AI 编辑能力包 | 参考 `ai-context`、AI icons、Improve/Ask AI/continue/regenerate/summarize/translate;先接 mnote 现有 AI command/tool 真源,再做 Wolai 菜单入口和流式状态 |
|
||||
| E28 | TODO | Mention / Emoji 能力包 | 参考 mention trigger 与 emoji menu;实现 `@`、emoji 搜索、键盘导航、插入后的 Tiptap JSON 和 mnote 保存链,不作为纯文本占位 |
|
||||
| E29 | TODO | Comment / History 能力包 | 参考评论入口、块历史入口的菜单形态,结合 mnote 后端能力决定先做 smoke 占位还是真实存储;`Ctrl/Cmd+Alt+M`、评论气泡数量、块历史恢复需单列对标 |
|
||||
| E30 | TODO | Menu / Floating 状态机能力包 | 参考 `use-floating-element`、`use-menu-navigation`、`use-floating-toolbar-visibility`;统一 Esc、外部点击、鼠标移出、方向键、Enter、层级菜单收起逻辑,避免每个菜单各写一套状态机 |
|
||||
| E26 | PARTIAL | UniqueID / Anchor 能力包 | 已完成最小真源闭环:Rust `EditorBlock.block_id` -> Tiptap `attrs.blockId` -> DOM `data-block-id` + `id` -> 复制链接 hash -> `page.body.save` / `/api/documents/content` -> reload 后 `:target` 定位;`task154-e26-anchor-smoke.js` 覆盖保存、复制、reload/hash 和截图。Tiptap `UniqueID` 仍只作为参考/辅助口径,不作为正式块 id;剩余更多块类型 anchor 覆盖、Wolai 视觉细节、引用预览和移动端行为。 |
|
||||
| E27 | PARTIAL | AI 编辑能力包 | 已完成块菜单 `AI 助理` 主路径与最小写入闭环:点击后发起 `/api/ai-agent/run`,payload 使用 `scope=document`、`stream=true`、`options.ai.provider=online`,携带 `documentId`、`workspaceId`、Rust `blockId`、selection、selected text、Tiptap 快照和 `action=ask_ai`;历史基线里 `Hermes` 只作为 `/api/ai-agent/run` 内部 fallback。2026-05-05 起长期口径改为:`/api/ai-agent/run` 后续应收口为 `mnote-cli` 唯一长期 agent 执行面上的 host / adapter,`Hermes`、`Codex`、`openai-agents-python` 仅为可插拔外置 agent;`task155-e27-ai-edit-smoke.js` 与 `task156-e27-ai-writeback-smoke.js` 保留为过渡主链行为基线。Auth 验收必须复用 Convex Auth 测试账号,真实 token / actor 优先,`dev identity` 仅为本地 fallback。当前主线程已于 2026-05-03 先切 E28;E27 暂停在 online smoke 的 `20128 /v1/responses` 模型网关排障与真实 actor 收口。剩余 slash AI/selection toolbar AI、Improve/continue/regenerate/summarize/translate、Wolai 视觉基线、SSE 分段 UI、`doc_insert_blocks` 多块插入与标题写入。 |
|
||||
| E28 | PAUSED | Mention / Emoji 能力包 | 2026-05-03 暂停;Wolai baseline 已纠偏:正文 `@` 当前是提醒/会议/成员候选入口,不是页面引用搜索,恢复时先重定 mention/emoji 口径,再决定 Tiptap JSON 与 mnote 保存链 |
|
||||
| E29 | PAUSED | Comment / History 能力包 | 2026-05-03 暂停;评论/历史入口仍需后端边界和 Wolai 基线复核,待 E30 统一菜单状态机后再接入,避免继续复制独立弹层逻辑 |
|
||||
| E30 | PARTIAL | Menu / Floating 状态机能力包 | 2026-05-03 第一刀已完成本地统一状态机 smoke:`task158` 覆盖 slash、块菜单/二级菜单、selection toolbar/color panel、image floating toolbar、table toolbar/options 的互斥打开、Esc 统一关闭、方向键 active,以及打开块菜单时关闭 image toolbar;Wolai 只读基线已确认 selection/type menu 和 table popper 的 Esc/外部点击/URL 不变,slash 与块菜单二级菜单在只读条件下不稳定,后续仍需 editable-test 复核 Enter、外部点击和更多层级收起 |
|
||||
| E31 | PARTIAL | Tiptap 参考对标 smoke 矩阵 | `task137-wolai-phase-e-smoke.js` 已覆盖 E13 分割线的 DOM `<hr>`、`/api/documents/content` `divider`、刷新恢复和页面转换 `_self` 打开;后续每完成一个能力包仍必须同时断言 Tiptap JSON/schema、mnote 真源保存、Wolai 视觉/交互截图、刷新恢复;截图差异未复核不得标 DONE |
|
||||
|
||||
## 9. Phase F:Page Aggregate 和命令边界
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
> 状态说明:
|
||||
> - 本稿对应 `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 执行面
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v2.md`
|
||||
> - `/mnt/Data1T/mnote/design/07-ai/done/7-1-phase7-document-ai-minimum-loop-checklist-v1.md`
|
||||
>
|
||||
> 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 触发”,而不是独立内置编排主线
|
||||
|
||||
---
|
||||
|
||||
@@ -38,7 +43,7 @@
|
||||
- `ai_note node`
|
||||
- `reference edge`
|
||||
2. 只允许围绕**当前文档页**创建,不做跨页、跨工作区写链
|
||||
3. 触发方式不是自然语言,不做自动推断,只允许页面 AI 面板里的固定按钮触发
|
||||
3. 触发方式不是自然语言,不做自动推断,只允许页面 AI 面板里的固定按钮触发;该面板长期应只是 `mnote-cli` host
|
||||
4. 点击按钮后直接创建,不走“先预览再确认”的两阶段流
|
||||
5. `summary node` 默认单例覆盖更新;`ai_note node` 每次新建
|
||||
6. 两者都落成**可编辑的页面型节点**
|
||||
@@ -91,7 +96,7 @@
|
||||
|
||||
- 它依赖更稳定的摄取边界
|
||||
- 它会引入更重的异步任务与检索协议
|
||||
- 它不是当前页 AI 面板的最小邻接能力
|
||||
- 它不是当前页 AI host 面板的最小邻接能力
|
||||
|
||||
所以本稿故意不把阶段 5 全写成一个“大包”,而是只切出:
|
||||
|
||||
@@ -283,7 +288,7 @@
|
||||
- “看起来像摘要就自动生成”
|
||||
- “只要语义明确就直接落库”
|
||||
|
||||
只支持页面 AI 面板里的两个固定按钮:
|
||||
只支持页面 AI host 面板里的两个固定按钮:
|
||||
|
||||
- `创建 Summary`
|
||||
- `创建 AI Note`
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
> - 2026-04-23 验证补充:
|
||||
> - `cd /mnt/Data1T/mnote/wolai-backend && ./.venv/bin/python -m pytest -q tests/test_ai_document_agent.py` -> `15 passed`
|
||||
> - `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- --runInBand src/app/api/ai-agent/run/route.test.ts src/app/api/ai-agent/document/config/route.test.ts src/components/editor/DocumentAiAgentPanel.runtime.test.tsx src/components/ai-agent/panelShared.test.ts` -> `202 passed`
|
||||
> - 2026-05-05 口径修正:
|
||||
> - 本稿记录的 `openai-agents-python` 文档页主链收口,当前仅作为过渡阶段基线
|
||||
> - 长期方向已被 `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md` 覆盖
|
||||
> - 当前长期口径固定为:`mnote-cli` 是唯一长期 agent 执行面;`openai-agents-python`、Hermes、Codex 都视为可插拔外置 agent
|
||||
|
||||
---
|
||||
|
||||
@@ -41,7 +45,7 @@
|
||||
|
||||
1. 如果现在开始做 `Phase 7`,第一交付物到底是什么
|
||||
2. `Phase 7` 应该接在哪条现有主线之后,而不是另起一套理想结构
|
||||
3. `openai-agents-python` 到底如何接入当前文档页 AI 主链
|
||||
3. 过渡期 `openai-agents-python` 适配链到底如何接入当前文档页 AI 主链
|
||||
4. 哪些 `v1` 里的目标继续保留,哪些必须降级到后续阶段
|
||||
|
||||
一句话收口:
|
||||
@@ -54,7 +58,9 @@
|
||||
|
||||
当前推荐口径固定如下:
|
||||
|
||||
> **`mnote` 的长期 AI 主线仍然采用“Rust kernel / Rust runtime 做唯一事实源与真执行面,`openai-agents-python` 作为 `mnote` 专用编排层,`Hermes` 退回过渡与实验平台”的结构。**
|
||||
> **本稿原始判断是“Rust kernel / Rust runtime 做唯一事实源与真执行面,`openai-agents-python` 作为 `mnote` 专用编排层,`Hermes` 退回过渡与实验平台”。**
|
||||
>
|
||||
> **该判断现已退化为历史过渡口径;当前长期口径改为:`Rust kernel / Rust runtime` 做唯一事实源与真执行面,`mnote-cli` 做唯一长期 agent 执行面,`openai-agents-python` 与 `Hermes` 都作为可插拔外置 agent。**
|
||||
|
||||
但如果按真实执行顺序来排,当前 `Phase 7` 必须服从下面这个前置条件:
|
||||
|
||||
@@ -153,7 +159,7 @@
|
||||
|
||||
- 已有一个可工作的文档页 AI 过渡链
|
||||
- 这条链已经开始向 `page aggregate command family` 回接
|
||||
- `Phase 7` 的第一任务,应是把这条链从 Hermes 兼容桥迁到正式 `openai-agents-python` 编排层
|
||||
- `Phase 7` 的第一任务,应是把这条链从 Hermes 兼容桥收口到统一 `mnote-cli` host / adapter;`openai-agents-python`、Hermes、Codex 只作为可插拔外置 agent
|
||||
|
||||
---
|
||||
|
||||
@@ -212,7 +218,7 @@
|
||||
|
||||
1. 明确它是过渡链
|
||||
2. 冻结它的保留边界
|
||||
3. 用 `openai-agents-python` 替换它的编排层,而不是推翻整条文档页 AI 回写链
|
||||
3. 用 `mnote-cli` 统一承接长期 agent 执行面,而不是把 `openai-agents-python` 或 Hermes 继续写成长期主编排
|
||||
|
||||
---
|
||||
|
||||
@@ -226,13 +232,13 @@ Document Page / Read View / AI Panel
|
||||
v
|
||||
AI Gateway / SSE Event Adapter
|
||||
|
|
||||
+---- current fallback: Hermes bridge
|
||||
|
|
||||
+---- target mainline: openai-agents-python
|
||||
+---- long-term execution surface: mnote-cli
|
||||
| |
|
||||
| +---- provider: OpenAI Responses API
|
||||
| +---- mnote page tools
|
||||
| +---- mnote tree tools
|
||||
| +---- external agent adapter: openai-agents-python
|
||||
| +---- external agent adapter: Hermes
|
||||
| +---- external agent adapter: Codex
|
||||
|
|
||||
+---- current fallback: Hermes bridge
|
||||
|
|
||||
v
|
||||
Rust runtime / mnote-web / bridge-runtime
|
||||
@@ -267,14 +273,14 @@ Rust kernel truth
|
||||
- 通用 agent 编排框架
|
||||
- 通用聊天产品壳
|
||||
|
||||
#### `openai-agents-python`
|
||||
#### `mnote-cli`
|
||||
|
||||
负责:
|
||||
|
||||
- 文档页 AI 会话编排
|
||||
- tools / handoffs / tracing / guardrails / HITL
|
||||
- 调用 OpenAI `Responses API`
|
||||
- 组织 `mnote` 的文档页 AI 工具合同
|
||||
- 外置 agent adapter 调度
|
||||
- mnote page tools / tree tools 统一入口
|
||||
- CLI host / Web AI host 之间的执行契约
|
||||
|
||||
不负责:
|
||||
|
||||
@@ -282,6 +288,22 @@ Rust kernel truth
|
||||
- 绕过 Rust runtime 直接写产品数据
|
||||
- 自己持有第二套页面真相
|
||||
|
||||
#### `openai-agents-python`
|
||||
|
||||
负责:
|
||||
|
||||
- 作为可插拔外置 agent adapter / 对照实现
|
||||
- tools / handoffs / tracing / guardrails / HITL
|
||||
- 调用 OpenAI `Responses API`
|
||||
- 通过 `mnote-cli` 暴露的工具合同接入 `mnote`
|
||||
|
||||
不负责:
|
||||
|
||||
- 保存产品真相
|
||||
- 绕过 Rust runtime 直接写产品数据
|
||||
- 自己持有第二套页面真相
|
||||
- 文档页 AI 长期默认主编排
|
||||
|
||||
#### Hermes
|
||||
|
||||
负责:
|
||||
@@ -530,9 +552,9 @@ AI 第一批正式写能力只冻结为:
|
||||
|
||||
> **`Phase 7` 不删除过渡工具面,但也不把过渡工具名继续写成长期产品契约。**
|
||||
|
||||
### 8.3 `openai-agents-python` 的接入原则
|
||||
### 8.3 外置 agent adapter 的接入原则
|
||||
|
||||
`openai-agents-python` 接入时,优先接的不是抽象理想工具名,而是:
|
||||
`openai-agents-python`、Hermes、Codex 作为外置 adapter 接入时,优先接的不是抽象理想工具名,而是 `mnote-cli` 暴露的统一工具契约:
|
||||
|
||||
1. 当前页最小闭环所需的正式命令语义
|
||||
2. 当前已真实存在的过渡运行时工具能力
|
||||
@@ -574,7 +596,7 @@ AI 第一批正式写能力只冻结为:
|
||||
- [x] 明确当前第一闭环只覆盖文档页 AI 主写链
|
||||
- [x] 明确 `summary / ai_note / reference / index` 降为后续扩展
|
||||
- [x] 明确 `Hermes` 只保留为 fallback / 对照链
|
||||
- [x] 明确 `openai-agents-python` 为长期推荐编排层
|
||||
- [x] 明确 `openai-agents-python` 仅作为过渡期可插拔外置 agent / adapter 示例
|
||||
- [x] 明确页面 AI 模型配置真源是 `model_key`,不是 combo 名或 provider model
|
||||
- [x] 明确 `profile` 前端可设、后端持有真源
|
||||
- [x] 明确 tool registry 必须前端可见
|
||||
@@ -645,11 +667,11 @@ AI 第一批正式写能力只冻结为:
|
||||
|
||||
---
|
||||
|
||||
## 阶段 3:引入 `openai-agents-python` 文档页编排层
|
||||
## 阶段 3:整理并保留 `openai-agents-python` 过渡适配链
|
||||
|
||||
### 目标
|
||||
|
||||
在不推翻现有文档页 AI 回写链的前提下,用 `openai-agents-python` 替换 Hermes 作为长期文档页编排层。
|
||||
在不推翻现有文档页 AI 回写链的前提下,保留 `openai-agents-python` 这条已跑通的过渡外置 adapter,用它作为 `mnote-cli`-first 迁移期间的对照与行为基线,而不是把它定义成长期默认文档页编排层。
|
||||
|
||||
### 需要完成
|
||||
|
||||
@@ -669,19 +691,20 @@ AI 第一批正式写能力只冻结为:
|
||||
### 完成判定
|
||||
|
||||
- [x] 在不依赖 Hermes 主编排的情况下,文档页 AI 已能跑通第一闭环
|
||||
- [x] 新编排层已具备“模型 / profile / 工具”统一能力面出口
|
||||
- [x] 当前过渡 adapter 已具备“模型 / profile / 工具”统一能力面出口
|
||||
|
||||
---
|
||||
|
||||
## 阶段 4:切文档页 AI 默认主路径
|
||||
## 阶段 4:切文档页 AI 默认执行路径
|
||||
|
||||
### 目标
|
||||
|
||||
让文档页 AI 在产品可见行为上真正从 Hermes 过渡到新编排层。
|
||||
让文档页 AI 在产品可见行为上从 Hermes 兼容链过渡到 `mnote-cli` host / adapter;当前已跑通的 `openai-agents-python` 链只保留为外置 adapter 行为基线。
|
||||
|
||||
### 需要完成
|
||||
|
||||
- [x] 文档页 AI panel 默认走 `openai-agents-python`
|
||||
- [x] 历史基线中,文档页 AI panel 曾默认走 `openai-agents-python`
|
||||
- [x] 长期口径中,文档页 AI panel 默认应走 `mnote-cli` host / adapter
|
||||
- [x] 标题改名沿 `page.head.updateTitle` 回写
|
||||
- [x] 正文改写沿 `page.body.save` 回写
|
||||
- [x] 主编辑区 island 稳定回显 AI 结果
|
||||
@@ -726,7 +749,7 @@ AI 第一批正式写能力只冻结为:
|
||||
### 10.1 继续保留的价值
|
||||
|
||||
- 承接现有文档页 AI 运行链
|
||||
- 作为 `openai-agents-python` 的回归对照
|
||||
- 作为 `mnote-cli` host 与其他外置 adapter 的回归对照
|
||||
- 作为 fallback 开关
|
||||
- 承接非主链实验场景
|
||||
|
||||
@@ -741,8 +764,8 @@ AI 第一批正式写能力只冻结为:
|
||||
|
||||
最终可接受状态有两种:
|
||||
|
||||
1. Hermes 退化为非主链实验平台
|
||||
2. Hermes 完全下线,只保留 `openai-agents-python + Rust runtime`
|
||||
1. Hermes 退化为非主链实验平台 / 外置 agent adapter
|
||||
2. Hermes 完全下线,只保留 `mnote-cli` + Rust runtime,并按需接入 `openai-agents-python` / Codex 等外置 agent adapter
|
||||
|
||||
---
|
||||
|
||||
@@ -766,11 +789,11 @@ AI 第一批正式写能力只冻结为:
|
||||
|
||||
当前冻结如下:
|
||||
|
||||
> **`Phase 7` 仍然以 `openai-agents-python` 作为长期推荐编排层,以 Rust runtime 作为唯一事实源与真执行面。**
|
||||
> **本稿原始判断里,`openai-agents-python` 曾被写成长期推荐编排层;该口径现已失效。当前长期口径应以 `v4` 为准:`mnote-cli` 是唯一长期 agent 执行面,Rust runtime 仍是唯一事实源与真执行面;`openai-agents-python`、Hermes、Codex 都只是可插拔外置 agent。**
|
||||
|
||||
> **但当前 `Phase 7` 的第一交付物不再定义为“完整 AI 平台”或“完整结构化知识写链”,而是“文档页 AI 直接进入主编辑区,并沿 `page aggregate command family` 正式回写”。**
|
||||
|
||||
> **`Hermes` 可以继续作为过渡平台与实验平台存在,但不再作为文档页 AI 的长期语义中心。**
|
||||
> **`Hermes` 可以继续作为过渡平台与实验平台存在,但不再作为文档页 AI 的长期语义中心。`openai-agents-python` 也只保留为外置 adapter。**
|
||||
|
||||
> **页面 AI 的模型真源固定为 `model_key`,`resolved_combo / resolved_runtime_model` 只作为运行时调试信息;`profile` 前端可设但由后端持有真源;tool registry 必须前端可见。**
|
||||
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
# 7 [process] mnote Kernel Phase 7 AI 与 CLI 外置 Agent 边界实施方案 v3
|
||||
|
||||
> 更新时间:2026-05-05
|
||||
>
|
||||
> 上位依据:
|
||||
> - `/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/07-ai/process/7-phase7-ai-kernel-projection-plan-v2.md`
|
||||
>
|
||||
> 本稿与 `v2` 的关系:
|
||||
> - `v2` 记录的是文档页 AI 最小闭环与 `openai-agents-python` sidecar 的主线收口
|
||||
> - 本稿记录的是从“双中心并存”过渡到 `CLI-first` 之前的边界判断,重点保留当时为何要把页面内 AI 与外置 agent 拆层
|
||||
> - 若未来继续演进,长期口径以 `v4` 为准;本稿不再作为当前长期判断依据
|
||||
>
|
||||
> 2026-05-05 追加说明:
|
||||
> - 本稿已被 `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md` 覆盖
|
||||
> - `v3` 只保留用于记录“双中心并存”的过渡判断
|
||||
> - 当前长期口径不再采用本稿,而采用 `v4` 的 `CLI-first`
|
||||
> - 当前统一口径是:`mnote-cli` 是唯一长期 agent 执行面,`openai-agents-python`、Hermes、Codex 都只是可插拔外置 agent
|
||||
|
||||
---
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
这份稿只回答一个问题:
|
||||
|
||||
> **`mnote` 的 AI 能力到底应该以“内置 agent”为中心,还是以“CLI 兼容外置 agent”为中心。**
|
||||
|
||||
当前长期结论已被 `v4` 修正为单一执行面:
|
||||
|
||||
1. Web 文档页 AI 面板继续保留,但只作为页面内交互壳 / CLI host
|
||||
2. `mnote-cli` 是唯一长期 agent 执行面
|
||||
3. Hermes、Codex、`openai-agents-python` 这类外置 agent 不再直接依赖产品内编排细节,而是统一通过 CLI / 稳定工具面进入系统
|
||||
4. Rust kernel 继续作为唯一事实源与真执行面
|
||||
|
||||
一句话收口:
|
||||
|
||||
> **本稿原始判断是“不要退回成只有 CLI”;该口径现已被 `v4` 覆盖。当前长期口径是:CLI 作为唯一执行面,Web AI 只保留为页面内交互壳。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前完成情况
|
||||
|
||||
### 2.1 文档页 AI 最小闭环已完成
|
||||
|
||||
`7-1` 已经完成,说明当前文档页 AI 至少已经跑通:
|
||||
|
||||
- 当前页 page aggregate 上下文读取
|
||||
- `openai-agents-python` sidecar 编排
|
||||
- 标题改名与正文写回
|
||||
- `Hermes` fallback / 对照链
|
||||
- `model_key / profile / tool registry` 的可见配置面
|
||||
|
||||
这意味着当前系统已经不是“要不要有 AI”,而是“AI 的长期边界该放在哪一层”。
|
||||
|
||||
### 2.2 `mnote-cli` 已经不是空壳
|
||||
|
||||
当前 Rust 侧已有 `mnote-cli`,并且已经覆盖:
|
||||
|
||||
- `page`
|
||||
- `block`
|
||||
- `mindmap`
|
||||
- `search`
|
||||
- `sidebar`
|
||||
- `editor`
|
||||
- `tool`
|
||||
|
||||
同时它已经有较清晰的执行参数面:
|
||||
|
||||
- `--json`
|
||||
- `--execute`
|
||||
- `--session-id`
|
||||
- `--reason`
|
||||
- `--idempotency-key`
|
||||
- `--validate-only`
|
||||
- `--dry-run`
|
||||
|
||||
这说明 CLI 已经具备成为“外置 agent 统一兼容层”的基础,而不是只做调试壳。
|
||||
|
||||
### 2.3 内置 AI 现在的定位已经足够清晰
|
||||
|
||||
当前 `wolai-backend/app/services/ai_document_agent.py` 这一层已经把文档页 AI 约束成:
|
||||
|
||||
- 只处理当前文档页
|
||||
- 只使用有限工具面
|
||||
- 通过 page aggregate 组织上下文
|
||||
- 通过 `slash_run / doc_insert_blocks / doc_replace_range` 这类写链回写
|
||||
|
||||
所以内置 AI 的价值不是“全能 agent 平台”,而是“产品内即时编辑体验”。
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心判断
|
||||
|
||||
### 3.1 `v3` 当时对 CLI-first 的顾虑
|
||||
|
||||
本节保留的是 `v3` 当时尚未接受 `CLI-first` 时的顾虑:
|
||||
|
||||
1. 担心产品内即时体验变差
|
||||
2. 担心页面上下文、审核、回写被拆散
|
||||
3. 担心外置 agent 变强但产品主链变弱
|
||||
|
||||
这些顾虑在 `v4` 中的处理方式不是退回“双中心”,而是明确:
|
||||
|
||||
- Web AI 面板继续保留
|
||||
- 但它只作为 `mnote-cli` 的页面内 host / client
|
||||
- 执行面不再由产品内 AI 单独持有
|
||||
|
||||
### 3.2 也不建议把内置 AI 变成唯一中心
|
||||
|
||||
相反,如果继续把内置 AI 当唯一中心,另一个问题会变得更严重:
|
||||
|
||||
- agent 更新能力受限
|
||||
- 记忆层容易变成产品私有状态
|
||||
- 能力面会偏向单一页面操作
|
||||
- Hermes / CLI 这类外置 agent 很难稳定接入
|
||||
|
||||
所以正确做法不是“只保留内置 AI”,而是**把 `mnote-cli` 收口为唯一长期 agent 执行面**。
|
||||
|
||||
### 3.3 当前长期分层应理解为三层
|
||||
|
||||
1. **Web AI 面板 / 页面内交互壳**
|
||||
- 负责文档页内交互、上下文读取、局部回写、审核辅助
|
||||
|
||||
2. **`mnote-cli`**
|
||||
- 负责唯一长期 agent 执行面,以及外置 agent、脚本、批处理、离线任务、可观测执行
|
||||
|
||||
3. **Rust kernel**
|
||||
- 负责所有事实源、命令、查询、投影、审计与回放
|
||||
|
||||
这三层之间不应该互相抢语义中心。
|
||||
|
||||
---
|
||||
|
||||
## 4. 架构边界
|
||||
|
||||
### 4.1 Rust kernel
|
||||
|
||||
负责:
|
||||
|
||||
- 页面、树、边、投影、查询、命令
|
||||
- 结构化写入的最终事实源
|
||||
- 审计、trace、回放、恢复
|
||||
|
||||
不负责:
|
||||
|
||||
- 直接承担 UI 体验
|
||||
- 直接承担通用 agent 编排
|
||||
|
||||
### 4.2 Web AI 面板(产品内交互壳)
|
||||
|
||||
负责:
|
||||
|
||||
- 当前文档页的即时编辑
|
||||
- 选中上下文的解释与改写
|
||||
- 通过正式命令面回写
|
||||
- 审核与继续编辑的体验闭环
|
||||
|
||||
不负责:
|
||||
|
||||
- 成为全局 agent 平台
|
||||
- 取代 CLI 的批处理入口
|
||||
- 持有独立长期记忆真源
|
||||
- 成为第二个长期执行面
|
||||
|
||||
### 4.3 `mnote-cli`
|
||||
|
||||
负责:
|
||||
|
||||
- 作为唯一长期 agent 执行面与统一命令面
|
||||
- 作为人类与脚本的可执行入口
|
||||
- 作为 Hermes、Codex、批处理、定时任务的兼容层
|
||||
|
||||
应该提供:
|
||||
|
||||
- 稳定的 JSON 输出
|
||||
- 明确的 plan / execute 分层
|
||||
- 会话与 trace 参数
|
||||
- 幂等键
|
||||
- 校验模式与 dry-run
|
||||
- 可发现的 capability manifest
|
||||
|
||||
### 4.4 Hermes / Codex / `openai-agents-python`
|
||||
|
||||
负责:
|
||||
|
||||
- 可插拔外置 agent 场景
|
||||
- 过渡平台
|
||||
- 回归对照
|
||||
|
||||
不负责:
|
||||
|
||||
- 成为产品内部独立长期主编排
|
||||
- 直接绕过 Rust runtime 写业务数据
|
||||
|
||||
---
|
||||
|
||||
## 5. CLI 应该补什么
|
||||
|
||||
### 5.1 统一能力发现
|
||||
|
||||
CLI 需要先变成“可发现能力集合”,而不是一堆散命令。
|
||||
|
||||
最少要能回答:
|
||||
|
||||
- 当前可写什么
|
||||
- 当前可读什么
|
||||
- 当前哪些命令是计划态
|
||||
- 当前哪些命令可直接执行
|
||||
- 当前命令属于哪个 scope
|
||||
|
||||
### 5.2 统一执行元数据
|
||||
|
||||
外置 agent 真正缺的不是命令本身,而是执行元数据一致:
|
||||
|
||||
- `session_id`
|
||||
- `actor_id`
|
||||
- `actor_type`
|
||||
- `reason`
|
||||
- `idempotency_key`
|
||||
- `validate_only`
|
||||
- `dry_run`
|
||||
- trace / audit id
|
||||
|
||||
这些都应该在 CLI 层成为一等参数。
|
||||
|
||||
### 5.3 统一记忆入口
|
||||
|
||||
这里的“记忆”不应该是产品壳里的隐式状态,而应该拆成三层:
|
||||
|
||||
1. 会话记忆
|
||||
- 某次 agent 运行的上下文与结果
|
||||
|
||||
2. 配置记忆
|
||||
- profile、工具注册、运行时偏好
|
||||
|
||||
3. kernel 记忆
|
||||
- 真实业务对象、projection、历史变更
|
||||
|
||||
CLI 负责把这三层显式化,外置 agent 通过它读取或写入,不再自己猜。
|
||||
|
||||
### 5.4 统一机器可读输出
|
||||
|
||||
如果 Hermes、Codex、脚本都要接入,CLI 输出必须稳定机器可读。
|
||||
|
||||
最低要求:
|
||||
|
||||
- `--json` 必须完整
|
||||
- 错误结构必须稳定
|
||||
- 成功结构必须能直接喂给上层 agent
|
||||
- 人类输出和机器输出要分开
|
||||
|
||||
---
|
||||
|
||||
## 6. Web AI 面板继续保留什么
|
||||
|
||||
### 6.1 继续保留
|
||||
|
||||
- 当前页正文改写
|
||||
- 当前页标题改名
|
||||
- 当前页上下文读取
|
||||
- 页面内审核与继续编辑
|
||||
- 与 page aggregate 对齐的最小闭环
|
||||
|
||||
### 6.2 不继续扩写
|
||||
|
||||
- 通用多 agent 平台壳
|
||||
- 全局记忆产品壳
|
||||
- 独立于页面主链的第二份真相
|
||||
- 把 CLI 功能重复做一遍
|
||||
|
||||
### 6.3 设计原则
|
||||
|
||||
Web AI 面板只做“最近的一层”,不要做“全部层”。
|
||||
|
||||
因为页面内 AI 交互壳的目标是让用户快,不是让系统像一个独立平台那样完整。
|
||||
|
||||
---
|
||||
|
||||
## 7. 迁移策略
|
||||
|
||||
### 阶段 1:收口 CLI 兼容面
|
||||
|
||||
- 把 `mnote-cli` 明确成唯一长期 agent 执行面
|
||||
- 保持现有命令树不乱长
|
||||
- 先统一 JSON / plan / execute / trace / idempotency
|
||||
|
||||
### 阶段 2:补稳定能力发现
|
||||
|
||||
- 输出 capability manifest
|
||||
- 区分 read / write / job
|
||||
- 区分 document / tree / workspace scope
|
||||
|
||||
### 阶段 3:外置 agent 接入
|
||||
|
||||
- Hermes 通过 CLI 进入系统
|
||||
- 后续其他 agent 也通过同一 CLI 进入
|
||||
- 不再为每个 agent 单独做一套产品内桥接逻辑
|
||||
|
||||
### 阶段 4:保留页面内 AI host
|
||||
|
||||
- 文档页 AI 继续保留当前页面内主路径
|
||||
- 只做 UI 内最小闭环
|
||||
- 不回退到全局壳
|
||||
- 不再把页面内 host 叙述成独立长期执行面
|
||||
|
||||
---
|
||||
|
||||
## 8. 非目标
|
||||
|
||||
本稿不做:
|
||||
|
||||
- 重新实现一个新的通用 AI 平台
|
||||
- 把 Hermes 直接升级成产品内主编排中心
|
||||
- 把内置 AI 删除掉
|
||||
- 把所有页面内交互体验都删除并强制改成手工 CLI 操作
|
||||
- 在 CLI 里重复一套产品 UI
|
||||
|
||||
---
|
||||
|
||||
## 9. 完成判定
|
||||
|
||||
当下面几项成立时,才算这个方向真正站稳:
|
||||
|
||||
- `mnote-cli` 是唯一长期 agent 执行面,而不是纯调试壳
|
||||
- Web AI 面板只负责页面内最小闭环
|
||||
- `openai-agents-python`、Hermes、Codex 等外置 agent 通过 CLI 进入系统
|
||||
- Rust kernel 仍然是唯一事实源
|
||||
- `model_key / profile / tool registry` 这些产品语义不被页面内 host 私有化
|
||||
|
||||
一句话收口:
|
||||
|
||||
> **本稿保留的是“产品内 AI + CLI 兼容层”并存的过渡判断;当前长期口径已经改为:`mnote-cli` 是唯一执行面,Web AI 只是页面内交互壳,Rust kernel 继续负责真相。**
|
||||
@@ -0,0 +1,698 @@
|
||||
# 7 [process] mnote Kernel Phase 7 CLI-First 外置 Agent 统一执行面方案 v4
|
||||
|
||||
> 更新时间:2026-05-05
|
||||
>
|
||||
> 上位依据:
|
||||
> - `/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/07-ai/process/7-phase7-ai-kernel-projection-plan-v2.md`
|
||||
> - `/mnt/Data1T/mnote/design/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` 接入
|
||||
|
||||
---
|
||||
|
||||
## 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 最小闭环已经完成,这个事实不变:
|
||||
|
||||
- page aggregate 上下文读取
|
||||
- 标题改名与正文改写
|
||||
- `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 的图形客户端。**
|
||||
|
||||
### 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/process/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` 直入独立 bridge,统一走 `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 都统一走 CLI
|
||||
|
||||
### 阶段 1:CLI 能力补齐
|
||||
|
||||
优先补:
|
||||
|
||||
- capability manifest
|
||||
- 标准 JSON 输出
|
||||
- 事件流输出
|
||||
- 标准上下文输入
|
||||
- 标准 trace / session 参数
|
||||
|
||||
### 阶段 2:Web 面板降为 CLI host
|
||||
|
||||
把当前文档页 AI 面板从:
|
||||
|
||||
- “调用内置 sidecar 主编排”
|
||||
|
||||
改成:
|
||||
|
||||
- “调用 CLI host / CLI adapter”
|
||||
|
||||
### 阶段 3:外置 agent 接入统一化
|
||||
|
||||
统一支持:
|
||||
|
||||
- Hermes -> `mnote-cli`
|
||||
- Codex -> `mnote-cli`
|
||||
- `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