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    /// Prompt header for TOON context block.
64    pub prompt_toon_header: String,
65
66    /// Instructional note for the AI about TOON protocol.
67    pub prompt_toon_note: String,
68
69    /// Feedback prefix for self-healing retries.
70    pub prompt_healing_feedback: String,
71
72    /// Notice added when TDD mode is active.
73    pub prompt_tdd_notice: String,
74
75    /// Base delay for retry backoff in milliseconds.
76    pub retry_backoff_ms: u64,
77}
78
79impl Default for AetherConfig {
80    fn default() -> Self {
81        Self {
82            toon_enabled: false,
83            healing_enabled: false,
84            cache_enabled: false,
85            parallel: true,
86            inspector_enabled: false,
87            inspector_port: 3000,
88            max_retries: 2,
89            auto_toon_threshold: Some(2000),
90            cache_threshold: 0.90,
91            prompt_toon_header: "[CONTEXT:TOON]".to_string(),
92            prompt_toon_note: "[TOON Protocol Note]\nTOON is a compact key:value mapping protocol. Each line represents 'key: value'. Use this context to inform your code generation, respecting the framework, language, and architectural constraints defined within.".to_string(),
93            prompt_healing_feedback: "[SELF-HEALING FEEDBACK]\nYour previous output had validation errors. Please fix them and output ONLY the corrected code.\nERROR:\n".to_string(),
94            prompt_tdd_notice: "\n\nIMPORTANT: The system is running in TDD (Test-Driven Development) mode. Your code will be validated against compiler checks and functional tests. If possible, include unit tests in your response to help self-verify. If validation fails, you will receive feedback to fix the code.".to_string(),
95            retry_backoff_ms: 100,
96        }
97    }
98}
99
100impl AetherConfig {
101    /// Create a new config from environment variables.
102    /// Falls back to defaults for missing variables.
103    pub fn from_env() -> Self {
104        let mut config = Self::default();
105
106        if let Ok(v) = env::var("AETHER_TOON") {
107            config.toon_enabled = v.to_lowercase() == "true" || v == "1";
108        }
109        if let Ok(v) = env::var("AETHER_HEALING") {
110            config.healing_enabled = v.to_lowercase() == "true" || v == "1";
111        }
112        if let Ok(v) = env::var("AETHER_CACHE") {
113            config.cache_enabled = v.to_lowercase() == "true" || v == "1";
114        }
115        if let Ok(v) = env::var("AETHER_PARALLEL") {
116            config.parallel = v.to_lowercase() != "false" && v != "0";
117        }
118        if let Ok(v) = env::var("AETHER_INSPECT") {
119            config.inspector_enabled = v.to_lowercase() == "true" || v == "1";
120        }
121        if let Ok(v) = env::var("AETHER_INSPECT_PORT") {
122            if let Ok(n) = v.parse() {
123                config.inspector_port = n;
124            }
125        }
126        if let Ok(v) = env::var("AETHER_MAX_RETRIES") {
127            if let Ok(n) = v.parse() {
128                config.max_retries = n;
129            }
130        }
131        if let Ok(v) = env::var("AETHER_TOON_THRESHOLD") {
132            if let Ok(n) = v.parse() {
133                config.auto_toon_threshold = Some(n);
134            }
135        }
136        if let Ok(v) = env::var("AETHER_CACHE_THRESHOLD") {
137            if let Ok(n) = v.parse() {
138                config.cache_threshold = n;
139            }
140        }
141        if let Ok(v) = env::var("AETHER_PROMPT_TOON_HEADER") {
142            config.prompt_toon_header = v;
143        }
144        if let Ok(v) = env::var("AETHER_PROMPT_TOON_NOTE") {
145            config.prompt_toon_note = v;
146        }
147        if let Ok(v) = env::var("AETHER_PROMPT_HEALING_FEEDBACK") {
148            config.prompt_healing_feedback = v;
149        }
150        if let Ok(v) = env::var("AETHER_PROMPT_TDD_NOTICE") {
151            config.prompt_tdd_notice = v;
152        }
153        if let Ok(v) = env::var("AETHER_RETRY_BACKOFF") {
154            if let Ok(n) = v.parse() {
155                config.retry_backoff_ms = n;
156            }
157        }
158
159        config
160    }
161
162    /// Builder: Enable or disable TOON protocol.
163    pub fn with_toon(mut self, enabled: bool) -> Self {
164        self.toon_enabled = enabled;
165        self
166    }
167
168    /// Builder: Enable or disable Self-Healing.
169    pub fn with_healing(mut self, enabled: bool) -> Self {
170        self.healing_enabled = enabled;
171        self
172    }
173
174    /// Builder: Enable or disable Semantic Cache.
175    pub fn with_cache(mut self, enabled: bool) -> Self {
176        self.cache_enabled = enabled;
177        self
178    }
179
180    /// Builder: Enable or disable parallel generation.
181    pub fn with_parallel(mut self, enabled: bool) -> Self {
182        self.parallel = enabled;
183        self
184    }
185
186    /// Builder: Enable or disable Aether Inspector.
187    pub fn with_inspector(mut self, enabled: bool) -> Self {
188        self.inspector_enabled = enabled;
189        self
190    }
191
192    /// Builder: Set Aether Inspector port.
193    pub fn with_inspector_port(mut self, port: u16) -> Self {
194        self.inspector_port = port;
195        self
196    }
197
198    /// Builder: Set maximum retries.
199    pub fn with_max_retries(mut self, retries: u32) -> Self {
200        self.max_retries = retries;
201        self
202    }
203
204    /// Builder: Set auto TOON threshold.
205    pub fn with_auto_toon_threshold(mut self, threshold: Option<usize>) -> Self {
206        self.auto_toon_threshold = threshold;
207        self
208    }
209
210    /// Check if TOON should be used for a given context length.
211    pub fn should_use_toon(&self, context_length: usize) -> bool {
212        if self.toon_enabled {
213            return true;
214        }
215        if let Some(threshold) = self.auto_toon_threshold {
216            return context_length >= threshold;
217        }
218        false
219    }
220
221    /// Create a recommended default cache for the engine.
222    /// Returns a `TieredCache` (Hybrid Exact + Semantic).
223    pub fn default_cache(&self) -> crate::Result<crate::cache::TieredCache> {
224        crate::cache::TieredCache::new()
225    }
226}
227
228#[cfg(test)]
229mod tests {
230    use super::*;
231
232    #[test]
233    fn test_default_config() {
234        let config = AetherConfig::default();
235        assert!(!config.toon_enabled);
236        assert!(!config.healing_enabled);
237        assert!(config.parallel);
238        assert_eq!(config.max_retries, 2);
239    }
240
241    #[test]
242    fn test_builder_pattern() {
243        let config = AetherConfig::default()
244            .with_toon(true)
245            .with_healing(true)
246            .with_max_retries(5);
247
248        assert!(config.toon_enabled);
249        assert!(config.healing_enabled);
250        assert_eq!(config.max_retries, 5);
251    }
252
253    #[test]
254    fn test_auto_toon() {
255        let config = AetherConfig::default();
256        assert!(!config.should_use_toon(1000)); // Below threshold
257        assert!(config.should_use_toon(3000));  // Above threshold
258    }
259}