383 lines
24 KiB
Markdown
383 lines
24 KiB
Markdown
# 7-72 Page AI Pi UI 补全方案 v1
|
||
|
||
状态:process
|
||
Owner:07-ai / mnote-web / browser runtime
|
||
日期:2026-07-05
|
||
|
||
## 1. 结论
|
||
|
||
当前 Pi Lab 已能通过真实 `desktop:hot` 链路调用 Skill 与 MCP,但 UI 只完成了最基础的聊天和 Markdown 渲染。它还没有达到 Pi 官方 TUI / OpenClaw 类 Web UI 的可用体验基线。
|
||
|
||
本阶段不应该继续只补零散样式。应按 Pi 事件模型重做一层 `PiRunViewModel`,把 `message_update`、`tool_execution_*`、`queue_update`、`abort`、extension UI dialog、notification、receipt、artifact 全部归一成浏览器可渲染的运行时间线。
|
||
|
||
真实验证证据:
|
||
|
||
- 清理后 Skill/MCP 配置截图:`/tmp/mnote-pi-clean-after-fix-1783222211192/01-admin-ai-skills-after-clean.png`
|
||
- 当前 UI 初始状态:`/tmp/mnote-pi-ui-gap-audit-1783222292502/01-current-pi-initial.png`
|
||
- 当前 UI streaming 状态:`/tmp/mnote-pi-ui-gap-audit-1783222292502/03-current-pi-streaming-early.png`
|
||
- 当前 UI 回复后状态:`/tmp/mnote-pi-ui-gap-audit-1783222292502/04-current-pi-after-reply.png`
|
||
- 清理后真实 Skill/MCP 链路:`/tmp/mnote-pi-real-after-clean-1783222483/result.json`
|
||
|
||
## 2. 已清理的问题
|
||
|
||
重复配置已清理:
|
||
|
||
- 删除空 source Skill:`mnote-browser-smoke-*`
|
||
- 删除临时 Skill:`mnote-pi-skill-proof`
|
||
- 删除重复 LightRAG smoke MCP:`lightrag-smoke-*`
|
||
|
||
清理后有效配置:
|
||
|
||
- Skills:`Chrome Bridge`、`CodeGraph`、`Context7`、`Global Search`、`MemPalace`、`SearXNG Search`、`VPN`
|
||
- MCP:`Chrome Bridge`、`CodeGraph`、`Context7`、`MemPalace`、`SearXNG`
|
||
- `emptySourceSkills=[]`
|
||
- `duplicateMcpEndpoints=[]`
|
||
|
||
同时修复了 `/api/ai-admin/settings` 的删除语义:`skills` 与 `mcpServers` 在 admin 编辑中代表完整目标 registry,不再把旧配置 merge 回来导致删除无效。
|
||
|
||
## 3. 对照基线
|
||
|
||
Pi 官方能力基线:
|
||
|
||
- RPC prompt streaming 中必须支持 `streamingBehavior: "steer"` 与 `"followUp"`;不传会在 streaming 中报错。
|
||
- RPC 有独立 `steer`、`follow_up`、`abort` 命令。
|
||
- JSON event stream 暴露 `queue_update`、`message_update`、`tool_execution_start`、`tool_execution_update`、`tool_execution_end`、`compaction_*`。
|
||
- TUI 中 Enter 是 steer,Alt+Enter 是 follow-up,Escape 是 abort,Alt+Up 可取回排队消息。
|
||
- TUI Markdown 不是简单 HTML 转换,而是处理 streaming partial fence、thinking block、宽度缓存、主题。
|
||
- extension UI 有 `ctx.ui.select()`、`ctx.ui.confirm()`、`ctx.ui.input()`、`ctx.ui.notify()`,并支持 AbortSignal 关闭。
|
||
|
||
OpenClaw / 第三方 Web UI 可参考:
|
||
|
||
- `openclaw/ui/src/ui/chat/tool-cards.ts`:工具卡片默认折叠,展开显示 input/output/raw details/error/sidebar。
|
||
- `openclaw/ui/src/ui/chat/grouped-render.ts`:消息分组、Markdown sanitation、thinking block、copy-as-markdown。
|
||
- `openclaw/ui/src/ui/components/modal-dialog.ts`:标准 modal dialog + backdrop + focus trap。
|
||
- `openclaw/extensions/qa-lab/web/src/ui-render.ts`:长任务 runner、artifact、evidence、capture timeline 的信息架构。
|
||
|
||
## 4. 当前 UI 缺口
|
||
|
||
真实浏览器审计结果:
|
||
|
||
- 有 streaming 状态与中止按钮,但 streaming 中输入框没有 steer / follow-up 模式,无法追加或插队。
|
||
- 有 tool receipt 折叠区,但没有按 turn 内时间线显示工具调用开始、参数增量、结果、错误、耗时。
|
||
- 工具调用过程没有和 assistant message 绑定;用户看到的是“模型说自己调用了工具”,不是 UI 明确展示调用过程。
|
||
- 没有 extension UI dialog。审计结果 `hasDialog=false`。
|
||
- 没有独立通知/Toast。当前“通知”只是一个静态按钮,不是 `ctx.ui.notify()` 的承载面。
|
||
- Markdown 渲染已存在,但缺 thinking block、copy-as-markdown、streaming partial fence 处理、表格/代码块稳定布局。
|
||
- session history 只是列表入口,缺少 resume/fork/tree entry 级别视图。
|
||
- abort 只可点一次停止,没有显示 abort response、aborted stopReason、被恢复的 queued messages。
|
||
- 没有 pending queue 可视化。审计结果 `hasFollowupOrSteerControl=false`。
|
||
- 没有 artifact / citation / diff right rail;LightRAG、file patch、reference.open 只能混在正文或 receipt 里。
|
||
|
||
## 5. 目标 UI 信息架构
|
||
|
||
Pi Lab 主体分四层:
|
||
|
||
1. 顶部运行栏
|
||
- session name / model / thinking / context usage / runtime pid / allowed roots badge
|
||
- streaming、queued、aborted、error 明确状态
|
||
- stop、new、history、settings 以 icon button 呈现
|
||
|
||
2. 消息流
|
||
- user / assistant / system 分组
|
||
- assistant 支持 live Markdown、thinking 折叠、copy-as-markdown
|
||
- 每个 turn 下嵌入 tool timeline,而不是只靠 receipt 区
|
||
|
||
3. Composer
|
||
- idle:普通发送
|
||
- streaming:显示 segmented control:`Steer` / `Follow-up`
|
||
- Stop 后恢复未发送/排队文本
|
||
- 支持图片/附件占位,但第一阶段不实现上传
|
||
|
||
4. 右侧/底部详情 rail
|
||
- Tool details:参数、结果、raw JSON、stderr、耗时、receipt id
|
||
- Artifacts:diff、citation、open-reference、文件变更
|
||
- Diagnostics:RPC events、session jsonl、policy snapshot,仅开发态默认折叠
|
||
|
||
## 6. 分阶段实施
|
||
|
||
## 6.0 执行 Checklist
|
||
|
||
### 已完成
|
||
|
||
- [x] 完成 Pi 官方 RPC / JSON event / TUI / extension UI 对照,确认 UI 缺口不只是 Markdown 渲染。
|
||
- [x] 完成当前 `/page-ai/pi` 真实浏览器 UI 缺口审计,证据:`/tmp/mnote-pi-ui-gap-audit-1783222292502/result.json`。
|
||
- [x] 清理重复 Skill/MCP 配置,并修复 admin 设置删除后被 merge 回来的问题。
|
||
- [x] 验证清理后真实 Skill/MCP 链路仍可用,证据:`/tmp/mnote-pi-real-after-clean-1783222483/result.json`。
|
||
- [x] 确认后端 `/api/page-ai/pi/send` 已支持 `streamingBehavior`,前端原先未传递。
|
||
- [x] 在 Pi Lab 消息流内新增折叠工具时间线与工具卡,支持 `tool_execution_*`、`toolcall_*`、后端 tool receipt 统一展示。
|
||
- [x] 工具时间线过滤 thinking/reasoning 内容,避免把模型思考块作为工具详情泄漏到 UI。
|
||
- [x] 在 composer 中新增 `Steer / Follow-up` 控件,streaming 中允许继续输入并发送 `streamingBehavior`。
|
||
- [x] Stop/abort 改为结构化 aborted 状态,不再把“已中止”拼进正常 Markdown 正文。
|
||
- [x] 新增 Phase 1 浏览器 smoke:`tmp/mnote-pi-ui-phase1-smoke.js`。
|
||
- [x] 使用 `npm run desktop:hot` 真启动环境完成 `/page-ai/pi` 浏览器验证,证据:`/tmp/mnote-pi-ui-phase1-1783228146571/result.json`。
|
||
- [x] 验证截图已产出:
|
||
- [x] 初始态:`/tmp/mnote-pi-ui-phase1-1783228146571/01-initial.png`
|
||
- [x] Steer/Follow-up 控件:`/tmp/mnote-pi-ui-phase1-1783228146571/02-started-with-steer-controls.png`
|
||
- [x] streaming 中止按钮:`/tmp/mnote-pi-ui-phase1-1783228146571/03-streaming-stop-visible.png`
|
||
- [x] 工具时间线展开:`/tmp/mnote-pi-ui-phase1-1783228146571/04-tool-timeline-expanded-followup.png`
|
||
- [x] Phase 1 smoke 断言通过:
|
||
- [x] `hasToolTimeline=true`
|
||
- [x] `toolCardCount=2`
|
||
- [x] `hasFollowupControls=true`
|
||
- [x] `hasQueueControls=true`
|
||
- [x] `streamingBehaviorSent=true`
|
||
- [x] `noReasoningLeakInToolTimeline=true`
|
||
- [x] 运行 `node --check rust/crates/mnote-web/browser/sidebar-page-ai-pi-lab-runtime.js` 通过。
|
||
- [x] 运行 `node --check tmp/mnote-pi-ui-phase1-smoke.js` 通过。
|
||
- [x] 运行 `cargo test -p mnote-web page_ai_pi --lib` 通过,10 tests passed。
|
||
- [x] 运行 `codegraph sync . && codegraph status .`,索引 up to date。
|
||
- [x] 处理 Pi JSONL `message` 事件中的 assistant `toolCall` 与 `toolResult`,MCP 不再只能靠正文证明。
|
||
- [x] MCP 工具卡标题已规范化为 `mcp:<server>/<tool>`,例如 `mcp:context7/list`、`mcp:mempalace/mempalace_mempalace_search`。
|
||
- [x] 新增真实 MCP 工具卡 smoke:`tmp/mnote-pi-mcp-toolcards-smoke.js`。
|
||
- [x] 使用 `npm run desktop:hot` 真启动环境完成 Context7 / MemPalace MCP 工具卡验证,证据:`/tmp/mnote-pi-mcp-toolcards-1783230894265/result.json`。
|
||
- [x] MCP 工具卡截图已产出:
|
||
- [x] Context7:`/tmp/mnote-pi-mcp-toolcards-1783230894265/02-context7-mcp-toolcards.png`
|
||
- [x] MemPalace:`/tmp/mnote-pi-mcp-toolcards-1783230894265/03-mempalace-mcp-toolcards.png`
|
||
- [x] MCP 工具卡 smoke 断言通过:
|
||
- [x] `hasContext7ToolCard=true`
|
||
- [x] `hasMemPalaceToolCard=true`
|
||
- [x] `context7McpCalled=true`
|
||
- [x] `mempalaceMcpCalled=true`
|
||
- [x] `noReasoningLeakInToolTimeline=true`
|
||
- [x] 新增 `PiRunViewModel` reducer,统一承接 user prompt、assistant streaming/done/abort、tool upsert、citation、diff、queue_update、clear。
|
||
- [x] 新增 reducer 单元测试:`tmp/mnote-pi-run-viewmodel-reducer-test.js`。
|
||
- [x] reducer 测试通过:`node tmp/mnote-pi-run-viewmodel-reducer-test.js`。
|
||
- [x] Phase 1 smoke 支持桌面/移动 viewport 参数,工具卡可见性断言改为真实可见节点,避免折叠历史 timeline 误判。
|
||
- [x] 使用当前重启后的 `npm run desktop:hot` 完成桌面真实浏览器验证,证据:`/tmp/mnote-pi-ui-phase1-1783234193679/result.json`。
|
||
- [x] 桌面截图已产出:`/tmp/mnote-pi-ui-phase1-1783234193679/04-tool-timeline-expanded-followup.png`。
|
||
- [x] 使用当前重启后的 `npm run desktop:hot` 完成移动 viewport 真实浏览器验证,证据:`/tmp/mnote-pi-ui-phase1-1783234215942/result.json`。
|
||
- [x] 移动截图已产出:`/tmp/mnote-pi-ui-phase1-1783234215942/04-tool-timeline-expanded-followup.png`。
|
||
- [x] 移动 composer 控件补齐响应式换行,`Steer / Follow-up / queue / model` 不再挤出右侧边界。
|
||
- [x] 使用当前重启后的 `npm run desktop:hot` 完成 Context7 / MemPalace MCP 工具卡复验,证据:`/tmp/mnote-pi-mcp-toolcards-1783234246744/result.json`。
|
||
- [x] 历史 session replay 改为复用 Pi RPC 事件处理链与 `PiRunViewModel`,不再只把 text delta 渲染成简化消息。
|
||
- [x] `queue_update` 在 live UI 和 history replay 中都进入同一个 reducer 状态。
|
||
- [x] Phase 1 浏览器 smoke 增加 history replay 断言与截图,证据:`/tmp/mnote-pi-ui-phase1-1783240450668/result.json`。
|
||
- [x] History replay 截图已产出:`/tmp/mnote-pi-ui-phase1-1783240450668/05-history-replay-tool-timeline.png`。
|
||
- [x] 使用 Context7 核对 Pi 官方 extension UI RPC:`extension_ui_request` / `extension_ui_response`,方法包括 `confirm/select/input/editor/notify`。
|
||
- [x] 后端新增 `/api/page-ai/pi/ui-response`,把浏览器 dialog 结果写回 Pi RPC stdin,并持久化 `extension_ui_response` 事件。
|
||
- [x] 前端新增 Extension UI modal host,支持 `confirm/select/input/editor`,并支持 timeout/cancel。
|
||
- [x] 前端新增 `ctx.ui.notify()` toast stack,支持 `info/warning/error/success` 风格。
|
||
- [x] 新增 extension UI 浏览器 smoke:`tmp/mnote-pi-extension-ui-smoke.js`。
|
||
- [x] 使用 `npm run desktop:hot` 真启动环境完成 Extension UI 浏览器验证,证据:`/tmp/mnote-pi-extension-ui-1783241631879/result.json`。
|
||
- [x] Extension UI 截图已产出:
|
||
- [x] Confirm dialog:`/tmp/mnote-pi-extension-ui-1783241631879/01-confirm-dialog.png`
|
||
- [x] Select dialog:`/tmp/mnote-pi-extension-ui-1783241631879/02-select-dialog.png`
|
||
- [x] Input dialog:`/tmp/mnote-pi-extension-ui-1783241631879/03-input-dialog.png`
|
||
- [x] Notify toast:`/tmp/mnote-pi-extension-ui-1783241631879/04-notify-toast.png`
|
||
- [x] Extension UI 弹窗位置已按 Pi UI 习惯改为 Pi 面板内部、输入框上方弹出,不再使用全系统居中遮罩。复验证据:`/tmp/mnote-pi-extension-ui-1783242363461/result.json`。
|
||
- [x] Pi 内嵌弹窗/通知截图已产出:
|
||
- [x] Confirm dialog:`/tmp/mnote-pi-extension-ui-1783242363461/01-confirm-dialog.png`
|
||
- [x] Notify toast:`/tmp/mnote-pi-extension-ui-1783242363461/04-notify-toast.png`
|
||
- [x] Extension UI 弹窗底边已对齐到 Pi 输入区上边界,不再遮住输入框。复验证据:`/tmp/mnote-pi-extension-ui-1783242834885/result.json`。
|
||
- [x] 对齐后截图:`/tmp/mnote-pi-extension-ui-1783242834885/01-confirm-dialog.png`。
|
||
- [x] Artifact / Diff / Citation rail 初步完成,消息状态中的 citation、diff、MCP tool result 会进入右侧 Artifacts。
|
||
- [x] Artifact rail 支持 citation 打开引用入口、MCP raw 复制、artifact Markdown 复制,assistant 消息支持 copy-as-markdown。
|
||
- [x] 工具详情已改为默认压缩摘要,Input / Output / Raw 详情折叠显示,避免长 MCP 结果默认占满消息区。
|
||
- [x] Receipts rail 增加打开当前 session JSONL 的入口,使用当前 Pi session events 生成 NDJSON。
|
||
- [x] Artifact rail 浏览器 smoke 已覆盖 citation/diff/MCP/copy/open-session-jsonl/折叠详情断言,证据:`/tmp/mnote-pi-artifact-rail-1783244314915/result.json`。
|
||
- [x] Artifact rail 截图已产出:
|
||
- [x] rail 与工具摘要:`/tmp/mnote-pi-artifact-rail-1783244314915/01-artifact-rail.png`
|
||
- [x] session JSONL 入口:`/tmp/mnote-pi-artifact-rail-1783244314915/02-session-jsonl-action.png`
|
||
- [x] Artifacts 不再默认常驻右栏占用 Pi 主界面,改为 commandbar 图标 + 数量 badge,点击后作为 Pi 内部浮层展开。
|
||
- [x] Artifacts 浮层底部停在 composer 上方,不遮住输入框。复验证据:`/tmp/mnote-pi-artifact-rail-1783245137938/result.json`。
|
||
- [x] Artifacts 默认折叠/按需展开截图已产出:
|
||
- [x] 默认折叠,仅显示 badge:`/tmp/mnote-pi-artifact-rail-1783245137938/01-artifact-button-collapsed.png`
|
||
- [x] 点击后 Pi 内部浮层:`/tmp/mnote-pi-artifact-rail-1783245137938/02-artifact-popover.png`
|
||
- [x] session JSONL 入口:`/tmp/mnote-pi-artifact-rail-1783245137938/03-session-jsonl-action.png`
|
||
- [x] 临时 Pi UI completion smoke 已纳入正式回归基线:`scripts/task-pi-lab-ui-completion-smoke.js`。
|
||
- [x] History / session tree 已补齐 `打开 / 重命名 / Fork` 操作入口;重命名走 `PATCH /api/page-ai/pi/sessions/{session_id}`,Fork 以当前历史上下文启动新 Pi runtime。
|
||
- [x] 高风险 MNote tool policy 已接入 Pi bridge 与后端强制校验:`policy=ask` 时未审批返回 `page_ai_pi_lab_tool_approval_required`,审批结果写入 tool receipt/audit UI。
|
||
- [x] abort response 已返回并显示 `stopReason=aborted`、`command=abort` 与当前 queued steer/follow-up 数量。
|
||
- [x] 新增 completion 浏览器 smoke 断言:
|
||
- [x] `hasHistoryOpen=true`
|
||
- [x] `hasHistoryRename=true`
|
||
- [x] `hasHistoryFork=true`
|
||
- [x] `unapprovedToolCode=page_ai_pi_lab_tool_approval_required`
|
||
- [x] `hasApprovalReceipt=true`
|
||
- [x] abort note 显示 `stopReason=aborted` 与 `queued steer=1 follow-up=1`
|
||
- [x] 使用 `npm run desktop:hot` 真启动环境完成 completion 浏览器验证,证据:`/tmp/mnote-pi-ui-completion-1783246949920/result.json`。
|
||
- [x] Completion 截图已产出:
|
||
- [x] History 操作入口:`/tmp/mnote-pi-ui-completion-1783246949920/01-history-session-actions.png`
|
||
- [x] 高风险审批 receipt/audit:`/tmp/mnote-pi-ui-completion-1783246949920/02-approval-audit-ui.png`
|
||
- [x] Abort stopReason / queued messages:`/tmp/mnote-pi-ui-completion-1783246949920/03-abort-stopreason-queue.png`
|
||
- [x] 新增真实 Pi Skill/MCP 浏览器 smoke:`scripts/task-pi-lab-real-skill-mcp-smoke.js`,先为 `mnote-e2e` seed 全部 Skill/MCP 权限,再走真实 `/page-ai/pi` RPC 链路。
|
||
- [x] 使用 `MNOTE_WEB_ALLOW_DEV_FIXTURES=1 npm run desktop:hot` 真启动环境完成 Context7 Skill + Context7 MCP + MemPalace MCP 验证,证据:`/tmp/mnote-pi-real-skill-mcp-1783253985608/result.json`。
|
||
- [x] 真实 Skill/MCP 截图已产出:
|
||
- [x] Pi RPC 启动:`/tmp/mnote-pi-real-skill-mcp-1783253985608/01-real-pi-started.png`
|
||
- [x] Context7 Skill/MCP:`/tmp/mnote-pi-real-skill-mcp-1783253985608/02-context7-skill-mcp.png`
|
||
- [x] MemPalace MCP:`/tmp/mnote-pi-real-skill-mcp-1783253985608/03-mempalace-mcp.png`
|
||
- [x] 真实 Skill/MCP smoke 断言通过:
|
||
- [x] `allSkillsEnabled=true`
|
||
- [x] `allMcpEnabled=true`
|
||
- [x] `context7SkillCliSource=true`
|
||
- [x] `vpnSkillCliSource=true`
|
||
- [x] `context7McpConfigured=true`
|
||
- [x] `mempalaceMcpConfigured=true`
|
||
- [x] `context7McpCalled=true`
|
||
- [x] `mempalaceMcpCalled=true`
|
||
- [x] `noReasoningLeakInToolTimeline=true`
|
||
- [x] 运行 `node --check rust/crates/mnote-web/browser/sidebar-page-ai-pi-lab-runtime.js` 通过。
|
||
- [x] 运行 `node --check scripts/task-pi-lab-ui-completion-smoke.js` 通过。
|
||
- [x] 运行 `node --check scripts/task-pi-lab-real-skill-mcp-smoke.js` 通过。
|
||
- [x] 运行 `cargo test -p mnote-web page_ai_pi --lib` 通过,11 tests passed。
|
||
- [x] 运行 `cargo test -p mnote-web dev_seed --lib` 通过,3 tests passed。
|
||
- [x] 运行 `codegraph sync . && codegraph status .`,索引 up to date。
|
||
- [x] 对照 Pi 官方能力完成输入区收口:Pi 官方支持 `--thinking`,但无原生 permission popup / plan mode;MNote 侧展示 MNote 实际 tool policy / directory grant。
|
||
- [x] 后端 `PiLabStartRequest` / `PiLabSession` 增加 `thinkingLevel`,真实 Pi RPC 启动时传 `--thinking <level>`,并写入 runtime JSON。
|
||
- [x] Pi 输入区新增 `+` 菜单,包含当前页、选区、LightRAG、目录权限、执行中引导/排队;附件/拍照与规划模式保持禁用,避免展示未接入假功能。
|
||
- [x] Pi 输入区新增思考深度选择器与 MNote 权限/审批 chip,权限 chip 文案来自当前 runtime policy 与 allowed roots。
|
||
- [x] completion 浏览器 smoke 增加 `+` 菜单、thinking control、permission chip、plan mode disabled 断言与截图。
|
||
- [x] 使用当前 dev:hot 真启动环境完成输入区 `+` 菜单 / 权限 / thinking 浏览器验证,证据:`/mnt/Data1T/mnote/tmp/pi-plus-20260706-140632/result.json`。
|
||
- [x] 输入区截图已产出:`/mnt/Data1T/mnote/tmp/pi-plus-20260706-140632/00a-plus-permission-thinking-menu.png`。
|
||
- [x] 运行 `node --check rust/crates/mnote-web/browser/sidebar-page-ai-pi-lab-runtime.js` 通过。
|
||
- [x] 运行 `node --check scripts/task-pi-lab-ui-completion-smoke.js` 通过。
|
||
- [x] 运行 `node scripts/task-pi-lab-static-smoke.js` 通过。
|
||
- [x] 运行 `cargo test -p mnote-web page_ai_pi --lib` 通过,11 tests passed。
|
||
- [x] 新增输入区真实可用性浏览器 smoke:`scripts/task-pi-lab-input-controls-smoke.js`,覆盖底部快捷按钮、`+` 菜单、权限 chip、thinking selector、发送按钮、streaming 中 steer/follow-up、目录权限入口、禁用附件/拍照/规划模式。
|
||
- [x] 修复 Pi RPC `message_update.text_start` 后 UI 未进入 streaming 状态的问题,确保菜单里的“作为引导发送 / 作为排队追问发送”真实发送 `streamingBehavior=steer/followUp`。
|
||
- [x] 修正 Pi 输入区目录权限入口为当前设置页真实 panel:`/user/ai#ai-admin-access`。
|
||
- [x] 使用 `dev:hot` 真启动环境在 `http://127.0.0.1:3000` 完成输入区全部功能浏览器验证,真实 Pi `runtimeMode=rpc`,证据:`/mnt/Data1T/mnote/tmp/pi-input-3000-real-20260706-151725/result.json`。
|
||
- [x] 输入区真实功能截图已产出:
|
||
- [x] 当前页/选区/LightRAG/权限 chip:`/mnt/Data1T/mnote/tmp/pi-input-3000-real-20260706-151725/01-context-actions-working.png`
|
||
- [x] streaming 中 steer/follow-up:`/mnt/Data1T/mnote/tmp/pi-input-3000-real-20260706-151725/02-streaming-send-menu-working.png`
|
||
- [x] 目录权限入口:`/mnt/Data1T/mnote/tmp/pi-input-3000-real-20260706-151725/03-directory-permission-entry.png`
|
||
- [x] 输入区 smoke 断言通过:
|
||
- [x] `bottomReadPage=true`
|
||
- [x] `bottomSelection=true`
|
||
- [x] `bottomRag=true`
|
||
- [x] `menuReadPage=true`
|
||
- [x] `menuSelection=true`
|
||
- [x] `menuRag=true`
|
||
- [x] `menuSteerStreamingBehavior=steer`
|
||
- [x] `menuFollowupStreamingBehavior=followUp`
|
||
- [x] `restartThinkingLevel=xhigh`
|
||
- [x] `sendButtonMessage="send button input controls smoke"`
|
||
- [x] `directoryPermissionUrl=http://127.0.0.1:3000/user/ai#ai-admin-access`
|
||
- [x] `attachDisabled=true`
|
||
- [x] `cameraDisabled=true`
|
||
- [x] `planDisabled=true`
|
||
|
||
### 进行中
|
||
|
||
- 无。
|
||
|
||
### 未开始
|
||
|
||
- 无。
|
||
|
||
### Phase 1:运行事件时间线
|
||
|
||
目标:用户必须看见工具正在做什么。
|
||
|
||
- 后端把 Pi `tool_execution_start/update/end`、`message_update`、`queue_update`、`agent_start/end` 解包成稳定 SSE event。
|
||
- 浏览器建立 `PiRunViewModel`:
|
||
- `turns[]`
|
||
- `messages[]`
|
||
- `toolCallsById`
|
||
- `pendingQueue`
|
||
- `currentAssistant`
|
||
- `runtimeStatus`
|
||
- 每个工具卡默认折叠显示:工具名、状态、摘要、耗时、allowed/denied。
|
||
- 展开后显示:Input、Output、Raw details、Error。
|
||
- `mnote.tool_receipt.write` 与 MCP 调用都映射成统一 tool card。
|
||
|
||
验收:
|
||
|
||
- Context7 / MemPalace 测试截图中必须可见折叠工具卡。
|
||
- 工具卡展开后能看到 server/tool/args/result 摘要。
|
||
- browser audit 中 `hasToolTimeline=true`。
|
||
|
||
### Phase 2:Streaming 中断与追加回复
|
||
|
||
目标:补齐 Pi 官方 queue 语义。
|
||
|
||
- composer streaming 状态下允许继续输入。
|
||
- 发送按钮旁提供 mode segmented control:
|
||
- `Steer`:发送 `{type:"prompt", streamingBehavior:"steer"}`
|
||
- `Follow-up`:发送 `{type:"prompt", streamingBehavior:"followUp"}`
|
||
- 后端暴露并持久化 `queue_update`。
|
||
- Stop 调用 RPC abort 后显示 `abort` response 与 `stopReason=aborted`。
|
||
|
||
验收:
|
||
|
||
- streaming 时输入一条 steer,UI 显示 queued/steering。
|
||
- follow-up 在当前 turn 完成后自动执行。
|
||
- Escape 或 Stop 后 assistant message 显示 aborted 状态,不把“已中止”混进正常 Markdown 正文。
|
||
|
||
### Phase 3:Extension UI Dialog 与通知
|
||
|
||
目标:让 Pi extension 的交互能力可见可控。
|
||
|
||
- 扩展桥支持 `ctx.ui.select/confirm/input/notify` 事件。
|
||
- 浏览器提供统一 dialog host:
|
||
- confirm:标题、说明、Cancel/Confirm
|
||
- select:搜索/键盘选择
|
||
- input:单行/多行输入
|
||
- timeout / AbortSignal 自动关闭
|
||
- 通知用右上角 toast stack,类型包括 info/warning/error/success。
|
||
- 高风险工具审批复用 confirm,但审批结果必须写 audit/receipt。
|
||
|
||
验收:
|
||
|
||
- 测试 extension 调 `ctx.ui.confirm()`,浏览器出现 modal。
|
||
- AbortSignal 触发后 modal 关闭。
|
||
- `ctx.ui.notify()` 可见且自动消退。
|
||
|
||
### Phase 4:Artifact / Diff / Citation Rail
|
||
|
||
目标:把 Page AI 和 MNote 工作区真正接上。
|
||
|
||
- file patch 工具显示 diff summary 与 changed files。
|
||
- LightRAG citation 显示引用卡,点击走 `mnote.reference.open`。
|
||
- MCP 结果可作为 artifact 固定在右侧 rail。
|
||
- 支持 copy raw / copy markdown / open session jsonl。
|
||
|
||
验收:
|
||
|
||
- local file patch 后可见文件路径、diff summary、watcher refresh 状态。
|
||
- LightRAG 回答中 citations 不只在文本中出现,而是可点击卡片。
|
||
|
||
### Phase 5:History / Session Tree / Replay
|
||
|
||
目标:补齐 Pi 的 session 能力。
|
||
|
||
- 历史列表显示 session name、model、last turn、tool count、updated time。
|
||
- 支持 resume、new、fork、rename。
|
||
- 事件 replay 用同一 `PiRunViewModel`,历史会话不走另一套渲染。
|
||
- debug 才显示原始 JSONL。
|
||
|
||
验收:
|
||
|
||
- 重新打开 `/page-ai/pi` 可恢复最近 session。
|
||
- 历史会话 tool cards、Markdown、receipts 展示一致。
|
||
|
||
## 7. 实施边界
|
||
|
||
- 不开放 Pi raw `bash/read/write/edit` 给普通 Page AI。
|
||
- MCP 继续走 MNote facade-only / sandbox 控制面。
|
||
- Tool card 展示不是权限来源;权限来源仍是 `AiAccessScope`、allowed roots、admin/user AI policy。
|
||
- Debug / diagnostics 默认折叠,不挤占用户首屏。
|
||
- 不把 OpenClaw 的 UI 代码直接复制进 MNote;只采用信息架构和交互模型。
|
||
|
||
## 8. 测试矩阵
|
||
|
||
- Unit:
|
||
- `PiRunViewModel` event reducer
|
||
- tool card folding
|
||
- queue_update reducer
|
||
- dialog lifecycle
|
||
- Browser smoke:
|
||
- `/page-ai/pi` start -> prompt -> streaming -> tool timeline -> final Markdown
|
||
- Context7 MCP call tool card
|
||
- MemPalace MCP call tool card
|
||
- Stop/abort visible state
|
||
- Steer/follow-up queue visible state
|
||
- extension confirm/select/input/notify
|
||
- Regression:
|
||
- `/api/ai-admin/settings` 删除 Skill/MCP 后 effective 不再出现残留
|
||
- admin/user AI policy 不能越权启用全局未授权 skill/mcp/model/root
|
||
|
||
## 9. 后续完成记录
|
||
|
||
- 2026-07-10:7-74 已完成 RPC parity、session tree/fork、composer draft/@ 引用、artifact diff/citation 产品化补全,归档到 `design/07-ai/done/7-74-page-ai-pi-rpc-parity-and-productization-checklist-v1.md`。
|