doum_cli/cli/
config.rs

1use crate::cli::args::ConfigAction;
2use crate::system::{get_config_path, load_config, load_default_config, save_config};
3use anyhow::Result;
4use std::{fmt::Display, str::FromStr};
5
6pub fn handle_config_command(action: Option<ConfigAction>) -> Result<()> {
7    let action = action.unwrap_or(ConfigAction::Show);
8
9    match action {
10        ConfigAction::Show => {
11            let config_path = get_config_path()?;
12            let config = load_config()?;
13            let toml_str = toml::to_string_pretty(&config)
14                .map_err(|e| anyhow::anyhow!("Failed to serialize config to TOML: {}", e))?;
15            println!("Config file location: {}\n", config_path.display());
16            println!("{}", toml_str);
17            Ok(())
18        }
19        ConfigAction::Reset => {
20            let default_config = load_default_config()?;
21            save_config(&default_config)?;
22            println!("✅ Configuration reset to default");
23            Ok(())
24        }
25        ConfigAction::Set { key, value } => {
26            set_value(&key, &value)?;
27            println!("✅ Config {} = {}", key, value);
28            Ok(())
29        }
30        ConfigAction::Get { key } => {
31            let value = get_value(&key)?;
32            println!("{}", value);
33            Ok(())
34        }
35        ConfigAction::Unset { key } => {
36            unset_value(&key)?;
37            println!("✅ Config {} reset to default", key);
38            Ok(())
39        }
40    }
41}
42
43fn get_value(key: &str) -> Result<String> {
44    let config = load_config()?;
45
46    let value = match key {
47        "llm.provider" => config.llm.provider.as_str().to_string(),
48        "llm.model" => config.llm.model,
49        "llm.timeout" => config.llm.timeout.to_string(),
50        "llm.use_thinking" => config.llm.use_thinking.to_string(),
51        "llm.use_web_search" => config.llm.use_web_search.to_string(),
52        "context.max_lines" => config.context.max_lines.to_string(),
53        "context.max_size_kb" => config.context.max_size_kb.to_string(),
54        "logging.enabled" => config.logging.enabled.to_string(),
55        "logging.level" => config.logging.level,
56        _ => anyhow::bail!("Unknown config key: {}", key),
57    };
58
59    Ok(value)
60}
61
62fn set_value(key: &str, value: &str) -> Result<()> {
63    let mut config = load_config()?;
64
65    match key {
66        "llm.provider" => {
67            config.llm.provider = value.parse()?;
68        }
69        "llm.model" => {
70            config.llm.model = value.to_string();
71        }
72        "llm.timeout" => {
73            config.llm.timeout = parse_value(value, "timeout")?;
74        }
75        "llm.use_thinking" => {
76            config.llm.use_thinking = parse_value(value, "use_thinking")?;
77        }
78        "llm.use_web_search" => {
79            config.llm.use_web_search = parse_value(value, "use_web_search")?;
80        }
81        "context.max_lines" => {
82            config.context.max_lines = parse_value(value, "max_lines")?;
83        }
84        "context.max_size_kb" => {
85            config.context.max_size_kb = parse_value(value, "max_size_kb")?;
86        }
87        "logging.enabled" => {
88            config.logging.enabled = parse_value(value, "logging.enabled")?;
89        }
90        "logging.level" => {
91            config.logging.level = value.to_string();
92        }
93        _ => anyhow::bail!("Unknown config key: {}", key),
94    }
95
96    save_config(&config)?;
97    Ok(())
98}
99
100fn unset_value(key: &str) -> Result<()> {
101    let default_config = load_default_config()?;
102    let mut config = load_config()?;
103
104    match key {
105        "llm.provider" => config.llm.provider = default_config.llm.provider,
106        "llm.model" => config.llm.model = default_config.llm.model,
107        "llm.timeout" => config.llm.timeout = default_config.llm.timeout,
108        "llm.use_thinking" => config.llm.use_thinking = default_config.llm.use_thinking,
109        "llm.use_web_search" => config.llm.use_web_search = default_config.llm.use_web_search,
110        "context.max_lines" => config.context.max_lines = default_config.context.max_lines,
111        "context.max_size_kb" => config.context.max_size_kb = default_config.context.max_size_kb,
112        "logging.enabled" => config.logging.enabled = default_config.logging.enabled,
113        "logging.level" => config.logging.level = default_config.logging.level,
114        _ => anyhow::bail!("Unknown config key: {}", key),
115    }
116
117    save_config(&config)?;
118    Ok(())
119}
120
121fn parse_value<T: FromStr>(value: &str, field_name: &str) -> Result<T>
122where
123    T::Err: Display,
124{
125    value
126        .parse()
127        .map_err(|e| anyhow::anyhow!("Invalid {} value: {} - {}", field_name, value, e))
128}