Skip to main content

vtcode_core/commands/
validate.rs

1//! Validate command implementation - environment and configuration validation
2
3use crate::config::constants::tools;
4use crate::config::types::AgentConfig;
5use crate::llm::factory::create_provider_for_model;
6use crate::llm::provider::{LLMRequest, Message};
7use crate::prompts::system::lightweight_instruction_text;
8use crate::tools::ToolRegistry;
9use crate::utils::colors::style;
10use anyhow::Result;
11use serde_json::json;
12use std::sync::Arc;
13
14/// Handle the validate command - check environment and configuration
15pub async fn handle_validate_command(
16    config: AgentConfig,
17    check_api: bool,
18    check_filesystem: bool,
19    _check_tools: bool,
20    _check_config: bool,
21    all: bool,
22) -> Result<()> {
23    println!(
24        "{}",
25        style(" Validating environment and configuration...")
26            .cyan()
27            .bold()
28    );
29
30    let mut all_checks = true;
31
32    // Check API connectivity if requested
33    if check_api || all {
34        println!("{}", style("Checking API connectivity...").dim());
35        match check_api_connectivity(&config).await {
36            Ok(_) => println!("  {} API connectivity OK", style("[+]").green()),
37            Err(e) => {
38                println!("  {} API connectivity failed: {}", style("[X]").red(), e);
39                all_checks = false;
40            }
41        }
42    }
43
44    // Check filesystem permissions if requested
45    if check_filesystem || all {
46        println!("{}", style("Checking filesystem permissions...").dim());
47        match check_filesystem_permissions(&config).await {
48            Ok(_) => println!("  {} Filesystem permissions OK", style("[+]").green()),
49            Err(e) => {
50                println!(
51                    "  {} Filesystem permissions issue: {}",
52                    style("[X]").red(),
53                    e
54                );
55                all_checks = false;
56            }
57        }
58    }
59
60    // Summary
61    if all_checks {
62        println!("{}", style("All validation checks passed!").green().bold());
63    } else {
64        println!("{}", style(" Some validation checks failed.").red().bold());
65        println!("{}", style("Please address the issues above.").dim());
66    }
67
68    Ok(())
69}
70
71/// Check API connectivity
72async fn check_api_connectivity(config: &AgentConfig) -> Result<()> {
73    let provider = create_provider_for_model(&config.model, config.api_key.clone(), None, None)?;
74    let request = LLMRequest {
75        messages: vec![Message::user("Hello".to_string())],
76        system_prompt: Some(Arc::new(lightweight_instruction_text())),
77        model: config.model.to_string(),
78        max_tokens: Some(10),
79        temperature: Some(0.1),
80        ..Default::default()
81    };
82
83    provider.generate(request).await?;
84    Ok(())
85}
86
87/// Check filesystem permissions
88async fn check_filesystem_permissions(config: &AgentConfig) -> Result<()> {
89    let workspace = config.workspace.clone(); // Clone only once for reuse
90    let registry = ToolRegistry::new(workspace).await;
91
92    // Try to list files in the workspace
93    registry
94        .execute_tool(
95            tools::UNIFIED_SEARCH,
96            json!({"action": "list", "path": ".", "max_items": 5}),
97        )
98        .await?;
99
100    // Try to create a test file
101    registry
102        .execute_tool(
103            tools::WRITE_FILE,
104            json!({
105                "path": ".vtcode_test",
106                "content": "test",
107                "overwrite": true
108            }),
109        )
110        .await?;
111
112    // Clean up test file
113    // Delete is supported via delete_file tool in ToolRegistry; we still validate permissions here
114
115    Ok(())
116}