runifold-tool 0.3.0

Typed, capability-gated tool execution boundary for Runifold
Documentation
use std::{future::Future, pin::Pin};

use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{ToolContext, ToolDescriptor, ToolError};

/// A boxed, sendable future returned by a tool.
#[cfg(not(target_arch = "wasm32"))]
pub type ToolFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

/// A boxed Tool future on single-threaded WASM.
#[cfg(target_arch = "wasm32")]
pub type ToolFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;

/// Successful canonical tool output.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ToolOutput {
    /// Structured output value.
    pub value: Value,
    /// Whether the value is safe to expose verbatim to a model.
    pub model_visible: bool,
}

impl ToolOutput {
    /// Creates model-visible output.
    pub const fn model_visible(value: Value) -> Self {
        Self {
            value,
            model_visible: true,
        }
    }
}

/// Object-safe execution boundary implemented by tools.
pub trait Tool: Send + Sync {
    /// Returns the tool's immutable semantic contract.
    fn descriptor(&self) -> &ToolDescriptor;

    /// Executes one invocation.
    fn invoke(
        &self,
        input: Value,
        context: ToolContext,
    ) -> ToolFuture<'_, Result<ToolOutput, ToolError>>;
}