use crate::config::ProviderType;
#[derive(Debug, Clone, Copy)]
pub struct ModelAlias {
pub alias: &'static str,
pub model_id: &'static str,
pub provider: ProviderType,
}
pub const LOCAL_ALIAS: &str = "local";
static ALIASES: &[ModelAlias] = &[
ModelAlias {
alias: "gemini-flash-lite",
model_id: "gemini-flash-lite-latest",
provider: ProviderType::Gemini,
},
ModelAlias {
alias: "gemini-flash",
model_id: "gemini-flash-latest",
provider: ProviderType::Gemini,
},
ModelAlias {
alias: "gemini-pro",
model_id: "gemini-pro-latest",
provider: ProviderType::Gemini,
},
ModelAlias {
alias: "claude-haiku",
model_id: "claude-haiku-4-5-20251001",
provider: ProviderType::Anthropic,
},
ModelAlias {
alias: "claude-sonnet",
model_id: "claude-sonnet-4-6",
provider: ProviderType::Anthropic,
},
ModelAlias {
alias: "claude-opus",
model_id: "claude-opus-4-6",
provider: ProviderType::Anthropic,
},
];
pub fn resolve(name: &str) -> Option<ResolvedAlias> {
if name == LOCAL_ALIAS {
return Some(ResolvedAlias {
alias: LOCAL_ALIAS,
model_id: "auto-detect",
provider: ProviderType::LMStudio,
});
}
ALIASES
.iter()
.find(|a| a.alias == name)
.map(|a| ResolvedAlias {
alias: a.alias,
model_id: a.model_id,
provider: a.provider,
})
}
#[derive(Debug, Clone)]
pub struct ResolvedAlias {
pub alias: &'static str,
pub model_id: &'static str,
pub provider: ProviderType,
}
impl ResolvedAlias {
pub fn needs_auto_detect(&self) -> bool {
self.model_id == "auto-detect"
}
}
pub fn all() -> &'static [ModelAlias] {
ALIASES
}
pub fn alias_names() -> Vec<&'static str> {
let mut names: Vec<&str> = ALIASES.iter().map(|a| a.alias).collect();
names.push(LOCAL_ALIAS);
names
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resolve_known_alias() {
let r = resolve("claude-sonnet").unwrap();
assert_eq!(r.model_id, "claude-sonnet-4-6");
assert_eq!(r.provider, ProviderType::Anthropic);
assert!(!r.needs_auto_detect());
}
#[test]
fn resolve_local_alias() {
let r = resolve("local").unwrap();
assert!(r.needs_auto_detect());
assert_eq!(r.provider, ProviderType::LMStudio);
}
#[test]
fn resolve_unknown_returns_none() {
assert!(resolve("not-a-real-model").is_none());
}
#[test]
fn resolve_literal_model_id_returns_none() {
assert!(resolve("claude-sonnet-4-6").is_none());
assert!(resolve("gemini-2.5-pro").is_none());
}
#[test]
fn all_aliases_non_empty() {
assert!(!all().is_empty());
}
#[test]
fn alias_names_includes_local() {
let names = alias_names();
assert!(names.contains(&"local"));
assert!(names.contains(&"gemini-flash-lite"));
}
#[test]
fn no_duplicate_aliases() {
let names = alias_names();
let mut seen = std::collections::HashSet::new();
for name in &names {
assert!(seen.insert(name), "duplicate alias: {name}");
}
}
#[test]
fn no_duplicate_model_ids() {
let mut seen = std::collections::HashSet::new();
for a in all() {
assert!(
seen.insert(a.model_id),
"duplicate model_id: {}",
a.model_id
);
}
}
}