use crate::types::{LLMConfig, Provider};
use anyhow::{Result, anyhow};
use std::sync::Arc;
use praxis_llm::{LLMClient, ReasoningClient};
pub struct ClientFactory;
impl ClientFactory {
pub fn supports_reasoning(model: &str) -> bool {
model.starts_with("gpt-5") || model.starts_with("o1")
}
pub fn validate_config(config: &LLMConfig) -> Result<()> {
match config.provider {
Provider::OpenAI => Ok(()),
Provider::Azure => {
Err(anyhow!("Azure provider not yet implemented. Use Provider::OpenAI for now."))
}
Provider::Anthropic => {
Err(anyhow!("Anthropic provider not yet implemented. Use Provider::OpenAI for now."))
}
}
}
pub fn should_use_reasoning_api(
config: &LLMConfig,
reasoning_client: &Option<Arc<dyn ReasoningClient>>,
) -> bool {
Self::supports_reasoning(&config.model) && reasoning_client.is_some()
}
#[allow(dead_code)]
pub fn create_client(_config: &LLMConfig, _api_key: &str) -> Result<Arc<dyn LLMClient>> {
Err(anyhow!("Dynamic client creation not yet implemented. Create clients at application level and pass to GraphBuilder."))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::LLMConfig;
#[test]
fn test_supports_reasoning() {
assert!(ClientFactory::supports_reasoning("gpt-5"));
assert!(ClientFactory::supports_reasoning("gpt-5-turbo"));
assert!(ClientFactory::supports_reasoning("o1-preview"));
assert!(ClientFactory::supports_reasoning("o1-mini"));
assert!(!ClientFactory::supports_reasoning("gpt-4o"));
assert!(!ClientFactory::supports_reasoning("gpt-4o-mini"));
assert!(!ClientFactory::supports_reasoning("gpt-3.5-turbo"));
}
#[test]
fn test_validate_config() {
let openai_config = LLMConfig::new("gpt-4o").with_provider(Provider::OpenAI);
assert!(ClientFactory::validate_config(&openai_config).is_ok());
let azure_config = LLMConfig::new("gpt-4o").with_provider(Provider::Azure);
assert!(ClientFactory::validate_config(&azure_config).is_err());
let anthropic_config = LLMConfig::new("claude-3").with_provider(Provider::Anthropic);
assert!(ClientFactory::validate_config(&anthropic_config).is_err());
}
}