1use crate::system::{get_config_path, load_config, load_default_config, save_config};
2use anyhow::Result;
3
4pub struct ConfigManager;
5
6impl ConfigManager {
7 pub fn get_value(key: &str) -> Result<String> {
9 let config = load_config()?;
10
11 let value = match key {
12 "llm.provider" => config.llm.provider,
13 "llm.model" => config.llm.model,
14 "llm.timeout" => config.llm.timeout.to_string(),
15 "llm.max_retries" => config.llm.max_retries.to_string(),
16 "llm.use_thinking" => config.llm.use_thinking.to_string(),
17 "llm.use_web_search" => config.llm.use_web_search.to_string(),
18 "context.max_lines" => config.context.max_lines.to_string(),
19 "context.max_size_kb" => config.context.max_size_kb.to_string(),
20 "logging.enabled" => config.logging.enabled.to_string(),
21 "logging.level" => config.logging.level,
22 _ => {
23 anyhow::bail!("Unknown config key: {}", key);
24 }
25 };
26
27 Ok(value)
28 }
29
30 pub fn set_value(key: &str, value: &str) -> Result<()> {
32 let mut config = load_config()?;
33
34 match key {
35 "llm.provider" => {
36 Self::validate_provider(value)?;
37 config.llm.provider = value.to_string();
38 }
39 "llm.model" => {
40 config.llm.model = value.to_string();
41 }
42 "llm.timeout" => {
43 config.llm.timeout = Self::parse_value(value, "timeout")?;
44 }
45 "llm.max_retries" => {
46 config.llm.max_retries = Self::parse_value(value, "max_retries")?;
47 }
48 "llm.use_thinking" => {
49 config.llm.use_thinking = Self::parse_value(value, "use_thinking")?;
50 }
51 "llm.use_web_search" => {
52 config.llm.use_web_search = Self::parse_value(value, "use_web_search")?;
53 }
54 "context.max_lines" => {
55 config.context.max_lines = Self::parse_value(value, "max_lines")?;
56 }
57 "context.max_size_kb" => {
58 config.context.max_size_kb = Self::parse_value(value, "max_size_kb")?;
59 }
60 "logging.enabled" => {
61 config.logging.enabled = Self::parse_value(value, "logging.enabled")?;
62 }
63 "logging.level" => {
64 config.logging.level = value.to_string();
65 }
66 _ => {
67 anyhow::bail!("Unknown config key: {}", key);
68 }
69 }
70
71 save_config(&config)?;
72 Ok(())
73 }
74
75 pub fn reset() -> Result<()> {
77 let default_config = load_default_config()?;
78 save_config(&default_config)
79 }
80
81 pub fn unset_value(key: &str) -> Result<()> {
83 let default_config = load_default_config()?;
84 let mut config = load_config()?;
85
86 match key {
87 "llm.provider" => config.llm.provider = default_config.llm.provider,
88 "llm.model" => config.llm.model = default_config.llm.model,
89 "llm.timeout" => config.llm.timeout = default_config.llm.timeout,
90 "llm.max_retries" => config.llm.max_retries = default_config.llm.max_retries,
91 "llm.use_thinking" => config.llm.use_thinking = default_config.llm.use_thinking,
92 "llm.use_web_search" => config.llm.use_web_search = default_config.llm.use_web_search,
93 "context.max_lines" => config.context.max_lines = default_config.context.max_lines,
94 "context.max_size_kb" => {
95 config.context.max_size_kb = default_config.context.max_size_kb
96 }
97 "logging.enabled" => config.logging.enabled = default_config.logging.enabled,
98 "logging.level" => config.logging.level = default_config.logging.level,
99 _ => {
100 anyhow::bail!("Unknown config key: {}", key);
101 }
102 }
103
104 save_config(&config)?;
105 Ok(())
106 }
107
108 pub fn get_all_as_toml() -> Result<String> {
110 let config = load_config()?;
111 toml::to_string_pretty(&config)
112 .map_err(|e| anyhow::anyhow!("Failed to serialize config to TOML: {}", e))
113 }
114
115 pub fn get_config_path() -> Result<std::path::PathBuf> {
117 get_config_path()
118 }
119
120 fn validate_provider(provider: &str) -> Result<()> {
122 if provider != "openai" && provider != "anthropic" {
123 anyhow::bail!(
124 "Invalid provider: {}. Available: openai, anthropic",
125 provider
126 );
127 }
128 Ok(())
129 }
130
131 fn parse_value<T: std::str::FromStr>(value: &str, field_name: &str) -> Result<T>
132 where
133 T::Err: std::fmt::Display,
134 {
135 value
136 .parse()
137 .map_err(|e| anyhow::anyhow!("Invalid {} value: {} - {}", field_name, value, e))
138 }
139}