Files
mnote/design/07-ai/done/7-39-page-ai-agent-selector-context-authorization-settings-v1.md
T

14 KiB
Raw Blame History

7-39 Page AI agent selector / context authorization settings v1

创建时间:2026-05-28 状态:done 来源:用户反馈:旧 Page AI UI 信息过载;“编辑当前文件 / 工作区任务”模式难以区分;应参考 Cline 在聊天输入区选择 agent,并在设置里按 agent 拆分配置;共性设置包含授权区域,且授权区域应按用户保存到 SQLite。

1. 背景

当前 Page AI sidebar 已能接 Hermes / Reasonix ACP、run target snapshot、changed files 审计和 SQLite directory grant。但 UI 仍把 agent、profile、runtime、skills、history、gateway、工具参数和错误解释混在一个抽屉中。

这导致两个问题:

  • 用户真正要做的只是“选择 agent + 勾选要发给 AI 的上下文地址”,但现有 UI 暴露了太多 Hermes/ACP 运行细节。
  • “编辑当前文件”和“工作区任务”作为主模式不稳定:本地 Markdown、打开资源、选区、文件夹和 changed files 都可能参与同一轮请求,按模式分流反而会误导。

因此后续 Page AI 主线应从“模式切换”改为“agent 选择 + contextRefs 勾选 + SQLite 授权区域”的结构。

2. 参考对照

2.1 Cline

可借鉴模型:

  • 聊天输入区附近直接选择当前 agent / provider,让用户在提问前完成路由决策。
  • 设置页按 agent/provider 拆分,只把模型、profile、API、能力开关等差异配置放在各自页面。
  • 共性配置只放所有 agent 都需要理解的内容,例如上下文、授权、审计、历史保留。

只作参考实现:

  • Cline 的 VSCode extension 状态和 provider 配置模型不能直接搬到 MNote;MNote 的授权区域必须继续走 SQLite control-plane,而不是浏览器 localStorage 或扩展全局状态。

不适合 MNote

  • 不把“工作区 root”当作天然可读写范围。MNote 必须基于 directory_grants / AiAccessScope / allowed roots 显式授权。

2.2 Sidex / VSCode workbench

可借鉴模型:

  • 资源、编辑器、工作区和最近修改项应以可选引用表达,而不是把 UI 分成互斥大模式。
  • Explorer / editor / panel 可以共享同一份打开资源快照,但不把 UI 层选择变成新的树或页面真相。

只作参考实现:

  • VSCode / Sidex 的工作台布局、tab model、context key 可以作为交互参考;MNote 的真实对象边界仍由 Rust kernel projection、local-first source 和 control-plane 决定。

不适合 MNote

  • 不把 VSCode extension host 或工作台状态当成 MNote 的资源生命周期真相。

3. 产品决策

3.1 主聊天面

主聊天面只保留四类默认可见元素:

  • 当前 agent 选择器:位于输入框下方或紧邻输入框,默认可快速切换 HermesReasonixChat-only,未来可扩展其他 agent。
  • ContextRefs 选择器:用勾选 chip / popover 选择要发送的地址,例如当前页、当前选区、当前打开资源、指定文件、指定文件夹、最近 changed files。
  • 输入框和发送/停止按钮。
  • 简短状态:只显示“可用 / 需要授权 / 正在运行 / 失败”,不默认显示 gateway、profile、tool trace、参数 JSON。

“编辑当前文件 / 工作区任务”不再作为主模式。它们退化为 contextRefs 的预设组合:

  • 编辑当前文件:勾选当前页或当前文件 + 必要的写权限 allowed root。
  • 工作区任务:勾选一个或多个文件夹 / changed files / 打开资源 + 必要的读写授权。

3.2 共性设置

共性设置只保留所有 agent 共享的配置:

  • 授权区域:来自 SQLite directory_grants,按当前用户隔离;展示 root、权限、递归、来源、状态。
  • 默认上下文勾选:保存到 SQLite user_ui_preferences,按用户、workspace、source 隔离。
  • changed files 展示策略:默认收起,只显示摘要;需要时展开路径/hash/mtime/actor。
  • 隐私与审计:是否记录 local agent audit、是否展示工具细节、是否允许发送选区/页面摘要。

共性设置不放 Hermes profile、Reasonix skill、provider API key、模型 preset 等 agent 差异项。

3.3 Agent 设置

设置页按 agent 拆分:

  • Hermesprofile、Hermes 设置入口、Hermes/ACP runtime 兼容提示、Hermes 专属 tool 开关。
  • ReasonixACP runtime、Reasonix skill 只读/可用状态、Reasonix 专属能力说明。
  • Chat-only:模型或 provider 选择、是否允许读取 contextRefs;默认不请求文件写权限。
  • 未来 agent:通过 registry 增加 agentId、显示名、能力、设置 schema、运行入口。

每个 agent 只能保存自身差异设置。默认 agent、默认 contextRefs 和授权区域仍属于共性设置。

4. 数据与合同

4.1 SQLite 使用边界

