@eddyskywalker/dsh-chatgpt-subscription 0.23.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +34 -10
  3. package/lib/client.js +14 -0
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +7519 -6689
  6. package/lib/types/client/index.d.ts.map +1 -1
  7. package/lib/types/compat.d.ts +9 -0
  8. package/lib/types/compat.d.ts.map +1 -1
  9. package/lib/types/host/agent-preset.d.ts.map +1 -1
  10. package/lib/types/host/antigravity/account-pool.d.ts +43 -0
  11. package/lib/types/host/antigravity/account-pool.d.ts.map +1 -1
  12. package/lib/types/host/antigravity/adapter.d.ts +28 -0
  13. package/lib/types/host/antigravity/adapter.d.ts.map +1 -1
  14. package/lib/types/host/antigravity/catalog-limits.d.ts +23 -0
  15. package/lib/types/host/antigravity/catalog-limits.d.ts.map +1 -0
  16. package/lib/types/host/antigravity/client.d.ts.map +1 -1
  17. package/lib/types/host/antigravity/image-tool.d.ts +65 -0
  18. package/lib/types/host/antigravity/image-tool.d.ts.map +1 -0
  19. package/lib/types/host/antigravity/mapper.d.ts +30 -1
  20. package/lib/types/host/antigravity/mapper.d.ts.map +1 -1
  21. package/lib/types/host/antigravity/routes.d.ts.map +1 -1
  22. package/lib/types/host/antigravity/token-store.d.ts +4 -0
  23. package/lib/types/host/antigravity/token-store.d.ts.map +1 -1
  24. package/lib/types/host/antigravity/types.d.ts +15 -3
  25. package/lib/types/host/antigravity/types.d.ts.map +1 -1
  26. package/lib/types/host/subagent-model-authorization.d.ts +72 -3
  27. package/lib/types/host/subagent-model-authorization.d.ts.map +1 -1
  28. package/lib/types/index.d.ts +1 -0
  29. package/lib/types/index.d.ts.map +1 -1
  30. package/package.json +1 -1
  31. package/presets/dispatch/README.md +25 -2
  32. package/presets/dispatch/agent.cordis.yml +124 -103
