# 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 选择器:位于输入框下方或紧邻输入框,默认可快速切换 `Hermes`、`Reasonix`、`Chat-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 拆分: - Hermes:profile、Hermes 设置入口、Hermes/ACP runtime 兼容提示、Hermes 专属 tool 开关。 - Reasonix:ACP 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 请求合同草案 ```json { "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 - 现状冻结与视觉基线 - [x] 截图记录当前 Page AI sidebar 默认聊天面、Agent、Runtime、Skills、History 页。 - [x] 标注必须删除/折叠的冗余信息:profile/model/gateway、runtime queue、tool trace、长空态说明、Hermes 固定文案。 - [x] 对照 Cline agent selector 和 Sidex/VSCode context/resource 模型,形成最小信息架构图。 - [x] 验证:浏览器截图 + 本文档补充截图路径或 smoke 证据。 证据:旧 UI 基线截图在 `tmp/task502-page-ai-baseline/01-chat.png`、`02-agent.png`、`03-skills.png`、`04-runtime.png`、`05-history.png`;收敛后截图在 `tmp/task502-page-ai-agent-selector-context-smoke/01-agent-selector-context.png`。 ### Batch B - Agent registry 与主选择器 - [x] 定义 `agentId` registry:`hermes`、`reasonix`、`chat_only`,包含显示名、能力、是否可写文件、设置页入口。 - [x] 在聊天输入区附近增加 agent selector,替代“Hermes 固定入口”。 - [x] 发送请求时 payload 显式包含 `agentId`,旧 Hermes/Reasonix ACP 路径保持兼容。 - [x] 验证:node smoke 断言切换 agent 后 payload 和 UI badge 正确。 证据:`rust/crates/mnote-web/browser/sidebar-page-ai-runtime.js` 的 `PAGE_AI_AGENT_REGISTRY`;`scripts/task502-page-ai-agent-selector-context-smoke.js` 断言 `hermes/reasonix/chat_only` 和 run payload `agentId=reasonix`。 ### Batch C - ContextRefs 勾选器 - [x] 定义 `contextRefs` 类型:当前页、选区、当前打开资源、文件、文件夹、changed files。 - [x] ContextRefs 从 `OpenEditorsSnapshot`、当前 selection 和授权目录解析,不新增第二套页面/树真相。 - [x] “编辑当前文件 / 工作区任务”改为预设组合,不再作为主模式。 - [x] 验证:浏览器 smoke 勾选/取消 contextRefs 后 payload 稳定。 证据:`PAGE_AI_CONTEXT_REF_REGISTRY` 覆盖 `current_page/selection/active_editor/file/folder/changed_files`;`task502` 断言取消 `current_page` 后 payload 不含 `current_page/pageText/pageXml/contextBlocks`,并保留 `active_editor/folder/changed_files`。 ### Batch D - SQLite per-user 授权区域 - [x] 共性设置页展示当前用户的 `directory_grants`,支持按 read/write、recursive、source、status 展示。 - [x] allowedRoots 只从当前用户 SQLite grant 解析;未授权目录必须提示授权,不允许前端绕过。 - [x] 修复/补齐 Page AI 与 ACP session create 的授权路径一致性,确保已授权本地文件夹不会误报无权访问。 - [x] 验证:Rust 定点测试覆盖不同用户 grant 隔离;浏览器 smoke 覆盖授权目录可用、未授权目录阻断。 证据:`hermes_client.rs::enforce_local_ai_run_access` 服务端按当前 actor 调 `resolve_access` 重算 `allowedRoots`;`sqlite.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 持久化 - [x] 用 `user_ui_preferences` 保存默认 agent、默认 contextRefs、授权区域排序/默认勾选、changed files 折叠策略。 - [x] preference key 必须带 user/workspace/source/scope 边界。 - [x] 不用 localStorage 作为长期真相;最多作为临时 UI cache。 - [x] 验证:Rust/JS smoke 覆盖 Alice/Bob 设置隔离。 证据:`ui_preferences.rs` 支持 `ai.common.*` 与 `ai.agent.*`,并返回 `aiPreferences`;`ui_preferences_api_persists_ai_preferences_per_user_and_workspace` 验证 Alice/Bob 隔离;`task502` 捕获 PUT `ai.common.default_agent_id` 与 `ai.common.context_refs.default_selected`。 ### Batch F - Agent 分页设置 - [x] 设置页拆为 Common / Hermes / Reasonix / Chat-only。 - [x] Common 只放授权、默认 contextRefs、隐私/审计、changed files 显示策略。 - [x] Hermes 只放 Hermes profile/upstream/tool 相关设置。 - [x] Reasonix 只放 Reasonix ACP/skill 相关设置。 - [x] Chat-only 默认不申请文件写权限。 - [x] 验证:浏览器 smoke 检查不同 agent 设置页不串项。 证据:`ensurePageAiDrawer` 拆出 Common/Hermes/Reasonix/Chat-only/高级面板;`task502` 用真实浏览器检查 Common 不含 `Hermes profile/ACP runtime`,Hermes 不混 Reasonix,Reasonix 不混 Hermes,Chat-only 不混 ACP runtime。 ### Batch G - 旧 UI 冗余收敛 - [x] 默认聊天面隐藏 gateway/model/profile 技术细节,只保留 agent badge 和简短状态。 - [x] Runtime/Skills/History 收敛为高级/调试入口,默认不进入主聊天流。 - [x] 工具调用卡默认只展示摘要;args/result/raw trace 需展开。 - [x] changed files 默认摘要,展开后才显示路径/hash/mtime/actor。 - [x] 验证:浏览器截图对比,确保主面没有冗余解释和技术噪音。 证据:`sidebar-page-ai-runtime.js` 默认标题状态改为 agent/授权/AI session,旧 `Hermes session` 与固定 `问 Hermes` 文案退出默认聊天面;`task502` 断言默认聊天面不含 `问 Hermes/model.default/gateway:/Hermes profile`;changed files 仍由 `task453-local-folder-page-ai-changed-files-smoke.js` 验证摘要与 dirty 阻断。 ### Batch H - 合同与回归 - [x] 补最小 JS/Rust 合同注释或文档,说明 `agentId + contextRefs + allowedRoots + runTargetSnapshot` 的边界。 - [x] 保持 Hermes / Reasonix 旧 payload 兼容,必要时在 route 层做窄 adapter。 - [x] 更新 Page AI smoke,覆盖 agent 切换、contextRefs、SQLite 授权、per-user preference、旧路径兼容。 - [x] 运行 `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 是否允许读取文件夹摘要,或严格只允许聊天文本和显式勾选的页面摘要。 - 技术调试入口默认是否仅管理员可见,还是普通用户也可展开。