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}