feat(qwen): Alibaba Qwen built-in over Model Studio's OpenAI-compatible mode
Gadfly review (reusable) / review (pull_request) Successful in 5m14s
Adversarial Review (Gadfly) / review (pull_request) Successful in 5m14s
CI / Tidy (pull_request) Successful in 9m24s
CI / Build & Test (pull_request) Successful in 9m53s

Adds the `qwen` built-in provider and the `qwen://` DSN scheme, keyed by
QWEN_API_KEY and defaulting to Model Studio's international host. Like kimi
(ADR-0026) it is `provider/openai` pointed elsewhere — no new client.

Model Studio serves the same models over two protocols, so the real decision
was which wire format to speak. ADR-0027 records why it is the OpenAI one:
down the anthropic client `ReasoningEffort` is ignored by design, structured
output rides the first-party `output_config.format` mechanism the shim does
not implement, and cached-token accounting reads Anthropic-only usage fields.
Each of those fails silently rather than loudly, which is what makes the
choice worth writing down. The shim stays reachable ad hoc via an
`anthropic://` DSN.

The kimi and qwen DSN factories were byte-identical, so they now share one
`openaiCompatScheme` helper: the "credential comes from the DSN token, and
the missing-key hint names LLM_<NAME>" rules hold by construction instead of
by copy.

Tests are hermetic and break-checked (all six fail on a deliberate mutation),
including the reverse credential leak — a visible QWEN_API_KEY must not
authenticate the openai built-in — and reasoning_effort asserted on the wire
body, which is the ADR's load-bearing claim.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
2026-08-12 16:07:41 -04:00
co-authored by Claude Opus 5
parent 1bbbdaa1e5
commit 02cd561eaf
8 changed files with 461 additions and 20 deletions
+29
View File
@@ -285,3 +285,32 @@ tests flush out.
(footnote ³), `.env.example`, ADR-0026 (+ index; also backfilled the missing
0024/0025 index rows).
- Consumer: mort names Kimi as a failover tier.
## 2026-08-12 — Qwen (Alibaba) built-in provider (ADR-0027)
- New built-in `qwen` provider + `qwen://` DSN scheme over Alibaba Model
Studio's OpenAI-compatible mode, reusing `provider/openai` (no new client,
mirrors kimi/llama-swap). Default base URL
`https://dashscope-intl.aliyuncs.com/compatible-mode/v1`; China/regional
hosts via `LLM_QCN=qwen://[email protected]/compatible-mode/v1`.
- Credential is `QWEN_API_KEY` (via the registry's injected envLookup).
`WithAPIKey` passed unconditionally so an unset key cannot fall through to
`OPENAI_API_KEY`; `WithAPIKeyName` names `QWEN_API_KEY` in the 401 hint.
- **Chose OpenAI-compat over Model Studio's Anthropic-compatible
`/apps/anthropic` shim** (ADR-0027): on the anthropic client
`ReasoningEffort` is ignored by design, `Request.Schema` rides
`output_config.format` (which the shim does not implement), and cached-token
accounting reads Anthropic-only usage fields. The shim is still reachable
ad hoc via an `anthropic://` DSN.
- kimi and qwen DSN factories were byte-identical, so they now share one
`openaiCompatScheme` helper — the credential + key-hint rules come by
construction, not by copy.
- Hermetic tests: built-in base URL + bearer, missing key names QWEN_API_KEY
with no OPENAI fallthrough and no network hit, the reverse leak (a visible
QWEN_API_KEY must not authenticate the openai built-in), `qwen://` round-trip
against the China host, its keyless hint naming LLM_QCN, and
`reasoning_effort` asserted on the wire body (the ADR's load-bearing claim).
captureRT now records the request body; all six break-checked.
- Docs in sync: README built-in table + Qwen paragraph + DSN scheme list +
support matrix (footnote ⁴), `.env.example`, ADR-0027 (+ index).
- Consumer: mort wants Qwen as a failover tier.