syncable_cli/agent/tools/
analyze.rs

1//! Analyze tool - wraps the analyze command using Rig's Tool trait
2
3use rig::completion::ToolDefinition;
4use rig::tool::Tool;
5use serde::{Deserialize, Serialize};
6use serde_json::json;
7use std::path::PathBuf;
8
9/// Arguments for the analyze tool
10#[derive(Debug, Deserialize)]
11pub struct AnalyzeArgs {
12    /// Optional subdirectory path to analyze
13    pub path: Option<String>,
14}
15
16/// Error type for analyze tool
17#[derive(Debug, thiserror::Error)]
18#[error("Analysis error: {0}")]
19pub struct AnalyzeError(String);
20
21/// Tool to analyze a project
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct AnalyzeTool {
24    project_path: PathBuf,
25}
26
27impl AnalyzeTool {
28    pub fn new(project_path: PathBuf) -> Self {
29        Self { project_path }
30    }
31}
32
33impl Tool for AnalyzeTool {
34    const NAME: &'static str = "analyze_project";
35
36    type Error = AnalyzeError;
37    type Args = AnalyzeArgs;
38    type Output = String;
39
40    async fn definition(&self, _prompt: String) -> ToolDefinition {
41        ToolDefinition {
42            name: Self::NAME.to_string(),
43            description: "Analyze the project to detect programming languages, frameworks, dependencies, build tools, and architecture patterns. Returns a comprehensive overview of the project's technology stack.".to_string(),
44            parameters: json!({
45                "type": "object",
46                "properties": {
47                    "path": {
48                        "type": "string",
49                        "description": "Optional subdirectory path to analyze (relative to project root). If not provided, analyzes the entire project."
50                    }
51                }
52            }),
53        }
54    }
55
56    async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
57        let path = if let Some(subpath) = args.path {
58            self.project_path.join(subpath)
59        } else {
60            self.project_path.clone()
61        };
62
63        match crate::analyzer::analyze_project(&path) {
64            Ok(analysis) => serde_json::to_string_pretty(&analysis)
65                .map_err(|e| AnalyzeError(format!("Failed to serialize: {}", e))),
66            Err(e) => Err(AnalyzeError(format!("Analysis failed: {}", e))),
67        }
68    }
69}