aether_core/
config.rs

1//! # Aether Configuration
2//! 
3//! Central configuration management for the Aether framework.
4//! Supports loading from environment variables, files, and programmatic defaults.
5
6use std::env;
7
8/// Global configuration for the Aether engine.
9/// 
10/// # Example
11/// ```rust
12/// use aether_core::AetherConfig;
13/// 
14/// // Load from environment
15/// let config = AetherConfig::from_env();
16/// 
17/// // Or customize
18/// let config = AetherConfig::default()
19///     .with_toon(true)
20///     .with_healing(true);
21/// ```
22#[derive(Debug, Clone)]
23pub struct AetherConfig {
24    /// Enable TOON (Token-Oriented Object Notation) for context compression.
25    /// Reduces token usage by 30-60% for structured data.
26    /// Default: false, Env: AETHER_TOON=true
27    pub toon_enabled: bool,
28
29    /// Enable Self-Healing mode (automatic validation and retry on errors).
30    /// Default: false, Env: AETHER_HEALING=true
31    pub healing_enabled: bool,
32
33    /// Enable Semantic Cache (reduces API costs for similar prompts).
34    /// Default: false, Env: AETHER_CACHE=true
35    pub cache_enabled: bool,
36
37    /// Enable parallel slot generation.
38    /// Default: true, Env: AETHER_PARALLEL=false
39    pub parallel: bool,
40
41    /// Whether to enable the Aether Inspector UI.
42    /// Default: false, Env: AETHER_INSPECT=true
43    pub inspector_enabled: bool,
44
45    /// Port for the Aether Inspector UI.
46    /// Default: 3000, Env: AETHER_INSPECT_PORT=8080
47    pub inspector_port: u16,
48
49    /// Maximum retries for failed generations.
50    /// Default: 2, Env: AETHER_MAX_RETRIES=3
51    pub max_retries: u32,
52
53    /// Auto-enable TOON when context exceeds this character count.
54    /// If None, TOON is only enabled manually.
55    /// Default: Some(2000), Env: AETHER_TOON_THRESHOLD=2000
56    pub auto_toon_threshold: Option<usize>,
57
58    /// Cache similarity threshold (0.0 - 1.0).
59    /// Higher values require more similar prompts to hit the cache.
60    /// Default: 0.90, Env: AETHER_CACHE_THRESHOLD=0.90
61    pub cache_threshold: f32,
62}
63
64impl Default for AetherConfig {
65    fn default() -> Self {
66        Self {
67            toon_enabled: false,
68            healing_enabled: false,
69            cache_enabled: false,
70            parallel: true,
71            inspector_enabled: false,
72            inspector_port: 3000,
73            max_retries: 2,
74            auto_toon_threshold: Some(2000),
75            cache_threshold: 0.90,
76        }
77    }
78}
79
80impl AetherConfig {
81    /// Create a new config from environment variables.
82    /// Falls back to defaults for missing variables.
83    pub fn from_env() -> Self {
84        let mut config = Self::default();
85
86        if let Ok(v) = env::var("AETHER_TOON") {
87            config.toon_enabled = v.to_lowercase() == "true" || v == "1";
88        }
89        if let Ok(v) = env::var("AETHER_HEALING") {
90            config.healing_enabled = v.to_lowercase() == "true" || v == "1";
91        }
92        if let Ok(v) = env::var("AETHER_CACHE") {
93            config.cache_enabled = v.to_lowercase() == "true" || v == "1";
94        }
95        if let Ok(v) = env::var("AETHER_PARALLEL") {
96            config.parallel = v.to_lowercase() != "false" && v != "0";
97        }
98        if let Ok(v) = env::var("AETHER_INSPECT") {
99            config.inspector_enabled = v.to_lowercase() == "true" || v == "1";
100        }
101        if let Ok(v) = env::var("AETHER_INSPECT_PORT") {
102            if let Ok(n) = v.parse() {
103                config.inspector_port = n;
104            }
105        }
106        if let Ok(v) = env::var("AETHER_MAX_RETRIES") {
107            if let Ok(n) = v.parse() {
108                config.max_retries = n;
109            }
110        }
111        if let Ok(v) = env::var("AETHER_TOON_THRESHOLD") {
112            if let Ok(n) = v.parse() {
113                config.auto_toon_threshold = Some(n);
114            }
115        }
116        if let Ok(v) = env::var("AETHER_CACHE_THRESHOLD") {
117            if let Ok(n) = v.parse() {
118                config.cache_threshold = n;
119            }
120        }
121
122        config
123    }
124
125    /// Builder: Enable or disable TOON protocol.
126    pub fn with_toon(mut self, enabled: bool) -> Self {
127        self.toon_enabled = enabled;
128        self
129    }
130
131    /// Builder: Enable or disable Self-Healing.
132    pub fn with_healing(mut self, enabled: bool) -> Self {
133        self.healing_enabled = enabled;
134        self
135    }
136
137    /// Builder: Enable or disable Semantic Cache.
138    pub fn with_cache(mut self, enabled: bool) -> Self {
139        self.cache_enabled = enabled;
140        self
141    }
142
143    /// Builder: Enable or disable parallel generation.
144    pub fn with_parallel(mut self, enabled: bool) -> Self {
145        self.parallel = enabled;
146        self
147    }
148
149    /// Builder: Enable or disable Aether Inspector.
150    pub fn with_inspector(mut self, enabled: bool) -> Self {
151        self.inspector_enabled = enabled;
152        self
153    }
154
155    /// Builder: Set Aether Inspector port.
156    pub fn with_inspector_port(mut self, port: u16) -> Self {
157        self.inspector_port = port;
158        self
159    }
160
161    /// Builder: Set maximum retries.
162    pub fn with_max_retries(mut self, retries: u32) -> Self {
163        self.max_retries = retries;
164        self
165    }
166
167    /// Builder: Set auto TOON threshold.
168    pub fn with_auto_toon_threshold(mut self, threshold: Option<usize>) -> Self {
169        self.auto_toon_threshold = threshold;
170        self
171    }
172
173    /// Check if TOON should be used for a given context length.
174    pub fn should_use_toon(&self, context_length: usize) -> bool {
175        if self.toon_enabled {
176            return true;
177        }
178        if let Some(threshold) = self.auto_toon_threshold {
179            return context_length >= threshold;
180        }
181        false
182    }
183
184    /// Create a recommended default cache for the engine.
185    /// Returns a `TieredCache` (Hybrid Exact + Semantic).
186    pub fn default_cache(&self) -> crate::Result<crate::cache::TieredCache> {
187        crate::cache::TieredCache::new()
188    }
189}
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194
195    #[test]
196    fn test_default_config() {
197        let config = AetherConfig::default();
198        assert!(!config.toon_enabled);
199        assert!(!config.healing_enabled);
200        assert!(config.parallel);
201        assert_eq!(config.max_retries, 2);
202    }
203
204    #[test]
205    fn test_builder_pattern() {
206        let config = AetherConfig::default()
207            .with_toon(true)
208            .with_healing(true)
209            .with_max_retries(5);
210
211        assert!(config.toon_enabled);
212        assert!(config.healing_enabled);
213        assert_eq!(config.max_retries, 5);
214    }
215
216    #[test]
217    fn test_auto_toon() {
218        let config = AetherConfig::default();
219        assert!(!config.should_use_toon(1000)); // Below threshold
220        assert!(config.should_use_toon(3000));  // Above threshold
221    }
222}