ai_lib/
config.rs

1use std::time::Duration;
2
3/// Minimal explicit connection/configuration options.
4///
5/// Library users can pass an instance of this struct to `AiClient::with_options` to
6/// explicitly control base URL, proxy, API key and timeout without relying exclusively
7/// on environment variables. Any field left as `None` will fall back to existing
8/// environment variable behavior or library defaults.
9#[derive(Clone, Debug)]
10pub struct ConnectionOptions {
11    pub base_url: Option<String>,
12    pub proxy: Option<String>,
13    pub api_key: Option<String>,
14    pub timeout: Option<Duration>,
15    pub disable_proxy: bool,
16}
17
18impl Default for ConnectionOptions {
19    fn default() -> Self {
20        Self {
21            base_url: None,
22            proxy: None,
23            api_key: None,
24            timeout: None,
25            disable_proxy: false,
26        }
27    }
28}
29
30impl ConnectionOptions {
31    /// Hydrate unset fields from environment variables (lightweight fallback logic).
32    ///
33    /// `provider_env_prefix` may be something like `OPENAI`, `GROQ`, etc., used to look up
34    /// a provider specific API key prior to the generic fallback `AI_API_KEY`.
35    pub fn hydrate_with_env(mut self, provider_env_prefix: &str) -> Self {
36        // API key precedence: explicit > <PROVIDER>_API_KEY > AI_API_KEY
37        if self.api_key.is_none() {
38            let specific = format!("{}_API_KEY", provider_env_prefix);
39            self.api_key = std::env::var(&specific)
40                .ok()
41                .or_else(|| std::env::var("AI_API_KEY").ok());
42        }
43        // Base URL precedence: explicit > AI_BASE_URL (generic) > leave None (caller/adapter handles default)
44        if self.base_url.is_none() {
45            if let Ok(v) = std::env::var("AI_BASE_URL") {
46                self.base_url = Some(v);
47            }
48        }
49        // Proxy precedence: explicit > AI_PROXY_URL
50        if self.proxy.is_none() && !self.disable_proxy {
51            self.proxy = std::env::var("AI_PROXY_URL").ok();
52        }
53        // Timeout precedence: explicit > AI_TIMEOUT_SECS > default handled by caller
54        if self.timeout.is_none() {
55            if let Ok(v) = std::env::var("AI_TIMEOUT_SECS") {
56                if let Ok(secs) = v.parse::<u64>() {
57                    self.timeout = Some(Duration::from_secs(secs));
58                }
59            }
60        }
61        self
62    }
63}