llama-cpp-v3-agent-sdk 0.1.7

Agentic tool-use loop on top of llama-cpp-v3 — local LLM agents with built-in tools
Documentation
use crate::error::AgentError;
use crate::tool::{Tool, ToolResult};

/// Find files matching a glob pattern.
pub struct GlobTool;

impl Tool for GlobTool {
    fn name(&self) -> &str {
        "glob"
    }

    fn description(&self) -> &str {
        "Find files matching a glob pattern. Returns a list of matching file paths. \
         Supports standard glob patterns like '**/*.rs', 'src/*.cpp', etc."
    }

    fn parameters_schema(&self) -> serde_json::Value {
        serde_json::json!({
            "type": "object",
            "properties": {
                "pattern": {
                    "type": "string",
                    "description": "Glob pattern to match files (e.g. '**/*.rs', 'src/**/*.cpp')"
                }
            },
            "required": ["pattern"]
        })
    }

    fn execute(&self, args: &serde_json::Value) -> Result<ToolResult, AgentError> {
        let pattern = args["pattern"].as_str().ok_or_else(|| AgentError::Tool {
            tool: "glob".to_string(),
            message: "Missing 'pattern' argument".to_string(),
        })?;

        match glob::glob(pattern) {
            Ok(paths) => {
                let mut results = Vec::new();
                let mut errors = 0;

                for entry in paths {
                    match entry {
                        Ok(path) => results.push(path.display().to_string()),
                        Err(_) => errors += 1,
                    }
                }

                if results.is_empty() {
                    return Ok(ToolResult::ok(format!(
                        "No files matched pattern '{}'",
                        pattern
                    )));
                }

                let mut output = format!("Found {} file(s) matching '{}':\n", results.len(), pattern);
                for path in &results {
                    output.push_str(&format!("  {}\n", path));
                }
                if errors > 0 {
                    output.push_str(&format!("({} entries could not be read)\n", errors));
                }

                Ok(ToolResult::ok(output))
            }
            Err(e) => Ok(ToolResult::err(format!(
                "Invalid glob pattern '{}': {}",
                pattern, e
            ))),
        }
    }

    fn requires_permission(&self) -> bool {
        false
    }
}