fix(core): support qwen3.8 side queries on DashScope - #7303
Conversation
|
Thanks for the PR! Template looks good ✓ Problem: observed bug with clear reproduction. #7270 reports HTTP 400 ( Direction: aligned — Token Plan users selecting qwen3.8-max-preview currently have broken side-queries (web fetch, permission classification, subagent generation, etc.). This is core functionality breakage for a supported model. Size: 151 production logic lines (core: 137, cli: 14), 344 test lines. Well under thresholds. Cross-package (core + cli) but the cli change is small and self-contained. Approach: the scope feels right. A model-level Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题:已观测到的 bug,有明确复现。#7270 报告了当 方向:对齐——Token Plan 用户选择 qwen3.8-max-preview 时,side-query(web fetch、权限分类、子代理生成等)全部失败。这是已支持模型的核心功能中断。 规模:151 行生产逻辑(core: 137, cli: 14),344 行测试。远低于阈值。跨包(core + cli)但 CLI 改动小且自包含。 方案:范围合理。模型级 进入代码审查 🔍 — Qwen Code · qwen3.7-max Reviewed at |
Hardcoding a single model id in the pipeline snapshots a server-side constraint into client logic and breaks again on the next thinking-mandatory model. Move the knowledge to preset data: a thinkingMandatory generation-config flag marks models that reject enable_thinking=false with a 400, so the pipeline never emits the disable for them and drops forced tool selection while thinking is on. Hybrid models that merely declare extra_body.enable_thinking keep the side-query force-disable, preserving the QwenLM#4501 token savings.
Code ReviewIndependent proposal: given the problem (side-queries force Comparison with the diff: the PR matches this approach exactly. No simpler path missed. Key observations:
TestingUnit tests (all pass on the PR branch at
Real-scenario smoke test (tmux, PR code via CLI starts and responds correctly with the PR code. Full before/after reproduction of the DashScope 400 error requires a Token Plan API key with 中文说明代码审查独立方案: 给定问题(side-query 强制 与 diff 对比: PR 完全匹配此方案。没有遗漏更简路径。 关键观察:
测试单元测试(PR 分支全部通过):
真实场景冒烟测试(tmux,PR 代码):CLI 正常启动并响应。完整的 DashScope 400 错误 before/after 复现需要配置了 — Qwen Code · qwen3.7-max Reviewed at |
|
Confidence: 4/5 — clean, well-tested fix that matches the problem exactly; the two new commits (promptHookRunner model resolution + config inheritance prevention) close the remaining gaps from the initial pass. Only reservation remains the inability to verify against the live DashScope endpoint from CI. This is a well-scoped fix for a real user-facing breakage. The The new promptHookRunner change is the right call — without it, a hook with Every change in the diff is necessary for the stated goal. The test coverage is thorough: 7 new parameterized pipeline cases, 2 leak-prevention tests, 3 promptHookRunner tests (including timeout-during-resolution), 2 provider-update tests, and 1 cache-clearing test. All 576 tests across the changed files pass. If I had to maintain this in six months, I'd thank the author — the flag is self-documenting, the comments explain the why (DashScope rejects the disable with a 400), and the test names read like specifications. Approving. ✅ 中文说明置信度:4/5 — 干净、测试充分的修复,完全匹配问题;两个新提交(promptHookRunner 模型解析 + 配置继承防护)弥补了初次审查的剩余缺口。唯一保留仍是无法从 CI 验证 DashScope 实际端点行为。 这是一个范围良好的修复,解决了真实的用户功能中断。 新的 promptHookRunner 改动是正确的——没有它,带 diff 中每个改动都是目标所必需的。测试覆盖充分:576 个测试全部通过。 批准。✅ — Qwen Code · qwen3.7-max Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
|
@qwen-code /triage |
ReviewOverviewThis PR introduces a
Tests are meaningful: parameterized wire-shape assertions (including the Findings1. The clearing special-case ( 2.
3. Previously 4. Style: the string special-case for capability fields
5. Docs The pipeline comment says the flag can be "set by the preset, or by users via model generation config", but 6. Scope confirmation The VerdictSolid, well-tested change with careful attention to propagation paths most PRs would miss. Finding 1 is worth fixing in this PR since it undermines the isolation guarantee the PR itself adds a test for; 2 is a cheap hardening; the rest are minor/optional. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
|
Addressed findings 1 and 2 in
Focused tests pass ( For the remaining notes: keeping |
Code Review — #7303
|
|
@qwen-code /triage |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
0bdf03e
|
Fixed the Ubuntu CI failure by updating the prompt hook integration mock to match the resolved-model path. Verified with |
Code Review —
|
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅
— qwen3.7-max via Qwen Code /review
|
Released in v0.20.1. |
What this PR does
This change treats
qwen3.8-max-previewas a mandatory-thinking model on DashScope-compatible routes. Side queries no longer override it withenable_thinking: false. Structured requests also let the model select the response tool automatically because its thinking mode rejectstool_choice: required. Other Qwen models and non-DashScope routes retain their existing behavior. For mandatory-thinking models, the compatibility flag also takes precedence over a globalreasoning: falsesetting because the endpoint rejects the opt-out. Runtime model switches also clear this capability when a same-provider side/fast model does not declare it, while provider preset updates refresh the matching active generator and invalidate per-model generator caches so the fix takes effect without a restart. Prompt hooks with a model override now resolve that model's generator and generation settings instead of reusing the active generator; resolution and generation share the existing hook timeout and cancellation budget.Why it's needed
Token Plan users selecting
qwen3.8-max-previewas their fast or main model currently see side-query failures in features such as web fetching, permission classification, subagent generation, suggestions, summaries, compression, and related helpers. The model requires thinking, while Qwen Code's side-query pipeline normally disables thinking to reduce latency and token use. Structured side queries have a second incompatibility because thinking mode does not accept forced tool selection.Reviewer Test Plan
How to verify
Configure a DashScope-compatible provider with
qwen3.8-max-preview, then run both a text-only side query and a schema-based side query. The text request should preserve thinking and complete. The schema-based request should preserve thinking, omit forced tool selection, and return the requested structured result. Confirm that another Qwen model still disables thinking and that globalreasoning: falsestill sends the explicit opt-out for models that do not declare thinking as mandatory. For a mandatory-thinking model, confirm that the request keeps thinking enabled instead of sending a guaranteed-invalid opt-out. Update an existing Token Plan provider and confirm the fix takes effect in the current session without a restart. With qwen3.8 as the main model and another same-provider model as the side/fast target, confirm the target does not inherit mandatory thinking and still disables thinking when supported.Evidence (Before & After)
Before: a real Token Plan request with
enable_thinking: falsereturned HTTP 400 withThe value of the enable_thinking parameter is restricted to True.A structured request with thinking enabled plustool_choice: requiredalso returned HTTP 400 because forced tool selection is unsupported in thinking mode.After: the equivalent text request preserves thinking, and the structured request omits forced tool selection. A real protocol request completed with HTTP 200 and returned a valid
respond_in_schematool call.Tested on
Environment (optional)
Local TypeScript workspace (full monorepo build and typecheck) and the live Alibaba ModelStudio Token Plan compatible API.
Risk & Scope
qwen3.8-max-previewside queries must incur the thinking latency and token cost required by the model. Structured calls use automatic rather than forced tool selection, with existing schema validation and fail-closed behavior unchanged. Provider preset updates now refresh the matching active generator and invalidate per-model caches, so an active-provider refresh failure rolls back the update through the existing install transaction.Linked Issues
Closes #7270
Closes #7332
Supersedes #7333
Related to #7284
中文说明
本 PR 做了什么
这个改动把
qwen3.8-max-preview作为 DashScope 兼容路由上的强制思考模型处理。Side query 不再用enable_thinking: false覆盖它。结构化请求也改为让模型自动选择响应工具,因为该模型的思考模式会拒绝tool_choice: required。其他 Qwen 模型和非 DashScope 路由保持原有行为。对于强制思考模型,兼容性标记也会优先于全局reasoning: false,因为发送关闭参数会被端点拒绝。运行时切换到未声明该能力的同 provider side/fast 模型时也会清除该标记;provider preset 更新则会刷新精确匹配的当前 generator 并失效 per-model generator 缓存,使修复无需重启即可生效。带 model override 的 prompt hook 现在也会解析目标模型对应的 generator 与 generation settings,而不是复用当前 active generator;模型解析和生成共用既有的 hook timeout 与取消预算。为什么需要
当 Token Plan 用户把
qwen3.8-max-preview设为 fast model 或 main model 时,web fetch、权限分类、子代理生成、建议、摘要、压缩等依赖 side query 的功能会失败。该模型强制要求思考,而 Qwen Code 的 side query 流程通常会为了降低延迟和 token 消耗而关闭思考。结构化 side query 还有第二个兼容问题:思考模式不接受强制工具选择。Reviewer Test Plan
如何验证
在 DashScope 兼容 provider 上配置
qwen3.8-max-preview,分别运行纯文本 side query 和基于 schema 的 side query。纯文本请求应保持思考并成功完成;结构化请求应保持思考、移除强制工具选择,并返回要求的结构化结果。同时确认其他 Qwen 模型仍会关闭思考,且对于未声明强制思考的模型,全局reasoning: false仍会发送显式关闭参数;对于强制思考模型,请求应保持开启思考,避免发送必然无效的关闭参数。更新一个已安装的 Token Plan provider,确认修复在当前会话中无需重启即可生效。以 qwen3.8 作为主模型、另一个同 provider 模型作为 side/fast 目标时,确认目标模型不会继承强制思考标记,并在支持时仍会关闭思考。证据(修改前后)
修改前:真实 Token Plan 请求携带
enable_thinking: false时返回 HTTP 400,错误为The value of the enable_thinking parameter is restricted to True.;结构化请求在开启思考并携带tool_choice: required时也返回 HTTP 400,因为思考模式不支持强制工具选择。修改后:等价的纯文本请求会保持思考,结构化请求会省略强制工具选择。真实协议请求返回 HTTP 200,并得到有效的
respond_in_schema工具调用。测试平台
环境(可选)
本地 TypeScript 工作区(完整 monorepo 构建与类型检查)和真实的阿里云百炼 Token Plan OpenAI 兼容 API。
风险与范围
qwen3.8-max-previewside query 必须承担模型强制思考带来的延迟和 token 成本。结构化调用从强制工具选择降级为自动选择,现有 schema 校验和 fail-closed 行为保持不变。Provider preset 更新现在会刷新精确匹配的当前 generator 并失效 per-model 缓存,因此当前 provider 刷新失败时会通过现有安装事务回滚本次更新。关联 Issue
Closes #7270
Closes #7332
Supersedes #7333
Related to #7284