package/CHANGELOG.md CHANGED
@@ -2,6 +2,54 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.24.1 - 2026-10-14
6
+ - **[调度模式 & 子代理授权守卫] 插件端机制级修复模型调用 `list_subagent_models` 后仍疯狂翻找本地文件定义的问题,并全面优化预设提示词(现场会话 `session-01724ca8`)**
7
+ - **现象**:主模型在启动阶段已调用 `list_subagent_models`,但因无参调用 `list_subagent_models({})` 只返回 provider 摘要,或看到上游工具描述写着 `"Catalog membership is advisory"` / `"Child LLM selection is optional..."`,不敢直接采信返回值,紧接着连续 9 个回合在工作区 grep `subagentModelAuthorization`、读取源码、递归扫描 `~/.dsh`(触发 120s 命令超时)并翻看 `settings.json` / `cordis.patch.yml` 以寻找「真正的允许清单定义」。
8
+ - **插件端机制级修复(`src/host/subagent-model-authorization.ts`,零修改上游 DSH)**:
9
+ 1. **`tools/post-execute` 输出增强(`enrichListSubagentModelsOutput`)**:当会话开启子代理模型授权守卫且允许清单生效时,拦截成功的 `list_subagent_models` 调用(含 PTC `run_code` 内调用),在原始输出末尾直接附上本会话全部已授权的 `{ provider, model }` 拆解对(`- <provider>/<model> -> provider: "<provider>", model: "<model>"`),使模型哪怕只调一次无参 `list_subagent_models({})` 也能一步拿到完整授权路由与精确传参字段。
10
+ 2. **`system-prompt/assemble` 工具描述原位重写(`rewriteAuthorizedPromptAssembly`)**:当会话受允许清单管控时,在系统提示组装阶段原位改写 PTC 模式的 `tools:sdk` section 与 Native 模式的 `assembly.tools` 中 `list_subagent_models` 的 `"Catalog membership is advisory..."` 及 `subagent` 的 `"Child LLM selection is optional..."` 误导描述,直接替换为本会话的强制显式选模型要求与已授权路由清单,从源头消除工具 schema 与守卫规则的冲突。
11
+ - **预设提示词全面优化并统一为英文(`src/host/agent-preset.ts` 与 `presets/dispatch/agent.cordis.yml` 逐字节同步)**:
12
+ 1. **全英文统一与执行主线对齐**:将 `persona.config.prefix` 与 `plan-mode.config.section` 统一为高信噪比英文指令(与 DSH 工具签名及运行时系统提示词语言保持一致);在顶部新增 `[Execution Pipeline]` 速查流水线,并将 `## R0.5 · Compatibility Gate` 调整至 `## R0 · Complexity Triage` 之前,使阅读顺序与实际执行顺序完全一致。
13
+ 2. **消除 `G4` 与 `R2` 的张力**:在 `R-G` 的 `G4` 中明确补注本会话允许的子代理模型路由由 `list_subagent_models` 直接提供而非仓库文件,防止模型把「查仓库事实」泛化到搜本地允许清单。
14
+ 3. **重写 `R2 · Model Routing`**:明确允许清单的唯一真源是 `list_subagent_models`(无参调用末尾已直接附上完整 `provider/model` 拆解清单),直接采信其输出而无需去翻本地配置文件或工作区代码交叉核对(避免硬性禁读文件影响正常的配置/源码任务),移除诱发 grep 的内部符号名 `subagentModelAuthorization`,并新增 Anti-Pattern 第 16 条。
15
+ 4. **精简重写 `plan-mode.config.section`**:消除了原本与 `R-G` 大段重复的冗余段落,收敛为与 `R0 / R-G / R2` 紧密衔接的英文四段式规则(`[Plan Mode]`、`[Read-Only Exploration & Clarification Interview]`、`[Plan Completeness]`、`[Plan Approval]`),并在只读探查段同步指明直接使用 `list_subagent_models` 返回的路由。
16
+
17
+ ## 0.24.0 - 2026-10-14
18
+ - **[Antigravity] 新增 Gemini 4 Argon(`gemini-4-argon`)并同步官方 2.23.0 客户端版本标识(2026-10-14 线上实测)**
19
+ - **版本门控(User-Agent)**:实测确认 `/v1internal:fetchAvailableModels` 对 `User-Agent` 版本存在门控——旧 `2.8.0` (`cl=963137146`) 仅下发 26 个模型且默认模型停留在 `gemini-3.8-flash-high`;升级为官方最新客户端 `2.23.0` (`cl=998057262`) 后服务端下发 29 个模型(新增 `gemini-4-argon-low` / `-medium` / `-high`),并将 `defaultAgentModelId` 切至 `gemini-4-argon-medium`。同步更新 `DEFAULT_ANTIGRAVITY_VERSION = '2.23.0'` 与 `DEFAULT_ANTIGRAVITY_CL = '998057262'`。
20
+ - **模型与路由**:在可选目录首位新增 `gemini-4-argon`(`Gemini 4 Argon`,上下文 `1048576`,最大输出 `65536`,支持文本与图片输入及 `low` / `medium` / `high` 三档思考);线上实测不存在裸 `gemini-4-argon` 或 `gemini-4-argon-tiered`(均返回 404),路由按档位映射至 `gemini-4-argon-low` / `gemini-4-argon-medium` / `gemini-4-argon-high`(默认 `gemini-4-argon-medium`,`off` 走 `gemini-4-argon-low` 并在 `thinkingConfig` 中设 `includeThoughts: false`)。
21
+ - **思考配置**:`mapper.ts` 的 `isGemini3` 扩展为 `isGemini3Or4`(`/^gemini-[34][.-]/`),覆盖 Gemini 4 系列运行时。
22
+ - **[调度模式] 与 Agent Teams 改为刻意互斥:检测到就停,不再「换一套词汇接着干」(现场问题:开了智能体团队后这套调度就不好使)**
23
+ - **现象**:组合了 `@deepseek-ai/dsh-experimental-agent-team-profile` 的部署里,调度模式「派得出去、回访不了」——`list_agents` 看不到 `subagent` 的孩子,`send_message` 只认成员名,`interrupt_agent` 同理。复审、返工、追问三条通道同时失灵。
24
+ - **根因(两层)**:① **时机**——`TeamRoster.tryMembership` 对任何「无 `parentSession`、且不是 subagent descriptor」的 Agent 直接判为 `lead`,不需要先有 teammate,于是 team 工具从会话第一轮就装在 Lead 上,顶替掉内置的 `send_message`/`list_agents`/`interrupt_agent`——**还没派发就已经失去协调工具**。② **组合非法**——team 的 scoped 注册与内置同名工具按「近的层遮蔽远的层」解析,而 `dispatch` 正是那组旧定义的持有者(0.1.7+ 由本插件在运行时注册里挂载四行,preset 每一代独立 `createScope`,与宿主组合里被 patch 置 `disabled` 的那四行不是同一批实例)。上游文档对此写得很直接:`tool-agent-team`「当同名的旧全局 subagent 工具必须继续可用时,请不要选择……想同时使用两者的组合必须禁用旧定义」。
25
+ - **原设计为什么不够**:R0.5 原本做的是「侦测协作模式 → 按模式换协调词汇」(原 R-T)。它在有 teammate 时让模型改用成员词汇继续编排,但遮蔽由 scope 链决定、persona 改不回注册表,于是「适配」只能改行为、改不了「哪些工具被顶替」这个事实。更糟的是它把失败**藏**起来了:roster 里查不到孩子 ≠ 孩子没了,模型会误判成子代理丢失并重复派发。第三,teammate 结构上拿不到 per-task 路由(`SpawnTeammateRequest` 无 model 字段,构造 `startContinuable` 时整段省略 `agentOptions`),组队等于自愿放弃 R2。
26
+ - **改法**:persona 的 R0.5 由「协作模式侦测」改写为**兼容性闸门**(每个新会话判一次,早于 R0 分诊):两个 team 工具都不存在 → 写一行「编排可用:subagent」后照常编排;任一存在 → 本会话**不可编排**,按顺序只做三件:一句话说明不兼容 → 一次 `ask_user_question` 给出三条出路(关掉 bundle 重启并新建会话 / 换 preset / 本次直接做)→ 用户答复前不分诊、不规划、不派发、不动文件。**原 R-T 整段删除**,teammate 词汇(`team_task_*`、`target: <成员名>`、`wait_agent()`)在两份 persona 里不再出现;R8 的 teammate 专属条款与反模式 11/12 一并重写为「停在闸门处把选择交给用户」。
27
+ - **边界不变的部分**:模型路由守卫不动。`spawn_teammate` 仍是 `subagentModelInheritTools` 的 inherit 成员(成员一律继承 Lead 路由,守卫校验它实际继承到的那条);README 新增一条建议——用调度模式时可把它从该列表去掉,误用即硬拒。插件默认值不改,因为那是全局设置、会波及不用调度模式的会话。
28
+ - **解除互斥的上游条件(尚未落地)**:① `agent-team/src/roster.ts` 构造 `startContinuable` 的 request 处补上 `agentOptions`,给 `SpawnTeammateRequest` 与工具 schema 加路由字段、创建前接 `assertAllowedModelSelection`;② 把 team 工具的安装条件从「是 team 成员」收紧为「**有 teammate**」——后者能直接消掉「Lead 第一轮就被顶替」。只做 ① 不够。
29
+ - **验证**:`npm run typecheck` 0 错误;`test/agent-preset.test.ts` 29 例全绿(新增「检测到不兼容就停、不适配」的用例,同时断言两份副本里 R-T / `team_task_*` / `wait_agent()` / 「说明你是子代理或 teammate」等降级措辞**一个都不剩**);全量 `npm test` **223 passed | 1 skipped(224 文件)、3706 passed | 7 skipped | 1 failed**——唯一失败是 `test/claude-oauth.test.ts` 的「占用端口时报告真实绑定的那个端口」,单跑该文件 43/43 通过。本轮三次全量里出现过两个**不同**的环境敏感用例偶发(本次是端口占用,上一轮是 `antigravity-token-store` 的真实 DPAPI 写入),二者都只依赖真实 OS 资源、与本次 diff 无交集;此前一次全量基线为 3708 passed | 0 failed,差的 2 例来自被合并掉的 teammate 词汇用例。
30
+ - **[调度模式] 新增规则段 R-W「回合边界」,一次修掉三处现场问题:占位长命令等待、目标续跑打断等待、需要拍板时用文字停下**
31
+ - **问题 1(等待 = 自己造一个)**:派出子代理后,模型会去跑一条长时间命令挂着等(`sleep`、轮询、`watch`)。子代理完成的通知本来就是自带的,这条命令换回来的信息量是零,却实打实烧掉上下文与预算,还把用户晾在一段沉默里。
32
+ - **问题 2(目标把等待从中间劈开)**:部分模型在任务开头主动创建目标。目标一旦激活,DSH 会自动续跑把主代理叫醒,而子代理何时返回不由它控制——于是主代理在半路被续跑打断,重新分诊、重新检查「还差什么」,一次干净的等待被拆成两段,附带每次续跑都要重载整段历史。
33
+ - **问题 3(该问的不问,该停的用文字停)**:收到子代理全部内容后需要用户决策时,模型用一段文字结尾就停下,等用户自己把那段话翻译成一次输入。提问本是代理的工具,不该转嫁给用户。
34
+ - **修法**:新增编号规则段 `R-W · 回合边界(等待 / 目标 / 提问)`,三件事放在一起是因为它们都落在回合边界上。① 等待:默认结束本轮回复、一个工具都不调,由完成通知唤醒;禁止 `sleep`/轮询/`watch` 等占位长命令;确实被阻塞时才用 `job_output({ wait: true })` 有界地等一次(teammate 模式对应 `wait_agent()`),并在停下前说清「派出去了谁、在等什么、拿到证据要做什么」。② 目标:除非用户明确要求,不调用 `create_goal` / `/goal`,任务清单一律落 `todo_write`(R7 同步改了措辞)。③ 提问:一切「我停在这里是因为缺一个决定」的停点都用 `ask_user_question` 递出去,含选项、推荐答案与自定义输入口子;例外只有 plan mode 的计划审批(走 `exit_plan_mode`)与任务完成后的收尾。
35
+ - **交叉引用**:反模式列表新增第 13–15 条,逐条对应上面三件事;`R-G` 的 G3 补一句「同一条要求覆盖访谈之外的每一个停点」;【角色识别】把 `R-W` 列入面向调度者、对子代理/teammate 不生效的规则清单。
36
+ - **两份副本**:persona 在 `src/host/agent-preset.ts`(0.1.7+ 运行时注册的声明)与 `presets/dispatch/agent.cordis.yml`(0.1.6 及以前的文件同步)里各存一份,`test/agent-preset.test.ts` 逐字节校验二者一致,因此本次两处同步修改;测试新增 1 例(30 例),文档同步更新 `presets/dispatch/README.md` 与根 `README.md`。
37
+ - **验证**:`npm run typecheck` 0 错误;`npm test` **223 passed | 1 skipped(224 文件)、3708 passed | 7 skipped | 0 failed**;`test/agent-preset.test.ts` 由 29 例增至 30 例(新增 1 例断言 R-W 的三条规则与反模式 13–15)。首次全量运行时 `test/antigravity-token-store.test.ts` 的真实 DPAPI 用例在并行下失败 1 次,单跑该文件(8/8)与第二次全量均全绿,属既有的偶发;本次 diff 只涉及 preset 文本、文档与该一个测试文件,与凭据存储无交集。
38
+ - **[Antigravity] 模型目录与路由对齐线上 `fetchAvailableModels`(2026-10-12 快照)**
39
+ - **目录**:删除已下线的 Claude Opus 4.6 / Sonnet 4.6(目录里 Claude 只剩 5.5);Gemini 3.7 Flash 改用目录中真实存在的 `-low/-medium/-high`,不再走未列出的 `gemini-3.7-flash-tiered`;修正 Gemini 3.5 Flash 错位一档(官方 “(Low)” 是 `extra-low`,选 low 原先拿到的是 Medium);新增 Gemini 3.5 Flash Lite、Gemini 3.1 Flash Lite;目录过滤掉 `tab_*` 编辑器补全模型。
40
+ - **生图模型下架**:`gemini-3.1-flash-image` 的产出是图片,而 Harness 只接受纯文本的助手输出(dsh-llm `ImageBlock` 注释),聊天线路只能丢掉图片;应改为图片生成工具承载。
41
+ - **不再静默跨模型降级**:每次请求只发用户所选模型对应的一个运行时 ID。原先 404/429 会悄悄换到 `off` 档或别的模型(3.8 → 3.7 → 3.6、3.1 Pro High → Low),用户拿到的并不是自己选的模型。
42
+ - **429 按配额族冷却**:Gemini 与 “Claude and GPT” 是分开计量的配额,一族耗尽不再让该账号另一族一起停用 15 分钟;冷却时长优先读 Google 错误体里的 `quotaResetTimeStamp` / `quotaResetDelay` / `RetryInfo.retryDelay`,最后才用 `Retry-After`。
43
+ - **Gemini 2.5 思考预算按模型收敛**:Flash/Lite 上限 24576(原先 high 发 32768),Pro 下限 128 且不能关闭。
44
+ - **异常结束原因不再当作正常结束**:`SAFETY`、`RECITATION`、`PROHIBITED_CONTENT`、`MALFORMED_FUNCTION_CALL` 等,以及 `promptFeedback.blockReason`(提示被拦截),都改为 error finish 并附上上游 `finishMessage`;原先会以空回复结束本轮。
45
+ - **[Antigravity] 新增生图工具 `antigravity_image_generate`(同 Codex 生图工具的形态)**
46
+ - 走已登录的 Antigravity 账号池调用 `gemini-3.1-flash-image`,参数 `prompt`(必填)与可选 `aspectRatio`;返回图片存为附件、渲染为图片块,嵌套调用时以 notice 注入下一轮请求。客户端复用 Codex 的生图卡片。
47
+ - 计入 Gemini 配额族:429 只冷却该账号的 Gemini 配额并换下一个账号;Antigravity 线路关闭时工具拒绝执行。
48
+ - 返回图片在入库前校验媒体类型白名单、base64、大小上限与文件头魔数,`thought: true` 的草稿图被跳过;无图时把 `finishReason` 与模型文字一并报出。
49
+ - **[Antigravity] Claude 工具调用使用 `VALIDATED` 模式**:带工具且未显式指定 `toolChoice`(或为 `auto`)的 Claude 请求发送 `functionCallingConfig.mode: VALIDATED`,显式 none/any 不变;Gemini 不受影响。若服务端以 400 拒绝该模式,同一模型去掉 `toolConfig` 重试一次,并在本进程内不再发送(协议回退,不换模型)。
50
+ - **[Antigravity] 上下文/输出上限改为优先读 `fetchAvailableModels`**:目录条目解析 `maxTokens`(或 `inputTokenLimit`)与 `maxOutputTokens`(或 `outputTokenLimit`),兼容 int64 字符串;一个可选模型对应多个运行时 ID 时取最小值,目录缺失时回落内置表;用户覆盖值仍然优先,设置页「默认上下文」随之一致。
51
+ - **诚实声明**:生图请求的 `requestType: 'image_gen'`、Claude 对 `VALIDATED` 的接受情况、目录上限字段名,均来自社区客户端与公开文档,**没有**用真实账号抓包或实测;三处都留了回退(生图失败如实报错、VALIDATED 被拒自动回退、字段缺失回落内置表)。
52
+
5
53
  ## 0.23.0 - 2026-10-13