优先复用现有 control-plane

  • directory_grants:每用户授权区域真相。用于生成 allowed roots,不能由前端本地状态代替。
  • user_ui_preferences:每用户 UI 偏好。用于默认 agent、contextRefs 默认勾选、授权区域排序/最近使用、UI 密度、changed files 默认折叠状态。

建议 preference scope / key

  • scope = "ai.common"key = "default_agent_id"
  • scope = "ai.common"key = "context_refs.default_selected"
  • scope = "ai.common"key = "allowed_roots.default_selected"
  • scope = "ai.common"key = "allowed_roots.order"
  • scope = "ai.common"key = "changed_files.visibility"
  • scope = "ai.agent.hermes"key = "profile_id"
  • scope = "ai.agent.reasonix"key = "skill_panel_filter"
  • scope = "ai.agent.chat_only"key = "model_id"

除非现有表无法表达这些键值,否则第一阶段不新增 SQLite 表。

4.2 请求合同草案

{
  "agentId": "reasonix",
  "message": "把选中的 Markdown 小节整理成 checklist",
  "contextRefs": [
    {
      "kind": "current_page",
      "documentId": "local:page:example",
      "rootUri": "file:///mnt/Data1T/mnote"
    },
    {
      "kind": "folder",
      "rootUri": "file:///mnt/Data1T/mnote",
      "relativePath": "design/07-ai"
    }
  ],
  "allowedRoots": [
    {
      "rootUri": "file:///mnt/Data1T/mnote",
      "permission": "write",
      "source": "sqlite_directory_grant"
    }
  ],
  "runTargetSnapshot": {
    "version": "mnote.page_ai_run_target_snapshot.v1",
    "source": "open_editors_snapshot"
  },
  "audit": true
}

合同要求:

  • agentId 是主路由字段,不能再隐含在 Hermes profile 或 ACP runtime 里。
  • contextRefs 是用户勾选的上下文地址,不等同于授权。
  • allowedRoots 必须由 SQLite 授权区域和当前用户权限解析得到。
  • runTargetSnapshot 继续从 OpenEditorsSnapshot 冻结,防止 run 过程中 UI 切换导致目标漂移。

5. 旧 UI 精简规则

默认聊天面应移除或收敛:

  • 顶部同时展示 Hermes/profile/model/gateway 的多重状态。
  • 空态长解释、示例段落和“后端 AI 会话”等实现细节文案。
  • Runtime 页默认暴露 gateway health、queue、tools、trace、audit JSON。
  • Skills 页默认展示大量参数、来源和技术标签。
  • 工具调用卡默认展示 args/result/raw trace。
  • 输入框 placeholder 固定写“问 Hermes...”。

替代方式:

  • 默认只显示 agent 名称、上下文 chips、运行状态和最终回答。
  • 工具调用、changed files、audit、gateway、queue 进入“高级 / 调试”折叠区。
  • 错误文案先给用户动作,例如“需要授权该文件夹”,再提供可展开技术详情。
  • Hermes / Reasonix 的差异通过 agent selector 和 agent 设置页表达,不在聊天主面堆说明。

6. Checklist

Batch A - 现状冻结与视觉基线

  • 截图记录当前 Page AI sidebar 默认聊天面、Agent、Runtime、Skills、History 页。
  • 标注必须删除/折叠的冗余信息:profile/model/gateway、runtime queue、tool trace、长空态说明、Hermes 固定文案。
  • 对照 Cline agent selector 和 Sidex/VSCode context/resource 模型,形成最小信息架构图。
  • 验证:浏览器截图 + 本文档补充截图路径或 smoke 证据。

证据:旧 UI 基线截图在 tmp/task502-page-ai-baseline/01-chat.png02-agent.png03-skills.png04-runtime.png05-history.png;收敛后截图在 tmp/task502-page-ai-agent-selector-context-smoke/01-agent-selector-context.png

Batch B - Agent registry 与主选择器

  • 定义 agentId registryhermesreasonixchat_only,包含显示名、能力、是否可写文件、设置页入口。
  • 在聊天输入区附近增加 agent selector,替代“Hermes 固定入口”。
  • 发送请求时 payload 显式包含 agentId,旧 Hermes/Reasonix ACP 路径保持兼容。
  • 验证:node smoke 断言切换 agent 后 payload 和 UI badge 正确。

证据:rust/crates/mnote-web/browser/sidebar-page-ai-runtime.jsPAGE_AI_AGENT_REGISTRYscripts/task502-page-ai-agent-selector-context-smoke.js 断言 hermes/reasonix/chat_only 和 run payload agentId=reasonix

Batch C - ContextRefs 勾选器

  • 定义 contextRefs 类型:当前页、选区、当前打开资源、文件、文件夹、changed files。
  • ContextRefs 从 OpenEditorsSnapshot、当前 selection 和授权目录解析,不新增第二套页面/树真相。
  • “编辑当前文件 / 工作区任务”改为预设组合,不再作为主模式。
  • 验证:浏览器 smoke 勾选/取消 contextRefs 后 payload 稳定。

