gigi-cli 1.0.0

Gigi — A Claude Code-like AI coding assistant CLI in Rust
use anyhow::Result;
use async_trait::async_trait;
use serde_json::Value;
use std::path::Path;

use super::{Tool, ToolOutput};
use crate::tools::file_ops::{grep_search_in_workspace, GrepSearchInput};

pub struct GrepSearchTool;

impl GrepSearchTool {
    pub fn new() -> Self {
        Self
    }
}

impl Default for GrepSearchTool {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl Tool for GrepSearchTool {
    fn name(&self) -> &str {
        "grep_search"
    }

    fn description(&self) -> &str {
        "Search file contents with a regex pattern."
    }

    fn parameters_schema(&self) -> Value {
        serde_json::json!({
            "type": "object",
            "properties": {
                "pattern": { "type": "string" },
                "path": { "type": "string" },
                "glob": { "type": "string" },
                "output_mode": { "type": "string" },
                "-B": { "type": "integer", "minimum": 0 },
                "-A": { "type": "integer", "minimum": 0 },
                "-C": { "type": "integer", "minimum": 0 },
                "context": { "type": "integer", "minimum": 0 },
                "-n": { "type": "boolean" },
                "-i": { "type": "boolean" },
                "type": { "type": "string" },
                "head_limit": { "type": "integer", "minimum": 1 },
                "offset": { "type": "integer", "minimum": 0 },
                "multiline": { "type": "boolean" }
            },
            "required": ["pattern"],
            "additionalProperties": false
        })
    }

    async fn execute(&self, input: Value) -> Result<ToolOutput> {
        let grep_input: GrepSearchInput = serde_json::from_value(input)?;
        let workspace_root = std::env::current_dir()?;

        match grep_search_in_workspace(&grep_input, &workspace_root) {
            Ok(output) => {
                let serialized = serde_json::to_string_pretty(&output)?;
                Ok(ToolOutput::success(serialized))
            }
            Err(e) => Ok(ToolOutput::error(format!("Error performing grep search: {}", e))),
        }
    }
}