const DEFAULTS: &[(&str, &str)] = &[
("anthropic", "claude-fable-5"),
("claude", "claude-fable-5"),
("chatgpt", "gpt-5.6-sol"),
("openai", "gpt-5.4"),
("copilot", "gpt-5.4"),
("github-copilot", "gpt-5.4"),
("xai", "grok-build-0.1"),
("grok", "grok-build-0.1"),
("gemini", "gemini-3.1-pro-preview"),
("deepseek", "deepseek-v4-pro"),
("moonshot", "kimi-k3"),
("kimi", "kimi-k3"),
("minimax", "MiniMax-M3"),
("huggingface", "moonshotai/Kimi-K2.5"),
("openrouter", "z-ai/glm-5.2"),
];
pub fn default_model_for_provider(provider: &str) -> Option<&'static str> {
let key = provider.trim();
DEFAULTS
.iter()
.find(|(name, _)| name.eq_ignore_ascii_case(key))
.map(|(_, model)| *model)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn oauth_providers_get_their_own_defaults() {
assert_eq!(default_model_for_provider("chatgpt"), Some("gpt-5.6-sol"));
assert_eq!(default_model_for_provider("xai"), Some("grok-build-0.1"));
assert_eq!(
default_model_for_provider("anthropic"),
Some("claude-fable-5")
);
}
#[test]
fn aliases_resolve_to_the_same_model() {
for (a, b) in [
("claude", "anthropic"),
("grok", "xai"),
("kimi", "moonshot"),
] {
assert_eq!(
default_model_for_provider(a),
default_model_for_provider(b),
"{a} and {b} should agree"
);
}
}
#[test]
fn lookup_ignores_case_and_padding() {
assert_eq!(
default_model_for_provider(" AnThRoPiC "),
Some("claude-fable-5")
);
}
#[test]
fn an_unknown_provider_picks_nothing() {
assert_eq!(default_model_for_provider("not-a-provider"), None);
assert_eq!(default_model_for_provider(""), None);
}
}