diff --git a/CHANGELOG.md b/CHANGELOG.md index 9623b3b3..6500136f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index 39713d19..f595f5b7 100644 --- a/README.md +++ b/README.md @@ -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" diff --git a/crates/agent/src/lib.rs b/crates/agent/src/lib.rs index 7c3bbdf7..9b56f591 100644 --- a/crates/agent/src/lib.rs +++ b/crates/agent/src/lib.rs @@ -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 { + 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(); diff --git a/crates/tui/CHANGELOG.md b/crates/tui/CHANGELOG.md index 9623b3b3..6500136f 100644 --- a/crates/tui/CHANGELOG.md +++ b/crates/tui/CHANGELOG.md @@ -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 diff --git a/docs/PROVIDERS.md b/docs/PROVIDERS.md index a4ddc01c..f2a126de 100644 --- a/docs/PROVIDERS.md +++ b/docs/PROVIDERS.md @@ -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. |