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 {
76 name: String,
77 schema: Value,
78 },
79}
80
81impl ResponseFormat {
82 pub fn to_api_value(&self) -> Value {
83 match self {
84 ResponseFormat::JsonObject => {
85 serde_json::json!({ "type": "json_object" })
86 }
87 ResponseFormat::JsonSchema { name, schema } => {
88 serde_json::json!({
89 "type": "json_schema",
90 "json_schema": {
91 "name": name,
92 "schema": schema,
93 }
94 })
95 }
96 }
97 }
98}
99
100use crate::llm::ReasoningConfig;
101
102#[derive(Clone, Debug)]
107pub struct SafetyConfig {
108 pub max_tool_calls_per_turn: usize,
112
113 pub max_consecutive_failures: usize,
116}
117
118impl Default for SafetyConfig {
119 fn default() -> Self {
120 Self {
121 max_tool_calls_per_turn: 128,
122 max_consecutive_failures: 3,
123 }
124 }
125}
126
127#[derive(Clone, Debug)]
128pub struct AgentConfig {
129 pub system_prompt: Option<String>,
130 pub enable_thought: bool,
142 pub reasoning: Option<ReasoningConfig>,
148 pub language: Language,
149 pub execution: ExecutionConfig,
150 pub llm: LlmConfig,
151 pub tool: ToolConfig,
152 pub session: SessionConfig,
153 pub safety: SafetyConfig,
154}
155
156impl Default for AgentConfig {
157 fn default() -> Self {
158 Self {
159 system_prompt: None,
160 enable_thought: false,
161 reasoning: None,
162 language: Language::default(),
163 execution: ExecutionConfig::default(),
164 llm: LlmConfig::default(),
165 tool: ToolConfig::default(),
166 session: SessionConfig::default(),
167 safety: SafetyConfig::default(),
168 }
169 }
170}
171
172impl AgentConfig {
173
174 pub fn validate(&self) -> crate::types::AgentResult<()> {
176 use crate::types::AgentError;
177
178 if let Some(max_turns) = self.execution.max_turns {
179 if max_turns == 0 {
180 return Err(AgentError::config_error(
181 "execution.max_turns must be > 0".to_string(),
182 ));
183 }
184 }
185
186 if let Some(max_sessions) = self.session.max_sessions {
187 if max_sessions == 0 {
188 return Err(AgentError::config_error(
189 "session.max_sessions must be > 0".to_string(),
190 ));
191 }
192 }
193
194 if let Some(tool_timeout_ms) = self.tool.tool_timeout_ms {
195 if tool_timeout_ms == 0 {
196 return Err(AgentError::config_error(
197 "tool.tool_timeout_ms must be > 0".to_string(),
198 ));
199 }
200 }
201
202 if self.safety.max_tool_calls_per_turn == 0 {
203 return Err(AgentError::config_error(
204 "safety.max_tool_calls_per_turn must be > 0".to_string(),
205 ));
206 }
207
208 Ok(())
209 }
210}
211
212#[derive(Clone, Debug)]
213pub struct ExecutionConfig {
214 pub max_turns: Option<u32>,
215 pub approval_timeout_ms: Option<u64>,
216 pub fail_on_persist_error: bool,
217}
218
219impl Default for ExecutionConfig {
220 fn default() -> Self {
221 Self {
222 max_turns: None,
223 approval_timeout_ms: None,
224 fail_on_persist_error: false,
225 }
226 }
227}
228
229#[derive(Clone, Debug)]
230pub struct LlmConfig {
231 pub response_format: Option<ResponseFormat>,
232 pub llm_retry: Option<RetryConfig>,
233}
234
235impl Default for LlmConfig {
236 fn default() -> Self {
237 Self {
238 response_format: None,
239 llm_retry: None,
240 }
241 }
242}
243
244#[derive(Clone, Debug)]
245pub struct ToolConfig {
246 pub tool_timeout_ms: Option<u64>,
247 pub max_tool_output_chars: Option<usize>,
248 pub tool_error_retry_prompt: Option<String>,
249}
250
251impl Default for ToolConfig {
252 fn default() -> Self {
253 Self {
254 tool_timeout_ms: None,
255 max_tool_output_chars: None,
256 tool_error_retry_prompt: None,
257 }
258 }
259}
260
261#[derive(Clone, Debug)]
262pub struct SessionConfig {
263 pub max_sessions: Option<usize>,
266
267 pub max_turns_per_session: Option<usize>,
270
271 pub max_message_tokens: Option<usize>,
275}
276
277impl Default for SessionConfig {
278 fn default() -> Self {
279 Self {
280 max_sessions: None,
281 max_turns_per_session: None,
282 max_message_tokens: None,
283 }
284 }
285}