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

260 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 拆分:
- 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 请求合同草案
```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 不混 ReasonixReasonix 不混 HermesChat-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 是否允许读取文件夹摘要,或严格只允许聊天文本和显式勾选的页面摘要。
- 技术调试入口默认是否仅管理员可见,还是普通用户也可展开。