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 #[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), }
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}