Skip to main content

codei_llm/
factory.rs

1use std::sync::Arc;
2
3use codei_config::ResolvedConfig;
4
5use crate::provider::{AnthropicProvider, LlmProvider, OpenAiProvider};
6use crate::{LlmError, ToolFormat};
7
8pub fn create_provider(config: &ResolvedConfig) -> Result<Arc<dyn LlmProvider>, LlmError> {
9    create_provider_by_name(config, &config.config.defaults.provider)
10}
11
12pub fn create_provider_by_name(
13    config: &ResolvedConfig,
14    provider_name: &str,
15) -> Result<Arc<dyn LlmProvider>, LlmError> {
16    let provider_cfg = config.config.providers.get(provider_name).ok_or_else(|| {
17        LlmError::ProviderNotConfigured {
18            provider: provider_name.to_string(),
19        }
20    })?;
21
22    let api_key = provider_cfg.resolve_api_key().map_err(|err| match err {
23        codei_config::ConfigError::MissingApiKey { env } => LlmError::MissingApiKey { env },
24        other => LlmError::Config(other.to_string()),
25    })?;
26
27    let api_style = provider_cfg.api_style.as_deref().unwrap_or("openai");
28
29    match api_style {
30        "openai" => {
31            let tool_format = ToolFormat::parse(provider_cfg.tool_format.as_deref());
32            let openai = OpenAiProvider::from_config(
33                provider_name.to_string(),
34                api_key,
35                provider_cfg.base_url.as_deref(),
36                tool_format,
37            )?;
38            Ok(Arc::new(openai))
39        }
40        "anthropic" => {
41            let anthropic = AnthropicProvider::from_config(
42                provider_name.to_string(),
43                api_key,
44                provider_cfg.base_url.as_deref(),
45            )?;
46            Ok(Arc::new(anthropic))
47        }
48        other => Err(LlmError::UnsupportedProvider(other.to_string())),
49    }
50}