vtcode_config/types/
mod.rs

1//! Common types and interfaces used throughout the application
2
3use 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/// Supported reasoning effort levels configured via vtcode.toml
12#[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    /// Return the textual representation expected by downstream APIs
23    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    /// Attempt to parse an effort level from user configuration input
32    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    /// Enumerate the allowed configuration values for validation and messaging
46    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/// Preferred rendering surface for the interactive chat UI
83#[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    /// String representation used in configuration and logging
94    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    /// Parse a surface preference from configuration input
103    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    /// Enumerate the accepted configuration values for validation messaging
119    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/// Source describing how the active model was selected
156#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub enum ModelSelectionSource {
158    /// Model provided by workspace configuration
159    WorkspaceConfig,
160    /// Model provided by CLI override
161    CliOverride,
162}
163
164impl Default for ModelSelectionSource {
165    fn default() -> Self {
166        Self::WorkspaceConfig
167    }
168}
169
170/// Configuration for the agent
171#[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/// Workshop agent capability levels
192#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
193pub enum CapabilityLevel {
194    /// Basic chat only
195    Basic,
196    /// Can read files
197    FileReading,
198    /// Can read files and list directories
199    FileListing,
200    /// Can read files, list directories, and run bash commands
201    Bash,
202    /// Can read files, list directories, run bash commands, and edit files
203    Editing,
204    /// Full capabilities including code search
205    CodeSearch,
206}
207
208/// Session information
209#[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/// Conversation turn information
219#[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/// Tool call information
230#[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/// Decision information for tracking
240#[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/// Error information for tracking
252#[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/// Task information for project workflows
262#[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/// Project creation specification
274#[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/// Workspace analysis result
283#[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/// Command execution result
298#[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/// File operation result
309#[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/// Performance metrics
319#[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/// Quality metrics for agent actions
331#[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/// Configuration for tool behavior
341#[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/// Context management settings
351#[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/// Logging configuration
360#[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/// Analysis depth for workspace analysis
370#[derive(Debug, Clone, Serialize, Deserialize)]
371pub enum AnalysisDepth {
372    Basic,
373    Standard,
374    Deep,
375}
376
377/// Output format for commands
378#[derive(Debug, Clone, Serialize, Deserialize)]
379pub enum OutputFormat {
380    Text,
381    Json,
382    Html,
383}
384
385/// Compression level for context compression
386#[derive(Debug, Clone, Serialize, Deserialize)]
387pub enum CompressionLevel {
388    Light,
389    Medium,
390    Aggressive,
391}