Persist PageTree expand state via control-plane view-state and align chevron/DOM with restored expansion; keep Sidex-style shallow page-tree scan and drop the unused recursive scanner that only added cargo noise. Add password vault workbench routes/runtime/skill/CLI, split page_ai_pi into a module package, and retire Hermes/ACP/OpenHub recycle + root harness evidence from the index while gitignoring recycle and local diag dumps. Archive superseded design/bugs docs under old/, point architecture at ARCHITECTURE.md, and refresh smokes for Pi S1–S7, vault, and editor regressions so the working tree can stay clean.
26 KiB
7-71 MNote 统一 AI 管理面板与 Pi Lab 功能接入设计 v1
状态:process Owner:07-ai / mnote-web / control-plane / Page AI 日期:2026-07-04
1. 结论
应该做 MNote 原生统一 AI 管理面板,但顺序不是先堆 UI,而是先把 control-plane 合同、持久化和 effective config API 做成唯一真相,再让 Pi Rust Page AI / LightRAG 消费同一套配置。
文件夹授权必须只有一套:当前 /admin/access-policy 与 /user/access-policy 管理的 directory_grants 同时就是 MNote 工作区访问授权和 AI allowed roots 的事实源。AI 管理面板可以把它纳入同一个信息架构,但不能再维护第二套 AI-only allowed roots。
OpenHub 的 admin 面板(历史)证明了正确产品结构:provider/model、skills、tools、MCP、目录权限、知识库、历史、用量、健康状态必须先有管理面,聊天 UI 只展示用户可用的有效配置。MNote 不能把 OpenHub admin 作为 MNote AI 的长期真相。2026-07-18:OpenHub 已不再是默认 Page AI 主线;Pi Rust 为默认入口。 MNote AI 管理中心应落在 Turso/libSQL control-plane。上位收口见 checklist 21。
2. 调研依据
2.1 OpenHub
源码:
/mnt/Data1T/Mnote_data/openhub/OpenHub/smart-query-frontend/src/pages/AdminPage.jsx/mnt/Data1T/Mnote_data/openhub/OpenHub/smart-query-frontend/src/components/UserSettingsDrawer.jsx/mnt/Data1T/Mnote_data/openhub/OpenHub/smart-query-frontend/src/components/HistoryDrawer.jsx/mnt/Data1T/Mnote_data/openhub/OpenHub/smart-query-frontend/src/services/api.js/mnt/Data1T/Mnote_data/openhub/OpenHub/smart-query-backend/app/api/admin.py
可复用的产品模型:
- 管理后台按区段管理:用户、模型配置、工具权限、技能、目录权限、知识库、用量、系统健康。
- 用户设置抽屉只显示管理员已允许的有效配置:模型、技能、MCP、目录、工具、用量。
- 权限是三层:admin global policy -> user override -> effective policy。
- 历史记录是左侧抽屉,支持新建、刷新、归档、分页/滚动。
不应直接搬的部分:
- opencode 服务管理、飞书渠道、WeKnora 配置导出。
- React/AntD 组件主链。
- OpenHub SQLite 表作为 MNote 真相层。
2.2 Pi / Pi Web UI
源码:
/mnt/Data1T/tmp/pi-web-ui-shot/node_modules/@earendil-works/pi-web-ui/src//mnt/Data1T/tmp/pi-web-ui-shot/node_modules/@earendil-works/pi-agent-core/dist/rust/crates/mnote-web/src/routes/page_ai_pi.rsrust/crates/mnote-web/browser/sidebar-page-ai-pi-lab-runtime.js
可复用的合同:
SessionData:id/title/model/thinkingLevel/messages/createdAt/lastModifiedSessionMetadata:id/title/lastModified/messageCount/usage/thinkingLevel/previewAgentEvent:agent_start/end、message_update/end、tool_execution_start/update/endThinkingLevel:off/minimal/low/medium/high/xhigh- Provider/model 设置形态:SettingsDialog、ModelSelector、ProvidersModelsTab、CustomProvider。
不能照搬的部分:
- IndexedDB 是 Pi standalone browser app 的存储,不是 MNote 真相层。
- Pi 原始
bash/read/write/edit仍必须禁用。 - Pi web-ui 是 Lit Web Components;MNote 当前 Pi Lab 保持原生 runtime,不 iframe、不让 Pi UI 接管 provider key 或工具权限。
2.3 MNote 当前底座
已有:
directory_grants:当前文件夹授权事实。ai_policies:已有allowed_roots_json / model_policy_json / quota_json,但无 HTTP 管理 API 和 UI。ai_runtime_runs / ai_runtime_events:已有跨 provider run/event journal。ai_external_conversation_bindings:已有 MNote session 与外部 provider conversation 绑定。/admin/access-policy与/user/access-policy:已有文件夹授权面板。
缺口:
- Pi Lab session 仍在内存 HashMap,重启丢失。
- Pi Lab receipt 仍在内存 + JSONL adapter,无法按用户/工作区查询。
- provider/model/skills/MCP/tools 的 MNote-native 管理 API 和 UI 不存在。
- Pi Lab UI 的历史、设置、模型选择还没有接入真实配置源。
3. 目标架构
MNote AI 管理中心
/admin/ai admin global policy
/user/ai user effective settings
|
v
Turso/libSQL control-plane
directory_grants
ai_policies
ai_runtime_runs / ai_runtime_events
ai_external_conversation_bindings
ai_provider_configs / ai_model_catalog / ai_model_grants
ai_tool_policies / ai_skill_registry / ai_mcp_servers
ai_tool_events / ai_file_patches
|
v
MNote AI Facade APIs
effective config
allowed roots
model/provider catalog
skills/tools/MCP policy
LightRAG facade
session history / receipts
|
+--> OpenHub iframe/default Page AI
+--> Pi Lab native drawer
+--> future native agents
OpenHub 继续保持默认 Page AI 入口。MNote 管理中心不替换 OpenHub admin,而是成为 MNote 侧 AI 权限和配置的真相层;需要同步给 OpenHub 时,通过 provider identity sync / OpenHub admin API 做下游同步。
4. 管理面板信息架构
4.1 Admin:/admin/ai
沿用现有 /admin/access-policy 的 SSR 页面方式,新增 AI 管理中心。左侧区段建议:
Overview- AI runtime 状态、OpenHub 状态、Pi Lab 状态、LightRAG 状态、最近错误。
Providers & Models- Omniroute/OpenAI/Anthropic/Google/local providers。
- API key/base URL/认证状态。
- 模型可见性、默认 Build/Plan/Task 模型、failover chain。
- 默认保留
omniroute/freefirst作为 Pi Lab dev/default model。
Access Scopes- 直接复用当前
/admin/access-policy、/user/access-policy文件夹授权 UI 和既有授权 API,不新增 AI-only 授权目录。 directory_grants是 MNote 与 AI 共用的 allowed roots 事实源。AiAccessScope.allowed_roots、OpenHub allowedRoots、Pi Lab allowed roots 都从directory_grants派生。- 支持 read/write、recursive、capabilities、workspace/user 维度。
- 该区段只提供授权摘要、effective scope 预览和进入现有授权页的入口;若后续内嵌编辑,也必须调用同一套
directory_grantscommand/API。
- 直接复用当前
Tools- MNote-owned tools 全局策略:allow/ask/deny。
- 默认 deny raw bash/read/write/edit。
- Pi 只显示并使用 MNote facade tools。
Skills- MNote builtin skills、Codex/Acontext skills、OpenHub/opencode skills 的 registry。
- 全局启停,用户可在授权范围内开关。
MCP- MCP server registry、启动命令、allowed roots、network policy、env/secret 引用。
- 默认不让 Pi 直接接管 raw MCP;Pi 通过 MNote facade 调用。
Knowledge- LightRAG 是唯一默认 provider。
- 管理 source registry、index 状态、citation/open-reference 映射。
Sessions & Receipts- Page AI / OpenHub / Pi Lab / native agent 历史。
- tool events、deny reason、diff summary、file version、citation count。
Usage & Quota- 按用户、workspace、provider、model 统计。
- token、cost、request count、失败率。
4.2 User:/user/ai
用户设置只显示 effective config:
- 可用模型:来自 admin allowed models;用户只能隐藏或选择默认,不提升权限。
- 可用 skills/tools/MCP:只能在 admin 允许范围内开关或降级。
- 目录权限:查看由
directory_grants派生的 allowed roots,并进入/user/access-policy请求或调整授权;不保存 AI 私有目录配置。 - 历史记录:自己的 Page AI / Pi Lab sessions。
- 用量:自己的 quota 与调用统计。
4.3 Pi Lab 抽屉接入
Pi Lab 顶部工具栏:
- 历史按钮:打开 Pi Lab history drawer,数据来自 MNote
/api/page-ai/pi/sessions或统一/api/page-ai/sessions?provider=pi。 - 设置按钮:打开 MNote-native user AI settings overlay;管理员可跳到
/admin/ai。 - 模型选择:读取 effective model options,不再硬编码单个 select。
- Build/Plan:读取 agent mode policy,决定可用模型、thinkingLevel、tool policy。
- 工具/引用/diff:继续只显示 MNote facade 返回的 receipt 和 citation。
5. 数据合同
5.1 复用现有表
directory_grants:MNote 与 AI 共用的唯一文件夹授权事实源,也是 allowed roots 派生源。ai_policies:workspace/user 的模型、配额、工具、skills/MCP 策略汇总层;不得作为第二套 allowed roots 真相。历史字段allowed_roots_json只能视为缓存/兼容快照,写入时必须由directory_grants派生。ai_runtime_runs:统一 AI session/run 元数据。Pi Lab 不新建独立 session 真相表,先复用它。ai_runtime_events:统一 message/tool/runtime event journal。ai_external_conversation_bindings:OpenHub remote conversation / future external provider binding。user_ui_preferences:前端折叠状态、默认 tab 等低风险 UI preference。
5.2 授权目录单一真相规则
- 不新增
ai_allowed_roots、pi_allowed_roots、openhub_allowed_roots或任何同义表。 - 不允许 Pi Lab、OpenHub、AI 管理页或 session 设置单独写一份目录授权 JSON。
- 所有目录授权变更统一写入
directory_grants,沿用现有管理员/用户权限边界、审计和路径校验。 - AI effective config 按 user/workspace 读取
directory_grants,生成AiAccessScope.allowed_roots。 - Pi Lab 创建 session/run 时记录 effective scope 快照,但每次工具执行仍按当前
directory_grants重新校验。 - OpenHub
allowedRoots是 MNote 下发的下游投影,不能反向成为授权真相。 ai_policies.allowed_roots_json只能作为不可独立编辑的兼容快照、迁移输入或缓存;满足迁移条件后应删除或改名,避免误用和双写。
5.3 新增或规范化表
第一阶段优先最小新增:
ai_tool_events(
id,
user_id,
workspace_id,
session_id,
run_id,
provider,
provider_session_id,
tool_name,
allowed,
deny_reason,
root_uri,
page_path,
normalized_file_path,
diff_summary,
citation_count,
before_file_version,
after_file_version,
payload_json,
created_at,
deleted_at
)
ai_file_patches(
id,
user_id,
workspace_id,
session_id,
run_id,
tool_event_id,
root_uri,
relative_path,
before_file_version,
after_file_version,
patch_summary_json,
created_at
)
第二阶段再规范化:
ai_provider_configsai_model_catalogai_model_grantsai_tool_policiesai_skill_registryai_skill_grantsai_mcp_serversai_mcp_grantsai_usage_logsai_model_failover_chains
说明:不要急着新增 ai_provider_sessions。MNote 已有 ai_runtime_runs / ai_runtime_events,Pi Lab history 可以先落这里;只有当 provider 原生 thread 与 MNote run/event journal 差异太大时,再加 provider-specific session detail 表。
6. API 合同
6.1 管理 API
GET /api/ai-admin/overview
GET /api/ai-admin/providers
PUT /api/ai-admin/providers/{provider_id}
GET /api/ai-admin/models
PUT /api/ai-admin/models/{provider_id}/{model_id}/policy
GET /api/ai-admin/access-scopes
GET /api/ai-admin/tools
PUT /api/ai-admin/tools/{tool_name}/policy
GET /api/ai-admin/skills
PUT /api/ai-admin/skills/{skill_id}/policy
GET /api/ai-admin/mcp
PUT /api/ai-admin/mcp/{server_id}/policy
GET /api/ai-admin/knowledge
GET /api/ai-admin/sessions
GET /api/ai-admin/receipts
GET /api/ai-admin/usage
6.2 用户有效配置 API
GET /api/ai-settings/effective
GET /api/ai-settings/models
PUT /api/ai-settings/models/{provider_id}/{model_id}
GET /api/ai-settings/tools
PUT /api/ai-settings/tools/{tool_name}
GET /api/ai-settings/skills
PUT /api/ai-settings/skills/{skill_id}
GET /api/ai-settings/mcp
GET /api/ai-settings/access-scopes
GET /api/ai-settings/usage
GET /api/ai-admin/access-scopes 与 GET /api/ai-settings/access-scopes 只读返回由 directory_grants 计算的 effective scope,并返回现有授权管理页入口。授权写入继续使用现有 access-policy / directory_grants command/API;不在 AI admin route 中定义第二套 grants 写语义。
6.3 Pi Lab history API
可以做成 Pi-specific facade,但底层写 ai_runtime_runs/events:
GET /api/page-ai/pi/sessions
GET /api/page-ai/pi/sessions/{session_id}
PUT /api/page-ai/pi/sessions/{session_id}/title
DELETE /api/page-ai/pi/sessions/{session_id}
GET /api/page-ai/pi/sessions/{session_id}/events
响应参考 Pi SessionMetadata:
{
"id": "pi_lab_...",
"title": "当前页解释",
"model": "omniroute/freefirst",
"thinkingLevel": "medium",
"lastModified": "2026-07-04T14:20:00Z",
"messageCount": 8,
"usage": {"input": 1200, "output": 400, "totalTokens": 1600},
"preview": "帮我解释当前页面的逻辑..."
}
7. 实施顺序
P0:合同与只读聚合
- 新增设计和 smoke baseline。
- 增加
/api/ai-settings/effective只读 API。 - 聚合已有
directory_grants、ai_policies、agent descriptors、Pi defaults。 - 明确
effective.allowedRoots只从directory_grants派生;若ai_policies.allowed_roots_json存在,只作为兼容只读快照或迁移源,不参与新增写入。 - Pi Lab model selector 改为消费 effective models,但仍保留
omniroute/freefirstfallback。
验收:
- OpenHub 默认入口不变。
- Pi Lab 打开后能显示来自 MNote effective config 的模型、allowed roots、tool policy。
P1:Pi Lab history 入库
- Pi Lab start/send/end 写
ai_runtime_runs / ai_runtime_events。 - 历史 drawer 读 MNote DB,不读 IndexedDB、不读内存 HashMap。
- 现有 JSONL receipt 保留为 debug fallback。
验收:
- 重启 mnote-web 后 Pi Lab 历史仍可见。
- 同一 user/workspace 隔离生效。
P2:Receipt 与 patch 入库
- 新增
ai_tool_events / ai_file_patches。 mnote.local_file.read/patch、LightRAG query、reference.open、tool_receipt.write 全部写入。- Pi Lab receipt rail 改读 DB event stream。
验收:
- allowed roots deny、diff summary、file version、citation count 可在管理面板查询。
- patch 后 watcher refresh 仍不新增轮询。
P3:MNote AI 管理中心首版
/admin/ai先做四个可用 tab:Overview、Providers & Models、Access Scopes、Sessions & Receipts。/user/ai做 Models、Access、History、Usage。- 复用
/admin/access-policy//user/access-policy逻辑,不拆第二套授权事实;AI 面板里的 Access Scopes 本质上是该授权页面的 AI 视角入口。
验收:
- 管理员可设置 Pi Lab 默认模型和可见模型。
- 用户只能选择管理员允许的模型。
- 文件夹授权仍同步 OpenHub,不破坏 OpenHub。
P4:Skills / MCP / Tools / LightRAG 管理
- Skills registry 与 grants。
- MCP registry 与 sandbox policy。
- MNote-owned tools allow/ask/deny。
- LightRAG source/index/status 管理。
验收:
- Pi Lab settings 能显示 skills/MCP/tools effective 状态。
- Pi 仍不能直接启用 raw bash/read/write/edit。
- LightRAG 仍是唯一默认 knowledge provider。
8. 关键决策
- MNote 管理中心是必需的,但第一步是 control-plane + effective API,不是先做完整 UI。
- OpenHub admin 只作为参考和下游同步对象,不作为 MNote AI 真相层。
- 文件夹授权只保留一套:
directory_grants同时服务 MNote 工作区访问、OpenHuballowedRoots和 Pi LabAiAccessScope.allowed_roots;AI 管理页只提供同源视图和现有授权入口。 - Pi IndexedDB schema 可参考,不能作为 MNote 持久化方案。
- Pi Lab history 先复用
ai_runtime_runs/events,避免新增重复 session 表。 - receipt/patch 必须入 Turso/libSQL,JSONL 只保留 debug/crash recovery。
- skills/MCP/tools 先管权限,再接 UI;否则会把未受控工具暴露给 Pi。
- secrets 不进前端、不硬编码;provider API key 应只存 secret reference/env key,后续再接正式 secret store。
9. 风险
- 直接把 OpenHub admin 嵌进 MNote 会形成第二个 iframe 管理系统,和 Pi Lab 原生化目标冲突。
- 先做 Pi UI settings 会把配置写进临时 DOM/内存,后续仍要重接 Turso。
- 如果不先统一 history,Pi Lab 与 OpenHub 会话会分裂,用户无法判断哪个入口产生了修改。
- MCP 管理若过早放开,容易绕过 AiAccessScope;必须默认只注册、只显示,不默认启用。
- Model/provider secret 管理不能复用 Codex auth 作为产品实现;Codex auth 只可作为 dev smoke 输入。
10. 下一步最小可执行设计稿
建议下一张执行稿拆成:
7-72-page-ai-pi-lab-history-and-effective-config-control-plane-v1
范围只做:
/api/ai-settings/effective- Pi Lab model options 读取 effective config
- Pi Lab session 写入
ai_runtime_runs/events - Pi Lab history drawer 读 DB
- receipt 仍保留 JSONL,但设计 migration 到
ai_tool_events - smoke 覆盖重启后历史存在、用户隔离、OpenHub 默认入口不变
做完 7-72 后,再做 /admin/ai 首版 UI。这样不会在 UI 上先行制造第二套事实源。
11. 实施进度(2026-07-04)
P0: 合同与只读聚合 — 进度
| 项 | 状态 | 证据 |
|---|---|---|
| 新增设计和 smoke baseline | ✅ 已完成 | design/07-ai/process/7-71-* 设计文档、scripts/task-ai-management-control-plane-static-smoke.js 静态 smoke(27/27 通过) |
/api/ai-settings/effective 只读 API |
✅ 已实现 | routes/ai_settings.rs::effective_settings — GET-only,读 directory_grants 和 ai_policies.model_policy_json/quota_json |
/api/ai-settings/access-scopes 用户只读 API |
✅ 已实现 | routes/ai_settings.rs::user_access_scopes — GET-only |
/api/ai-admin/access-scopes 管理员只读 API |
✅ 已实现 | routes/ai_settings.rs::admin_access_scopes — GET-only,管理员鉴权 |
聚合 directory_grants、ai_policies、agent descriptors、Pi defaults |
✅ 已实现 | effective 响应聚合 providers、models、tool_catalog、lightrag_provider、access_policy_links |
effective.allowedRoots 只从 directory_grants 派生 |
✅ 已验证 | load_active_directory_grants 读取 list_directory_grants_for_actor;ai_policies.allowed_roots_json 不被读取 |
| Pi Lab model selector 消费 effective models | ✅ 已实现 | effective_settings 响应含 models、default_model;Pi Lab 前端消费 |
| 静态 smoke 覆盖:路由注册、source of truth、无写操作 | ✅ 27/27 通过 | scripts/task-ai-management-control-plane-static-smoke.js |
P1: Pi Lab history 入库 — 进度
| 项 | 状态 | 证据 |
|---|---|---|
Pi Lab start/send/end 写 ai_runtime_runs / ai_runtime_events |
✅ 已实现 | page_ai_pi.rs::persist_upsert_run / persist_append_event |
| 历史 drawer 读 MNote DB | ✅ 已实现 | list_sessions 读 control_plane.list_ai_runtime_runs;get_session_history / get_session_events 分别读 run 和 events |
| 现有 JSONL receipt 保留为 debug fallback | ✅ 已保留 | PI_LAB_RECEIPT_STORE JSONL 静态存储仍在 |
| Pi Lab session 路由注册 | ✅ 已验证 | GET /api/page-ai/pi/sessions、GET .../{session_id}、GET .../{session_id}/events |
| Pi Lab session 按 pi_lab/pi profile/acp_runtime 过滤 | ✅ 已验证 | list_sessions 过滤 r.profile == PI_LAB_PROFILE && r.acp_runtime == PI_LAB_ACP_RUNTIME |
P2: Receipt 与 patch 入库 — 已完成
| 项 | 状态 | 证据 |
|---|---|---|
ai_tool_events / ai_file_patches migration |
✅ | control-plane/migrations/009-ai-tool-events-file-patches.sql |
| SQLite 与 Turso/libSQL store | ✅ | append/list_ai_tool_event、append/list_ai_file_patch |
| Pi tool receipt 入 control-plane | ✅ | page_ai_pi.rs::write_receipt |
| patch 关联写入 file patch journal | ✅ | receipt id 作为 tool_event_id |
| JSONL 降级为 debug fallback | ✅ | 仅 control-plane 写失败后追加 |
| 管理 API 查询 receipts / patches | ✅ | /api/ai-settings/receipts、/api/ai-admin/receipts |
P3: MNote AI 管理中心首版 — 管理员写管理完成
| 项 | 状态 | 证据 |
|---|---|---|
/admin/ai 路由与入口 |
✅ 已实现 | gateway.rs::admin_ai_entry,鉴权后跳转,管理员模式 |
/user/ai 路由与入口 |
✅ 已实现 | gateway.rs::user_ai_entry,鉴权后跳转,用户模式 |
| 账户菜单独立 AI 管理入口 | ✅ 已实现 | sidebar-workspace-runtime.js mnote-account-ai-management,按角色跳 /admin/ai 或 /user/ai |
| AI 管理页面 SSR | ✅ 已实现 | ssr/pages/ai_admin.rs::AiManagementPage — 对齐 OpenHub Admin 左侧分页、白色 Card 壳、表格、抽屉与分组权限面板;管理 Overview、模型、服务、用量、工具、Skills/MCP、目录、知识库、会话与监控 |
| Access Scopes 只读展示 | ✅ 已验证 | 页面脚本只 GET access-scopes 数据,无 POST/PUT/DELETE,无写表单 |
| Sessions & Receipts 区域 | ✅ 已接真实数据 | 展示 Pi session、tool receipt、deny reason、diff summary、patch 数量 |
/admin/ai 管理写操作(provider/model 编辑等) |
✅ 已实现 | GET/PUT /api/ai-admin/settings;模型配置浏览器保存与刷新持久化通过 |
/user/ai 用户设置 |
❌ 未实现 | 当前 /user/ai 复用 AiManagementPage 用户模式,仅有只读视图;逐用户模型/工具/Skill/MCP override 已在管理员用户抽屉完成 |
P4: Skills / MCP / Tools / LightRAG 管理 — 部分完成
- Skills、MCP 与工具策略已通过原子管理 API 和 SSR 管理 UI 写入
ai_policies.model_policy_json - MCP 强制
facadeOnly=true、sandbox=true,secret 仅接受env:///secret:// - MNote-owned tools 已支持 allow/ask/deny
- LightRAG source/index/status 管理 UI 未实现
- provider/skill/MCP 专用规范化表未实现;出现独立查询、授权或生命周期需求时再迁移
OpenHub / Pi Lab 独立入口状态
| 项 | 状态 |
|---|---|
OpenHub /page-ai/openhub/ai 未删除 |
✅ |
OpenHub /page-ai/openhub/admin 未删除 |
✅ |
| OpenHub status API 未删除 | ✅ |
Pi Lab shell /page-ai/pi 未删除 |
✅ |
| Pi Lab start/send/abort/events 路由未删除 | ✅ |
验证命令占位
# 静态 smoke(只读代码审计)
node scripts/task-ai-management-control-plane-static-smoke.js
# 运行时 smoke(需要 mnote-web 运行中)
# curl -s http://localhost:3000/api/ai-settings/effective | jq '.sourceOfTruth'
# curl -s http://localhost:3000/api/ai-settings/access-scopes | jq '.sourceOfTruth'
# curl -s http://localhost:3000/api/ai-admin/access-scopes | jq '.sourceOfTruth'
# curl -s -o /dev/null -w '%{http_code}' http://localhost:3000/admin/ai
# curl -s -o /dev/null -w '%{http_code}' http://localhost:3000/user/ai
# curl -s http://localhost:3000/api/page-ai/pi/sessions | jq '.schema'
# curl -s http://localhost:3000/api/ai-settings/receipts | jq '{receiptCount, patchCount}'
运行时与浏览器证据
- 隔离运行端口:
127.0.0.1:33171 task-pi-lab-mock-api-smoke.js:通过task-pi-lab-browser-smoke.js:通过- Pi Lab 截图:
tmp/7-71-pi-lab-browser-final.png - AI 管理页截图:
tmp/7-71-ai-admin-final.png - 模型写管理截图:
tmp/7-71-ai-admin-openhub-like-ui-final/models.png - Skills/MCP 写管理截图:
tmp/7-71-ai-admin-openhub-like-ui-final/skills-mcp.png - OpenHub-like 逐用户配置抽屉截图:
tmp/7-71-ai-admin-openhub-like-ui-final/users.png - 管理页实测摘要:会话 1、回执 3、文件补丁 1
- OpenHub 仍为默认 Page AI,Pi Lab 继续使用独立按钮、独立抽屉与独立 session
mnote-e2e已通过 control-planerole=admin验证管理员访问和写入;浏览器 smoke 使用 dev seed 仅为临时验收账号准备,不写第二套授权目录
P4: Skills / MCP / Tools 管理 — 验收结果
| 项 | 状态 | 证据 |
|---|---|---|
| admin 原子策略 GET/PUT | ✅ 通过 | /api/ai-admin/settings,统一保存模型、工具、Skills、MCP |
| 浏览器保存与刷新持久化 | ✅ 通过 | scripts/task-ai-management-browser-smoke.js |
| secretRef-only 检查 | ✅ 通过 (3 项) | Section 9: 无硬编码 api_key/secret,仅 env 引用 |
| allowed roots 不可写检查 | ✅ 通过 (4 项) | Section 10: 无写路由、无写函数、无写表单 |
| MCP facade-only 检查 | ✅ 通过 (3 项) | Section 11: Pi 仅暴露 mnote. 工具,MCP 经 facade 管控 |
P5: OpenHub 式逐用户 AI 配置 — 已完成
- OpenHub Admin 的真实用户管理入口为用户表格 + 模型/工具/Skill/目录权限操作;MCP 仅展示用户工作区
.opencode/mcp文件,不存在 Admin per-user MCP 策略。 - MNote 新增用户列表与逐用户 AI 策略 API,用户 override 继续落
ai_policies(user_id, workspace_id=NULL)。 - 当前
ai_policies没有系统全局行,因此暂以MNOTE_ADMIN_USER_IDS首个用户作为全局策略 owner;迁移到规范化 policy 表时移除此兼容约定。 - 本轮已把 MNote
/admin/ai用户配置抽屉改成 OpenHub-like 体验:模型按 provider 分组、工具按 risk level 分组、Skill/MCP 使用启停开关、目录权限只读并跳转统一授权管理页。 - effective 合并规则:
- 模型只能从管理员 allowed models 中选择;
- 工具只能降权,不能从 deny/ask 提升到 allow;
- Skill/MCP 只能关闭或启用全局已允许项;
- MCP 始终保持 facade-only + sandbox;
- allowed roots 完全不参与该合并,继续只读
directory_grants。
- 浏览器截图:
tmp/7-71-ai-admin-openhub-like-ui-final/users.png。 - 浏览器 smoke 同时以普通用户
ai-user登录,确认 effective API 不返回被禁用模型和 Skill。
本轮 smoke 结果
静态 smoke:47 通过,0 失败。浏览器 smoke 验证模型、工具、Skills/MCP 保存、OpenHub Admin 独立入口保留、OpenHub-like 用户抽屉、逐用户 override、刷新持久化及 effective 投影全部通过。
$ node scripts/task-ai-management-control-plane-static-smoke.js
通过: 47 失败: 0 跳过: 0
$ MNOTE_AI_ADMIN_OUTPUT_DIR=tmp/7-71-ai-admin-openhub-like-ui-final \
node scripts/task-ai-management-browser-smoke.js
ok: true
后续范围
/user/ai用户模型/Skills/MCP 偏好- LightRAG source/index/status 写管理
- provider/skill/MCP 专用规范化表迁移