1use oxi_ai::CompactionStrategy;
3use serde::{Deserialize, Serialize};
4use std::sync::Arc;
5
6fn default_context_window() -> usize {
7 128_000
8}
9
10#[derive(Debug, Clone)]
12pub struct ShouldStopAfterTurnContext {
13 pub message: oxi_ai::AssistantMessage,
15 pub tool_results: Vec<oxi_ai::ToolResultMessage>,
17 pub iteration: usize,
19}
20
21#[derive(Debug, Clone, Default)]
23pub struct BeforeToolCallResult {
24 pub block: bool,
26 pub reason: Option<String>,
28}
29
30#[derive(Debug, Clone, Default)]
32pub struct AfterToolCallResult {
33 pub content: Option<String>,
35 pub is_error: Option<bool>,
37 pub terminate: Option<bool>,
39}
40
41#[derive(Debug, Clone)]
43pub struct BeforeToolCallContext {
44 pub tool_call_id: String,
46 pub tool_name: String,
48 pub args: serde_json::Value,
50}
51
52#[derive(Debug, Clone)]
54pub struct AfterToolCallContext {
55 pub tool_call_id: String,
57 pub tool_name: String,
59 pub result: String,
61 pub is_error: bool,
63}
64
65#[derive(Default)]
70#[allow(clippy::type_complexity)]
71pub struct AgentHooks {
72 pub should_stop_after_turn:
77 Option<Arc<dyn Fn(&ShouldStopAfterTurnContext) -> bool + Send + Sync>>,
78
79 #[allow(clippy::type_complexity)]
82 pub before_tool_call:
83 Option<Box<dyn Fn(&BeforeToolCallContext) -> BeforeToolCallResult + Send + Sync>>,
84
85 #[allow(clippy::type_complexity)]
87 pub after_tool_call:
88 Option<Box<dyn Fn(&AfterToolCallContext) -> AfterToolCallResult + Send + Sync>>,
89
90 #[allow(clippy::type_complexity)]
93 pub get_steering_messages: Option<Box<dyn Fn() -> Vec<String> + Send + Sync>>,
94
95 #[allow(clippy::type_complexity)]
98 pub get_follow_up_messages: Option<Box<dyn Fn() -> Vec<String> + Send + Sync>>,
99
100 pub tool_execution: ToolExecutionMode,
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
106pub enum ToolExecutionMode {
107 Sequential,
109 #[default]
111 Parallel,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct AgentConfig {
117 pub name: String,
119 pub description: Option<String>,
121 pub model_id: String,
123 pub system_prompt: Option<String>,
125 pub max_iterations: usize,
127 pub timeout_seconds: u64,
129 pub temperature: Option<f64>,
131 pub max_tokens: Option<usize>,
133 #[serde(default)]
135 pub compaction_strategy: CompactionStrategy,
136 #[serde(default)]
138 pub compaction_instruction: Option<String>,
139 #[serde(default = "default_context_window")]
141 pub context_window: usize,
142 #[serde(default)]
147 pub api_key: Option<String>,
148 #[serde(default)]
150 pub workspace_dir: Option<std::path::PathBuf>,
151 #[serde(default)]
158 pub output_mode: Option<String>,
159}
160
161impl Default for AgentConfig {
162 fn default() -> Self {
163 Self {
164 name: "oxi-agent".to_string(),
165 description: None,
166 model_id: "claude-sonnet-4-20250514".to_string(),
167 system_prompt: None,
168 max_iterations: 10,
169 timeout_seconds: 300,
170 temperature: None,
171 max_tokens: None,
172 compaction_strategy: CompactionStrategy::default(),
173 compaction_instruction: None,
174 context_window: 128_000,
175 api_key: None,
176 workspace_dir: None,
177 output_mode: None,
178 }
179 }
180}
181
182impl AgentConfig {
183 pub fn new(model_id: impl Into<String>) -> Self {
185 Self {
186 model_id: model_id.into(),
187 ..Default::default()
188 }
189 }
190
191 pub fn with_name(mut self, name: impl Into<String>) -> Self {
193 self.name = name.into();
194 self
195 }
196
197 pub fn with_system_prompt(mut self, prompt: impl Into<String>) -> Self {
199 self.system_prompt = Some(prompt.into());
200 self
201 }
202
203 pub fn with_max_iterations(mut self, max: usize) -> Self {
205 self.max_iterations = max;
206 self
207 }
208
209 pub fn with_timeout(mut self, seconds: u64) -> Self {
211 self.timeout_seconds = seconds;
212 self
213 }
214
215 pub fn with_compaction_strategy(mut self, strategy: CompactionStrategy) -> Self {
217 self.compaction_strategy = strategy;
218 self
219 }
220
221 pub fn with_compaction_instruction(mut self, instruction: impl Into<String>) -> Self {
223 self.compaction_instruction = Some(instruction.into());
224 self
225 }
226}