Skip to content

feat(chat): add V2 subagent collaboration - #1482

Open
CATMIAOZHI wants to merge 2 commits into
AAswordman:devfrom
CATMIAOZHI:feat/chat-subagent-current
Open

CATMIAOZHI wants to merge 2 commits into
AAswordman:devfrom
CATMIAOZHI:feat/chat-subagent-current

Conversation

@CATMIAOZHI

@CATMIAOZHI CATMIAOZHI commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

feat(chat): add V2 subagent collaboration

变更说明 / Description

普通聊天可以并行启动子代理,向运行中的子会话投递消息,或在其空闲后发起下一轮,并从主聊天查看只读记录。

背景与动机 / Context and motivation

本 PR 堆叠在消息队列 #1481 之上;GitHub 的目标为 dev,因此当前差异包含父层。父层合并后会重放本层并缩小差异。

改动范围 / Changes

  • 提供协作工具、运行状态、终止控制和模型选择。
  • 持久化父子关系;子代理不混入普通聊天列表。插件内部 v1 任务继续运行。
  • JSON v5 导出完整会话图并在导入时验证和重映射关系;保留原 group 分组及 JSON v2 导入。
  • 子会话为只读记录,普通发送和开场白同步不能改写它;嵌套删除的确认数量与实际范围一致。
  • 重启已归档任务时恢复其可见性;以计数和单条查询避免不必要的整段正文加载。

兼容性与风险 / Compatibility and risks

#1478 为兼容 Operit2 恢复了 Room 21。本层基于该版本,迁移 21→23,仅增加会话类型、运行记录及索引,不重新引入文件夹实体、聊天收藏或最近时间缓存。

维护者已在协调回复中确认本次改动不受此前对话树层级问题影响。PR 已转为 Ready,仍按父层依赖顺序审阅;该回复不代替数据库升级及备份导入验证。

没有提供已撤回文件夹预览版数据库的升级路径;本构建不能覆盖安装到那些预览版。包含子代理的 v5 备份需要支持该格式的客户端。孤儿普通分支导出为独立聊天;源数据不变。

关联 Issue / Related issue

相关讨论:#573。本次涉及子代理,不包含 Goal 模式。

验证方式 / Verification

  • Windows,JDK 21,Android debug;:app:testDebugUnitTest 成功:1827 项,1818 通过、9 跳过,0 失败。
  • 当前适配的逻辑、性能、界面三项独立静态审计通过。未运行本地 Lint。
  • 迁移测试检查 Room 21 的历史、group 和大数值 token 统计保留;DAO 测试覆盖子树删除和归档后重启。
  • 真机待验证:在主聊天启动子代理、发送消息、等待并返回父会话;检查子会话只读和隐藏。用隔离环境检查历史升级和 v5 备份恢复。

证据 / Evidence

本地测试报告:app/build/reports/tests/testDebugUnitTest/index.html。真机画面尚未采集。

检查清单 / Checklist

  • 已记录验证命令、结果和未运行项。
  • 上游目标为 dev。
  • 创建 PR 后核对 Candidate checks。
  • 发布前对最终远端基线再检查一次差异。
  • 补充真机画面或录屏。

@CATMIAOZHI

Copy link
Copy Markdown
Collaborator Author

@luojiaping 想请教一下这组子代理 PR 与 Operit2 的数据库兼容方向。

#1478 为兼容旧版快照导入恢复了 Room v21。本 PR 的子代理存储需要 21→23 迁移,后续界面层 #1484 再升级到 24;保留 chats.group,没有重新引入已撤回的文件夹结构。不过,新数据库版本仍需要与 Operit2 的导入契约协调。

想先确认两点:

  1. Operit2 导入桥是否方便增加对这套 v23/v24 结构的支持?子代理聊天和运行记录需要一起迁入,还是只导入普通聊天?
  2. 如果近期仍需保持 v21 快照兼容,更建议这边提供兼容导出,还是将子代理存储独立出来?也欢迎建议其他更合适的方案。

目前相关 PR 都保持 Draft,兼容方案确认前不合并。可以按确认后的字段和导入范围配合调整,并补充对应的迁移、导出导入验证。

@luojiaping

Copy link
Copy Markdown
Collaborator

@luojiaping 想请教一下这组子代理 PR 与 Operit2 的数据库兼容方向。

#1478 为兼容旧版快照导入恢复了 Room v21。本 PR 的子代理存储需要 21→23 迁移,后续界面层 #1484 再升级到 24;保留 chats.group,没有重新引入已撤回的文件夹结构。不过,新数据库版本仍需要与 Operit2 的导入契约协调。

想先确认两点:

  1. Operit2 导入桥是否方便增加对这套 v23/v24 结构的支持?子代理聊天和运行记录需要一起迁入,还是只导入普通聊天?
  2. 如果近期仍需保持 v21 快照兼容,更建议这边提供兼容导出,还是将子代理存储独立出来?也欢迎建议其他更合适的方案。

目前相关 PR 都保持 Draft,兼容方案确认前不合并。可以按确认后的字段和导入范围配合调整,并补充对应的迁移、导出导入验证。

这个不影响,上一个是因为改了对话树的层级,那边不支持,迁移会麻烦一点就撤销了。

