openfunctions-rs 0.1.0

A universal framework for creating and managing LLM tools and agents
Documentation
//! Runtime for executing tools and agent functions.
//!
//! This module provides the `Runtime`, which is responsible for safely
//! executing tools in a sandboxed environment. It manages the execution
//! lifecycle, including setting up the environment, invoking the tool,
//! and capturing the results.

use crate::core::{Config, Registry, Tool};
use crate::models::{ExecutionResult, FunctionCall};
use anyhow::Result;
use tracing::info;

pub mod environment;
pub mod executor;
pub mod sandbox;

pub use environment::Environment;
pub use executor::Executor;
pub use sandbox::Sandbox;

/// The runtime for executing tools.
///
/// The `Runtime` orchestrates the execution of tools, using an `Executor`
/// to run the tool's code in a controlled `Sandbox` with a prepared
/// `Environment`.
pub struct Runtime {
    #[allow(dead_code)]
    config: Config,
    // TODO: executor: executor::Executor,
}

impl Runtime {
    /// Creates a new `Runtime` with the given configuration.
    pub fn new(config: Config) -> Self {
        Self {
            config,
            // TODO: executor: executor::Executor::new(&config.runtime),
        }
    }

    /// Executes a tool with the given arguments.
    ///
    /// # Arguments
    /// * `tool` - The tool to execute.
    /// * `args` - The arguments for the tool, as a JSON value.
    pub async fn execute_tool(
        &self,
        tool: &Tool,
        args: serde_json::Value,
    ) -> Result<ExecutionResult> {
        info!(tool = %tool.name, args = ?args, "Executing tool");
        // TODO: Implement the full execution logic.
        // This will involve:
        // 1. Creating an environment for the execution.
        // 2. Preparing the arguments.
        // 3. Using the executor to run the tool in a sandbox.
        // 4. Capturing and returning the ExecutionResult.

        let start_time = std::time::Instant::now();

        Ok(ExecutionResult {
            success: true,
            output: "Executing tool... (not yet implemented)".to_string(),
            error: None,
            duration: start_time.elapsed(),
            metadata: std::collections::HashMap::new(),
        })
    }

    /// Executes a function call request.
    ///
    /// This is a convenience method that looks up the tool in the registry
    /// and then calls `execute_tool`.
    ///
    /// # Arguments
    /// * `call` - The `FunctionCall` request.
    /// * `registry` - The `Registry` to look up the tool in.
    pub async fn execute_function_call(
        &self,
        call: &FunctionCall,
        registry: &Registry,
    ) -> Result<ExecutionResult> {
        info!(function_name = %call.name, "Executing function call");
        let tool = registry
            .get_tool(&call.name)
            .ok_or_else(|| anyhow::anyhow!("Tool not found: {}", call.name))?;

        self.execute_tool(tool, call.arguments.clone()).await
    }
}