Skip to main content

litellm_rs/core/traits/provider/
config.rs

1//! Provider configuration trait
2//!
3//! Defines the configuration interface for all AI providers
4
5use std::fmt::Debug;
6
7use crate::core::net::ProviderEndpointAccess;
8
9/// Provider configuration trait
10///
11/// All provider configurations must implement this trait to ensure consistent
12/// validation and access to common settings.
13///
14/// # Design Principles
15/// - Type-safe configuration management
16/// - Validation before provider initialization
17/// - Common settings abstraction (API key, timeout, retries)
18/// - Clone and Debug for testability
19///
20/// # Example
21/// ```rust
22/// use std::time::Duration;
23/// use litellm_rs::core::traits::provider::ProviderConfig;
24///
25/// #[derive(Debug, Clone)]
26/// struct MyProviderConfig {
27///     api_key: String,
28///     api_base: Option<String>,
29///     timeout_secs: u64,
30///     max_retries: u32,
31/// }
32///
33/// impl ProviderConfig for MyProviderConfig {
34///     fn validate(&self) -> Result<(), String> {
35///         if self.api_key.is_empty() {
36///             return Err("API key is required".to_string());
37///         }
38///         Ok(())
39///     }
40///
41///     fn api_key(&self) -> Option<&str> {
42///         Some(&self.api_key)
43///     }
44///
45///     fn api_base(&self) -> Option<&str> {
46///         self.api_base.as_deref()
47///     }
48///
49///     fn timeout(&self) -> Duration {
50///         Duration::from_secs(self.timeout_secs)
51///     }
52///
53///     fn max_retries(&self) -> u32 {
54///         self.max_retries
55///     }
56/// }
57/// ```
58pub trait ProviderConfig: Send + Sync + Clone + Debug + 'static {
59    /// Validate configuration
60    ///
61    /// # Returns
62    /// `Ok(())` if configuration is valid, `Err(String)` with error message otherwise
63    ///
64    /// # Implementation Notes
65    /// - Check required fields are present
66    /// - Validate field formats (e.g., URL format)
67    /// - Verify value ranges are acceptable
68    /// - Called before provider initialization
69    fn validate(&self) -> Result<(), String>;
70
71    /// Get API key
72    ///
73    /// # Returns
74    /// Optional API key for authentication with the provider
75    ///
76    /// # Note
77    /// Returns `None` if the provider doesn't require an API key
78    fn api_key(&self) -> Option<&str>;
79
80    /// Get API base URL
81    ///
82    /// # Returns
83    /// Optional base URL for the provider API
84    ///
85    /// # Use Cases
86    /// - Custom API endpoints (e.g., Azure OpenAI)
87    /// - Self-hosted models
88    /// - Proxy configurations
89    /// - Development/testing environments
90    fn api_base(&self) -> Option<&str>;
91
92    /// Get request timeout
93    ///
94    /// # Returns
95    /// Maximum duration to wait for a request to complete
96    ///
97    /// # Implementation Notes
98    /// - Should include both connection and read timeouts
99    /// - Typical values: 30-120 seconds for chat completion
100    /// - Consider longer timeouts for streaming requests
101    fn timeout(&self) -> std::time::Duration;
102
103    /// Get maximum retry attempts
104    ///
105    /// # Returns
106    /// Number of times to retry failed requests
107    ///
108    /// # Implementation Notes
109    /// - Retries should use exponential backoff
110    /// - Typical values: 2-5 retries
111    /// - Consider rate limits when setting this value
112    fn max_retries(&self) -> u32;
113
114    /// Network scope allowed for this provider's configured endpoint.
115    fn endpoint_access(&self) -> ProviderEndpointAccess {
116        ProviderEndpointAccess::PublicOnly
117    }
118
119    /// Whether this provider requires an SSRF-safe HTTP client.
120    ///
121    /// Return `true` for providers whose endpoint URL is user-controlled.
122    /// The SSRF-safe client re-validates the resolved IP on every request,
123    /// preventing DNS-rebinding attacks.
124    fn use_ssrf_safe_client(&self) -> bool {
125        false
126    }
127
128    /// Standard validation: API key required, timeout > 0, max_retries <= 10.
129    ///
130    /// Call from `validate()` to avoid repeating common checks.
131    /// Providers with optional API keys or custom fields should implement
132    /// `validate()` directly instead.
133    fn validate_standard(&self, provider_name: &str) -> Result<(), String> {
134        if self.api_key().is_none_or(|k| k.is_empty()) {
135            return Err(format!("{} API key is required", provider_name));
136        }
137        if self.timeout().as_secs() == 0 {
138            return Err("Timeout must be greater than 0".to_string());
139        }
140        if self.max_retries() > 10 {
141            return Err("Max retries should not exceed 10".to_string());
142        }
143        Ok(())
144    }
145}
146
147#[cfg(test)]
148mod tests {
149    use super::ProviderConfig;
150    use crate::core::net::ProviderEndpointAccess;
151    use crate::core::providers::mistral::MistralConfig;
152
153    #[test]
154    fn endpoint_access_defaults_to_public_only() {
155        assert_eq!(
156            MistralConfig::default().endpoint_access(),
157            ProviderEndpointAccess::PublicOnly
158        );
159    }
160}