monothink 0.6.0

A totally non-agentic coding assistant
/*
* This file is part of monothink.
*
* monothink is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* monothink is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with monothink.
* If not, see <https://www.gnu.org/licenses/>.

*/

use rig::tool::{Tool, ToolContext};
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::sync::Arc;
use tokio::sync::Mutex;

use crate::common::package_resolver::PackageResolver;

#[derive(Debug, Deserialize, Serialize)]
pub struct FindPackageArgs {
    pattern: String,
}

pub struct FindPackage {
    dependencies: Arc<Mutex<PackageResolver>>,
}

impl FindPackage {
    pub fn new(dependencies: Arc<Mutex<PackageResolver>>) -> Self {
        Self { dependencies }
    }
}
impl Tool for FindPackage {
    const NAME: &'static str = "find_package";

    type Error = super::ToolError;
    type Args = FindPackageArgs;
    type Output = Vec<String>;

    #[tracing::instrument(skip(self, _context))]
    async fn call(
        &self,
        _context: &mut ToolContext,
        args: Self::Args,
    ) -> Result<Self::Output, Self::Error> {
        let dependencies = self.dependencies.lock().await;

        Ok(dependencies.search_dependency(&args.pattern))
    }

    fn description(&self) -> String {
        // @todo check for multiple package manager when supported
        "Find all packages/dependencies whose name matches the provided pattern. \
            Returns a list of identifiers for the packages that match the pattern. \
            Each identifier follows the format `{package_manager}:name@version` (e.g., `cargo:tokio@1.42.0`)."
            .to_string()
    }

    fn parameters(&self) -> serde_json::Value {
        // @todo support pacman parameter once multiple package managers are supported
        json!({
            "type": "object",
            "properties": {
                "pattern": {
                    "type": "string",
                    "description": "Text pattern to search for within package or dependency names. \
                    Performs a **substring match** (e.g., `\"tokio\"` will match both `\"tokio\"` and `\"tokio-util\"`). \
                    Use short keywords rather than full descriptions."
                },
            },
            "required": ["pattern"]
        })
    }

    fn map_error(&self, error: Self::Error) -> rig::tool::ToolExecutionError {
        rig::tool::ToolExecutionError::from_error(error)
    }
}