use llm_stack_core::registry::{ProviderConfig, ProviderFactory};
use llm_stack_core::{DynProvider, LlmError};
use crate::{AnthropicConfig, AnthropicProvider};
#[derive(Debug, Clone, Copy, Default)]
pub struct AnthropicFactory;
impl ProviderFactory for AnthropicFactory {
fn name(&self) -> &'static str {
"anthropic"
}
fn build(&self, config: &ProviderConfig) -> Result<Box<dyn DynProvider>, LlmError> {
let api_key = config.api_key.clone().ok_or_else(|| {
LlmError::InvalidRequest("anthropic provider requires api_key".into())
})?;
if config.model.is_empty() {
return Err(LlmError::InvalidRequest(
"anthropic provider requires model".into(),
));
}
let mut anthropic_config = AnthropicConfig {
api_key,
model: config.model.clone(),
..Default::default()
};
if let Some(base_url) = &config.base_url {
anthropic_config.base_url.clone_from(base_url);
}
if let Some(timeout) = config.timeout {
anthropic_config.timeout = Some(timeout);
}
if let Some(max_tokens) = config.get_extra_i64("max_tokens") {
anthropic_config.max_tokens =
u32::try_from(max_tokens).unwrap_or(anthropic_config.max_tokens);
}
if let Some(api_version) = config.get_extra_str("api_version") {
anthropic_config.api_version = api_version.to_string();
}
Ok(Box::new(AnthropicProvider::new(anthropic_config)))
}
}
pub fn register_global() {
llm_stack_core::ProviderRegistry::global().register(Box::new(AnthropicFactory));
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_factory_name() {
let factory = AnthropicFactory;
assert_eq!(factory.name(), "anthropic");
}
#[test]
fn test_factory_build_success() {
let factory = AnthropicFactory;
let config = ProviderConfig::new("anthropic", "claude-3")
.api_key("sk-test")
.timeout(Duration::from_secs(30))
.extra("max_tokens", 2048i64);
let provider = factory.build(&config).unwrap();
assert_eq!(provider.metadata().name, "anthropic");
assert_eq!(provider.metadata().model, "claude-3");
}
#[test]
fn test_factory_missing_api_key() {
let factory = AnthropicFactory;
let config = ProviderConfig::new("anthropic", "claude-3");
let err = factory.build(&config).err().unwrap();
assert!(matches!(err, LlmError::InvalidRequest(_)));
}
#[test]
fn test_factory_empty_model() {
let factory = AnthropicFactory;
let config = ProviderConfig::new("anthropic", "").api_key("sk-test");
let err = factory.build(&config).err().unwrap();
assert!(matches!(err, LlmError::InvalidRequest(_)));
}
}