fix(agent): pass through explicit AtlasCloud model ids

Refs #2569

Harvests the safe part of PR #2569 by allowing AtlasCloud provider-hinted namespaced model IDs to route exactly as requested, without freezing a volatile provider model catalog in the static registry.

Co-authored-by: lucaszhu-hue <lucas.zhu@atlascloud.ai>
This commit is contained in:
Hunter B
2026-06-01 20:06:26 -07:00
parent 88f34fc9dd
commit eedeb5290b
5 changed files with 78 additions and 13 deletions
+9 -6
View File
@@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
adds/removes only the exact current-user PATH entry.
- Added deterministic session timestamps in session listings, receipt-export
boundary docs, and current-model turn metadata for routed/auto sessions.
- Added exact AtlasCloud provider-hinted model ID pass-through for explicit
`vendor/model-id` selections, harvested from #2569 without freezing a
brittle provider catalog.
### Changed
@@ -42,12 +45,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Community
Thanks to **@ZhulongNT** (#2045), **@cyq1017** (#2521, #2536, #2537, #2559,
#2562, #2563, #2564), and **@HUQIANTAO** (#2527) for the work harvested into
this release pass. Thanks also to issue reporters and verification helpers
including **@New2Niu** (#2561), **@buko** (#2533, #2369), **@wywsoor**
(#2494), **@ctxyao** (#2556), **@Dr3259** (#2380), and **@caiyilian**
(#2567) for reports and acceptance details that shaped these fixes, plus the
WeChat/Chinese UX reports relayed during the final triage pass.
#2562, #2563, #2564), **@HUQIANTAO** (#2527), and **@lucaszhu-hue** (#2569)
for the work harvested into this release pass. Thanks also to issue reporters
and verification helpers including **@New2Niu** (#2561), **@buko** (#2533,
#2369), **@wywsoor** (#2494), **@ctxyao** (#2556), **@Dr3259** (#2380), and
**@caiyilian** (#2567) for reports and acceptance details that shaped these
fixes, plus the WeChat/Chinese UX reports relayed during the final triage pass.
## [0.8.49] - 2026-06-01
+1
View File
@@ -308,6 +308,7 @@ codewhale --provider nvidia-nim
# AtlasCloud
codewhale auth set --provider atlascloud --api-key "YOUR_ATLASCLOUD_API_KEY"
codewhale --provider atlascloud
codewhale --provider atlascloud --model vendor/model-id
# Wanjie Ark
codewhale auth set --provider wanjie-ark --api-key "YOUR_WANJIE_API_KEY"
+58
View File
@@ -503,6 +503,16 @@ impl ModelRegistry {
fallback_chain,
};
}
if provider_hint == Some(ProviderKind::Atlascloud)
&& let Some(model) = atlascloud_passthrough_model(name)
{
return ModelResolution {
requested: Some(name.to_string()),
resolved: model,
used_fallback: false,
fallback_chain,
};
}
if let Some(idx) = self.alias_map.get(&normalize(name)) {
return ModelResolution {
requested: Some(name.to_string()),
@@ -562,6 +572,21 @@ fn preserve_requested_model_id_case(mut model: ModelInfo, requested: &str) -> Mo
model
}
fn atlascloud_passthrough_model(requested: &str) -> Option<ModelInfo> {
let requested = requested.trim();
if requested.is_empty() || !requested.contains('/') {
return None;
}
Some(ModelInfo {
id: requested.to_string(),
provider: ProviderKind::Atlascloud,
aliases: Vec::new(),
supports_tools: true,
supports_reasoning: true,
})
}
#[cfg(test)]
mod tests {
use super::*;
@@ -630,6 +655,39 @@ mod tests {
assert_eq!(resolved.resolved.id, "deepseek-ai/deepseek-v4-pro");
}
#[test]
fn atlascloud_provider_hint_passes_through_explicit_model_id() {
let registry = ModelRegistry::default();
let resolved =
registry.resolve(Some("openai/gpt-5.2-chat"), Some(ProviderKind::Atlascloud));
assert_eq!(resolved.resolved.provider, ProviderKind::Atlascloud);
assert_eq!(resolved.resolved.id, "openai/gpt-5.2-chat");
assert!(resolved.resolved.supports_tools);
assert!(resolved.resolved.supports_reasoning);
assert!(!resolved.used_fallback);
}
#[test]
fn atlascloud_provider_hint_preserves_explicit_model_id_case() {
let registry = ModelRegistry::default();
let resolved = registry.resolve(Some("Qwen/Qwen3-Coder"), Some(ProviderKind::Atlascloud));
assert_eq!(resolved.resolved.provider, ProviderKind::Atlascloud);
assert_eq!(resolved.resolved.id, "Qwen/Qwen3-Coder");
assert!(!resolved.used_fallback);
}
#[test]
fn atlascloud_plain_unknown_model_still_uses_provider_default() {
let registry = ModelRegistry::default();
let resolved = registry.resolve(Some("not-in-atlas"), Some(ProviderKind::Atlascloud));
assert_eq!(resolved.resolved.provider, ProviderKind::Atlascloud);
assert_eq!(resolved.resolved.id, "deepseek-ai/deepseek-v4-flash");
assert!(resolved.used_fallback);
}
#[test]
fn openrouter_default_uses_namespaced_model_id() {
let registry = ModelRegistry::default();
+9 -6
View File
@@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
adds/removes only the exact current-user PATH entry.
- Added deterministic session timestamps in session listings, receipt-export
boundary docs, and current-model turn metadata for routed/auto sessions.
- Added exact AtlasCloud provider-hinted model ID pass-through for explicit
`vendor/model-id` selections, harvested from #2569 without freezing a
brittle provider catalog.
### Changed
@@ -42,12 +45,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Community
Thanks to **@ZhulongNT** (#2045), **@cyq1017** (#2521, #2536, #2537, #2559,
#2562, #2563, #2564), and **@HUQIANTAO** (#2527) for the work harvested into
this release pass. Thanks also to issue reporters and verification helpers
including **@New2Niu** (#2561), **@buko** (#2533, #2369), **@wywsoor**
(#2494), **@ctxyao** (#2556), **@Dr3259** (#2380), and **@caiyilian**
(#2567) for reports and acceptance details that shaped these fixes, plus the
WeChat/Chinese UX reports relayed during the final triage pass.
#2562, #2563, #2564), **@HUQIANTAO** (#2527), and **@lucaszhu-hue** (#2569)
for the work harvested into this release pass. Thanks also to issue reporters
and verification helpers including **@New2Niu** (#2561), **@buko** (#2533,
#2369), **@wywsoor** (#2494), **@ctxyao** (#2556), **@Dr3259** (#2380), and
**@caiyilian** (#2567) for reports and acceptance details that shaped these
fixes, plus the WeChat/Chinese UX reports relayed during the final triage pass.
## [0.8.49] - 2026-06-01
+1 -1
View File
@@ -114,7 +114,7 @@ endpoint.
| `deepseek` | `[providers.deepseek]` | `DEEPSEEK_API_KEY` | `CODEWHALE_BASE_URL` / `DEEPSEEK_BASE_URL`; default `https://api.deepseek.com/beta` | `deepseek-v4-pro`, `deepseek-v4-flash`; compatibility aliases `deepseek-chat`, `deepseek-reasoner` | First-class default. Beta URL enables strict tool mode, chat prefix completion, and FIM completion. Set `https://api.deepseek.com` or `/v1` explicitly to opt out of beta-only features. |
| `nvidia-nim` | `[providers.nvidia_nim]` | `NVIDIA_API_KEY`, `NVIDIA_NIM_API_KEY`, fallback `DEEPSEEK_API_KEY` | `NVIDIA_NIM_BASE_URL`, `NIM_BASE_URL`, `NVIDIA_BASE_URL`; default `https://integrate.api.nvidia.com/v1` | `deepseek-ai/deepseek-v4-pro`, `deepseek-ai/deepseek-v4-flash` | Hosted DeepSeek V4 through NVIDIA NIM. `NVIDIA_NIM_MODEL` is accepted by the TUI config path. |
| `openai` | `[providers.openai]` | `OPENAI_API_KEY` | `OPENAI_BASE_URL`; default `https://api.openai.com/v1` | Registry entries: `deepseek-v4-pro`, `deepseek-v4-flash`; default config model `deepseek-v4-pro` | Generic OpenAI-compatible route for gateways and custom endpoints. Use this for explicit third-party OpenAI-compatible routes instead of inventing a new provider ID. `OPENAI_MODEL` is accepted. |
| `atlascloud` | `[providers.atlascloud]` | `ATLASCLOUD_API_KEY` | `ATLASCLOUD_BASE_URL`; default `https://api.atlascloud.ai/v1` | `deepseek-ai/deepseek-v4-flash`, `deepseek-ai/deepseek-v4-pro` | OpenAI-compatible hosted route. `ATLASCLOUD_MODEL` is accepted by the TUI config path, and the static `ModelRegistry` includes AtlasCloud fallback rows for CLI model resolution. |
| `atlascloud` | `[providers.atlascloud]` | `ATLASCLOUD_API_KEY` | `ATLASCLOUD_BASE_URL`; default `https://api.atlascloud.ai/v1` | Default `deepseek-ai/deepseek-v4-flash`; explicit `vendor/model-id` values pass through when AtlasCloud is selected | OpenAI-compatible hosted route. `ATLASCLOUD_MODEL` is accepted by the TUI config path, the static `ModelRegistry` keeps DeepSeek V4 fallback rows, and provider-hinted CLI model IDs are sent to AtlasCloud exactly as requested. |
| `wanjie-ark` | `[providers.wanjie_ark]` | `WANJIE_ARK_API_KEY`, `WANJIE_API_KEY`, `WANJIE_MAAS_API_KEY` | `WANJIE_ARK_BASE_URL`, `WANJIE_BASE_URL`, `WANJIE_MAAS_BASE_URL`; default `https://maas-openapi.wanjiedata.com/api/v1` | `deepseek-reasoner` | OpenAI-compatible hosted route. `WANJIE_ARK_MODEL`, `WANJIE_MODEL`, and `WANJIE_MAAS_MODEL` are accepted. |
| `volcengine` | `[providers.volcengine]` | `VOLCENGINE_API_KEY`, `VOLCENGINE_ARK_API_KEY`, `ARK_API_KEY` | `VOLCENGINE_BASE_URL`, `VOLCENGINE_ARK_BASE_URL`, `ARK_BASE_URL`; default `https://ark.cn-beijing.volces.com/api/coding/v3` | `DeepSeek-V4-Pro`, `DeepSeek-V4-Flash` | Volcengine/Volcano Engine Ark OpenAI-compatible coding endpoint. `VOLCENGINE_MODEL` and `VOLCENGINE_ARK_MODEL` are accepted. |
| `openrouter` | `[providers.openrouter]` | `OPENROUTER_API_KEY` | `OPENROUTER_BASE_URL`; default `https://openrouter.ai/api/v1` | `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`; recent large IDs include `arcee-ai/trinity-large-thinking`, `minimax/minimax-m3`, `xiaomi/mimo-v2.5-pro`, `qwen/qwen3.6-35b-a3b`, `google/gemma-4-31b-it`, `z-ai/glm-5.1`, `moonshotai/kimi-k2.6` | Additive open-model routing layer. It does not replace DeepSeek; it lets users route supported model IDs through OpenRouter when they choose it. |