1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
5pub enum Language {
6 En,
7 Zh,
8}
9
10impl Default for Language {
11 fn default() -> Self {
12 Language::En
13 }
14}
15
16impl std::fmt::Display for Language {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 Language::En => write!(f, "en"),
20 Language::Zh => write!(f, "zh"),
21 }
22 }
23}
24
25#[derive(Clone, Debug)]
26pub struct RetryConfig {
27 pub max_retries: u32,
28 pub initial_backoff_ms: u64,
29 pub max_backoff_ms: u64,
30 pub backoff_multiplier: f64,
31 pub jitter: bool,
32}
33
34impl Default for RetryConfig {
35 fn default() -> Self {
36 Self {
37 max_retries: 3,
38 initial_backoff_ms: 500,
39 max_backoff_ms: 10_000,
40 backoff_multiplier: 2.0,
41 jitter: true,
42 }
43 }
44}
45
46impl RetryConfig {
47 pub fn new() -> Self {
48 Self::default()
49 }
50
51 pub fn max_retries(mut self, n: u32) -> Self {
52 self.max_retries = n;
53 self
54 }
55
56 pub fn initial_backoff_ms(mut self, ms: u64) -> Self {
57 self.initial_backoff_ms = ms;
58 self
59 }
60
61 pub fn max_backoff_ms(mut self, ms: u64) -> Self {
62 self.max_backoff_ms = ms;
63 self
64 }
65
66 pub fn no_jitter(mut self) -> Self {
67 self.jitter = false;
68 self
69 }
70}
71
72#[derive(Clone, Debug)]
73pub enum ResponseFormat {
74 JsonObject,
75 JsonSchema { name: String, schema: Value },
76}
77
78impl ResponseFormat {
79 pub fn to_api_value(&self) -> Value {
80 match self {
81 ResponseFormat::JsonObject => {
82 serde_json::json!({ "type": "json_object" })
83 }
84 ResponseFormat::JsonSchema { name, schema } => {
85 serde_json::json!({
86 "type": "json_schema",
87 "json_schema": {
88 "name": name,
89 "schema": schema,
90 }
91 })
92 }
93 }
94 }
95}
96
97use crate::llm::ReasoningConfig;
98
99#[derive(Clone, Debug)]
104pub struct SafetyConfig {
105 pub max_tool_calls_per_turn: usize,
109
110 pub max_consecutive_failures: usize,
113}
114
115impl Default for SafetyConfig {
116 fn default() -> Self {
117 Self {
118 max_tool_calls_per_turn: 128,
119 max_consecutive_failures: 3,
120 }
121 }
122}
123
124#[derive(Clone, Debug)]
125pub struct AgentConfig {
126 pub system_prompt: Option<String>,
127 pub enable_thought: bool,
139 pub reasoning: Option<ReasoningConfig>,
145 pub language: Language,
146 pub execution: ExecutionConfig,
147 pub llm: LlmConfig,
148 pub tool: ToolConfig,
149 pub session: SessionConfig,
150 pub safety: SafetyConfig,
151}
152
153impl Default for AgentConfig {
154 fn default() -> Self {
155 Self {
156 system_prompt: None,
157 enable_thought: false,
158 reasoning: None,
159 language: Language::default(),
160 execution: ExecutionConfig::default(),
161 llm: LlmConfig::default(),
162 tool: ToolConfig::default(),
163 session: SessionConfig::default(),
164 safety: SafetyConfig::default(),
165 }
166 }
167}
168
169impl AgentConfig {
170 pub fn validate(&self) -> crate::types::AgentResult<()> {
172 use crate::types::AgentError;
173
174 if let Some(max_turns) = self.execution.max_turns {
175 if max_turns == 0 {
176 return Err(AgentError::config_error(
177 "execution.max_turns must be > 0".to_string(),
178 ));
179 }
180 }
181
182 if let Some(max_sessions) = self.session.max_sessions {
183 if max_sessions == 0 {
184 return Err(AgentError::config_error(
185 "session.max_sessions must be > 0".to_string(),
186 ));
187 }
188 }
189
190 if let Some(tool_timeout_ms) = self.tool.tool_timeout_ms {
191 if tool_timeout_ms == 0 {
192 return Err(AgentError::config_error(
193 "tool.tool_timeout_ms must be > 0".to_string(),
194 ));
195 }
196 }
197
198 if self.safety.max_tool_calls_per_turn == 0 {
199 return Err(AgentError::config_error(
200 "safety.max_tool_calls_per_turn must be > 0".to_string(),
201 ));
202 }
203
204 Ok(())
205 }
206}
207
208#[derive(Clone, Debug)]
209pub struct ExecutionConfig {
210 pub max_turns: Option<u32>,
211 pub approval_timeout_ms: Option<u64>,
212 pub fail_on_persist_error: bool,
213}
214
215impl Default for ExecutionConfig {
216 fn default() -> Self {
217 Self {
218 max_turns: None,
219 approval_timeout_ms: None,
220 fail_on_persist_error: false,
221 }
222 }
223}
224
225#[derive(Clone, Debug)]
226pub struct LlmConfig {
227 pub response_format: Option<ResponseFormat>,
228 pub llm_retry: Option<RetryConfig>,
229}
230
231impl Default for LlmConfig {
232 fn default() -> Self {
233 Self {
234 response_format: None,
235 llm_retry: None,
236 }
237 }
238}
239
240#[derive(Clone, Debug)]
241pub struct ToolConfig {
242 pub tool_timeout_ms: Option<u64>,
243 pub max_tool_output_chars: Option<usize>,
244 pub tool_error_retry_prompt: Option<String>,
245}
246
247impl Default for ToolConfig {
248 fn default() -> Self {
249 Self {
250 tool_timeout_ms: None,
251 max_tool_output_chars: None,
252 tool_error_retry_prompt: None,
253 }
254 }
255}
256
257#[derive(Clone, Debug)]
258pub struct SessionConfig {
259 pub max_sessions: Option<usize>,
262
263 pub max_turns_per_session: Option<usize>,
266
267 pub max_message_tokens: Option<usize>,
271}
272
273impl Default for SessionConfig {
274 fn default() -> Self {
275 Self {
276 max_sessions: None,
277 max_turns_per_session: None,
278 max_message_tokens: None,
279 }
280 }
281}