vtcode_core/cli/
commands.rs

1//! Command definitions and interfaces
2
3use crate::config::types::*;
4use anyhow::Result;
5
6/// Result of executing a command
7#[derive(Debug, Clone)]
8pub struct CommandResult {
9    pub success: bool,
10    pub message: String,
11    pub data: Option<serde_json::Value>,
12    pub metrics: Option<PerformanceMetrics>,
13}
14
15/// Chat command configuration
16pub struct ChatCommand {
17    pub initial_prompt: Option<String>,
18    pub verbose: bool,
19    pub show_stats: bool,
20}
21
22impl Default for ChatCommand {
23    fn default() -> Self {
24        Self {
25            initial_prompt: None,
26            verbose: false,
27            show_stats: true,
28        }
29    }
30}
31
32/// Analyze command configuration
33pub struct AnalyzeCommand {
34    pub depth: AnalysisDepth,
35    pub format: OutputFormat,
36    pub include_hidden: bool,
37    pub max_depth: Option<usize>,
38}
39
40#[derive(Debug, Clone)]
41pub enum AnalysisDepth {
42    Basic,
43    Standard,
44    Deep,
45}
46
47#[derive(Debug, Clone)]
48pub enum OutputFormat {
49    Text,
50    Json,
51    Html,
52}
53
54/// Project creation configuration
55pub struct CreateProjectCommand {
56    pub name: String,
57    pub features: Vec<String>,
58    pub template: Option<String>,
59    pub initialize_git: bool,
60    pub include_tests: bool,
61    pub include_docs: bool,
62}
63
64/// Validation command configuration
65pub struct ValidateCommand {
66    pub check_api: bool,
67    pub check_filesystem: bool,
68    pub check_tools: bool,
69    pub check_config: bool,
70    pub verbose: bool,
71}
72
73/// Statistics command configuration
74pub struct StatsCommand {
75    pub detailed: bool,
76    pub format: OutputFormat,
77    pub include_history: bool,
78    pub include_performance: bool,
79}
80
81/// Context compression command configuration
82pub struct CompressContextCommand {
83    pub input_file: Option<std::path::PathBuf>,
84    pub output_file: Option<std::path::PathBuf>,
85    pub compression_level: CompressionLevel,
86    pub preserve_decisions: bool,
87}
88
89#[derive(Debug, Clone)]
90pub enum CompressionLevel {
91    Light,      // 20-30% reduction
92    Medium,     // 40-50% reduction
93    Aggressive, // 60-70% reduction
94}
95
96/// Single prompt command configuration
97pub struct AskCommand {
98    pub prompt: String,
99    pub show_reasoning: bool,
100    pub include_metadata: bool,
101}
102
103/// Command factory for creating command configurations from CLI args
104pub struct CommandFactory;
105
106impl CommandFactory {
107    pub fn create_chat_command(verbose: bool, prompt: Option<String>) -> ChatCommand {
108        ChatCommand {
109            initial_prompt: prompt,
110            verbose,
111            show_stats: true,
112        }
113    }
114
115    pub fn create_analyze_command(depth: &str, format: &str) -> Result<AnalyzeCommand> {
116        let depth = match depth.to_lowercase().as_str() {
117            "basic" => AnalysisDepth::Basic,
118            "standard" => AnalysisDepth::Standard,
119            "deep" => AnalysisDepth::Deep,
120            _ => return Err(anyhow::anyhow!("Invalid analysis depth: {}", depth)),
121        };
122
123        let format = match format.to_lowercase().as_str() {
124            "text" => OutputFormat::Text,
125            "json" => OutputFormat::Json,
126            "html" => OutputFormat::Html,
127            _ => return Err(anyhow::anyhow!("Invalid output format: {}", format)),
128        };
129
130        Ok(AnalyzeCommand {
131            depth,
132            format,
133            include_hidden: false,
134            max_depth: Some(10),
135        })
136    }
137
138    pub fn create_project_command(
139        name: String,
140        features: String,
141        template: Option<String>,
142        git: bool,
143    ) -> CreateProjectCommand {
144        let features = if features.is_empty() {
145            vec![]
146        } else {
147            features.split(',').map(|s| s.trim().to_string()).collect()
148        };
149
150        CreateProjectCommand {
151            name,
152            features,
153            template,
154            initialize_git: git,
155            include_tests: true,
156            include_docs: true,
157        }
158    }
159
160    pub fn create_validate_command(api: bool, filesystem: bool, all: bool) -> ValidateCommand {
161        if all {
162            ValidateCommand {
163                check_api: true,
164                check_filesystem: true,
165                check_tools: true,
166                check_config: true,
167                verbose: true,
168            }
169        } else {
170            ValidateCommand {
171                check_api: api,
172                check_filesystem: filesystem,
173                check_tools: false,
174                check_config: false,
175                verbose: false,
176            }
177        }
178    }
179
180    pub fn create_ask_command(prompt: Vec<String>) -> AskCommand {
181        AskCommand {
182            prompt: prompt.join(" "),
183            show_reasoning: false,
184            include_metadata: false,
185        }
186    }
187}
188
189/// Command execution context
190pub struct CommandContext {
191    pub agent_config: AgentConfig,
192    pub session_info: SessionInfo,
193    pub performance_metrics: PerformanceMetrics,
194    pub start_time: std::time::Instant,
195}
196
197impl CommandContext {
198    pub fn new(config: AgentConfig) -> Self {
199        let session_id = format!(
200            "session_{}",
201            std::time::SystemTime::now()
202                .duration_since(std::time::UNIX_EPOCH)
203                .unwrap()
204                .as_secs()
205        );
206
207        Self {
208            agent_config: config,
209            session_info: SessionInfo {
210                session_id,
211                start_time: std::time::SystemTime::now()
212                    .duration_since(std::time::UNIX_EPOCH)
213                    .unwrap()
214                    .as_secs(),
215                total_turns: 0,
216                total_decisions: 0,
217                error_count: 0,
218            },
219            performance_metrics: PerformanceMetrics {
220                session_duration_seconds: 0,
221                total_api_calls: 0,
222                total_tokens_used: None,
223                average_response_time_ms: 0.0,
224                tool_execution_count: 0,
225                error_count: 0,
226                recovery_success_rate: 0.0,
227            },
228            start_time: std::time::Instant::now(),
229        }
230    }
231
232    pub fn update_metrics(&mut self) {
233        self.performance_metrics.session_duration_seconds = self.start_time.elapsed().as_secs();
234    }
235}