vtcode_core/commands/
validate.rs1use crate::config::constants::tools;
4use crate::config::types::AgentConfig;
5use crate::prompts::read_system_prompt_from_md;
6use crate::tools::ToolRegistry;
7use anyhow::Result;
8use console::style;
9use serde_json::json;
10
11pub async fn handle_validate_command(
13 config: AgentConfig,
14 check_api: bool,
15 check_filesystem: bool,
16 _check_tools: bool,
17 _check_config: bool,
18 all: bool,
19) -> Result<()> {
20 println!(
21 "{}",
22 style(" Validating environment and configuration...")
23 .cyan()
24 .bold()
25 );
26
27 let mut all_checks = true;
28
29 if check_api || all {
31 println!("{}", style("Checking API connectivity...").dim());
32 match check_api_connectivity(&config).await {
33 Ok(_) => println!(" {} API connectivity OK", style("✓").green()),
34 Err(e) => {
35 println!(" {} API connectivity failed: {}", style("✗").red(), e);
36 all_checks = false;
37 }
38 }
39 }
40
41 if check_filesystem || all {
43 println!("{}", style("Checking filesystem permissions...").dim());
44 match check_filesystem_permissions(&config).await {
45 Ok(_) => println!(" {} Filesystem permissions OK", style("✓").green()),
46 Err(e) => {
47 println!(" {} Filesystem permissions issue: {}", style("✗").red(), e);
48 all_checks = false;
49 }
50 }
51 }
52
53 if all_checks {
55 println!("{}", style("All validation checks passed!").green().bold());
56 } else {
57 println!(
58 "{}",
59 style(" Some validation checks failed.").yellow().bold()
60 );
61 println!("{}", style("Please address the issues above.").dim());
62 }
63
64 Ok(())
65}
66
67async fn check_api_connectivity(config: &AgentConfig) -> Result<()> {
69 use crate::gemini::models::SystemInstruction;
70 use crate::gemini::{Client, Content, GenerateContentRequest};
71 use crate::prompts::generate_lightweight_instruction;
72
73 let mut client = Client::new(config.api_key.clone(), config.model.clone());
74 let contents = vec![Content::user_text("Hello")];
75 let lightweight_instruction = generate_lightweight_instruction();
76
77 let system_instruction = if let Some(part) = lightweight_instruction.parts.first() {
79 if let Some(text) = part.as_text() {
80 SystemInstruction::new(text)
81 } else {
82 SystemInstruction::new(
83 read_system_prompt_from_md()
84 .unwrap_or_else(|_| "You are a helpful coding assistant.".to_string()),
85 )
86 }
87 } else {
88 SystemInstruction::new(
89 read_system_prompt_from_md()
90 .unwrap_or_else(|_| "You are a helpful coding assistant.".to_string()),
91 )
92 };
93
94 let request = GenerateContentRequest {
95 contents,
96 tools: None,
97 tool_config: None,
98 generation_config: Some(json!({
99 "maxOutputTokens": 10,
100 "temperature": 0.1
101 })),
102 system_instruction: Some(system_instruction),
103 reasoning_config: None,
104 };
105
106 client.generate(&request).await?;
107 Ok(())
108}
109
110async fn check_filesystem_permissions(config: &AgentConfig) -> Result<()> {
112 let mut registry = ToolRegistry::new(config.workspace.clone());
113
114 registry
116 .execute_tool(tools::LIST_FILES, json!({"path": ".", "max_items": 5}))
117 .await?;
118
119 registry
121 .execute_tool(
122 tools::WRITE_FILE,
123 json!({
124 "path": ".vtcode_test",
125 "content": "test",
126 "overwrite": true
127 }),
128 )
129 .await?;
130
131 Ok(())
135}