1use crate::constants::reasoning;
4use crate::core::PromptCachingConfig;
5use serde::{Deserialize, Deserializer, Serialize};
6use serde_json::Value;
7use std::collections::{BTreeMap, HashMap};
8use std::fmt;
9use std::path::PathBuf;
10
11#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
14#[serde(rename_all = "lowercase")]
15pub enum ReasoningEffortLevel {
16 Low,
17 Medium,
18 High,
19}
20
21impl ReasoningEffortLevel {
22 pub fn as_str(self) -> &'static str {
24 match self {
25 Self::Low => reasoning::LOW,
26 Self::Medium => reasoning::MEDIUM,
27 Self::High => reasoning::HIGH,
28 }
29 }
30
31 pub fn parse(value: &str) -> Option<Self> {
33 let normalized = value.trim();
34 if normalized.eq_ignore_ascii_case(reasoning::LOW) {
35 Some(Self::Low)
36 } else if normalized.eq_ignore_ascii_case(reasoning::MEDIUM) {
37 Some(Self::Medium)
38 } else if normalized.eq_ignore_ascii_case(reasoning::HIGH) {
39 Some(Self::High)
40 } else {
41 None
42 }
43 }
44
45 pub fn allowed_values() -> &'static [&'static str] {
47 reasoning::ALLOWED_LEVELS
48 }
49}
50
51impl Default for ReasoningEffortLevel {
52 fn default() -> Self {
53 Self::Medium
54 }
55}
56
57impl fmt::Display for ReasoningEffortLevel {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 f.write_str(self.as_str())
60 }
61}
62
63impl<'de> Deserialize<'de> for ReasoningEffortLevel {
64 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
65 where
66 D: Deserializer<'de>,
67 {
68 let raw = String::deserialize(deserializer)?;
69 if let Some(parsed) = Self::parse(&raw) {
70 Ok(parsed)
71 } else {
72 tracing::warn!(
73 input = raw,
74 allowed = ?Self::allowed_values(),
75 "Invalid reasoning effort level provided; falling back to default"
76 );
77 Ok(Self::default())
78 }
79 }
80}
81
82#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
85#[serde(rename_all = "lowercase")]
86pub enum UiSurfacePreference {
87 Auto,
88 Alternate,
89 Inline,
90}
91
92impl UiSurfacePreference {
93 pub fn as_str(self) -> &'static str {
95 match self {
96 Self::Auto => "auto",
97 Self::Alternate => "alternate",
98 Self::Inline => "inline",
99 }
100 }
101
102 pub fn parse(value: &str) -> Option<Self> {
104 let normalized = value.trim();
105 if normalized.eq_ignore_ascii_case("auto") {
106 Some(Self::Auto)
107 } else if normalized.eq_ignore_ascii_case("alternate")
108 || normalized.eq_ignore_ascii_case("alt")
109 {
110 Some(Self::Alternate)
111 } else if normalized.eq_ignore_ascii_case("inline") {
112 Some(Self::Inline)
113 } else {
114 None
115 }
116 }
117
118 pub fn allowed_values() -> &'static [&'static str] {
120 &["auto", "alternate", "inline"]
121 }
122}
123
124impl Default for UiSurfacePreference {
125 fn default() -> Self {
126 Self::Auto
127 }
128}
129
130impl fmt::Display for UiSurfacePreference {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.write_str(self.as_str())
133 }
134}
135
136impl<'de> Deserialize<'de> for UiSurfacePreference {
137 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
138 where
139 D: Deserializer<'de>,
140 {
141 let raw = String::deserialize(deserializer)?;
142 if let Some(parsed) = Self::parse(&raw) {
143 Ok(parsed)
144 } else {
145 tracing::warn!(
146 input = raw,
147 allowed = ?Self::allowed_values(),
148 "Invalid UI surface preference provided; falling back to default"
149 );
150 Ok(Self::default())
151 }
152 }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub enum ModelSelectionSource {
158 WorkspaceConfig,
160 CliOverride,
162}
163
164impl Default for ModelSelectionSource {
165 fn default() -> Self {
166 Self::WorkspaceConfig
167 }
168}
169
170#[derive(Debug, Clone)]
172pub struct AgentConfig {
173 pub model: String,
174 pub api_key: String,
175 pub provider: String,
176 pub api_key_env: String,
177 pub workspace: std::path::PathBuf,
178 pub verbose: bool,
179 pub theme: String,
180 pub reasoning_effort: ReasoningEffortLevel,
181 pub ui_surface: UiSurfacePreference,
182 pub prompt_cache: PromptCachingConfig,
183 pub model_source: ModelSelectionSource,
184 pub custom_api_keys: BTreeMap<String, String>,
185 pub checkpointing_enabled: bool,
186 pub checkpointing_storage_dir: Option<PathBuf>,
187 pub checkpointing_max_snapshots: usize,
188 pub checkpointing_max_age_days: Option<u64>,
189}
190
191#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
193pub enum CapabilityLevel {
194 Basic,
196 FileReading,
198 FileListing,
200 Bash,
202 Editing,
204 CodeSearch,
206}
207
208#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct SessionInfo {
211 pub session_id: String,
212 pub start_time: u64,
213 pub total_turns: usize,
214 pub total_decisions: usize,
215 pub error_count: usize,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct ConversationTurn {
221 pub turn_number: usize,
222 pub timestamp: u64,
223 pub user_input: Option<String>,
224 pub agent_response: Option<String>,
225 pub tool_calls: Vec<ToolCallInfo>,
226 pub decision: Option<DecisionInfo>,
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
231pub struct ToolCallInfo {
232 pub name: String,
233 pub args: Value,
234 pub result: Option<Value>,
235 pub error: Option<String>,
236 pub execution_time_ms: Option<u64>,
237}
238
239#[derive(Debug, Clone, Serialize, Deserialize)]
241pub struct DecisionInfo {
242 pub turn_number: usize,
243 pub action_type: String,
244 pub description: String,
245 pub reasoning: String,
246 pub outcome: Option<String>,
247 pub confidence_score: Option<f64>,
248 pub timestamp: u64,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct ErrorInfo {
254 pub error_type: String,
255 pub message: String,
256 pub turn_number: usize,
257 pub recoverable: bool,
258 pub timestamp: u64,
259}
260
261#[derive(Debug, Clone, Serialize, Deserialize)]
263pub struct TaskInfo {
264 pub task_type: String,
265 pub description: String,
266 pub completed: bool,
267 pub success: bool,
268 pub duration_seconds: Option<u64>,
269 pub tools_used: Vec<String>,
270 pub dependencies: Vec<String>,
271}
272
273#[derive(Debug, Clone, Serialize, Deserialize)]
275pub struct ProjectSpec {
276 pub name: String,
277 pub features: Vec<String>,
278 pub template: Option<String>,
279 pub dependencies: HashMap<String, String>,
280}
281
282#[derive(Debug, Clone, Serialize, Deserialize)]
284pub struct WorkspaceAnalysis {
285 pub root_path: String,
286 pub project_type: Option<String>,
287 pub languages: Vec<String>,
288 pub frameworks: Vec<String>,
289 pub config_files: Vec<String>,
290 pub source_files: Vec<String>,
291 pub test_files: Vec<String>,
292 pub documentation_files: Vec<String>,
293 pub total_files: usize,
294 pub total_size_bytes: u64,
295}
296
297#[derive(Debug, Clone, Serialize, Deserialize)]
299pub struct CommandResult {
300 pub command: String,
301 pub success: bool,
302 pub stdout: String,
303 pub stderr: String,
304 pub exit_code: Option<i32>,
305 pub execution_time_ms: u64,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
310pub struct FileOperationResult {
311 pub operation: String,
312 pub path: String,
313 pub success: bool,
314 pub details: HashMap<String, Value>,
315 pub error: Option<String>,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct PerformanceMetrics {
321 pub session_duration_seconds: u64,
322 pub total_api_calls: usize,
323 pub total_tokens_used: Option<usize>,
324 pub average_response_time_ms: f64,
325 pub tool_execution_count: usize,
326 pub error_count: usize,
327 pub recovery_success_rate: f64,
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct QualityMetrics {
333 pub decision_confidence_avg: f64,
334 pub tool_success_rate: f64,
335 pub error_recovery_rate: f64,
336 pub context_preservation_rate: f64,
337 pub user_satisfaction_score: Option<f64>,
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct ToolConfig {
343 pub enable_validation: bool,
344 pub max_execution_time_seconds: u64,
345 pub allow_file_creation: bool,
346 pub allow_file_deletion: bool,
347 pub working_directory: Option<String>,
348}
349
350#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct ContextConfig {
353 pub max_context_length: usize,
354 pub compression_threshold: usize,
355 pub summarization_interval: usize,
356 pub preservation_priority: Vec<String>,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct LoggingConfig {
362 pub level: String,
363 pub file_logging: bool,
364 pub log_directory: Option<String>,
365 pub max_log_files: usize,
366 pub max_log_size_mb: usize,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
371pub enum AnalysisDepth {
372 Basic,
373 Standard,
374 Deep,
375}
376
377#[derive(Debug, Clone, Serialize, Deserialize)]
379pub enum OutputFormat {
380 Text,
381 Json,
382 Html,
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize)]
387pub enum CompressionLevel {
388 Light,
389 Medium,
390 Aggressive,
391}