clau_core/
config.rs

1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct Config {
6    #[serde(skip_serializing_if = "Option::is_none")]
7    pub system_prompt: Option<String>,
8    
9    #[serde(skip_serializing_if = "Option::is_none")]
10    pub model: Option<String>,
11    
12    
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub mcp_config_path: Option<PathBuf>,
15    
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub allowed_tools: Option<Vec<String>>,
18    
19    #[serde(default)]
20    pub stream_format: StreamFormat,
21    
22    #[serde(default)]
23    pub non_interactive: bool,
24    
25    #[serde(default)]
26    pub verbose: bool,
27    
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub max_tokens: Option<usize>,
30    
31    /// Timeout in seconds for Claude CLI execution (default: 30s)
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub timeout_secs: Option<u64>,
34}
35
36#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq)]
37#[serde(rename_all = "lowercase")]
38pub enum StreamFormat {
39    #[default]
40    Text,
41    Json,
42    StreamJson,
43}
44
45impl Default for Config {
46    fn default() -> Self {
47        Self {
48            system_prompt: None,
49            model: None,
50            mcp_config_path: None,
51            allowed_tools: None,
52            stream_format: StreamFormat::default(),
53            non_interactive: true,
54            verbose: false,
55            max_tokens: None,
56            timeout_secs: Some(30), // Default 30 second timeout
57        }
58    }
59}
60
61impl Config {
62    pub fn builder() -> ConfigBuilder {
63        ConfigBuilder::new()
64    }
65}
66
67pub struct ConfigBuilder {
68    config: Config,
69}
70
71impl ConfigBuilder {
72    pub fn new() -> Self {
73        Self {
74            config: Config::default(),
75        }
76    }
77    
78    pub fn system_prompt(mut self, prompt: impl Into<String>) -> Self {
79        self.config.system_prompt = Some(prompt.into());
80        self
81    }
82    
83    pub fn model(mut self, model: impl Into<String>) -> Self {
84        self.config.model = Some(model.into());
85        self
86    }
87    
88    
89    pub fn mcp_config(mut self, path: impl Into<PathBuf>) -> Self {
90        self.config.mcp_config_path = Some(path.into());
91        self
92    }
93    
94    pub fn allowed_tools(mut self, tools: Vec<String>) -> Self {
95        self.config.allowed_tools = Some(tools);
96        self
97    }
98    
99    pub fn stream_format(mut self, format: StreamFormat) -> Self {
100        self.config.stream_format = format;
101        self
102    }
103    
104    pub fn non_interactive(mut self, non_interactive: bool) -> Self {
105        self.config.non_interactive = non_interactive;
106        self
107    }
108    
109    pub fn max_tokens(mut self, max_tokens: usize) -> Self {
110        self.config.max_tokens = Some(max_tokens);
111        self
112    }
113    
114    pub fn timeout_secs(mut self, timeout_secs: u64) -> Self {
115        self.config.timeout_secs = Some(timeout_secs);
116        self
117    }
118    
119    pub fn build(self) -> Config {
120        self.config
121    }
122}