robomotion 0.1.3

Official Rust SDK for building Robomotion RPA packages
Documentation
//! Tool response functions for AI tool integration.

use crate::message::Context;
use crate::runtime::{emit_input, Result};
use serde_json::{json, Value};
use std::collections::HashMap;

/// Check if the current message is a tool request.
pub fn is_tool_request(ctx: &Context) -> bool {
    ctx.get("__message_type__")
        .and_then(|v| v.as_str().map(|s| s == "tool_request"))
        .unwrap_or(false)
}

/// Send a response back to the LLM Agent and prevent message flow.
pub async fn tool_response(
    ctx: &Context,
    status: &str,
    data: Option<HashMap<String, Value>>,
    error_msg: &str,
) -> Result<()> {
    if !is_tool_request(ctx) {
        return Ok(());
    }

    let caller_id = ctx.get("__tool_caller_id__");
    let agent_node_id = ctx.get("__agent_node_id__");

    // Create response context
    let response_ctx = Context::new(b"{}");

    // Copy essential fields
    if let Some(msg_id) = ctx.get("id") {
        response_ctx.set("id", msg_id)?;
    }
    if let Some(session_id) = ctx.get("session_id") {
        response_ctx.set("session_id", session_id)?;
    }
    if let Some(query) = ctx.get("query") {
        response_ctx.set("query", query)?;
    }

    // Set tool response fields
    response_ctx.set("__message_type__", "tool_response")?;
    if let Some(caller) = caller_id {
        response_ctx.set("__tool_caller_id__", caller)?;
    }
    response_ctx.set("__tool_status__", status)?;

    if !error_msg.is_empty() {
        response_ctx.set("__tool_error__", error_msg)?;
    }
    if let Some(d) = data {
        response_ctx.set("__tool_data__", json!(d))?;
    }

    // Send response back to LLM Agent
    if let Some(agent_id) = agent_node_id {
        if let Some(agent_id_str) = agent_id.as_str() {
            let response_data = response_ctx.get_raw()?;
            emit_input(agent_id_str, &response_data).await?;
        }
    }

    // Prevent message flow by clearing context
    ctx.set_raw(None)?;

    Ok(())
}

/// Convenience function for successful tool response.
pub async fn tool_success(ctx: &Context, data: HashMap<String, Value>) -> Result<()> {
    tool_response(ctx, "success", Some(data), "").await
}

/// Convenience function for failed tool response.
pub async fn tool_error(ctx: &Context, error_msg: &str) -> Result<()> {
    tool_response(ctx, "error", None, error_msg).await
}