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}