证据:PAGE_AI_CONTEXT_REF_REGISTRY 覆盖 current_page/selection/active_editor/file/folder/changed_filestask502 断言取消 current_page 后 payload 不含 current_page/pageText/pageXml/contextBlocks,并保留 active_editor/folder/changed_files

Batch D - SQLite per-user 授权区域

  • 共性设置页展示当前用户的 directory_grants,支持按 read/write、recursive、source、status 展示。
  • allowedRoots 只从当前用户 SQLite grant 解析;未授权目录必须提示授权,不允许前端绕过。
  • 修复/补齐 Page AI 与 ACP session create 的授权路径一致性,确保已授权本地文件夹不会误报无权访问。
  • 验证:Rust 定点测试覆盖不同用户 grant 隔离;浏览器 smoke 覆盖授权目录可用、未授权目录阻断。

证据:hermes_client.rs::enforce_local_ai_run_access 服务端按当前 actor 调 resolve_access 重算 allowedRootssqlite.rs::resolve_access_does_not_match_sibling_uri_prefix 修复 URI 前缀串扰;local_ai_run_access_* 覆盖 Alice/Bob 隔离与 chat_only read-only 降级;task502 验证授权 chip 来源为 sqlite_directory_grant

Batch E - UI preference per-user 持久化

  • user_ui_preferences 保存默认 agent、默认 contextRefs、授权区域排序/默认勾选、changed files 折叠策略。
  • preference key 必须带 user/workspace/source/scope 边界。
  • 不用 localStorage 作为长期真相;最多作为临时 UI cache。
  • 验证:Rust/JS smoke 覆盖 Alice/Bob 设置隔离。

证据:ui_preferences.rs 支持 ai.common.*ai.agent.*,并返回 aiPreferencesui_preferences_api_persists_ai_preferences_per_user_and_workspace 验证 Alice/Bob 隔离;task502 捕获 PUT ai.common.default_agent_idai.common.context_refs.default_selected

Batch F - Agent 分页设置

  • 设置页拆为 Common / Hermes / Reasonix / Chat-only。
  • Common 只放授权、默认 contextRefs、隐私/审计、changed files 显示策略。
  • Hermes 只放 Hermes profile/upstream/tool 相关设置。
  • Reasonix 只放 Reasonix ACP/skill 相关设置。
  • Chat-only 默认不申请文件写权限。
  • 验证:浏览器 smoke 检查不同 agent 设置页不串项。

证据:ensurePageAiDrawer 拆出 Common/Hermes/Reasonix/Chat-only/高级面板;task502 用真实浏览器检查 Common 不含 Hermes profile/ACP runtimeHermes 不混 ReasonixReasonix 不混 HermesChat-only 不混 ACP runtime。

Batch G - 旧 UI 冗余收敛

  • 默认聊天面隐藏 gateway/model/profile 技术细节,只保留 agent badge 和简短状态。
  • Runtime/Skills/History 收敛为高级/调试入口,默认不进入主聊天流。
  • 工具调用卡默认只展示摘要;args/result/raw trace 需展开。
  • changed files 默认摘要,展开后才显示路径/hash/mtime/actor。
  • 验证:浏览器截图对比,确保主面没有冗余解释和技术噪音。

证据:sidebar-page-ai-runtime.js 默认标题状态改为 agent/授权/AI session,旧 Hermes session 与固定 问 Hermes 文案退出默认聊天面;task502 断言默认聊天面不含 问 Hermes/model.default/gateway:/Hermes profilechanged files 仍由 task453-local-folder-page-ai-changed-files-smoke.js 验证摘要与 dirty 阻断。

Batch H - 合同与回归

  • 补最小 JS/Rust 合同注释或文档,说明 agentId + contextRefs + allowedRoots + runTargetSnapshot 的边界。
  • 保持 Hermes / Reasonix 旧 payload 兼容,必要时在 route 层做窄 adapter。
  • 更新 Page AI smoke,覆盖 agent 切换、contextRefs、SQLite 授权、per-user preference、旧路径兼容。
  • 运行 git diff --check、相关 Rust 定点测试、node smoke;涉及代码图修改后运行 codegraph sync .

证据:JS 合同注释位于 PAGE_AI_AGENT_REGISTRY 前;服务端兼容仍走 /api/hermes/client/runs 和 ACP profile/acpRuntime adapter;最终验证矩阵见本次执行汇报。

7. 非目标

  • 不实现 Phase C 流式 apply / suggest review。
  • 不把 local-first 普通 Markdown 编辑改回粗粒度 mnote.page.save
  • 不新增第二套树真相、页面真相、资源生命周期真相或授权真相。
  • 不把 agent 设置写入浏览器 localStorage 作为长期存储。
  • 不在本批次重构 Hermes / Reasonix agent 内部运行时。

8. 待确认产品点

  • Agent selector 的精确位置:输入框下方一行,还是输入框左侧/上方 compact row。
  • ContextRefs 默认勾选:是否默认包含当前页和当前选区,还是只默认当前页。
  • Chat-only 是否允许读取文件夹摘要,或严格只允许聊天文本和显式勾选的页面摘要。
  • 技术调试入口默认是否仅管理员可见,还是普通用户也可展开。