use crate::ai::ProviderKind;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Hosted {
pub id: &'static str,
pub label: &'static str,
pub kind: ProviderKind,
pub base_url: &'static str,
pub env: &'static str,
pub console: &'static str,
}
const fn openai_like(
id: &'static str,
label: &'static str,
base_url: &'static str,
env: &'static str,
console: &'static str,
) -> Hosted {
Hosted { id, label, kind: ProviderKind::OpenAiCompatible, base_url, env, console }
}
pub const HOSTED: &[Hosted] = &[
Hosted {
id: "anthropic",
label: "Anthropic · Claude",
kind: ProviderKind::Anthropic,
base_url: "https://api.anthropic.com",
env: "ANTHROPIC_API_KEY",
console: "https://console.anthropic.com/settings/keys",
},
openai_like(
"openai",
"OpenAI",
"https://api.openai.com/v1",
"OPENAI_API_KEY",
"https://platform.openai.com/api-keys",
),
openai_like(
"opencode-go",
"OpenCode Go · suscripción",
crate::ai::opencode::BASE_URL,
"OPENCODE_API_KEY",
"https://opencode.ai/console",
),
openai_like(
"opencode-zen",
"OpenCode Zen",
"https://opencode.ai/zen/v1",
"OPENCODE_API_KEY",
"https://opencode.ai/console",
),
openai_like(
"deepseek",
"DeepSeek",
"https://api.deepseek.com",
"DEEPSEEK_API_KEY",
"https://platform.deepseek.com/api_keys",
),
openai_like(
"openrouter",
"OpenRouter",
"https://openrouter.ai/api/v1",
"OPENROUTER_API_KEY",
"https://openrouter.ai/keys",
),
openai_like(
"gemini",
"Google · Gemini",
"https://generativelanguage.googleapis.com/v1beta/openai",
"GEMINI_API_KEY",
"https://aistudio.google.com/apikey",
),
openai_like("xai", "xAI · Grok", "https://api.x.ai/v1", "XAI_API_KEY", "https://console.x.ai"),
openai_like(
"mistral",
"Mistral",
"https://api.mistral.ai/v1",
"MISTRAL_API_KEY",
"https://console.mistral.ai/api-keys",
),
openai_like("groq", "Groq", "https://api.groq.com/openai/v1", "GROQ_API_KEY", "https://console.groq.com/keys"),
openai_like(
"moonshot",
"Moonshot · Kimi",
"https://api.moonshot.ai/v1",
"MOONSHOT_API_KEY",
"https://platform.moonshot.ai/console/api-keys",
),
openai_like(
"zai",
"Z.ai · GLM",
"https://api.z.ai/api/paas/v4",
"ZAI_API_KEY",
"https://z.ai/manage-apikey/apikey-list",
),
openai_like(
"qwen",
"Qwen · Alibaba Cloud",
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
"DASHSCOPE_API_KEY",
"https://modelstudio.console.alibabacloud.com/",
),
];
pub fn hosted(id: &str) -> Option<&'static Hosted> {
HOSTED.iter().find(|hosted| hosted.id == id)
}
pub fn is_hosted(id: &str) -> bool {
hosted(id).is_some()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cada_proveedor_tiene_id_unico_https_y_pagina_de_claves() {
for (index, hosted) in HOSTED.iter().enumerate() {
assert!(HOSTED[index + 1..].iter().all(|other| other.id != hosted.id), "{} repetido", hosted.id);
assert!(crate::ai::connection::validate_base_url(hosted.base_url).is_ok(), "{}", hosted.id);
assert!(hosted.base_url.starts_with("https://") && hosted.console.starts_with("https://"), "{}", hosted.id);
assert!(hosted.env.ends_with("_API_KEY"), "{}", hosted.id);
}
assert!(is_hosted("deepseek") && !is_hosted("custom") && !is_hosted("ollama"));
}
}