@luojiaping
luojiaping marked this pull request as ready for review November 10, 2026 08:29

@CATMIAOZHI CATMIAOZHI left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审计结论:💬 意见

自审:本 PR 作者为 CATMIAOZHI(本人),本次为自审。

改动(179 文件,+16173/−1414):普通聊天可并行启动 V2 子代理、向运行中子会话投递消息、空闲后发起下一轮,并持久化父子关系与运行记录;JSON v5 导出完整会话图并在导入时验证重映射;子会话为只读记录。注意:本 diff 包含父层 #1481(消息队列/转向,41 文件),父层合并后需重放本层缩小差异。

通过的检查:

  • 目标分支为 dev;head SHA 与提交一致;无新增权限声明、无 token/密钥相关改动。
  • 工具权限:子代理禁用的 task / create_new_chat / send_message_to_ai(含 streaming)在 ToolExecutionManager 以 PERMISSION_DENIED 硬拦截,CliToolModeSupport 同步过滤;协作工具在执行时重新校验 CollaborationToolPolicy.visibility;v1 task 不能接管 v2 运行(TaskToolExecutor 要求用 followup_task)。
  • 只读 enforcement 三层一致:UI 层 readOnlyTranscript、服务层 ChatTurnDispatcher 预发检查拒绝非子任务轮次、HTTP 桥返回 403。
  • 迁移 21→23:仅加 chatKind 列、建 subagent_runs 表与索引,不动既有会话与 token 统计;ChatFeatureMigrationTest 覆盖 v21 历史/group/大数值 token 保留与 chatKind 回填;Room 迁移链 20→21→23 可衔接。
  • v5 导入导出:validateV5Archive 校验环、kind/父子一致性、run 与 child 一一对应、状态枚举与重复 tool call ID;导入时冲突 ID 重映射、进行中 run 置为 INTERRUPTED;孤儿 BRANCH 导出时降级为 NORMAL。
  • 删除:子先父后顺序删除 + child 外键 CASCADE + parent 外键 NO_ACTION 兜底;ChatDeletionGraphPolicy 使删除集在父子图上封闭,不会留下孤儿 run 行。
  • 并发/取消:CollaborationCoordinator(锁 + stopGate + 容量检查 + CancellationException→INTERRUPTED)与 SubagentCoordinator(分父 semaphore、模型门控、NonCancellable 清理、信号量释放)的取消语义基本正确;TurnInputInbox 与父层各 catch 均先重抛 CancellationException。
  • 子代理创建:子会话与 run 在同一 Room 事务内创建;活跃上限 3、默认嵌套深度 1、wait 上限 1 小时;wait_agent 超时下限 10 秒。
  • 文案:新 UI 无硬编码中文 Text(),中英 strings.xml 各增 114 行;新文件无 TODO/FIXME。

问题:

  1. [question] Operit2 兼容的自设 hold 是否已解除:PR 描述写着“本 PR 保持 Draft,数据库方案尚待协调”“解决前不应合并”,但 API 上 draft=false;@luojiaping 已在评论区回复“这个不影响,上一个是因为改了对话树的层级”。请作者在 PR 内明确确认该回复已解决兼容问题,并同步修正描述(Draft 状态与实际不一致),再合并。
  2. [question] 备份格式 v3/v4 被排除在 supportedVersions = {2, 5} 之外:若 v3/v4 曾随预览版对外发布过备份格式,这些旧备份将无法导入。请确认 v3/v4 从未对外发布,或在拒绝信息中说明原因。
  3. [P2] SubagentCoordinator.runResolvedTask 的模型 fallback 用 catch (error: Exception) 包裹首次 executeTurn,未先排除 CancellationException。目前因 isExplicitModelAvailabilityFailure 的标记串与取消消息无交集,取消仍会重抛、行为正确,但属于隐患:后续若标记串扩充,取消的任务可能被误判为模型不可用而用父模型重试。应在通用 catch 之前加 catch (error: CancellationException) { throw error }。
  4. [P2] SubagentMigration 为 21→23 直跳,无 22→23 路径:装过已撤回文件夹预览版(Room v22)的设备升级后,Room 会抛 A migration from 22 to 23 was required but not found、无法打开数据库。PR 描述已声明不支持覆盖安装到那些预览版,建议在发布说明中明确提示受影响用户需卸载重装或保留数据导出路径。
  5. [P3] CollaborationCoordinator.caller() 在只读路径也会创建并持久化 root agent 记录(如 list_agents、工具可见性计算时对普通聊天调用),属于 write-on-read;建议仅在真正需要协作上下文时创建。
  6. [P3] 备份格式由 v2 跳到 v5,旧版客户端无法导入新备份(PR 描述已披露);建议发布说明中注明最低可导入版本。
  7. [P3] 真机验证与 Lint 尚未完成(作者已在 PR 中披露);合并前建议至少补一次真机主流程验证(主聊天启动子代理、投递消息、等待返回父会话、子会话只读与隐藏)。

后续可跟进(不阻塞):#1484 界面层升级到 Room 24 时复核本次迁移与 v5 格式的衔接;全量单测(作者报告 1827 项通过)与 Lint 由 CI/作者复核,本次未独立复跑。

由 水晴喵的muse 审计

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants