1use std::env;
7
8#[derive(Debug, Clone)]
23pub struct AetherConfig {
24 pub toon_enabled: bool,
28
29 pub healing_enabled: bool,
32
33 pub cache_enabled: bool,
36
37 pub parallel: bool,
40
41 pub inspector_enabled: bool,
44
45 pub inspector_port: u16,
48
49 pub max_retries: u32,
52
53 pub auto_toon_threshold: Option<usize>,
57
58 pub cache_threshold: f32,
62
63 pub prompt_toon_header: String,
65
66 pub prompt_toon_note: String,
68
69 pub prompt_healing_feedback: String,
71
72 pub prompt_tdd_notice: String,
74
75 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 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 pub fn with_toon(mut self, enabled: bool) -> Self {
164 self.toon_enabled = enabled;
165 self
166 }
167
168 pub fn with_healing(mut self, enabled: bool) -> Self {
170 self.healing_enabled = enabled;
171 self
172 }
173
174 pub fn with_cache(mut self, enabled: bool) -> Self {
176 self.cache_enabled = enabled;
177 self
178 }
179
180 pub fn with_parallel(mut self, enabled: bool) -> Self {
182 self.parallel = enabled;
183 self
184 }
185
186 pub fn with_inspector(mut self, enabled: bool) -> Self {
188 self.inspector_enabled = enabled;
189 self
190 }
191
192 pub fn with_inspector_port(mut self, port: u16) -> Self {
194 self.inspector_port = port;
195 self
196 }
197
198 pub fn with_max_retries(mut self, retries: u32) -> Self {
200 self.max_retries = retries;
201 self
202 }
203
204 pub fn with_auto_toon_threshold(mut self, threshold: Option<usize>) -> Self {
206 self.auto_toon_threshold = threshold;
207 self
208 }
209
210 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 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)); assert!(config.should_use_toon(3000)); }
259}