vtcode_core/commands/
analyze.rs1use crate::config::constants::tools;
4use crate::config::types::{AgentConfig, AnalysisDepth, OutputFormat};
5use crate::tools::ToolRegistry;
6use crate::utils::colors::style;
7use anyhow::Result;
8use serde_json::json;
9
10pub async fn handle_analyze_command(
12 config: AgentConfig,
13 depth: String,
14 format: String,
15) -> Result<()> {
16 println!("{}", style("Analyzing workspace...").cyan().bold());
17
18 let depth = match depth.to_lowercase().as_str() {
19 "basic" => AnalysisDepth::Basic,
20 "standard" => AnalysisDepth::Standard,
21 "deep" => AnalysisDepth::Deep,
22 _ => {
23 println!("{}", style("Invalid depth. Using 'standard'.").red());
24 AnalysisDepth::Standard
25 }
26 };
27
28 let _output_format = match format.to_lowercase().as_str() {
29 "text" => OutputFormat::Text,
30 "json" => OutputFormat::Json,
31 "html" => OutputFormat::Html,
32 _ => {
33 println!("{}", style("Invalid format. Using 'text'.").red());
34 OutputFormat::Text
35 }
36 };
37
38 let registry = ToolRegistry::new(config.workspace.clone()).await;
39
40 println!("{}", style("1. Getting workspace structure...").dim());
42 let root_files = registry
43 .execute_tool(
44 tools::UNIFIED_SEARCH,
45 json!({"action": "list", "path": ".", "max_items": 50}),
46 )
47 .await;
48
49 match root_files {
50 Ok(result) => {
51 println!("{}", style("Root directory structure obtained").green());
52 if let Some(files_array) = result.get("files") {
53 println!(
54 " Found {} files/directories in root",
55 files_array.as_array().unwrap_or(&vec![]).len()
56 );
57 }
58 }
59 Err(e) => println!("{} {}", style("Failed to list root directory:").red(), e),
60 }
61
62 println!("{}", style("2. Identifying project type...").dim());
64 let important_files = vec![
65 "README.md",
66 "Cargo.toml",
67 "package.json",
68 "go.mod",
69 "requirements.txt",
70 "Makefile",
71 ];
72
73 for file in important_files {
74 let check_file = registry
75 .execute_tool(
76 tools::UNIFIED_SEARCH,
77 json!({"action": "list", "path": ".", "include_hidden": false}),
78 )
79 .await;
80 if let Ok(result) = check_file
81 && let Some(files) = result.get("files")
82 && let Some(files_array) = files.as_array()
83 {
84 for file_obj in files_array {
85 if let Some(path) = file_obj.get("path")
86 && path.as_str().unwrap_or("") == file
87 {
88 println!(" {} Detected: {}", style("Detected").green(), file);
89 break;
90 }
91 }
92 }
93 }
94
95 println!("{}", style("3. Reading project configuration...").dim());
97 let config_files = vec!["AGENTS.md", "README.md", "Cargo.toml", "package.json"];
98
99 for config_file in config_files {
100 let read_result = registry
101 .execute_tool(
102 tools::READ_FILE,
103 json!({"path": config_file, "max_bytes": 2000}),
104 )
105 .await;
106 if let Ok(result) = read_result {
107 println!(
108 " {} Read {} ({} bytes)",
109 style("Read").green(),
110 config_file,
111 result
112 .get("metadata")
113 .and_then(|m| m.get("size"))
114 .unwrap_or(&serde_json::json!(null))
115 );
116 }
117 }
118
119 println!("{}", style("4. Analyzing source code structure...").dim());
121
122 let src_dirs = vec!["src", "lib", "pkg", "internal", "cmd"];
124 for dir in src_dirs {
125 let check_dir = registry
126 .execute_tool(
127 tools::UNIFIED_SEARCH,
128 json!({"action": "list", "path": ".", "include_hidden": false}),
129 )
130 .await;
131 if let Ok(result) = check_dir
132 && let Some(files) = result.get("files")
133 && let Some(files_array) = files.as_array()
134 {
135 for file_obj in files_array {
136 if let Some(path) = file_obj.get("path")
137 && path.as_str().unwrap_or("") == dir
138 {
139 println!(
140 " {} Found source directory: {}",
141 style("Found").green(),
142 dir
143 );
144 break;
145 }
146 }
147 }
148 }
149
150 if matches!(depth, AnalysisDepth::Deep) {
151 println!(
152 "{}",
153 style("Deep analysis: use grep/search tools for detailed code inspection.").dim()
154 );
155 }
156
157 println!("{}", style("Workspace analysis complete!").green().bold());
158 println!(
159 "{}",
160 style("You can now ask me specific questions about the codebase.").dim()
161 );
162
163 Ok(())
164}