1use serde::{Deserialize, Serialize};
5use std::path::PathBuf;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, clap::ValueEnum)]
9#[serde(rename_all = "lowercase")]
10pub enum ExecutionMode {
11 #[default]
13 Normal,
14 AutoEdit,
16 Yolo,
18 Daemon,
20}
21
22impl std::fmt::Display for ExecutionMode {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 ExecutionMode::Normal => write!(f, "normal"),
26 ExecutionMode::AutoEdit => write!(f, "auto-edit"),
27 ExecutionMode::Yolo => write!(f, "yolo"),
28 ExecutionMode::Daemon => write!(f, "daemon"),
29 }
30 }
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct UiConfig {
36 #[serde(default = "default_theme")]
38 pub theme: String,
39 #[serde(default = "default_true")]
41 pub animations: bool,
42 #[serde(default)]
44 pub compact_mode: bool,
45 #[serde(default)]
47 pub verbose_mode: bool,
48 #[serde(default = "default_true")]
52 pub allow_clarification: bool,
53 #[serde(default)]
55 pub show_tokens: bool,
56 #[serde(default = "default_animation_speed")]
58 pub animation_speed: f64,
59}
60
61impl Default for UiConfig {
62 fn default() -> Self {
63 Self {
64 theme: default_theme(),
65 animations: true,
66 compact_mode: false,
67 verbose_mode: false,
68 allow_clarification: true,
69 show_tokens: false,
70 animation_speed: 1.0,
71 }
72 }
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct ContinuousWorkConfig {
78 #[serde(default = "default_true")]
80 pub enabled: bool,
81 #[serde(default = "default_checkpoint_interval_tools")]
83 pub checkpoint_interval_tools: usize,
84 #[serde(default = "default_checkpoint_interval_secs")]
86 pub checkpoint_interval_secs: u64,
87 #[serde(default = "default_true")]
89 pub auto_recovery: bool,
90 #[serde(default = "default_max_recovery_attempts")]
92 pub max_recovery_attempts: u32,
93}
94
95impl Default for ContinuousWorkConfig {
96 fn default() -> Self {
97 Self {
98 enabled: true,
99 checkpoint_interval_tools: default_checkpoint_interval_tools(),
100 checkpoint_interval_secs: default_checkpoint_interval_secs(),
101 auto_recovery: true,
102 max_recovery_attempts: default_max_recovery_attempts(),
103 }
104 }
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct RetrySettings {
110 #[serde(default = "default_retry_max_retries")]
112 pub max_retries: u32,
113 #[serde(default = "default_retry_base_delay_ms")]
115 pub base_delay_ms: u64,
116 #[serde(default = "default_retry_max_delay_ms")]
118 pub max_delay_ms: u64,
119}
120
121impl Default for RetrySettings {
122 fn default() -> Self {
123 Self {
124 max_retries: default_retry_max_retries(),
125 base_delay_ms: default_retry_base_delay_ms(),
126 max_delay_ms: default_retry_max_delay_ms(),
127 }
128 }
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct YoloFileConfig {
134 #[serde(default)]
136 pub enabled: bool,
137 #[serde(default)]
139 pub max_operations: usize,
140 #[serde(default)]
142 pub max_hours: f64,
143 #[serde(default = "default_true")]
145 pub allow_git_push: bool,
146 #[serde(default)]
148 pub allow_destructive_shell: bool,
149 #[serde(default)]
151 pub audit_log_path: Option<PathBuf>,
152 #[serde(default = "default_status_interval")]
154 pub status_interval: usize,
155}
156
157impl Default for YoloFileConfig {
158 fn default() -> Self {
159 Self {
160 enabled: false,
161 max_operations: 0,
162 max_hours: 0.0,
163 allow_git_push: true,
164 allow_destructive_shell: false,
165 audit_log_path: None,
166 status_interval: 100,
167 }
168 }
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173#[serde(deny_unknown_fields)]
174pub struct ConcurrencyConfig {
175 #[serde(default = "default_max_streams")]
177 pub max_streams: usize,
178 #[serde(default = "default_max_tools")]
180 pub max_tools: usize,
181 #[serde(default = "default_max_global")]
183 pub max_global: usize,
184}
185
186impl ConcurrencyConfig {
187 pub fn validate(&self) -> anyhow::Result<()> {
189 for (name, value) in [
190 ("max_streams", self.max_streams),
191 ("max_tools", self.max_tools),
192 ("max_global", self.max_global),
193 ] {
194 if value < 1 {
195 anyhow::bail!(
196 "Config error: concurrency.{} must be >= 1, got {}",
197 name,
198 value
199 );
200 }
201 if value > 256 {
202 anyhow::bail!(
203 "Config error: concurrency.{} must be <= 256, got {}",
204 name,
205 value
206 );
207 }
208 }
209 Ok(())
210 }
211}
212
213impl Default for ConcurrencyConfig {
214 fn default() -> Self {
215 Self {
216 max_streams: default_max_streams(),
217 max_tools: default_max_tools(),
218 max_global: default_max_global(),
219 }
220 }
221}
222
223#[derive(Debug, Clone, Default, Serialize, Deserialize)]
225pub struct EvolutionTomlConfig {
226 #[serde(default)]
229 pub hypothesis_model: Option<String>,
230 #[serde(default)]
232 pub prompt_logic: Vec<String>,
233 #[serde(default)]
235 pub tool_code: Vec<String>,
236 #[serde(default)]
238 pub cognitive: Vec<String>,
239 #[serde(default)]
241 pub config_keys: Vec<String>,
242}
243
244pub(crate) fn default_true() -> bool {
247 true
248}
249pub(crate) fn default_status_interval() -> usize {
250 100
251}
252pub(crate) fn default_theme() -> String {
253 "amber".to_string()
254}
255pub(crate) fn default_animation_speed() -> f64 {
256 1.0
257}
258pub(crate) fn default_checkpoint_interval_tools() -> usize {
259 10
260}
261pub(crate) fn default_checkpoint_interval_secs() -> u64 {
262 300
263}
264pub(crate) fn default_max_recovery_attempts() -> u32 {
265 3
266}
267pub(crate) fn default_retry_max_retries() -> u32 {
268 5
269}
270pub(crate) fn default_retry_base_delay_ms() -> u64 {
271 1000
272}
273pub(crate) fn default_retry_max_delay_ms() -> u64 {
274 60000
275}
276pub(crate) fn default_max_streams() -> usize {
277 4
278}
279pub(crate) fn default_max_tools() -> usize {
280 8
281}
282pub(crate) fn default_max_global() -> usize {
283 12
284}
285
286#[cfg(test)]
287#[path = "../../tests/unit/config/types/types_test.rs"]
288mod tests;