Repository navigation
feat(modes): 用户可管理的对话模式 — 权限、确认与运行预算 - #4
Conversation
模式改为可编辑的 ModeProfile:工具权限(无/只读/完全)、逐调用确认和运行预算均可在 设置→模式 中创建、修改、删除,内置模式同样可编辑或移除,可一键恢复默认。模式列表存储于 SharedPreferences(ModeProfileStore),会话、运行和计划任务记录模式 id;旧库中的枚举名即为内置 id,无需数据库迁移。引擎行为类(CHAT/CHAT_PLUS/ACT/MAX)由权限推导,预算经 budgetOverride 传入 AgentLoop。计划任务编辑器与模式选择器改为列出全部模式。
新增设置→模式→编辑器的独立全屏页面(导航路由,非拉伸弹窗):名称、工具权限、逐调用确认、「长任务」开关、模式专属指令(拼接到该模式的系统提示)、预算(预设+滑块)、重置为默认与删除(带确认与最少一个模式保护)。「长任务」开关将 MAX 的任务协议(计划、完成报告、结束横幅)与普通对话分离:自定义全权限模式默认关闭,不再在每次回答后弹出完成横幅;内置 MAX 默认开启。任务协议文本按开关选择,计划块与横幅同源受控。旧配置行自动沿用旧行为(仅 MAX 弹横幅)。
新模式开关「完全同意」(默认关):外部内容进入对话后,run_shell/manage_app 不再降级为确认,直接执行并在调用流中带「自动」标记;子任务继承该同意。范围仅限推荐的两项:模式自身的逐调用确认仍生效(独立开关),计划任务/自动化仍照旧拒绝无人值守的高危调用。
Verlintas
left a comment
There was a problem hiding this comment.
整体实现很完整。我在本地 worktree 跑了 test、lintDebug、assembleDebug、assembleRelease、许可证头、字符串同步和 tool schema,全部通过;fullConsent 的 gate 测试也覆盖了 unattended、ACT 确认和 autoConsent 标记,方向没问题。
建议先处理下面几项再合。
1. ChatScreen 里有一个字符错误(确定)
feature/chat/src/main/java/com/verlintas/baic2/feature/chat/ChatScreen.kt 第 1921/1925 行的 " В· " 用了 Cyrillic В(U+0412),不是中点 ·,界面上会显示成 В·。应改为 " · "。
2. fullConsent 和 requiresConfirmation 同时打开时语义冲突(确定)
编辑器允许两个开关同时打开,但 AgentLoop.gate() 里 fullConsent 只解除 taint 后的 HIGH 降级,mode.requiresConfirmation 仍然会返回 NeedsConfirm。UI 提示写的是“高危调用……不询问”,实际还会询问。
建议二选一:
- 打开 fullConsent 时联动/强制关闭逐次确认,并加一条明确警告;
- 或者保留组合,但 UI 明确写“仍需逐次确认”,不要写成不询问。
3. fullConsent 在聊天模式选择器里不可见(建议修)
ChatScreen.modeDescription() 对 stock 模式的判断只比较 toolAccess 和 requiresConfirmation,没有比较 fullConsent 和 isTask;自定义模式描述也只拼了“全部工具 · 免确认 · 长任务”,没有“完全同意”。结果是一个被编辑成 fullConsent 的 stock MAX,在聊天选择器里仍然显示普通 MAX 描述,顶部模式芯片也没有标记。
建议:
- stock 描述判断加入
fullConsent/isTask; - 自定义描述加入 fullConsent;
- 或在
Baic2ModeChip上加一个明确的 full-consent 标记。
4. 定时任务模式与 Tasks 过滤不一致(需要确认)
ScheduledTaskEditor 现在列出全部模式(含 CHAT / READ_ONLY),ScheduledTaskRunner 也会为它们创建 Run;但 TasksViewModel 只保留 modes.resolve(run.mode).agentic(toolAccess == FULL)的运行。这样 READ_ONLY / CHAT 定时任务会跑,但 Tasks 里看不到对应 Run。
另外 RunDao.observeSummaries() 的 LIMIT 100 仍在分类过滤之前,历史非 agentic 运行多了可能把 agentic 运行挤出列表。
建议二选一:
- 编辑器只允许 agentic 模式;
- 或 Tasks 同时展示 read-only / chat 运行并分组;
- 过滤尽量下推到 SQL,或把 limit 放到过滤之后。
5. 删除模式只提醒定时任务,不提醒会话/历史 Run(需要确认)
ModeProfilesPage 只检查 tasks.any { it.mode == mode.id };ModeProfileStore.delete() 不更新会话或 Run。删除后 resolve() 回退到 CHAT,历史 Run 会在 Tasks 里被 agentic 过滤掉,会话降级为普通聊天。
建议删除确认里补上会话/历史运行的影响,或给 Run 存一个不可变的 agentic/category 字段。
6. 子代理继承 fullConsent(需要决定)
SpawnAgentTool 把 fullConsent = run.fullConsent 传给子代理,子代理的 confirmationGate 固定返回 false。因此 MAX + fullConsent 的父运行可以 spawn 一个 MAX 子代理,子代理在 tainted 后直接跑 HIGH 工具。
如果这是有意的,建议在 UI/文档写清“完全同意包括子代理”;如果不是,建议默认不继承,或只在显式开关下继承。
小问题
.github/workflows/build.yml上传 debug APK 可以加retention-days: 7,避免 70MB artifact 长期堆积;文件末尾缺换行。ModeProfileStore.read()JSON 损坏时会静默回退到 stock,自定义模式丢失;至少 log 一次。
已验证
test/lintDebug/assembleDebug/assembleRelease通过check-license-headers/check-strings-sync/check-tool-schemas通过ModeProfileTest、AgentLoopTest的 fullConsent 用例通过OpenAiCompatibleProviderTest的空 API Key 用例通过- 这些结果只代表构建和单测;OS 端 UI 交互和真机 fullConsent 行为还需要手动验收
Verlintas
left a comment
There was a problem hiding this comment.
上一轮的 blocking 项都已处理并验证通过:
В·已改为·- fullConsent 与逐次确认改为互斥,旧配置在读取时归一化
- 模式描述/自定义描述补充 fullConsent 与长任务
Run.toolAccess不可变落库 + DB 21→22 迁移,Tasks 按代理/研究/对话分组,状态过滤下推 SQL- 删除模式提示补充会话与历史运行的影响
- 子代理继承 fullConsent 已在设置提示中明确说明
ModeProfileStore损坏日志、CI artifact 撤回
本地 test / lintDebug / assembleDebug / assembleRelease / 许可证 / 字符串 / schema 均通过,CI build 通过;21→22 迁移 SQL 已用 21.json 建库模拟验证。
还有一个小的一致性问题:fullConsent 开启时 confirm 开关仍可打开,界面显示开但保存会被强制写回 false。不阻塞合并,我会在合并后直接在 main 上修。
Uh oh!
There was an error while loading. Please reload this page.