feat(core): add native DashScope integration - #8714
Conversation
|
Qwen precheck requires maintainer approval before automated triage/review. Head SHA: Reason:
A maintainer with write access can inspect the PR and manually request a run with |
There was a problem hiding this comment.
Pull request overview
Adds a new first-class dashscope auth/protocol path that speaks Alibaba ModelStudio’s native DashScope generation API directly (via fetch), and wires it through telemetry, config/env resolution, CLI UX (auth/model/effort/settings/control-surface), SDK schemas/validation, and user docs.
Changes:
- Introduces a native DashScope content generator (request/response conversion, SSE parsing + accumulation, thinking controls, prompt-cache markers, usage normalization, typed errors, transport + stream guards) with extensive unit tests and fixtures.
- Extends core/CLI/SDK types, schemas, env mappings, provider presets, and telemetry plumbing to recognize
dashscope. - Updates CLI dialogs/commands/control APIs to show only model-supported reasoning effort tiers for native
qwen3.8-max, clamping persisted legacy tiers where needed.
Reviewed changes
Copilot reviewed 82 out of 82 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/vscode-ide-companion/schemas/settings.schema.json | Documents dashscope as an automatically routed built-in protocol id. |
| packages/sdk-typescript/test/unit/queryOptionsSchema.test.ts | Adds TS SDK test accepting authType: 'dashscope'. |
| packages/sdk-typescript/src/types/queryOptionsSchema.ts | Extends TS SDK query options schema to include dashscope. |
| packages/sdk-typescript/src/types/protocol.ts | Extends TS SDK AuthType union to include dashscope. |
| packages/sdk-python/tests/unit/test_validation.py | Adds Python SDK test accepting auth_type='dashscope'. |
| packages/sdk-python/src/qwen_code_sdk/validation.py | Extends Python SDK validation/auth-type error message for dashscope. |
| packages/sdk-python/src/qwen_code_sdk/types.py | Extends Python SDK AuthType literal set to include dashscope. |
| packages/core/src/telemetry/gen-ai-request.ts | Adds DashScope request attribute extraction + request reporting entrypoint. |
| packages/core/src/telemetry/gen-ai-request.test.ts | Tests DashScope request attribute extraction. |
| packages/core/src/telemetry/gen-ai-provider.ts | Extends telemetry auth type/provider naming to include dashscope. |
| packages/core/src/telemetry/gen-ai-provider.test.ts | Tests provider resolution for dashscope auth type. |
| packages/core/src/telemetry/gen-ai-exchange.test.ts | Adds exchange observer test covering DashScope request + converted response. |
| packages/core/src/telemetry/gen-ai-content.ts | Adds DashScope message/tool extraction into canonical telemetry content. |
| packages/core/src/services/chatCompressionService.ts | Enables compression cache sharing for DashScope. |
| packages/core/src/services/chatCompressionService.test.ts | Expands cache-sharing test matrix to include DashScope. |
| packages/core/src/providers/provider-config.ts | Adds DashScope default base URL. |
| packages/core/src/providers/presets/alibaba-native.ts | New preset for “ModelStudio Native” (DashScope) provider configuration. |
| packages/core/src/providers/index.ts | Exports the new Alibaba native provider preset. |
| packages/core/src/providers/all-providers.ts | Registers the new provider preset in exports and ALL_PROVIDERS. |
| packages/core/src/providers/tests/presets/alibaba-native.test.ts | Tests Alibaba native provider preset, including ownership disambiguation. |
| packages/core/src/models/modelConfigErrors.ts | Adds default env var names for DashScope API key and model. |
| packages/core/src/models/constants.ts | Adds DashScope env mappings and default model (qwen3.8-max). |
| packages/core/src/core/reasoning-effort.ts | Adds model/provider-aware supported reasoning tiers helper. |
| packages/core/src/core/reasoning-effort.test.ts | Tests supported-tier logic for native DashScope qwen3.8-max. |
| packages/core/src/core/openaiContentGenerator/pipeline.ts | Exports shared stream-guard resolution helper for reuse. |
| packages/core/src/core/loggingContentGenerator/loggingContentGenerator.test.ts | Updates logging test to use typed DashScope API error mapping. |
| packages/core/src/core/dashscopeContentGenerator/usage.ts | New: normalizes DashScope usage into Gemini usageMetadata + provenance. |
| packages/core/src/core/dashscopeContentGenerator/usage.test.ts | New: tests usage normalization/provenance and cached-token semantics. |
| packages/core/src/core/dashscopeContentGenerator/types.ts | New: native DashScope request/response/tool/message type definitions. |
| packages/core/src/core/dashscopeContentGenerator/transport.ts | New: fetch-based transport with proxy/timeout integration + stream guards. |
| packages/core/src/core/dashscopeContentGenerator/transport.test.ts | New: transport unit tests (headers, errors, proxy redaction, guards). |
| packages/core/src/core/dashscopeContentGenerator/thinking.ts | New: resolves native thinking parameters + tool-choice interactions. |
| packages/core/src/core/dashscopeContentGenerator/thinking.test.ts | New: thinking parameter resolution tests. |
| packages/core/src/core/dashscopeContentGenerator/test-utils.ts | New: fake transport + helper config/fixture decoding for tests. |
| packages/core/src/core/dashscopeContentGenerator/stream-accumulator.ts | New: SSE frame → incremental Gemini chunk state machine. |
| packages/core/src/core/dashscopeContentGenerator/stream-accumulator.test.ts | New: accumulator fixture replay tests (tools/text/errors/truncation). |
| packages/core/src/core/dashscopeContentGenerator/sse.ts | New: DashScope SSE wire-format parser. |
| packages/core/src/core/dashscopeContentGenerator/sse.test.ts | New: SSE parser unit tests. |
| packages/core/src/core/dashscopeContentGenerator/response-converter.ts | New: non-streaming payload → Gemini response conversion. |
| packages/core/src/core/dashscopeContentGenerator/response-converter.test.ts | New: response conversion unit tests (finish reasons, ordering, tool calls). |
| packages/core/src/core/dashscopeContentGenerator/index.ts | New: DashScope generator factory/export surface. |
| packages/core/src/core/dashscopeContentGenerator/errors.ts | New: typed DashScope API/truncation error mapping. |
| packages/core/src/core/dashscopeContentGenerator/errors.test.ts | New: error parsing/mapping/classification tests. |
| packages/core/src/core/dashscopeContentGenerator/endpoints.ts | New: resolves baseUrl into native generation endpoint path. |
| packages/core/src/core/dashscopeContentGenerator/endpoints.test.ts | New: endpoint resolution unit tests. |
| packages/core/src/core/dashscopeContentGenerator/dashscope-native.live.test.ts | New: opt-in live smoke tests for the native provider. |
| packages/core/src/core/dashscopeContentGenerator/dashscope-content-generator.ts | New: native DashScope ContentGenerator implementation. |
| packages/core/src/core/dashscopeContentGenerator/dashscope-content-generator.test.ts | New: generator-level tests using scripted transport/fixtures. |
| packages/core/src/core/dashscopeContentGenerator/cache.ts | New: plans/attaches explicit cache-control markers to messages. |
| packages/core/src/core/dashscopeContentGenerator/cache.test.ts | New: cache marker planning tests (non-mutating, streaming rules). |
| packages/core/src/core/dashscopeContentGenerator/fixtures/stream-tools.sse.txt | New: recorded SSE fixture for parallel tool calls. |
| packages/core/src/core/dashscopeContentGenerator/fixtures/stream-text.sse.txt | New: recorded SSE fixture for text streaming. |
| packages/core/src/core/dashscopeContentGenerator/fixtures/error-frame.sse.txt | New: recorded SSE fixture for error framing. |
| packages/core/src/core/contentGenerator.ts | Adds USE_DASHSCOPE auth type and dispatch to DashScope generator. |
| packages/core/src/core/contentGenerator.test.ts | Tests DashScope dispatch and keeps compat-mode URLs on OpenAI path. |
| packages/core/src/core/baseLlmClient.ts | Includes DashScope in auth-type ordering list. |
| packages/cli/src/utils/modelConfigUtils.ts | Adds env-based auth-type resolution and model env vars for DashScope. |
| packages/cli/src/utils/apiPreconnect.ts | Updates DashScope default preconnect host to intl endpoint. |
| packages/cli/src/utils/apiPreconnect.test.ts | Tests DashScope default preconnect host. |
| packages/cli/src/ui/models/availableModels.ts | Adds DashScope model discovery via DASHSCOPE_MODEL. |
| packages/cli/src/ui/components/SettingsDialog.tsx | Filters reasoning-effort options to supported tiers for active provider/model. |
| packages/cli/src/ui/components/ModelDialog.tsx | Adds DashScope to auth type ordering in model dialog. |
| packages/cli/src/ui/components/EffortDialog.tsx | Allows effort picker to accept a model-aware supported-tier list. |
| packages/cli/src/ui/components/EffortDialog.test.tsx | Tests effort dialog tier filtering. |
| packages/cli/src/ui/components/DialogManager.tsx | Passes model-aware supported tiers (and clamps persisted tier) to effort dialog. |
| packages/cli/src/ui/commands/effort-command.ts | Makes /effort model-aware; rejects unsupported tiers and reports available list. |
| packages/cli/src/ui/commands/effort-command.test.ts | Tests model-aware effort tier behavior and generic argument hint. |
| packages/cli/src/ui/auth/useAuth.ts | Allows DashScope as a valid auth type in auth flow. |
| packages/cli/src/nonInteractive/control/controllers/systemController.ts | Validates effort values against model-aware supported tiers. |
| packages/cli/src/nonInteractive/control/controllers/systemController.test.ts | Tests rejecting/accepting tiers for native DashScope qwen3.8-max. |
| packages/cli/src/config/settingsSchema.ts | Updates schema description to include DashScope in providerProtocol note. |
| packages/cli/src/config/settingsSchema.test.ts | Adds assertion around reasoningEffort being dialog-visible. |
| packages/cli/src/config/config.ts | Extends CLI args auth-type choices to include DashScope. |
| packages/cli/src/config/auth.ts | Adds DashScope auth validation and error messaging. |
| packages/cli/src/config/auth.test.ts | Tests DashScope auth validation behavior. |
| packages/cli/src/acp-integration/authMethods.ts | Adds DashScope native auth method for ACP integration. |
| packages/cli/src/acp-integration/authMethods.test.ts | Tests ACP auth method list includes DashScope. |
| packages/cli/src/acp-integration/acpAgent.ts | Adds DashScope preflight env key list for ACP. |
| docs/users/configuration/model-providers.md | Documents native DashScope provider, regions, examples, and caveats. |
| docs/users/configuration/auth.md | Adds DashScope native protocol and setup instructions. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
A pasted compat URL can already be rooted at /api/v1 (e.g. https://host/api/v1/compatible-mode/v1). The compat-mode branch stripped /compatible-mode/v1 and then unconditionally appended /api/v1, producing /api/v1/api/v1/services/... Drop the suffix and fall through to the existing /api/v1 detection instead.
|
@qwen-code /review |
| _Qwen Code review request accepted. Review is queued in [workflow run](https://github.com/QwenLM/qwen-code/actions/runs/31243244591)._ |
qqqys
left a comment
There was a problem hiding this comment.
本 PR 引入的 CI 失败:Test (ubuntu-latest, Node 22.x) 红,阻塞合并。
位置
packages/cli/src/ui/commands/effort-command.ts:26—— 本 PR 把/effort的 description 源串从Set how hard reasoning-capable models think ({{tiers}}); mapped and clamped per provider.改写为Set how hard reasoning-capable models think; available tiers depend on the active provider/model.packages/cli/src/i18n/locales/zh.js:2223、packages/cli/src/i18n/locales/zh-TW.js:2017—— 两个 catalog 的 key 仍是旧串;新串在 8 个 locale 文件里一个都没有(grep -rn "available tiers depend on the active provider/model" packages/cli/src/i18n/locales/无命中),本 PR 也没改到任何locales/文件。
触发条件
packages/cli/src/i18n/mustTranslateKeys.test.ts:190 的 does not fall back to English for any built-in command description in strict-parity locale:切到 zh-CN / zh-TW 后逐条比对 built-in command description 是否与英文相同。新串在 zh / zh-TW catalog 中查不到,t() 回退成英文原串,fallbackDescriptions 因此包含 effort。
影响
Test (ubuntu-latest, Node 22.x) 失败,阻塞合并:
FAIL src/i18n/mustTranslateKeys.test.ts > must-translate locale coverage > does not fall back to English ... { code: 'zh-TW', ... }
FAIL src/i18n/mustTranslateKeys.test.ts > must-translate locale coverage > does not fall back to English ... { code: 'zh', ... }
AssertionError: expected [ 'effort' ] to deeply equal []
Tests 2 failed | 18419 passed | 22 skipped (18443)
见 head c6bb3d3 的 run 31240953067,全仓库仅此一处失败。merge base b9be6c8 上该串仍是旧文案且 zh/zh-TW 均有译文(设置具备推理能力的模型思考的强度({{tiers}});按各提供方进行映射与钳制。),所以这个失败只来自本 PR。除 CI 外,中文用户在 /help 里看到的 /effort 说明也会退化成英文。
修复方向
在 packages/cli/src/i18n/locales/ 下为新串补 key。strict-parity 的 zh.js / zh-TW.js 是必须的(否则该用例仍红);ca/de/fr/ja/pt/ru 与 en.js 建议一并补齐,保持与旧 key 一致的覆盖面。也可以选择保留原 key 文案不改,仅在别处说明 tier 是模型相关的。
|
Qwen Code review timed out. Qwen review timed out after 21600 seconds (of the 360-minute budget). This run already used the maximum 360 minute timeout. See workflow logs. |
The DashScope integration rewrote the /effort description source string but left the locale catalogs keyed on the old one, so zh-CN/zh-TW fell back to English and the strict-parity description test failed. Replace the now-unused key with the new string in all nine locales.
原问题已在 67e6430 修复:e4a2deed5 为 /effort 的新描述串补齐了全部 9 个 catalog 的 key —— en.js:2491、zh.js:2224、zh-TW.js:2018、ja.js:1469、ru.js:1933、de.js:1931、fr.js:1977、pt.js:1927、ca.js:1972,8 个非英文 catalog 均为实际译文而非英文回退,effort-command.ts:26 的源串与 key 逐字一致,mustTranslateKeys.test.ts 的 strict-parity 断言不再命中。解除本条 CHANGES_REQUESTED,不代表对本 PR 的整体批准。
|
@yiliang114 Would you mind merging this in? |
|
@qwen-code /resolve |
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
Qwen Code resolved the merge conflicts and pushed the branch update. Merge resolution for #8714 (native DashScope integration)Root cause. This PR made Semantic, not textual. Resolution keeps the PR's tier gating and adopts main's helpers for applying/reporting: const supportedTiers = getSupportedReasoningEffortTiers(
config.getAuthType(), config.getModel(),
);
if (!supportedTiers.includes(tier)) { /* reject with model-aware tier list */ }
applyReasoningEffort(config, tier); // main: set + read-back check
content: formatEffortChangeMessage(config, tier) // main: thinking-disabled + override msgsThe PR's inline "thinking is currently disabled" block was dropped because main's Load-bearing.
Not verified. No build/tests run here (by instruction). The auto-merged 中文说明根因:本 PR 让 属语义冲突:解决方式为保留 PR 的模型感知档位校验,采用 main 的应用与消息上报助手。PR 内联的"thinking 已禁用"提示由 main 的 关键点:① 档位校验必须先于 未验证:按指令未运行构建/测试;自动合并的两个测试文件合并了双方断言,已逐行核对但未执行。合并前已存在(未处理):"tier not supported" 错误文案缺 i18n 词条,双方均未添加。 |
|
@wenshao mind merging this? |
What this PR does
Adds
dashscopeas a first-class auth type that speaks Alibaba ModelStudio's native generation API directly, instead of routing through the OpenAI-compatible endpoint that the existingopenaiprotocol uses. It talks the native wire format over a built-infetch-based transport with no intermediary SDK, and currently targetsqwen3.8-max.The implementation is complete rather than a thin adapter: request and response conversion, event-stream parsing with incremental accumulation, native parallel tool calls,
reasoning_contentsurfaced as first-class thinking output, prompt-cache marker placement with cache-read and cache-creation tokens reported separately in usage, and a typed error surface mapped onto the shared error model.On the CLI side, selecting Alibaba ModelStudio in the auth flow now opens a sub-menu offering the native API alongside the existing standard key path — both read the same API key, only the protocol differs. The model picker, settings dialog, effort dialog, non-interactive control surface, and preconnect path all learn the new protocol. Reasoning effort maps onto the native effort parameter, which accepts a different tier set than other providers: unsupported tiers are hidden in the effort controls, and any left over in a persisted config are clamped at request-conversion time so an existing settings file cannot produce an invalid request. Telemetry attributes the new protocol, and both SDKs plus the VS Code settings schema accept the new auth type.
Docs cover regional endpoints, a settings example, a headless recipe, thinking control including native-only pass-through knobs, and the caveats below.
Why it's needed
Alibaba's own API is the reference surface for Qwen models, and everything else is a translation of it. Going native means talking to ModelStudio on its own terms rather than through a lowest-common-denominator shim shaped by another vendor's API.
The immediate wins are the things that survive translation badly. Thinking comes back in its own field, so it can be rendered as thinking directly instead of being recovered by scraping tags out of assistant text — a heuristic that is fragile by construction and worst exactly when the model writes about tags. Parallel tool calls, cache markers, and usage breakdowns come through as the API actually models them rather than as whatever the compatible layer can express.
The longer-term reason matters more: native capabilities land here as soon as ModelStudio ships them, instead of waiting on the compatible endpoint to grow a mapping for them. For a first-party Qwen tool, being able to use the first-party API in full seems worth having as an option.
Nothing changes for anyone on the compatible endpoint — this is a new choice next to it, not a replacement.
Reviewer Test Plan
How to verify
Unit tests ship with the change and cover each layer of the new provider — caching, endpoint resolution, error mapping, request and response conversion, event-stream parsing, accumulation, thinking, transport, and usage — plus updated tests for the auth, effort, dialog, control-surface, telemetry, and SDK schema paths it touches. Run the core and CLI suites; everything is offline and hermetic, driven by recorded stream fixtures.
A live smoke test against the real service is included but skipped unless both a run-live-tests flag and a DashScope API key are set, so it stays out of normal runs. Reviewers with a ModelStudio key can opt in; the file header documents the invocation.
End to end: set a DashScope API key and start the CLI with the new auth type against
qwen3.8-max. Confirm a plain prompt streams normally, that thinking renders as thinking rather than literal tag text in the answer, and that a tool-using prompt drives tools including more than one call in a turn.For the interactive surface, open the auth dialog and confirm Alibaba ModelStudio now presents a sub-menu with the native option, that it works with the same key as the standard option, and that the effort dialog offers only the tiers the native API accepts. Point a settings file containing an unsupported tier at the new provider and confirm it still runs, having been clamped, rather than erroring.
Evidence (Before & After)
N/A — the user-visible surface is an added menu entry and an adjusted tier list, not a redesign of existing screens.
Tested on
Environment (optional)
Linux, unit tests plus type checking locally. macOS and Windows are left to CI.
Risk & Scope
qwen3.8-maxis wired up. macOS and Windows are unverified locally.One caveat worth flagging because it looks like a bug and is not: forcing a tool choice disables thinking for that request. That is a constraint of the native API itself, not something introduced here.
Linked Issues
中文说明
本 PR 的内容
新增
dashscope作为一等的认证类型,直接对接阿里云百炼(ModelStudio)的原生生成 API,而不是走现有openai协议所使用的 OpenAI 兼容端点。它通过内置的fetch传输层直接使用原生通信格式,不经过任何中间 SDK,目前面向qwen3.8-max。这是完整实现,而非简单适配层:包括请求与响应转换、事件流解析与增量聚合、原生并行工具调用、将
reasoning_content作为一等思考内容呈现、提示词缓存标记放置并在用量中分别报告缓存读取与缓存写入 token,以及映射到共享错误模型的类型化错误处理。CLI 侧,在认证流程中选择「阿里云百炼」后会打开一个子菜单,在现有标准密钥方式之外提供原生 API 选项——两者读取同一个 API 密钥,区别仅在于协议。模型选择器、设置对话框、思考强度对话框、非交互控制面与预连接路径都已支持新协议。思考强度映射到原生 effort 参数,而原生 API 接受的档位与其他 provider 不同:不受支持的档位在强度控件中不再显示,配置文件中残留的此类取值会在请求转换阶段被收敛,因此既有设置文件不会产生非法请求。遥测会标注新协议,两个 SDK 以及 VS Code 设置 schema 也都接受新的认证类型。
文档涵盖各区域端点、设置示例、无界面(headless)用法、思考控制(含仅原生支持的透传参数)以及下文的注意事项。
为什么需要
阿里自家的 API 才是 Qwen 模型的参考接口,其他一切都是对它的转译。走原生意味着按百炼自己的方式与之对话,而不是通过一层由其他厂商 API 形态决定的最小公约数垫片。
眼前的收益集中在那些「经不起转译」的能力上。思考内容通过独立字段返回,因此可以直接按思考渲染,而不必从助手正文里抓取标签来还原——这种启发式做法天生脆弱,而且恰恰在模型讨论标签时最容易出错。并行工具调用、缓存标记与用量拆分也都按 API 本身的建模方式传递,而不是迁就兼容层所能表达的形式。
更长远的理由更重要:原生能力在百炼发布时即可在此使用,而不必等待兼容端点为其补上映射。对于一个第一方的 Qwen 工具来说,能够完整使用第一方 API,作为一个选项是值得拥有的。
对使用兼容端点的用户没有任何改变——这是它旁边的新选择,而不是替代。
评审测试计划
如何验证
本次改动自带单元测试,覆盖新 provider 的每一层——缓存、端点解析、错误映射、请求与响应转换、事件流解析、聚合、思考、传输与用量——并更新了所涉及的认证、思考强度、对话框、控制面、遥测与 SDK schema 相关测试。运行 core 与 CLI 测试套件即可;全部离线且可重复,由录制的流式固定数据驱动。
另有一个针对真实服务的在线冒烟测试,只有同时设置在线测试开关与 DashScope API 密钥时才会运行,因此不影响常规执行。拥有百炼密钥的评审者可主动开启;文件头部记录了调用方式。
端到端:设置 DashScope API 密钥,以新认证类型针对
qwen3.8-max启动 CLI。确认普通提示能正常流式返回、思考以思考形式呈现而非在回答中出现字面标签文本,以及使用工具的提示能正常驱动工具(含单轮多次调用)。交互界面方面:打开认证对话框,确认「阿里云百炼」现在展示包含原生选项的子菜单、使用与标准选项相同的密钥即可工作,并且思考强度对话框只提供原生 API 接受的档位。将包含不受支持档位的设置文件指向新 provider,确认它经收敛后仍能运行而不是报错。
证据(前后对比)
N/A——用户可见的变化是新增一个菜单项和调整档位列表,而不是对既有界面的重新设计。
测试环境
运行环境(可选)
Linux,本地运行单元测试与类型检查。macOS 与 Windows 交由 CI。
风险与范围
qwen3.8-max。macOS 与 Windows 未在本地验证。有一点值得提请注意,因为它看起来像 bug 但其实不是:强制指定工具选择会使该次请求的思考被禁用。这是原生 API 自身的限制,并非本次改动引入。