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))]
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
17#[serde(rename_all = "lowercase")]
18pub enum ReasoningEffortLevel {
19 None,
21 Minimal,
23 Low,
25 Medium,
27 High,
29}
30
31impl ReasoningEffortLevel {
32 pub fn as_str(self) -> &'static str {
34 match self {
35 Self::None => "none",
36 Self::Minimal => "minimal",
37 Self::Low => reasoning::LOW,
38 Self::Medium => reasoning::MEDIUM,
39 Self::High => reasoning::HIGH,
40 }
41 }
42
43 pub fn parse(value: &str) -> Option<Self> {
45 let normalized = value.trim();
46 if normalized.eq_ignore_ascii_case("none") {
47 Some(Self::None)
48 } else if normalized.eq_ignore_ascii_case("minimal") {
49 Some(Self::Minimal)
50 } else if normalized.eq_ignore_ascii_case(reasoning::LOW) {
51 Some(Self::Low)
52 } else if normalized.eq_ignore_ascii_case(reasoning::MEDIUM) {
53 Some(Self::Medium)
54 } else if normalized.eq_ignore_ascii_case(reasoning::HIGH) {
55 Some(Self::High)
56 } else {
57 None
58 }
59 }
60
61 pub fn allowed_values() -> &'static [&'static str] {
63 reasoning::ALLOWED_LEVELS
64 }
65}
66
67impl Default for ReasoningEffortLevel {
68 fn default() -> Self {
69 Self::Medium
70 }
71}
72
73#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
76#[serde(rename_all = "lowercase")]
77pub enum VerbosityLevel {
78 Low,
79 Medium,
80 High,
81}
82
83impl VerbosityLevel {
84 pub fn as_str(self) -> &'static str {
86 match self {
87 Self::Low => "low",
88 Self::Medium => "medium",
89 Self::High => "high",
90 }
91 }
92
93 pub fn parse(value: &str) -> Option<Self> {
95 let normalized = value.trim();
96 if normalized.eq_ignore_ascii_case("low") {
97 Some(Self::Low)
98 } else if normalized.eq_ignore_ascii_case("medium") {
99 Some(Self::Medium)
100 } else if normalized.eq_ignore_ascii_case("high") {
101 Some(Self::High)
102 } else {
103 None
104 }
105 }
106
107 pub fn allowed_values() -> &'static [&'static str] {
109 &["low", "medium", "high"]
110 }
111}
112
113impl Default for VerbosityLevel {
114 fn default() -> Self {
115 Self::Medium
116 }
117}
118
119impl fmt::Display for VerbosityLevel {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 f.write_str(self.as_str())
122 }
123}
124
125impl<'de> Deserialize<'de> for VerbosityLevel {
126 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
127 where
128 D: Deserializer<'de>,
129 {
130 let raw = String::deserialize(deserializer)?;
131 if let Some(parsed) = Self::parse(&raw) {
132 Ok(parsed)
133 } else {
134 tracing::warn!(
135 input = raw,
136 allowed = ?Self::allowed_values(),
137 "Invalid verbosity level provided; falling back to default"
138 );
139 Ok(Self::default())
140 }
141 }
142}
143
144impl fmt::Display for ReasoningEffortLevel {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 f.write_str(self.as_str())
147 }
148}
149
150impl<'de> Deserialize<'de> for ReasoningEffortLevel {
151 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
152 where
153 D: Deserializer<'de>,
154 {
155 let raw = String::deserialize(deserializer)?;
156 if let Some(parsed) = Self::parse(&raw) {
157 Ok(parsed)
158 } else {
159 tracing::warn!(
160 input = raw,
161 allowed = ?Self::allowed_values(),
162 "Invalid reasoning effort level provided; falling back to default"
163 );
164 Ok(Self::default())
165 }
166 }
167}
168
169#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
171#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
172#[serde(rename_all = "lowercase")]
173pub enum UiSurfacePreference {
174 Auto,
175 Alternate,
176 Inline,
177}
178
179impl UiSurfacePreference {
180 pub fn as_str(self) -> &'static str {
182 match self {
183 Self::Auto => "auto",
184 Self::Alternate => "alternate",
185 Self::Inline => "inline",
186 }
187 }
188
189 pub fn parse(value: &str) -> Option<Self> {
191 let normalized = value.trim();
192 if normalized.eq_ignore_ascii_case("auto") {
193 Some(Self::Auto)
194 } else if normalized.eq_ignore_ascii_case("alternate")
195 || normalized.eq_ignore_ascii_case("alt")
196 {
197 Some(Self::Alternate)
198 } else if normalized.eq_ignore_ascii_case("inline") {
199 Some(Self::Inline)
200 } else {
201 None
202 }
203 }
204
205 pub fn allowed_values() -> &'static [&'static str] {
207 &["auto", "alternate", "inline"]
208 }
209}
210
211impl Default for UiSurfacePreference {
212 fn default() -> Self {
213 Self::Auto
214 }
215}
216
217impl fmt::Display for UiSurfacePreference {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 f.write_str(self.as_str())
220 }
221}
222
223impl<'de> Deserialize<'de> for UiSurfacePreference {
224 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
225 where
226 D: Deserializer<'de>,
227 {
228 let raw = String::deserialize(deserializer)?;
229 if let Some(parsed) = Self::parse(&raw) {
230 Ok(parsed)
231 } else {
232 tracing::warn!(
233 input = raw,
234 allowed = ?Self::allowed_values(),
235 "Invalid UI surface preference provided; falling back to default"
236 );
237 Ok(Self::default())
238 }
239 }
240}
241
242#[derive(Debug, Clone, Copy, PartialEq, Eq)]
244pub enum ModelSelectionSource {
245 WorkspaceConfig,
247 CliOverride,
249}
250
251impl Default for ModelSelectionSource {
252 fn default() -> Self {
253 Self::WorkspaceConfig
254 }
255}
256
257#[derive(Debug, Clone)]
259pub struct AgentConfig {
260 pub model: String,
261 pub api_key: String,
262 pub provider: String,
263 pub api_key_env: String,
264 pub workspace: std::path::PathBuf,
265 pub verbose: bool,
266 pub theme: String,
267 pub reasoning_effort: ReasoningEffortLevel,
268 pub ui_surface: UiSurfacePreference,
269 pub prompt_cache: PromptCachingConfig,
270 pub model_source: ModelSelectionSource,
271 pub custom_api_keys: BTreeMap<String, String>,
272 pub checkpointing_enabled: bool,
273 pub checkpointing_storage_dir: Option<PathBuf>,
274 pub checkpointing_max_snapshots: usize,
275 pub checkpointing_max_age_days: Option<u64>,
276}
277
278#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
280pub enum CapabilityLevel {
281 Basic,
283 FileReading,
285 FileListing,
287 Bash,
289 Editing,
291 CodeSearch,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize)]
297pub struct SessionInfo {
298 pub session_id: String,
299 pub start_time: u64,
300 pub total_turns: usize,
301 pub total_decisions: usize,
302 pub error_count: usize,
303}
304
305#[derive(Debug, Clone, Serialize, Deserialize)]
307pub struct ConversationTurn {
308 pub turn_number: usize,
309 pub timestamp: u64,
310 pub user_input: Option<String>,
311 pub agent_response: Option<String>,
312 pub tool_calls: Vec<ToolCallInfo>,
313 pub decision: Option<DecisionInfo>,
314}
315
316#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct ToolCallInfo {
319 pub name: String,
320 pub args: Value,
321 pub result: Option<Value>,
322 pub error: Option<String>,
323 pub execution_time_ms: Option<u64>,
324}
325
326#[derive(Debug, Clone, Serialize, Deserialize)]
328pub struct DecisionInfo {
329 pub turn_number: usize,
330 pub action_type: String,
331 pub description: String,
332 pub reasoning: String,
333 pub outcome: Option<String>,
334 pub confidence_score: Option<f64>,
335 pub timestamp: u64,
336}
337
338#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct ErrorInfo {
341 pub error_type: String,
342 pub message: String,
343 pub turn_number: usize,
344 pub recoverable: bool,
345 pub timestamp: u64,
346}
347
348#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct TaskInfo {
351 pub task_type: String,
352 pub description: String,
353 pub completed: bool,
354 pub success: bool,
355 pub duration_seconds: Option<u64>,
356 pub tools_used: Vec<String>,
357 pub dependencies: Vec<String>,
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize)]
362pub struct ProjectSpec {
363 pub name: String,
364 pub features: Vec<String>,
365 pub template: Option<String>,
366 pub dependencies: HashMap<String, String>,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
371pub struct WorkspaceAnalysis {
372 pub root_path: String,
373 pub project_type: Option<String>,
374 pub languages: Vec<String>,
375 pub frameworks: Vec<String>,
376 pub config_files: Vec<String>,
377 pub source_files: Vec<String>,
378 pub test_files: Vec<String>,
379 pub documentation_files: Vec<String>,
380 pub total_files: usize,
381 pub total_size_bytes: u64,
382}
383
384#[derive(Debug, Clone, Serialize, Deserialize)]
386pub struct CommandResult {
387 pub command: String,
388 pub success: bool,
389 pub stdout: String,
390 pub stderr: String,
391 pub exit_code: Option<i32>,
392 pub execution_time_ms: u64,
393}
394
395#[derive(Debug, Clone, Serialize, Deserialize)]
397pub struct FileOperationResult {
398 pub operation: String,
399 pub path: String,
400 pub success: bool,
401 pub details: HashMap<String, Value>,
402 pub error: Option<String>,
403}
404
405#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct PerformanceMetrics {
408 pub session_duration_seconds: u64,
409 pub total_api_calls: usize,
410 pub total_tokens_used: Option<usize>,
411 pub average_response_time_ms: f64,
412 pub tool_execution_count: usize,
413 pub error_count: usize,
414 pub recovery_success_rate: f64,
415}
416
417#[derive(Debug, Clone, Serialize, Deserialize)]
419pub struct QualityMetrics {
420 pub decision_confidence_avg: f64,
421 pub tool_success_rate: f64,
422 pub error_recovery_rate: f64,
423 pub context_preservation_rate: f64,
424 pub user_satisfaction_score: Option<f64>,
425}
426
427#[derive(Debug, Clone, Serialize, Deserialize)]
429pub struct ToolConfig {
430 pub enable_validation: bool,
431 pub max_execution_time_seconds: u64,
432 pub allow_file_creation: bool,
433 pub allow_file_deletion: bool,
434 pub working_directory: Option<String>,
435}
436
437#[derive(Debug, Clone, Serialize, Deserialize)]
439pub struct ContextConfig {
440 pub max_context_length: usize,
441 pub compression_threshold: usize,
442 pub summarization_interval: usize,
443 pub preservation_priority: Vec<String>,
444}
445
446#[derive(Debug, Clone, Serialize, Deserialize)]
448pub struct LoggingConfig {
449 pub level: String,
450 pub file_logging: bool,
451 pub log_directory: Option<String>,
452 pub max_log_files: usize,
453 pub max_log_size_mb: usize,
454}
455
456#[derive(Debug, Clone, Serialize, Deserialize)]
458pub enum AnalysisDepth {
459 Basic,
460 Standard,
461 Deep,
462}
463
464#[derive(Debug, Clone, Serialize, Deserialize)]
466pub enum OutputFormat {
467 Text,
468 Json,
469 Html,
470}
471
472#[derive(Debug, Clone, Serialize, Deserialize)]
474pub enum CompressionLevel {
475 Light,
476 Medium,
477 Aggressive,
478}