agentool 0.2.0

Rust toolkit for AI agents: JSON Schema-defined tools for workspace files, search, web, Markdown, Git, memory, human-in-the-loop hooks, and todos.
Documentation
use serde_json::{json, Value};

use crate::core::json::{json_str, ok_data};
use crate::tool::ToolResult;

use super::backend::NotifyLevel;
use super::InteractContext;

fn options_from_params(params: &Value) -> Option<Vec<String>> {
    params.get("options").and_then(|v| v.as_array()).map(|arr| {
        arr.iter()
            .filter_map(|x| x.as_str().map(String::from))
            .collect::<Vec<_>>()
    })
}

pub(crate) async fn op_ask(ctx: &InteractContext, params: &Value) -> ToolResult {
    let question = json_str(params, "question")?;
    let mut options = options_from_params(params);
    if let Some(ref o) = options {
        if o.is_empty() {
            options = None;
        }
    }
    let timeout_secs = params.get("timeout").and_then(|v| v.as_u64());
    let answer = ctx.backend.ask(question, options, timeout_secs).await?;
    Ok(ok_data(json!({ "answer": answer })))
}

pub(crate) async fn op_confirm(ctx: &InteractContext, params: &Value) -> ToolResult {
    let message = json_str(params, "message")?;
    let default = params
        .get("default")
        .and_then(|v| v.as_bool())
        .unwrap_or(false);
    let timeout_secs = params.get("timeout").and_then(|v| v.as_u64());
    let confirmed = ctx.backend.confirm(message, default, timeout_secs).await?;
    Ok(ok_data(json!({ "confirmed": confirmed })))
}

pub(crate) async fn op_notify(ctx: &InteractContext, params: &Value) -> ToolResult {
    let message = json_str(params, "message")?;
    let level = match params.get("level").and_then(|v| v.as_str()) {
        None => NotifyLevel::Info,
        Some(s) => NotifyLevel::parse(s)?,
    };
    let sent = ctx.backend.notify(message, level).await?;
    Ok(ok_data(json!({ "sent": sent })))
}