diff --git a/src/config/schema.rs b/src/config/schema.rs index ca6a51a..41e556d 100644 --- a/src/config/schema.rs +++ b/src/config/schema.rs @@ -1,3 +1,4 @@ +use crate::providers::{is_glm_alias, is_zai_alias}; use crate::security::AutonomyLevel; use anyhow::{Context, Result}; use directories::UserDirs; @@ -1976,18 +1977,7 @@ impl Config { } } // API Key: GLM_API_KEY overrides when provider is a GLM/Zhipu variant. - if matches!( - self.default_provider.as_deref(), - Some( - "glm" - | "zhipu" - | "glm-global" - | "zhipu-global" - | "glm-cn" - | "zhipu-cn" - | "bigmodel" - ) - ) { + if self.default_provider.as_deref().is_some_and(is_glm_alias) { if let Ok(key) = std::env::var("GLM_API_KEY") { if !key.is_empty() { self.api_key = Some(key); @@ -1996,10 +1986,7 @@ impl Config { } // API Key: ZAI_API_KEY overrides when provider is a Z.AI variant. - if matches!( - self.default_provider.as_deref(), - Some("zai" | "z.ai" | "zai-global" | "z.ai-global" | "zai-cn" | "z.ai-cn") - ) { + if self.default_provider.as_deref().is_some_and(is_zai_alias) { if let Ok(key) = std::env::var("ZAI_API_KEY") { if !key.is_empty() { self.api_key = Some(key); diff --git a/src/integrations/registry.rs b/src/integrations/registry.rs index 6024300..442fb0f 100644 --- a/src/integrations/registry.rs +++ b/src/integrations/registry.rs @@ -1,4 +1,8 @@ use super::{IntegrationCategory, IntegrationEntry, IntegrationStatus}; +use crate::providers::{ + is_glm_alias, is_minimax_alias, is_moonshot_alias, is_qianfan_alias, is_qwen_alias, + is_zai_alias, +}; /// Returns the full catalog of integrations #[allow(clippy::too_many_lines)] @@ -329,19 +333,7 @@ pub fn all_integrations() -> Vec { description: "Kimi & Kimi Coding", category: IntegrationCategory::AiModel, status_fn: |c| { - if matches!( - c.default_provider.as_deref(), - Some( - "moonshot" - | "kimi" - | "moonshot-intl" - | "moonshot-global" - | "moonshot-cn" - | "kimi-intl" - | "kimi-global" - | "kimi-cn" - ) - ) { + if c.default_provider.as_deref().is_some_and(is_moonshot_alias) { IntegrationStatus::Active } else { IntegrationStatus::Available @@ -377,10 +369,7 @@ pub fn all_integrations() -> Vec { description: "Z.AI inference", category: IntegrationCategory::AiModel, status_fn: |c| { - if matches!( - c.default_provider.as_deref(), - Some("zai" | "z.ai" | "zai-global" | "z.ai-global" | "zai-cn" | "z.ai-cn") - ) { + if c.default_provider.as_deref().is_some_and(is_zai_alias) { IntegrationStatus::Active } else { IntegrationStatus::Available @@ -392,18 +381,7 @@ pub fn all_integrations() -> Vec { description: "ChatGLM / Zhipu models", category: IntegrationCategory::AiModel, status_fn: |c| { - if matches!( - c.default_provider.as_deref(), - Some( - "glm" - | "zhipu" - | "glm-global" - | "zhipu-global" - | "glm-cn" - | "zhipu-cn" - | "bigmodel" - ) - ) { + if c.default_provider.as_deref().is_some_and(is_glm_alias) { IntegrationStatus::Active } else { IntegrationStatus::Available @@ -415,17 +393,7 @@ pub fn all_integrations() -> Vec { description: "MiniMax AI models", category: IntegrationCategory::AiModel, status_fn: |c| { - if matches!( - c.default_provider.as_deref(), - Some( - "minimax" - | "minimax-intl" - | "minimax-io" - | "minimax-global" - | "minimax-cn" - | "minimaxi" - ) - ) { + if c.default_provider.as_deref().is_some_and(is_minimax_alias) { IntegrationStatus::Active } else { IntegrationStatus::Available @@ -437,21 +405,7 @@ pub fn all_integrations() -> Vec { description: "Alibaba DashScope Qwen models", category: IntegrationCategory::AiModel, status_fn: |c| { - if matches!( - c.default_provider.as_deref(), - Some( - "qwen" - | "dashscope" - | "qwen-cn" - | "dashscope-cn" - | "qwen-intl" - | "dashscope-intl" - | "qwen-international" - | "dashscope-international" - | "qwen-us" - | "dashscope-us" - ) - ) { + if c.default_provider.as_deref().is_some_and(is_qwen_alias) { IntegrationStatus::Active } else { IntegrationStatus::Available @@ -475,7 +429,7 @@ pub fn all_integrations() -> Vec { description: "Baidu AI models", category: IntegrationCategory::AiModel, status_fn: |c| { - if matches!(c.default_provider.as_deref(), Some("qianfan" | "baidu")) { + if c.default_provider.as_deref().is_some_and(is_qianfan_alias) { IntegrationStatus::Active } else { IntegrationStatus::Available diff --git a/src/onboard/wizard.rs b/src/onboard/wizard.rs index 49efdbc..38847fa 100644 --- a/src/onboard/wizard.rs +++ b/src/onboard/wizard.rs @@ -8,6 +8,10 @@ use crate::hardware::{self, HardwareConfig}; use crate::memory::{ default_memory_backend_key, memory_backend_profile, selectable_memory_backends, }; +use crate::providers::{ + canonical_china_provider_name, is_glm_alias, is_glm_cn_alias, is_minimax_alias, + is_moonshot_alias, is_qianfan_alias, is_qwen_alias, is_zai_alias, is_zai_cn_alias, +}; use anyhow::{bail, Context, Result}; use console::style; use dialoguer::{Confirm, Input, Select}; @@ -449,25 +453,14 @@ pub fn run_quick_setup( } fn canonical_provider_name(provider_name: &str) -> &str { + if let Some(canonical) = canonical_china_provider_name(provider_name) { + return canonical; + } + match provider_name { "grok" => "xai", "together" => "together-ai", "google" | "google-gemini" => "gemini", - "dashscope" - | "qwen-cn" - | "dashscope-cn" - | "qwen-intl" - | "dashscope-intl" - | "qwen-international" - | "dashscope-international" - | "qwen-us" - | "dashscope-us" => "qwen", - "zhipu" | "glm-global" | "zhipu-global" | "glm-cn" | "zhipu-cn" | "bigmodel" => "glm", - "kimi" | "moonshot-intl" | "moonshot-global" | "moonshot-cn" | "kimi-intl" - | "kimi-global" | "kimi-cn" => "moonshot", - "minimax-intl" | "minimax-io" | "minimax-global" | "minimax-cn" | "minimaxi" => "minimax", - "z.ai" | "zai-global" | "z.ai-global" | "zai-cn" | "z.ai-cn" => "zai", - "baidu" => "qianfan", _ => provider_name, } } @@ -485,7 +478,7 @@ fn default_model_for_provider(provider: &str) -> String { match canonical_provider_name(provider) { "anthropic" => "claude-sonnet-4-5-20250929".into(), "openai" => "gpt-5.2".into(), - "glm" | "zhipu" | "zai" | "z.ai" => "glm-5".into(), + "glm" | "zai" => "glm-5".into(), "minimax" => "MiniMax-M2.5".into(), "qwen" => "qwen-plus".into(), "ollama" => "llama3.2".into(), @@ -698,7 +691,7 @@ fn curated_models_for_provider(provider_name: &str) -> Vec<(String, String)> { "Kimi Thinking Preview (deep reasoning)".to_string(), ), ], - "glm" | "zhipu" | "zai" | "z.ai" => vec![ + "glm" | "zai" => vec![ ( "glm-4.7".to_string(), "GLM-4.7 (latest flagship)".to_string(), @@ -1603,48 +1596,38 @@ fn setup_provider(workspace_dir: &Path) -> Result<(String, String, String, Optio key } } else { - let key_url = match provider_name { - "openrouter" => "https://openrouter.ai/keys", - "openai" => "https://platform.openai.com/api-keys", - "venice" => "https://venice.ai/settings/api", - "groq" => "https://console.groq.com/keys", - "mistral" => "https://console.mistral.ai/api-keys", - "deepseek" => "https://platform.deepseek.com/api_keys", - "together-ai" => "https://api.together.xyz/settings/api-keys", - "fireworks" => "https://fireworks.ai/account/api-keys", - "perplexity" => "https://www.perplexity.ai/settings/api", - "xai" => "https://console.x.ai", - "cohere" => "https://dashboard.cohere.com/api-keys", - "moonshot" | "moonshot-intl" | "moonshot-global" | "moonshot-cn" | "kimi" - | "kimi-intl" | "kimi-global" | "kimi-cn" => { - "https://platform.moonshot.cn/console/api-keys" + let key_url = if is_moonshot_alias(provider_name) { + "https://platform.moonshot.cn/console/api-keys" + } else if is_glm_cn_alias(provider_name) || is_zai_cn_alias(provider_name) { + "https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys" + } else if is_glm_alias(provider_name) || is_zai_alias(provider_name) { + "https://platform.z.ai/" + } else if is_minimax_alias(provider_name) { + "https://www.minimaxi.com/user-center/basic-information" + } else if is_qwen_alias(provider_name) { + "https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key" + } else if is_qianfan_alias(provider_name) { + "https://cloud.baidu.com/doc/WENXINWORKSHOP/s/7lm0vxo78" + } else { + match provider_name { + "openrouter" => "https://openrouter.ai/keys", + "openai" => "https://platform.openai.com/api-keys", + "venice" => "https://venice.ai/settings/api", + "groq" => "https://console.groq.com/keys", + "mistral" => "https://console.mistral.ai/api-keys", + "deepseek" => "https://platform.deepseek.com/api_keys", + "together-ai" => "https://api.together.xyz/settings/api-keys", + "fireworks" => "https://fireworks.ai/account/api-keys", + "perplexity" => "https://www.perplexity.ai/settings/api", + "xai" => "https://console.x.ai", + "cohere" => "https://dashboard.cohere.com/api-keys", + "vercel" => "https://vercel.com/account/tokens", + "cloudflare" => "https://dash.cloudflare.com/profile/api-tokens", + "nvidia" | "nvidia-nim" | "build.nvidia.com" => "https://build.nvidia.com/", + "bedrock" => "https://console.aws.amazon.com/iam", + "gemini" => "https://aistudio.google.com/app/apikey", + _ => "", } - "glm" | "zhipu" | "glm-global" | "zhipu-global" | "zai" | "z.ai" | "zai-global" - | "z.ai-global" => "https://platform.z.ai/", - "glm-cn" | "zhipu-cn" | "bigmodel" | "zai-cn" | "z.ai-cn" => { - "https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys" - } - "minimax" | "minimax-intl" | "minimax-io" | "minimax-global" | "minimax-cn" - | "minimaxi" => "https://www.minimaxi.com/user-center/basic-information", - "qwen" - | "dashscope" - | "qwen-cn" - | "dashscope-cn" - | "qwen-intl" - | "dashscope-intl" - | "qwen-international" - | "dashscope-international" - | "qwen-us" - | "dashscope-us" => { - "https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key" - } - "qianfan" | "baidu" => "https://cloud.baidu.com/doc/WENXINWORKSHOP/s/7lm0vxo78", - "vercel" => "https://vercel.com/account/tokens", - "cloudflare" => "https://dash.cloudflare.com/profile/api-tokens", - "nvidia" | "nvidia-nim" | "build.nvidia.com" => "https://build.nvidia.com/", - "bedrock" => "https://console.aws.amazon.com/iam", - "gemini" => "https://aistudio.google.com/app/apikey", - _ => "", }; println!(); @@ -1778,7 +1761,7 @@ fn setup_provider(workspace_dir: &Path) -> Result<(String, String, String, Optio ("moonshot-v1-128k", "Moonshot V1 128K"), ("moonshot-v1-32k", "Moonshot V1 32K"), ], - "glm" | "zhipu" | "zai" | "z.ai" => vec![ + "glm" | "zai" => vec![ ("glm-5", "GLM-5 (latest)"), ("glm-4-plus", "GLM-4 Plus (flagship)"), ("glm-4-flash", "GLM-4 Flash (fast)"), @@ -1992,12 +1975,12 @@ fn provider_env_var(name: &str) -> &'static str { "fireworks" | "fireworks-ai" => "FIREWORKS_API_KEY", "perplexity" => "PERPLEXITY_API_KEY", "cohere" => "COHERE_API_KEY", - "moonshot" | "kimi" => "MOONSHOT_API_KEY", - "glm" | "zhipu" => "GLM_API_KEY", + "moonshot" => "MOONSHOT_API_KEY", + "glm" => "GLM_API_KEY", "minimax" => "MINIMAX_API_KEY", - "qwen" | "dashscope" => "DASHSCOPE_API_KEY", - "qianfan" | "baidu" => "QIANFAN_API_KEY", - "zai" | "z.ai" => "ZAI_API_KEY", + "qwen" => "DASHSCOPE_API_KEY", + "qianfan" => "QIANFAN_API_KEY", + "zai" => "ZAI_API_KEY", "synthetic" => "SYNTHETIC_API_KEY", "opencode" | "opencode-zen" => "OPENCODE_API_KEY", "vercel" | "vercel-ai" => "VERCEL_API_KEY", diff --git a/src/providers/mod.rs b/src/providers/mod.rs index d624999..15d8316 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -31,48 +31,150 @@ const QWEN_US_BASE_URL: &str = "https://dashscope-us.aliyuncs.com/compatible-mod const ZAI_GLOBAL_BASE_URL: &str = "https://api.z.ai/api/coding/paas/v4"; const ZAI_CN_BASE_URL: &str = "https://open.bigmodel.cn/api/coding/paas/v4"; +pub(crate) fn is_minimax_intl_alias(name: &str) -> bool { + matches!( + name, + "minimax" | "minimax-intl" | "minimax-io" | "minimax-global" + ) +} + +pub(crate) fn is_minimax_cn_alias(name: &str) -> bool { + matches!(name, "minimax-cn" | "minimaxi") +} + +pub(crate) fn is_minimax_alias(name: &str) -> bool { + is_minimax_intl_alias(name) || is_minimax_cn_alias(name) +} + +pub(crate) fn is_glm_global_alias(name: &str) -> bool { + matches!(name, "glm" | "zhipu" | "glm-global" | "zhipu-global") +} + +pub(crate) fn is_glm_cn_alias(name: &str) -> bool { + matches!(name, "glm-cn" | "zhipu-cn" | "bigmodel") +} + +pub(crate) fn is_glm_alias(name: &str) -> bool { + is_glm_global_alias(name) || is_glm_cn_alias(name) +} + +pub(crate) fn is_moonshot_intl_alias(name: &str) -> bool { + matches!( + name, + "moonshot-intl" | "moonshot-global" | "kimi-intl" | "kimi-global" + ) +} + +pub(crate) fn is_moonshot_cn_alias(name: &str) -> bool { + matches!(name, "moonshot" | "kimi" | "moonshot-cn" | "kimi-cn") +} + +pub(crate) fn is_moonshot_alias(name: &str) -> bool { + is_moonshot_intl_alias(name) || is_moonshot_cn_alias(name) +} + +pub(crate) fn is_qwen_cn_alias(name: &str) -> bool { + matches!(name, "qwen" | "dashscope" | "qwen-cn" | "dashscope-cn") +} + +pub(crate) fn is_qwen_intl_alias(name: &str) -> bool { + matches!( + name, + "qwen-intl" | "dashscope-intl" | "qwen-international" | "dashscope-international" + ) +} + +pub(crate) fn is_qwen_us_alias(name: &str) -> bool { + matches!(name, "qwen-us" | "dashscope-us") +} + +pub(crate) fn is_qwen_alias(name: &str) -> bool { + is_qwen_cn_alias(name) || is_qwen_intl_alias(name) || is_qwen_us_alias(name) +} + +pub(crate) fn is_zai_global_alias(name: &str) -> bool { + matches!(name, "zai" | "z.ai" | "zai-global" | "z.ai-global") +} + +pub(crate) fn is_zai_cn_alias(name: &str) -> bool { + matches!(name, "zai-cn" | "z.ai-cn") +} + +pub(crate) fn is_zai_alias(name: &str) -> bool { + is_zai_global_alias(name) || is_zai_cn_alias(name) +} + +pub(crate) fn is_qianfan_alias(name: &str) -> bool { + matches!(name, "qianfan" | "baidu") +} + +pub(crate) fn canonical_china_provider_name(name: &str) -> Option<&'static str> { + if is_qwen_alias(name) { + Some("qwen") + } else if is_glm_alias(name) { + Some("glm") + } else if is_moonshot_alias(name) { + Some("moonshot") + } else if is_minimax_alias(name) { + Some("minimax") + } else if is_zai_alias(name) { + Some("zai") + } else if is_qianfan_alias(name) { + Some("qianfan") + } else { + None + } +} + fn minimax_base_url(name: &str) -> Option<&'static str> { - match name { - "minimax" | "minimax-intl" | "minimax-io" | "minimax-global" => Some(MINIMAX_INTL_BASE_URL), - "minimax-cn" | "minimaxi" => Some(MINIMAX_CN_BASE_URL), - _ => None, + if is_minimax_cn_alias(name) { + Some(MINIMAX_CN_BASE_URL) + } else if is_minimax_intl_alias(name) { + Some(MINIMAX_INTL_BASE_URL) + } else { + None } } fn glm_base_url(name: &str) -> Option<&'static str> { - match name { - "glm" | "zhipu" | "glm-global" | "zhipu-global" => Some(GLM_GLOBAL_BASE_URL), - "glm-cn" | "zhipu-cn" | "bigmodel" => Some(GLM_CN_BASE_URL), - _ => None, + if is_glm_cn_alias(name) { + Some(GLM_CN_BASE_URL) + } else if is_glm_global_alias(name) { + Some(GLM_GLOBAL_BASE_URL) + } else { + None } } fn moonshot_base_url(name: &str) -> Option<&'static str> { - match name { - "moonshot-intl" | "moonshot-global" | "kimi-intl" | "kimi-global" => { - Some(MOONSHOT_INTL_BASE_URL) - } - "moonshot" | "kimi" | "moonshot-cn" | "kimi-cn" => Some(MOONSHOT_CN_BASE_URL), - _ => None, + if is_moonshot_intl_alias(name) { + Some(MOONSHOT_INTL_BASE_URL) + } else if is_moonshot_cn_alias(name) { + Some(MOONSHOT_CN_BASE_URL) + } else { + None } } fn qwen_base_url(name: &str) -> Option<&'static str> { - match name { - "qwen" | "dashscope" | "qwen-cn" | "dashscope-cn" => Some(QWEN_CN_BASE_URL), - "qwen-intl" | "dashscope-intl" | "qwen-international" | "dashscope-international" => { - Some(QWEN_INTL_BASE_URL) - } - "qwen-us" | "dashscope-us" => Some(QWEN_US_BASE_URL), - _ => None, + if is_qwen_cn_alias(name) { + Some(QWEN_CN_BASE_URL) + } else if is_qwen_intl_alias(name) { + Some(QWEN_INTL_BASE_URL) + } else if is_qwen_us_alias(name) { + Some(QWEN_US_BASE_URL) + } else { + None } } fn zai_base_url(name: &str) -> Option<&'static str> { - match name { - "zai" | "z.ai" | "zai-global" | "z.ai-global" => Some(ZAI_GLOBAL_BASE_URL), - "zai-cn" | "z.ai-cn" => Some(ZAI_CN_BASE_URL), - _ => None, + if is_zai_cn_alias(name) { + Some(ZAI_CN_BASE_URL) + } else if is_zai_global_alias(name) { + Some(ZAI_GLOBAL_BASE_URL) + } else { + None } } @@ -192,27 +294,12 @@ fn resolve_provider_credential(name: &str, credential_override: Option<&str>) -> "fireworks" | "fireworks-ai" => vec!["FIREWORKS_API_KEY"], "perplexity" => vec!["PERPLEXITY_API_KEY"], "cohere" => vec!["COHERE_API_KEY"], - "moonshot" | "kimi" | "moonshot-intl" | "moonshot-global" | "moonshot-cn" | "kimi-intl" - | "kimi-global" | "kimi-cn" => vec!["MOONSHOT_API_KEY"], - "glm" | "zhipu" | "glm-global" | "zhipu-global" | "glm-cn" | "zhipu-cn" | "bigmodel" => { - vec!["GLM_API_KEY"] - } - "minimax" | "minimax-intl" | "minimax-io" | "minimax-global" | "minimax-cn" - | "minimaxi" => vec!["MINIMAX_API_KEY"], - "qianfan" | "baidu" => vec!["QIANFAN_API_KEY"], - "qwen" - | "dashscope" - | "qwen-cn" - | "dashscope-cn" - | "qwen-intl" - | "dashscope-intl" - | "qwen-international" - | "dashscope-international" - | "qwen-us" - | "dashscope-us" => vec!["DASHSCOPE_API_KEY"], - "zai" | "z.ai" | "zai-global" | "z.ai-global" | "zai-cn" | "z.ai-cn" => { - vec!["ZAI_API_KEY"] - } + name if is_moonshot_alias(name) => vec!["MOONSHOT_API_KEY"], + name if is_glm_alias(name) => vec!["GLM_API_KEY"], + name if is_minimax_alias(name) => vec!["MINIMAX_API_KEY"], + name if is_qianfan_alias(name) => vec!["QIANFAN_API_KEY"], + name if is_qwen_alias(name) => vec!["DASHSCOPE_API_KEY"], + name if is_zai_alias(name) => vec!["ZAI_API_KEY"], "nvidia" | "nvidia-nim" | "build.nvidia.com" => vec!["NVIDIA_API_KEY"], "synthetic" => vec!["SYNTHETIC_API_KEY"], "opencode" | "opencode-zen" => vec!["OPENCODE_API_KEY"], @@ -343,7 +430,7 @@ pub fn create_provider_with_url( key, AuthStyle::Bearer, ))), - "qianfan" | "baidu" => Ok(Box::new(OpenAiCompatibleProvider::new( + name if is_qianfan_alias(name) => Ok(Box::new(OpenAiCompatibleProvider::new( "Qianfan", "https://aip.baidubce.com", key, AuthStyle::Bearer, ))), name if qwen_base_url(name).is_some() => Ok(Box::new(OpenAiCompatibleProvider::new( @@ -767,6 +854,45 @@ mod tests { assert_eq!(resolved, Some("explicit-key".to_string())); } + #[test] + fn regional_alias_predicates_cover_expected_variants() { + assert!(is_moonshot_alias("moonshot")); + assert!(is_moonshot_alias("kimi-global")); + assert!(is_glm_alias("glm")); + assert!(is_glm_alias("bigmodel")); + assert!(is_minimax_alias("minimax-io")); + assert!(is_minimax_alias("minimaxi")); + assert!(is_qwen_alias("dashscope")); + assert!(is_qwen_alias("qwen-us")); + assert!(is_zai_alias("z.ai")); + assert!(is_zai_alias("zai-cn")); + assert!(is_qianfan_alias("qianfan")); + assert!(is_qianfan_alias("baidu")); + + assert!(!is_moonshot_alias("openrouter")); + assert!(!is_glm_alias("openai")); + assert!(!is_qwen_alias("gemini")); + assert!(!is_zai_alias("anthropic")); + assert!(!is_qianfan_alias("cohere")); + } + + #[test] + fn canonical_china_provider_name_maps_regional_aliases() { + assert_eq!(canonical_china_provider_name("moonshot"), Some("moonshot")); + assert_eq!(canonical_china_provider_name("kimi-intl"), Some("moonshot")); + assert_eq!(canonical_china_provider_name("glm"), Some("glm")); + assert_eq!(canonical_china_provider_name("zhipu-cn"), Some("glm")); + assert_eq!(canonical_china_provider_name("minimax"), Some("minimax")); + assert_eq!(canonical_china_provider_name("minimax-cn"), Some("minimax")); + assert_eq!(canonical_china_provider_name("qwen"), Some("qwen")); + assert_eq!(canonical_china_provider_name("dashscope-us"), Some("qwen")); + assert_eq!(canonical_china_provider_name("zai"), Some("zai")); + assert_eq!(canonical_china_provider_name("z.ai-cn"), Some("zai")); + assert_eq!(canonical_china_provider_name("qianfan"), Some("qianfan")); + assert_eq!(canonical_china_provider_name("baidu"), Some("qianfan")); + assert_eq!(canonical_china_provider_name("openai"), None); + } + #[test] fn regional_endpoint_aliases_map_to_expected_urls() { assert_eq!(minimax_base_url("minimax"), Some(MINIMAX_INTL_BASE_URL));