use std::collections::HashMap;
use rig::providers::{anthropic, gemini, ollama, openai, openrouter};
use crate::config::ProviderEntry;
use super::{AnyClient, ProviderKind, resolve_api_key, resolve_provider_info};
pub(crate) fn create_client(
provider_name: &str,
api_key: Option<&str>,
providers: &HashMap<String, ProviderEntry>,
) -> anyhow::Result<AnyClient> {
let info = resolve_provider_info(provider_name, providers).ok_or_else(|| {
anyhow::anyhow!(
"Unknown provider: {}. Supported providers: openrouter, openai, anthropic, gemini, deepseek, glm, ollama, custom",
provider_name
)
})?;
let key = match (api_key, info.api_key_literal.as_deref()) {
(Some(k), _) if !k.is_empty() => k.to_string(),
(_, Some(k)) if !k.is_empty() => k.to_string(),
_ => resolve_api_key(info.kind, info.api_key_env.as_deref(), api_key)?,
};
let base_url = match info.kind {
ProviderKind::DeepSeek => Some(
std::env::var("DEEPSEEK_BASE_URL")
.unwrap_or_else(|_| "https://api.deepseek.com/v1".to_string()),
),
ProviderKind::Glm => Some(
std::env::var("GLM_BASE_URL")
.unwrap_or_else(|_| "https://open.bigmodel.cn/api/coding/paas/v4".to_string()),
),
ProviderKind::Custom => info
.base_url
.or_else(|| std::env::var("CUSTOM_BASE_URL").ok()),
_ => info.base_url,
};
match info.kind {
ProviderKind::OpenAI => {
let mut b = openai::CompletionsClient::builder().api_key(&key);
if let Some(base_url) = &base_url {
b = b.base_url(base_url);
}
Ok(AnyClient::OpenAI(b.build()?))
}
ProviderKind::Anthropic => {
let mut b = anthropic::Client::builder().api_key(&key);
if let Some(base_url) = &base_url {
b = b.base_url(base_url);
}
Ok(AnyClient::Anthropic(b.build()?))
}
ProviderKind::Gemini => {
let mut b = gemini::Client::builder().api_key(&key);
if let Some(base_url) = &base_url {
b = b.base_url(base_url);
}
Ok(AnyClient::Gemini(b.build()?))
}
ProviderKind::DeepSeek => {
let b = openai::CompletionsClient::builder()
.api_key(&key)
.base_url(base_url.as_deref().unwrap_or("https://api.deepseek.com/v1"));
Ok(AnyClient::DeepSeek(b.build()?))
}
ProviderKind::Glm => {
let b = openai::CompletionsClient::builder().api_key(&key).base_url(
base_url
.as_deref()
.unwrap_or("https://open.bigmodel.cn/api/coding/paas/v4"),
);
Ok(AnyClient::Glm(b.build()?))
}
ProviderKind::Ollama => {
let key: ollama::OllamaApiKey = key.as_str().into();
let mut b = ollama::Client::builder().api_key(key);
if let Some(base_url) = &base_url {
b = b.base_url(base_url);
}
Ok(AnyClient::Ollama(b.build()?))
}
ProviderKind::OpenRouter => {
let mut b = openrouter::Client::builder().api_key(&key);
if let Some(base_url) = &base_url {
b = b.base_url(base_url);
}
Ok(AnyClient::OpenRouter(b.build()?))
}
ProviderKind::Custom => {
let base_url = base_url.ok_or_else(|| {
anyhow::anyhow!(
"CUSTOM_BASE_URL environment variable must be set for custom provider"
)
})?;
let b = openai::CompletionsClient::builder()
.api_key(&key)
.base_url(&base_url);
Ok(AnyClient::Custom(b.build()?))
}
}
}