8.4 KiB
8.4 KiB
7-69 Page AI Pi-first Lab Spike 验收记录 v1
状态:done(最小可验证 spike) Owner:07-ai / mnote-web / control-plane 日期:2026-07-03
1. 本轮结论
7-69 已完成 MNote 侧最小可验证 Pi-first Page AI Lab spike:OpenHub 仍是默认 Page AI 主线,Pi Lab 仅在 MNOTE_PAGE_AI_PI_LAB=1 下作为 dev-only/internal 入口启用。
当前结论不是“替换 OpenHub”,而是:Pi 值得进入下一阶段受控验证;扩大前必须补真实 Pi CLI/RPC、Turso/libSQL receipt 表、auth 下浏览器 smoke 和 watcher 端到端证据。
2. 已实现内容
- 新增 Pi Lab 后端路由:
/api/page-ai/pi/status、bootstrap、start、send、abort、events、tool-call、/page-ai/pi。 - 新增 MNote 托管 runtime:
pi --mode rpcsubprocess 或MNOTE_PAGE_AI_PI_LAB_RUNTIME=mock,sessionDir 派生到 MNote 管控目录。 - 默认禁用 Pi builtin tools:启动参数包含
--no-builtin-tools,状态响应显式标注bash/read/write/edit不开放。 - 实现 MNote-owned tool facade:
mnote.current_page.read、mnote.selection.read、mnote.allowed_roots.describe、mnote.local_file.read、mnote.local_file.patch、mnote.knowledge_rag.query、mnote.reference.open、mnote.tool_receipt.write。 - 文件读写受 allowed roots 限制,越界读写返回 deny reason 且写 receipt。
- LightRAG 保持唯一默认知识 provider;Pi 只通过
knowledge_ragfacade 查询和 open-reference。 - receipt 先落
provider_neutral_jsonl_adapter_v1,字段含 session binding、tool event、deny reason、diff summary、file version、allowed roots snapshot,并写明迁移到 Turso/libSQLai_provider_sessions/ai_tool_events/ai_file_patches的条件。 - 文件 patch 响应声明
mnote local-folder watcher / document-session external refresh,并显式polling=false,不新增高频轮询。 - 新增 Pi Lab runtime UI:状态机、SSE/EventSource、stream、tool card、citation、diff、abort、receipt 诊断。
- Pi Lab 已从简陋独立 debug 页改为当前 MNote Page AI 抽屉内的 dev-only provider 面板,并保留悬浮
π入口;切回 OpenHub 时复用原抽屉与 iframe,OpenHub 仍是默认入口。 - Pi RPC stream 中
thinking_*事件默认不进入可见 assistant bubble;可见回复只渲染text_*/ assistant final text,避免 Omniroute/freefirst 的 reasoning_content 泄漏到页面。 - gateway 仅在
enable_page_ai_pi_lab开启时注入 Pi Lab runtime,默认 body 标记为 hidden,不改变 OpenHub 默认入口。 - 新增 smoke:静态结构、禁用态 API endpoint、mock-mode API 验证脚本、浏览器 smoke 脚本。
- 新增 spike checklist:
design/07-ai/done/7-69-page-ai-pi-first-lab-checklist-v1.md,逐项标注 Phase A-E 已完成项与下一阶段 gap。
3. 未完成内容
- 系统 PATH 仍未安装全局
pi,但已通过npx -y @earendil-works/pi-coding-agent@0.80.3包装器完成真实pi --mode rpc端到端 smoke;后续需决定是否固定安装方式或配置MNOTE_PAGE_AI_PI_BIN。 - receipt 尚未写入 Turso/libSQL 正式表,仍为 provider-neutral JSONL adapter。
mnote.tool_receipt.write当前仍是最小 tool envelope 路径,未作为独立持久化入口深化。- watcher 刷新已按 MNote 文件写入链路声明和返回 metadata,但还需登录态浏览器端 smoke 证明 tiptap 当前页被 watcher 刷新。
- 已基于最新
@earendil-works/pi-web-ui@0.75.3源码重新评估,而不是使用 recycle 旧源码。其ChatPanel/AgentInterface/MessageEditor/ message-tool renderer 是成熟 UI 参考,但直接接入会同时引入浏览器端pi-agent-core、IndexedDB session/provider key、API key prompt、proxy、attachments、artifacts 和Agent.state.tools事实源,与 MNote 托管 Pi RPC/SSE、AiAccessScope 和 MNote-owned tools 边界冲突。 - 本轮采用 MNote-native adapter:视觉与交互参考官方
ChatPanel/AgentInterface的消息流、composer、tool timeline、model/runtime controls 和 artifacts-style rail;session、API key、模型、工具权限、receipt 仍由 MNote 后端托管。若下一阶段要直接复用官方组件,迁移条件是先提供不依赖浏览器 API key/IndexedDB/Agent tools 的 remote-session adapter。 - API endpoint smoke 当前覆盖禁用态 3000;完整 mock-mode smoke 需要用
MNOTE_PAGE_AI_PI_LAB=1 MNOTE_PAGE_AI_PI_LAB_RUNTIME=mock启动独立服务后运行。
4. Pi 是否进入下一阶段
建议进入下一阶段,但仍保持 internal/lab:
- 通过:MNote 侧最小 runtime manager、tool facade、allowed roots、LightRAG facade、file patch、receipt adapter、SSE UI 已形成闭环。
- 未通过生产门槛:Turso receipt 表、正式登录态 browser smoke、watcher tiptap 刷新截图/断言仍未完整。
下一阶段应聚焦真实 runtime 和验收,不扩大默认入口。
5. OpenHub 状态
OpenHub 继续保持默认 Page AI 主线。Pi Lab 未替换、未破坏 OpenHub / LightRAG / Turso 路径;相关路由和 UI 均受 MNOTE_PAGE_AI_PI_LAB=1 / enable_page_ai_pi_lab 控制。
6. 验证记录
node scripts/task-pi-lab-static-smoke.js:通过,78 项。node scripts/task-pi-lab-api-endpoint-smoke.js:通过,10/10;当前 3000 服务未启用 Pi Lab,验证禁用态和 asset。node scripts/task-pi-lab-mock-api-smoke.js:通过;覆盖 mock runtime start、SSE events、allowed roots、当前页读取、越界拒绝、当前.mdpatch、watcher refresh metadata、LightRAG facade、citation/open-reference facade、send、abort。node scripts/task-pi-lab-browser-smoke.js:通过;覆盖当前 MNote Page AI 抽屉、dev-only 悬浮π入口、Pi/OpenHub 切换、omniroute/freefirst、MNote tool rail、composer、status API 和截图;不再把独立/page-ai/pi当作主要 UI 验收面。- Pi + Omniroute/freefirst 浏览器实测截图:
tmp/page-ai-pi-omniroute-freefirst-final-ok-20260704-v3.png;证据 JSON:tmp/page-ai-pi-omniroute-freefirst-final-ok-20260704-v3.json。最终 assistant 可见文本为OK,assistantStreaming=false,inDrawer=true,模型为omniroute/freefirst,runtime 为rpc。 node scripts/task-pi-lab-mock-api-smoke.js:通过;使用 mock mode 独立 3332 服务与MNOTE_PI_LAB_SMOKE_ROOT=/tmp/mnote-pi-lab-smoke,覆盖 start/send/abort/events、allowed roots、越界拒绝、当前页 read、文件 patch、receipt。node scripts/task-pi-lab-api-endpoint-smoke.js:通过,10/10;支持启用态 + Bearer smoke auth,验证 status schema、disabled builtins、runtime asset 和端点存在。codegraph sync . && codegraph status .:通过;索引 up to date。- 真实 Pi RPC smoke:通过;使用
/tmp/mnote-pi-cli-wrapper.sh调用npx -y @earendil-works/pi-coding-agent@0.80.3,MNote 以MNOTE_PAGE_AI_PI_LAB_RUNTIME=rpc/MNOTE_PAGE_AI_PI_BIN=/tmp/mnote-pi-cli-wrapper.sh启动,验证start返回runtimePid、当前页读取、越界拒绝、当前.mdpatch、sendaccepted、abort成功。 node scripts/task-pi-lab-rpc-api-smoke.js:新增 RPC API smoke 固化脚本(2026-07-04 7-69 收尾),覆盖 runtimeMode=rpc status、runtimePid 真实子进程验证、start/send/abort 端点、tool-call MNote facades(allowed roots、越界拒绝、.md patch 含 watcher refresh/version change、LightRAG、citation)、SSE 事件流(runtime_started 含 pid/mode/disabledBuiltinTools)、多会话生命周期、Pi 进程清理。需要真实 Pi CLI + API key 完整测试 send 实际 AI 调用。cd rust && cargo check -p mnote-web:通过。which pi:无输出;本轮通过MNOTE_PAGE_AI_PI_BIN指向 wrapper 完成真实 RPC smoke。
RPC 验证命令
# 启动 mnote-web(真实 Pi RPC 模式)
MNOTE_PAGE_AI_PI_LAB=1 \
MNOTE_PAGE_AI_PI_LAB_RUNTIME=rpc \
MNOTE_PAGE_AI_PI_BIN=/tmp/mnote-pi-cli-wrapper.sh \
MNOTE_PI_LAB_ALLOWED_ROOTS=/tmp/mnote-pi-rpc-smoke \
npm run desktop:hot
# 另一个终端运行 smoke
MNOTE_PI_LAB_BASE=http://127.0.0.1:3000 \
MNOTE_PI_LAB_AUTH="Bearer pi-lab-smoke" \
MNOTE_PAGE_AI_PI_BIN=/tmp/mnote-pi-cli-wrapper.sh \
MNOTE_PI_LAB_ALLOWED_ROOTS=/tmp/mnote-pi-rpc-smoke \
node scripts/task-pi-lab-rpc-api-smoke.js
mock 验证命令:
MNOTE_PAGE_AI_PI_LAB=1 \
MNOTE_PAGE_AI_PI_LAB_RUNTIME=mock \
MNOTE_PI_LAB_ALLOWED_ROOTS=/tmp/mnote-pi-lab-smoke \
MNOTE_PI_LAB_BASE=http://127.0.0.1:3000 \
node scripts/task-pi-lab-mock-api-smoke.js