Files
mnote/design/07-ai/process/7-71-unified-ai-management-control-plane-and-pi-lab-integration-v1.md
T

26 KiB
Raw Blame History

7-71 MNote 统一 AI 管理面板与 Pi Lab 功能接入设计 v1

状态:process Owner07-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-18OpenHub 已不再是默认 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 服务管理、飞书渠道、知识库配置导出。
  • 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.rs
  • rust/crates/mnote-web/browser/sidebar-page-ai-pi-lab-runtime.js

可复用的合同:

  • SessionData: id/title/model/thinkingLevel/messages/createdAt/lastModified
  • SessionMetadata: id/title/lastModified/messageCount/usage/thinkingLevel/preview
  • AgentEvent: agent_start/endmessage_update/endtool_execution_start/update/end
  • ThinkingLevel: 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 ComponentsMNote 当前 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 管理中心。左侧区段建议:

  1. Overview
    • AI runtime 状态、OpenHub 状态、Pi Lab 状态、LightRAG 状态、最近错误。
  2. Providers & Models
    • Omniroute/OpenAI/Anthropic/Google/local providers。
    • API key/base URL/认证状态。
    • 模型可见性、默认 Build/Plan/Task 模型、failover chain。
    • 默认保留 omniroute/freefirst 作为 Pi Lab dev/default model。
  3. 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_grants command/API。
  4. Tools
    • MNote-owned tools 全局策略:allow/ask/deny。
    • 默认 deny raw bash/read/write/edit。
    • Pi 只显示并使用 MNote facade tools。
  5. Skills
    • MNote builtin skills、Codex/Acontext skills、OpenHub/opencode skills 的 registry。
    • 全局启停,用户可在授权范围内开关。
  6. MCP
    • MCP server registry、启动命令、allowed roots、network policy、env/secret 引用。
    • 默认不让 Pi 直接接管 raw MCPPi 通过 MNote facade 调用。
  7. Knowledge
    • LightRAG 是唯一默认 provider。
    • 管理 source registry、index 状态、citation/open-reference 映射。
  8. Sessions & Receipts
    • Page AI / OpenHub / Pi Lab / native agent 历史。
    • tool events、deny reason、diff summary、file version、citation count。
  9. 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_policiesworkspace/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_bindingsOpenHub remote conversation / future external provider binding。
  • user_ui_preferences:前端折叠状态、默认 tab 等低风险 UI preference。

5.2 授权目录单一真相规则

  • 不新增 ai_allowed_rootspi_allowed_rootsopenhub_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_configs
  • ai_model_catalog
  • ai_model_grants
  • ai_tool_policies
  • ai_skill_registry
  • ai_skill_grants
  • ai_mcp_servers
  • ai_mcp_grants
  • ai_usage_logs
  • ai_model_failover_chains

说明:不要急着新增 ai_provider_sessions。MNote 已有 ai_runtime_runs / ai_runtime_eventsPi 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-scopesGET /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_grantsai_policies、agent descriptors、Pi defaults。
  • 明确 effective.allowedRoots 只从 directory_grants 派生;若 ai_policies.allowed_roots_json 存在,只作为兼容只读快照或迁移源,不参与新增写入。
  • Pi Lab model selector 改为消费 effective models,但仍保留 omniroute/freefirst fallback。

验收:

  • OpenHub 默认入口不变。
  • Pi Lab 打开后能显示来自 MNote effective config 的模型、allowed roots、tool policy。

P1Pi 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 隔离生效。

P2Receipt 与 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 仍不新增轮询。

P3MNote AI 管理中心首版

  • /admin/ai 先做四个可用 tabOverview、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。

P4Skills / 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. 关键决策

  1. MNote 管理中心是必需的,但第一步是 control-plane + effective API,不是先做完整 UI。
  2. OpenHub admin 只作为参考和下游同步对象,不作为 MNote AI 真相层。
  3. 文件夹授权只保留一套directory_grants 同时服务 MNote 工作区访问、OpenHub allowedRoots 和 Pi Lab AiAccessScope.allowed_roots;AI 管理页只提供同源视图和现有授权入口。
  4. Pi IndexedDB schema 可参考,不能作为 MNote 持久化方案
  5. Pi Lab history 先复用 ai_runtime_runs/events,避免新增重复 session 表。
  6. receipt/patch 必须入 Turso/libSQLJSONL 只保留 debug/crash recovery。
  7. skills/MCP/tools 先管权限,再接 UI;否则会把未受控工具暴露给 Pi。
  8. secrets 不进前端、不硬编码provider API key 应只存 secret reference/env key,后续再接正式 secret store。

9. 风险

  • 直接把 OpenHub admin 嵌进 MNote 会形成第二个 iframe 管理系统,和 Pi Lab 原生化目标冲突。
  • 先做 Pi UI settings 会把配置写进临时 DOM/内存,后续仍要重接 Turso。
  • 如果不先统一 historyPi 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 静态 smoke27/27 通过)
/api/ai-settings/effective 只读 API 已实现 routes/ai_settings.rs::effective_settings — GET-only,读 directory_grantsai_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_grantsai_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_actorai_policies.allowed_roots_json 不被读取
Pi Lab model selector 消费 effective models 已实现 effective_settings 响应含 models、default_modelPi 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_sessionscontrol_plane.list_ai_runtime_runsget_session_history / get_session_events 分别读 run 和 events
现有 JSONL receipt 保留为 debug fallback 已保留 PI_LAB_RECEIPT_STORE JSONL 静态存储仍在
Pi Lab session 路由注册 已验证 GET /api/page-ai/pi/sessionsGET .../{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_eventappend/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=truesandbox=truesecret 仅接受 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 AIPi Lab 继续使用独立按钮、独立抽屉与独立 session
  • mnote-e2e 已通过 control-plane role=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 结果

静态 smoke47 通过,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 专用规范化表迁移