6
54
  - **[Ollama] 思考档位从「猜白名单」改为「读模型自己声明的事实」,并接通设置页的默认档位(用户报障:ollama 线路缺少模型思考档位选择器)**
7
55
  - **问题(三层各缺一环,不是 UI 漏做)**:本插件其余每条线路都在 `adapter.resolveModel()` 里返回 `reasoning: { efforts, defaultEffort }`,Harness 的模型选择器只在拿到它时才渲染档位下拉——Ollama 是唯一不返回的线路,所以下拉根本不出现。而 Harness 侧的行为不是「静默忽略」而是硬拒绝:`resolveCallWithInfo` 在 `reasoning === undefined` 且调用方传了 `reasoningEffort` 时抛 `UNSUPPORTED_REASONING_EFFORT`。同时设置页的 `defaultReasoningEffort` 是一个**写进去就没人读的死字段**——`token-store.ts` 读写完备,但 `/settings` 路由只处理 `enabled`,卡片没有下拉,`OllamaWebStatus` 里也没有这个字段。
package/README.md CHANGED
@@ -452,7 +452,7 @@ DSH 模型选择器应显示 **“Codex(ChatGPT 订阅)”**。GPT-6 系列
452
452
 
453
453
  > 路径解析不写死相对路径:`src/host/preset-sync.ts` 从模块位置向上查找最近的 `package.json` 作为包根,因此 `src/` 布局、打包后的 `lib/` 布局,以及通过 pnpm symlink / Windows junction 安装都能正确解析。注意 `fs.cpSync({ recursive: true })` 在 Node 22 + Windows 上遇到含非 ASCII 的源路径会直接崩进程(nodejs/node#54476),所以复制是逐条目实现的。
454
454
 
455
- ### 协作模式自适应(teammate / subagent)
455
+ ### 与 Agent Teams 不兼容(刻意互斥)
456
456
 
457
457
  DSH 的 Agent Teams(bundle `@deepseek-ai/dsh-experimental-agent-team-profile`)会在**每个会话自己的作用域**里注册一套与内置**同名**的协调工具。工具注册表按作用域链解析、**近的层遮蔽远的层**,所以一旦该 bundle 被组合进来,会话里的 `send_message`、`list_agents`、`interrupt_agent` 就都换成了 teammate 版:
458
458
 
@@ -460,18 +460,42 @@ DSH 的 Agent Teams(bundle `@deepseek-ai/dsh-experimental-agent-team-profile`
460
460
  - `send_message` 的 `target` 只接受成员名,把子代理的 session id 传进去会抛 `active teammate "…" not found`(实测);
461
461
  - 于是「派得出去、回访不了」——`subagent` 的孩子只能等完成通知,无法追问。
462
462
 
463
- `dispatch` preset 现在**每个任务开始时先侦测一次协作模式**(persona 的 R0.5),再按模式选择协调词汇(R-T):
463
+ **坏消息在时机上**:Agent Teams 的 `agent-team/src/roster.ts` 里 `tryMembership` 对任何「无 `parentSession`、且不是 subagent descriptor」的 Agent 直接判为 `lead`,**不需要先有 teammate**。于是 team 工具从会话第一轮起就装在 Lead 上,调度模式还没派发第一个子代理,复审与返工所依赖的三个工具已经没了。
464
464
 
465
- | 侦测为 | 判据 | 协调词汇 | 派发 |
466
- |---|---|---|---|
467
- | teammate | `spawn_teammate` / `wait_agent` 存在 | `list_agents()`、`send_message({ target: <成员名> })`、`wait_agent()`、`team_task_*` | `spawn_teammate`(无路由参数,继承主代理路由)或 `subagent`(按 R2 显式路由) |
468
- | subagent | 二者都不存在 | `list_agents()`、`send_message({ agent_id })`、`interrupt_agent` | `subagent` / `subagent_fork` |
465
+ 上游对此的立场是明确的:`tool-agent-team` 的文档写着「当同名的旧全局 subagent 工具必须继续可用时,请不要选择……**想同时使用两者的组合必须禁用旧定义**」。而 `dispatch` preset 恰恰是那组旧定义的持有者——0.1.7+ 的运行时注册里由本插件自己挂了 `tool-subagent-control` / `tool-subagent-list-agents` / `tool-subagent` / `tool-subagent-fork` 四行(preset 每一代都是独立 `createScope`,与宿主组合里被 profile patch 置 `disabled` 的那四行不是同一批实例)。所以这不是「可以调好的配置」,而是一个上游明确不承诺的组合。
469
466
 
470
- 两种模式下 R0 分诊、R1 职责边界、R3 自治、R6 验收都照常执行;**模型路由守卫(`subagentModelAuthorization`)不变**——它默认把 `spawn_teammate` 与 `subagent_fork` 同为 **inherit 模式**(见下),校验的是成员实际继承到的路由,而不是要求它给出并不存在的路由参数。
467
+ `dispatch` 的处理是**停,不降级**(persona 的 R0.5 兼容性闸门,每个新会话判一次,早于 R0 分诊):
471
468
 
472
- > **不要**把 `spawn_teammate` 加进 `subagentModelTools`。该列表是 **explicit** 模式:要求每次调用成对给出 `provider` + `model`,而 `spawn_teammate` 的参数里根本没有这两个字段(DSH 设计如此:成员一律继承 Lead 的路由),结果是每一次 teammate 创建都会被硬拒,且模型无法通过补参数自救。它的正确归属是 `subagentModelInheritTools`(默认已包含)。
469
+ | 判据 | 行为 |
470
+ |---|---|
471
+ | `spawn_teammate` 与 `wait_agent` 都不存在 | 编排可用,写一行「编排可用:subagent」后按 R0 → R-G → R5 → R6 正常走 |
472
+ | 任一存在 | 本会话**不可编排**:一句话说明 → 一次 `ask_user_question` 给出三条出路 → 用户答复前**不分诊、不规划、不派发、不动文件** |
473
473
 
474
- ### 已知上游限制:teammate 不能选模型
474
+ 三条出路是:① 关掉 Agent Teams bundle、重启 Host 后**新建会话**;② 换用别的 preset,本会话不编排;③ 本次直接做,不进编排流程。**都要新建会话**——工具面在会话启动时就定死了,改完配置在旧会话里也不会回来。
475
+
476
+ 刻意**没有**保留「切到 teammate 词汇继续编排」这条分支(原 R-T)。三条理由:
477
+
478
+ 1. 遮蔽由 scope 链决定,persona 改不回工具注册表——「适配」只能改行为,改不了「哪些工具被顶替」这个事实;
479
+ 2. 那条分支把「回访不了」从**明摆着的失败**变成**看不见的失败**:roster 里查不到孩子 ≠ 孩子没了,模型会误判并重复派发,白烧一轮预算;
480
+ 3. teammate 结构上拿不到 per-task 路由(见下节),而 R2 显式路由正是这套设计里最值钱的部分——组队等于自愿放弃它。
481
+
482
+ > 想把误用也用机制挡掉:把 `spawn_teammate` 从 inherit 清单去掉即可,配置 `subagentModelInheritTools: ['subagent_fork']`,该工具在守卫里就变成**硬拒**(拒绝理由指向 `subagent`),而不是让它悄悄按 Lead 的路由跑完整轮。插件默认值不动——那是全局设置,改它会波及不使用调度模式的会话。
483
+
484
+ ### 回合边界纪律(R-W)
485
+
486
+ 调度模式的 persona 里有一条专门管「回合边界」的规则 `R-W`,约束三件最容易把编排拖慢、拖贵的事:
487
+
488
+ | 场景 | 规则 | 为什么 |
489
+ |---|---|---|
490
+ | 等子代理返回 | 默认**结束本轮回复**、一个工具都不调,由完成通知唤醒主代理;禁止 `sleep`、轮询循环和任何只为占位存在的长命令。确实被阻塞时才用 `job_output({ wait: true })` 有界地等一次 | 子代理完成通知是自带的;占位长命令不产出信息,只烧上下文和预算,还把用户晾在一段沉默里 |
491
+ | 任务开始建目标 | 除非用户明确要求,否则**不调用 `create_goal` / `/goal`**,任务清单一律走 `todo_write` | 机制性的:目标一旦激活,DSH 会自动续跑唤醒主代理,而子代理何时返回不由它控制——等待被从中间劈开,模型重新分诊、重新检查「还差什么」,每次续跑还要重载整段历史 |
492
+ | 需要用户拍板 | 一切「我停在这里是因为缺一个决定」的停点(收到子代理结果要选下一步、验收不过要定返工范围、前提被推翻要改计划)都用 `ask_user_question` 递出去,并给出选项与推荐答案 | 提问是代理的工具,不是用户的义务:否则用户得先替模型把那段话翻译成一次输入。例外是 plan mode 的计划审批(走 `exit_plan_mode`)与任务完成后的收尾 |
493
+
494
+ 三条各自对应 persona 反模式列表里的第 13–15 条。此外,本插件在运行时通过 `system-prompt/assemble` 原位重写 `list_subagent_models` 与 `subagent` 工具描述中的 `"Catalog membership is advisory"` / `"Child LLM selection is optional..."` 误导措辞,并通过 `tools/post-execute` 在每次 `list_subagent_models` 返回末尾直接附上本会话全部已授权的 `{ provider, model }` 拆解对;`R2` 与 `plan-mode` 提示词也同步写明 `list_subagent_models` 是本会话允许清单的**唯一真源**,直接采信其输出即可,无需仅为了确认哪些子代理模型可用去翻找本地配置文件或工作区代码(对应 Anti-Pattern 第 16 条)。
495
+
496
+ ### 为什么不降级:teammate 不能选模型
497
+
498
+ 这是上面第三条理由的技术底座,也是上游修好之后才谈得上重新评估兼容性的前提。
475
499
 
476
500
  `spawn_teammate` 目前**无法**指定 `provider`/`model`,这不是插件的问题,而是 Agent Teams 有意不做 per-teammate 路由。三层都已核对:
477
501
 
@@ -485,7 +509,7 @@ DSH 的 Agent Teams(bundle `@deepseek-ai/dsh-experimental-agent-team-profile`
485
509
 
486
510
  **插件侧无法绕过**,四条路都已验证死:pre-execute 明确排除输入改写(参数已被记录与呈现,`PreToolDecision` 只有 allow/deny/cancel/ask);`agentTeams` 服务在内部丢弃后包装不到;注册自定义 subagent provider 也拿不到路由(`agentOptions` 在 continuation manager 就已解析完,provider 只返回 `seed`);唯一能改子会话路由的 `selectForNextRequest` 只作用于「下一个请求」,而 teammate 创建后立刻开跑,抢不进去。
487
511
 
488
- **上游正路**:在 `packages/experimental/agent-team/src/roster.ts` 构造 `startContinuable` 的 `request` 处补上 `agentOptions`,并给 `SpawnTeammateRequest` 加字段、给工具 schema 加参数、创建前接 `assertAllowedModelSelection`。**该改动落地后**,`spawn_teammate` 就应从 `subagentModelInheritTools` 移到 `subagentModelTools`(explicit)——否则它会变成「能选模型却没人管」。
512
+ **上游正路**:在 `packages/experimental/agent-team/src/roster.ts` 构造 `startContinuable` 的 `request` 处补上 `agentOptions`,并给 `SpawnTeammateRequest` 加字段、给工具 schema 加参数、创建前接 `assertAllowedModelSelection`。**该改动落地后**,`spawn_teammate` 就应从 `subagentModelInheritTools` 移到 `subagentModelTools`(explicit)——否则它会变成「能选模型却没人管」。只补这一条还不足以解除互斥:team 工具的遮蔽发生在会话第一轮(见上节),要真正共存还需要把安装条件从「是 team 成员」收紧成「**有 teammate**」,让没有队友的会话保留内置的 subagent 协调工具。
489
513
 
490
514
  > 实践提醒:inherit 模式校验的是**当前会话路由**。若当前会话跑在允许清单之外的路由上(例如默认模型与勾选清单不是同一条),teammate 与 `subagent_fork` 都会被拒绝——拒绝文案会指出恢复路径(改用显式路由的 `subagent`,或先把会话切到清单内的模型)。`subagent` 的显式路由不受影响。
491
515
 
package/lib/client.js CHANGED
@@ -58,6 +58,14 @@ window.__ModuleLoader__.load({
58
58
  const ROUTE_PREFIX = "/api/dsh-chatgpt-subscription";
59
59
  const CODEX_CHATGPT_PROVIDER_ID = "codex-chatgpt";
60
60
  const CODEX_IMAGE_TOOL_NAME = "codex_image_generate";
61
+ /**
62
+ * The Antigravity image tool and the runtime it calls.
63
+ *
64
+ * `gemini-3.1-flash-image` is listed by `fetchAvailableModels`, but its product
65
+ * is an image and the harness accepts text-only assistant output, so it is
66
+ * served as a tool (like Codex images) rather than as a chat model.
67
+ */
68
+ const ANTIGRAVITY_IMAGE_TOOL_NAME = "antigravity_image_generate";
61
69
  //#endregion
62
70
  //#region src/client/common/use-store.ts
63
71
  /**
@@ -14891,6 +14899,12 @@ window.__ModuleLoader__.load({
14891
14899
  locale: NS,
14892
14900
  inject: (sessionId) => ({ loadImage: imageLoader(ctx, sessionId) })
14893
14901
  }, CodexImageToolView));
14902
+ ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
14903
+ name: "tool.call.toolview",
14904
+ key: ANTIGRAVITY_IMAGE_TOOL_NAME,
14905
+ locale: NS,
14906
+ inject: (sessionId) => ({ loadImage: imageLoader(ctx, sessionId) })
14907
+ }, CodexImageToolView));
14894
14908
  }
14895
14909
  /**
14896
14910
  * The seats every composer badge is handed.