mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-09 09:34:50 +08:00
feat(api): add qwen/ prefix routing for Alibaba DashScope provider
Users in Discord #clawcode-get-help (web3g) asked for Qwen 3.6 Plus via native Alibaba DashScope API instead of OpenRouter, which has stricter rate limits. This commit adds first-class routing for qwen/ and bare qwen- prefixed model names. Changes: - DEFAULT_DASHSCOPE_BASE_URL constant: /compatible-mode/v1 endpoint - OpenAiCompatConfig::dashscope() factory mirroring openai()/xai() - DASHSCOPE_ENV_VARS + credential_env_vars() wiring - metadata_for_model: qwen/ and qwen- prefix routes to DashScope with auth_env=DASHSCOPE_API_KEY, reuses ProviderKind::OpenAi because DashScope speaks the OpenAI REST shape - is_reasoning_model: detect qwen-qwq, qwq-*, and *-thinking variants so tuning params (temperature, top_p, etc.) get stripped before payload assembly (same pattern as o1/o3/grok-3-mini) Tests added: - providers::tests::qwen_prefix_routes_to_dashscope_not_anthropic - openai_compat::tests::qwen_reasoning_variants_are_detected 89 api lib tests passing, 0 failing. cargo fmt --check: clean. Closes the user-reported gap: 'use Qwen 3.6 Plus via Alibaba API directly, not OpenRouter' without needing OPENAI_BASE_URL override or unsetting ANTHROPIC_API_KEY.
This commit is contained in:
@@ -181,6 +181,19 @@ pub fn metadata_for_model(model: &str) -> Option<ProviderMetadata> {
|
||||
default_base_url: openai_compat::DEFAULT_OPENAI_BASE_URL,
|
||||
});
|
||||
}
|
||||
// Alibaba DashScope compatible-mode endpoint. Routes qwen/* and bare
|
||||
// qwen-* model names (qwen-max, qwen-plus, qwen-turbo, qwen-qwq, etc.)
|
||||
// to the OpenAI-compat client pointed at DashScope's /compatible-mode/v1.
|
||||
// Uses the OpenAi provider kind because DashScope speaks the OpenAI REST
|
||||
// shape — only the base URL and auth env var differ.
|
||||
if canonical.starts_with("qwen/") || canonical.starts_with("qwen-") {
|
||||
return Some(ProviderMetadata {
|
||||
provider: ProviderKind::OpenAi,
|
||||
auth_env: "DASHSCOPE_API_KEY",
|
||||
base_url_env: "DASHSCOPE_BASE_URL",
|
||||
default_base_url: openai_compat::DEFAULT_DASHSCOPE_BASE_URL,
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@@ -386,6 +399,36 @@ mod tests {
|
||||
assert_eq!(kind2, ProviderKind::OpenAi);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn qwen_prefix_routes_to_dashscope_not_anthropic() {
|
||||
// User request from Discord #clawcode-get-help: web3g wants to use
|
||||
// Qwen 3.6 Plus via native Alibaba DashScope API (not OpenRouter,
|
||||
// which has lower rate limits). metadata_for_model must route
|
||||
// qwen/* and bare qwen-* to the OpenAi provider kind pointed at
|
||||
// the DashScope compatible-mode endpoint, regardless of whether
|
||||
// ANTHROPIC_API_KEY is present in the environment.
|
||||
let meta = super::metadata_for_model("qwen/qwen-max")
|
||||
.expect("qwen/ prefix must resolve to DashScope metadata");
|
||||
assert_eq!(meta.provider, ProviderKind::OpenAi);
|
||||
assert_eq!(meta.auth_env, "DASHSCOPE_API_KEY");
|
||||
assert_eq!(meta.base_url_env, "DASHSCOPE_BASE_URL");
|
||||
assert!(meta.default_base_url.contains("dashscope.aliyuncs.com"));
|
||||
|
||||
// Bare qwen- prefix also routes
|
||||
let meta2 = super::metadata_for_model("qwen-plus")
|
||||
.expect("qwen- prefix must resolve to DashScope metadata");
|
||||
assert_eq!(meta2.provider, ProviderKind::OpenAi);
|
||||
assert_eq!(meta2.auth_env, "DASHSCOPE_API_KEY");
|
||||
|
||||
// detect_provider_kind must agree even if ANTHROPIC_API_KEY is set
|
||||
let kind = detect_provider_kind("qwen/qwen3-coder");
|
||||
assert_eq!(
|
||||
kind,
|
||||
ProviderKind::OpenAi,
|
||||
"qwen/ prefix must win over auth-sniffer order"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_existing_max_token_heuristic() {
|
||||
assert_eq!(max_tokens_for_model("opus"), 32_000);
|
||||
|
||||
Reference in New Issue
Block a user