Skip to content

fix(subagents): prioritize configured models over AI selection - #973

Draft
inorilzy wants to merge 6 commits into
vastsa:mainfrom
inorilzy:fix/subagent-pinned-model-priority
Draft

inorilzy wants to merge 6 commits into
vastsa:mainfrom
inorilzy:fix/subagent-pinned-model-priority

Conversation

@inorilzy

Copy link
Copy Markdown
Contributor

背景与根因

Related: #286

用户期望:子智能体已经配置主模型和 fallback 时,主智能体不能通过 Task.model 自行改用“允许 AI 调用”的其他模型。

在当前 main 9926e3b73784a3206a9163f5f129c0c9e874afc1 核实,buildSubagentTool() 明确采用 Task.model > definition.model > session model。Task 参数说明也鼓励覆盖默认模型;显式回传父会话 provider/model 同样能绕过子智能体固定模型。现有 fallback 本身已按定义排序,但起点可能在进入 fallback 控制器之前就被覆盖。

这是对旧 D278 优先级的有意修订,不声称旧实现违反当时的规格。按请求先提交 Draft,新的 ADR 保持 Proposed,不合并。

修改

  • 新委托固定模型优先:定义存在 model 时始终解析该绑定。冲突的 Task.model 被忽略,不查询 AI 模型目录,不调用按需解析;父会话模型回显也不能绕过。
  • 可观察的选择结果:Task 启动结果仍记录实际 modelId/thinkingLevel;返回文本解释冲突的 model 参数已被忽略。重复定义自身模型键保持无提示的空操作。
  • 未固定模型维持原行为:仍允许已授权的 Task.model 选择、按需授权和精确父会话模型继承;不放宽 availableForSubagents 权限。
  • fallback 顺序和恢复机制不变:提供商失败后仍由现有机制依次尝试该定义的 fallbackModels。AI 指定的模型不能跳过主模型、提前选择某个备选、或成为耗尽后的额外候选。保留已完成工具历史、取消、用量和 thinking 重新夹取语义。
  • resume 不重置:恢复旧委托仍拒绝同时传入 model,保留链路上次实际使用的模型,包括成功 fallback。
  • 同步模型目录提示、Task 描述/参数说明、中英文运行时/模型规格、D278 和 E2E-166;新增 ADR subagent-pinned-model-priority 并说明兼容性。

生产代码只改 packages/agent-runtime/src/runtime.ts,没有修改 UI、数据库 schema、IPC 参数、模型设置或其他贡献者的分支。

实际验证

在隔离 GitHub Actions 候选工作树中,使用 Node 24、仓库 pnpm 与 frozen lockfile 安装干净 CI 依赖;模型交互全部指向本地确定性 HTTP/SSE fixture,未使用真实服务商凭据或付费 API。

候选验证 run(全部步骤通过)

测试的代码提交:ea6bc8c02e124c52b363af6cfc665cb525a398b1
上游基线:9926e3b73784a3206a9163f5f129c0c9e874afc1

  1. 先红后绿:新增/修改的 8 个针对性选择用例在旧生产代码上是 7 failed / 1 passed。失败包括已启用模型覆盖 pin、父模型回显、指定 fallback、按需/未知键,以及绕过缺失主绑定;通过的是未固定定义的正常选模。
  2. 相关单测 318/318 通过,4 个文件:pnpm --filter @pi-desktop/agent-runtime exec vitest run src/runtime.test.ts src/subagent.test.ts src/subagent-fallback.test.ts src/subagent-definitions.test.ts。包含上述新用例,以及原有 fallback、取消、恢复和授权回归。
  3. 实际请求边界通过:pnpm test:e2e:subagent-models。驱动构建后的真实 sidecar/NDJSON 和 provider 适配器,捕获本地 HTTP 请求,验证固定模型胜过 opted-in/父模型/按需/未知选择;覆盖首选直接成功、前 1–3 个模型失败后成功、整个链耗尽仍不选择 AI 模型池,并检查 Task 返回及结算的实际模型。
  4. pnpm --filter '@pi-desktop/agent-runtime...' build 通过(含 shared 与 agent-runtime 的 TypeScript 构建)。
  5. pnpm docs:check、pnpm lint、架构检查、git diff --check、pnpm check:pr-base 均通过。
  6. 本地额外执行文档测试 11/11;80 对中英文规格与 512 个文档页面检查通过。

候选验证使用的临时 workflow/补丁传输文件已在随后提交中删除;最终 PR 差异不包含这些文件,测试过的生产代码、测试和规格字节不变。最终仓库 tree SHA 246696ffcce68998240d8b6490978946d821f731 与本地独立编辑结果完全一致。提交 PR 前再次检查 main,behind=0。

兼容性及剩余验证

  • 过去刻意用 Task.model 覆盖固定模型的调用者,现在会使用固定模型。需要 AI 选模时应显式取消定义的 pin;需要固定工作流时修改定义自己的主模型/fallback。
  • 主模型绑定不存在仍沿用原有启动前报错,不静默借用父模型或其他模型池;本 PR 不新增配置迁移或失效主绑定的自动修复。
  • 未运行完整 Electron GUI/设置持久化旅程、全工作区测试/桌面完整打包及真实服务商兼容测试。验证重点是此次变更的运行时、恢复、fallback 和实际模型请求边界。
  • 上游 PR 集成 CI 会独立运行,不将候选测试等同于尚未结束的上游 CI。保持 Draft,等待优先级变更的产品/维护者审阅。

@vastsa

vastsa commented Oct 2, 2026

Copy link
Copy Markdown
Owner

我核对了当前 main 的实现和 D278 / E2E-166:现有约定明确是 Task.model 优先于定义 pin,再优先于 session model,代码遵循该约定。PR 也说明这是有意修订旧优先级,而非修复旧实现违反规格的问题;它会改变已支持的模型选择行为。

因此这不是当前 fix 类 PR 所需修复的回归,我不会按 bug fix 合入这项契约变更。若产品决定调整优先级,请先完成相应的契约/兼容性决策,再以行为变更提请评审。感谢你把兼容性影响、回归覆盖和待决策状态都写清楚。

This branch has not been deployed

No deployments
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