use std::sync::Arc;
use nexo_config::types::llm::{LlmProviderConfig, RateLimitConfig, RetryConfig};
use crate::client::LlmClient;
use crate::openai_compat::OpenAiClient;
use crate::registry::LlmProviderFactory;
pub const DEFAULT_BASE_URL: &str = "https://api.deepseek.com/v1";
pub struct DeepSeekFactory;
impl LlmProviderFactory for DeepSeekFactory {
fn name(&self) -> &str {
"deepseek"
}
fn build(
&self,
provider_cfg: &LlmProviderConfig,
model: &str,
retry: RetryConfig,
) -> anyhow::Result<Arc<dyn LlmClient>> {
let cfg = if provider_cfg.base_url.trim().is_empty() {
LlmProviderConfig {
api_key: provider_cfg.api_key.clone(),
group_id: provider_cfg.group_id.clone(),
base_url: DEFAULT_BASE_URL.to_string(),
rate_limit: RateLimitConfig {
requests_per_second: provider_cfg.rate_limit.requests_per_second,
quota_alert_threshold: provider_cfg.rate_limit.quota_alert_threshold,
},
auth: provider_cfg.auth.clone(),
api_flavor: provider_cfg.api_flavor.clone(),
embedding_model: provider_cfg.embedding_model.clone(),
safety_settings: provider_cfg.safety_settings.clone(),
}
} else {
provider_cfg.clone()
};
Ok(Arc::new(OpenAiClient::new(&cfg, model, retry)))
}
}
#[cfg(test)]
mod tests {
use super::*;
use nexo_config::types::llm::{LlmProviderConfig, RateLimitConfig};
fn empty_cfg() -> LlmProviderConfig {
LlmProviderConfig {
api_key: "sk-deepseek-test".into(),
group_id: None,
base_url: String::new(),
rate_limit: RateLimitConfig {
requests_per_second: 1.0,
quota_alert_threshold: None,
},
auth: None,
api_flavor: None,
embedding_model: None,
safety_settings: None,
}
}
#[test]
fn factory_name_is_deepseek() {
assert_eq!(DeepSeekFactory.name(), "deepseek");
}
#[test]
fn build_succeeds_with_blank_base_url() {
let cfg = empty_cfg();
DeepSeekFactory
.build(&cfg, "deepseek-chat", RetryConfig::default())
.expect("DeepSeek client should build with blank base_url");
}
#[test]
fn build_preserves_explicit_base_url() {
let mut cfg = empty_cfg();
cfg.base_url = "https://gateway.example.com/v1".into();
DeepSeekFactory
.build(&cfg, "deepseek-chat", RetryConfig::default())
.expect("DeepSeek client should respect operator-set base_url");
}
}