use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, clap::ValueEnum)]
#[serde(rename_all = "lowercase")]
pub enum ExecutionMode {
#[default]
Normal,
AutoEdit,
Yolo,
Daemon,
}
impl std::fmt::Display for ExecutionMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ExecutionMode::Normal => write!(f, "normal"),
ExecutionMode::AutoEdit => write!(f, "auto-edit"),
ExecutionMode::Yolo => write!(f, "yolo"),
ExecutionMode::Daemon => write!(f, "daemon"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UiConfig {
#[serde(default = "default_theme")]
pub theme: String,
#[serde(default = "default_true")]
pub animations: bool,
#[serde(default)]
pub compact_mode: bool,
#[serde(default)]
pub verbose_mode: bool,
#[serde(default = "default_true")]
pub allow_clarification: bool,
#[serde(default)]
pub show_tokens: bool,
#[serde(default = "default_animation_speed")]
pub animation_speed: f64,
}
impl Default for UiConfig {
fn default() -> Self {
Self {
theme: default_theme(),
animations: true,
compact_mode: false,
verbose_mode: false,
allow_clarification: true,
show_tokens: false,
animation_speed: 1.0,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContinuousWorkConfig {
#[serde(default = "default_true")]
pub enabled: bool,
#[serde(default = "default_checkpoint_interval_tools")]
pub checkpoint_interval_tools: usize,
#[serde(default = "default_checkpoint_interval_secs")]
pub checkpoint_interval_secs: u64,
#[serde(default = "default_true")]
pub auto_recovery: bool,
#[serde(default = "default_max_recovery_attempts")]
pub max_recovery_attempts: u32,
}
impl Default for ContinuousWorkConfig {
fn default() -> Self {
Self {
enabled: true,
checkpoint_interval_tools: default_checkpoint_interval_tools(),
checkpoint_interval_secs: default_checkpoint_interval_secs(),
auto_recovery: true,
max_recovery_attempts: default_max_recovery_attempts(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RetrySettings {
#[serde(default = "default_retry_max_retries")]
pub max_retries: u32,
#[serde(default = "default_retry_base_delay_ms")]
pub base_delay_ms: u64,
#[serde(default = "default_retry_max_delay_ms")]
pub max_delay_ms: u64,
}
impl Default for RetrySettings {
fn default() -> Self {
Self {
max_retries: default_retry_max_retries(),
base_delay_ms: default_retry_base_delay_ms(),
max_delay_ms: default_retry_max_delay_ms(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct YoloFileConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default)]
pub max_operations: usize,
#[serde(default)]
pub max_hours: f64,
#[serde(default = "default_true")]
pub allow_git_push: bool,
#[serde(default)]
pub allow_destructive_shell: bool,
#[serde(default)]
pub audit_log_path: Option<PathBuf>,
#[serde(default = "default_status_interval")]
pub status_interval: usize,
}
impl Default for YoloFileConfig {
fn default() -> Self {
Self {
enabled: false,
max_operations: 0,
max_hours: 0.0,
allow_git_push: true,
allow_destructive_shell: false,
audit_log_path: None,
status_interval: 100,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConcurrencyConfig {
#[serde(default = "default_max_streams")]
pub max_streams: usize,
#[serde(default = "default_max_tools")]
pub max_tools: usize,
#[serde(default = "default_max_global")]
pub max_global: usize,
}
impl ConcurrencyConfig {
pub fn validate(&self) -> anyhow::Result<()> {
for (name, value) in [
("max_streams", self.max_streams),
("max_tools", self.max_tools),
("max_global", self.max_global),
] {
if value < 1 {
anyhow::bail!(
"Config error: concurrency.{} must be >= 1, got {}",
name,
value
);
}
if value > 256 {
anyhow::bail!(
"Config error: concurrency.{} must be <= 256, got {}",
name,
value
);
}
}
Ok(())
}
}
impl Default for ConcurrencyConfig {
fn default() -> Self {
Self {
max_streams: default_max_streams(),
max_tools: default_max_tools(),
max_global: default_max_global(),
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EvolutionTomlConfig {
#[serde(default)]
pub hypothesis_model: Option<String>,
#[serde(default)]
pub prompt_logic: Vec<String>,
#[serde(default)]
pub tool_code: Vec<String>,
#[serde(default)]
pub cognitive: Vec<String>,
#[serde(default)]
pub config_keys: Vec<String>,
}
pub(crate) fn default_true() -> bool {
true
}
pub(crate) fn default_status_interval() -> usize {
100
}
pub(crate) fn default_theme() -> String {
"amber".to_string()
}
pub(crate) fn default_animation_speed() -> f64 {
1.0
}
pub(crate) fn default_checkpoint_interval_tools() -> usize {
10
}
pub(crate) fn default_checkpoint_interval_secs() -> u64 {
300
}
pub(crate) fn default_max_recovery_attempts() -> u32 {
3
}
pub(crate) fn default_retry_max_retries() -> u32 {
5
}
pub(crate) fn default_retry_base_delay_ms() -> u64 {
1000
}
pub(crate) fn default_retry_max_delay_ms() -> u64 {
60000
}
pub(crate) fn default_max_streams() -> usize {
4
}
pub(crate) fn default_max_tools() -> usize {
8
}
pub(crate) fn default_max_global() -> usize {
12
}
#[cfg(test)]
#[path = "../../tests/unit/config/types/types_test.rs"]
mod tests;