use crate::messages::ToolDefinition;
use crate::tools::error::ToolError;
use serde_json::Value;
use std::fmt::Debug;
use std::future::Future;
use std::pin::Pin;
use std::time::Duration;
pub use crate::messages::ToolDefinition as ToolDef;
#[derive(Debug, Clone)]
pub struct ToolConfig {
pub definition: ToolDefinition,
pub sandboxed: bool,
pub timeout: Duration,
}
impl ToolConfig {
#[must_use]
pub fn new(definition: ToolDefinition) -> Self {
Self {
definition,
sandboxed: false,
timeout: Duration::from_secs(30),
}
}
#[must_use]
pub fn with_sandbox(mut self, sandboxed: bool) -> Self {
self.sandboxed = sandboxed;
self
}
#[must_use]
pub fn with_timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
}
impl Default for ToolConfig {
fn default() -> Self {
Self {
definition: ToolDefinition {
name: "unnamed".to_string(),
description: "An unnamed tool".to_string(),
input_schema: serde_json::json!({
"type": "object",
"properties": {},
"required": []
}),
},
sandboxed: false,
timeout: Duration::from_secs(30),
}
}
}
pub type ToolExecutionFuture =
Pin<Box<dyn Future<Output = Result<Value, ToolError>> + Send + Sync + 'static>>;
pub trait ToolExecutorTrait: Send + Sync + Debug {
fn execute(&self, args: Value) -> ToolExecutionFuture;
fn requires_sandbox(&self) -> bool {
false
}
fn timeout(&self) -> Duration {
Duration::from_secs(30)
}
fn validate_args(&self, _args: &Value) -> Result<(), ToolError> {
Ok(())
}
}
pub type BoxedToolExecutor = Box<dyn ToolExecutorTrait>;
#[cfg(test)]
mod tests {
use super::*;
fn make_test_definition(name: &str, description: &str) -> ToolDefinition {
ToolDefinition {
name: name.to_string(),
description: description.to_string(),
input_schema: serde_json::json!({"type": "object"}),
}
}
#[test]
fn tool_config_default_timeout() {
let config = ToolConfig::new(make_test_definition("t", "d"));
assert_eq!(config.timeout, Duration::from_secs(30));
}
#[test]
fn tool_config_with_sandbox() {
let config = ToolConfig::new(make_test_definition("t", "d")).with_sandbox(true);
assert!(config.sandboxed);
}
#[test]
fn tool_config_with_timeout() {
let config =
ToolConfig::new(make_test_definition("t", "d")).with_timeout(Duration::from_secs(60));
assert_eq!(config.timeout, Duration::from_secs(60));
}
#[test]
fn tool_config_default() {
let config = ToolConfig::default();
assert_eq!(config.definition.name, "unnamed");
assert!(!config.sandboxed);
assert_eq!(config.timeout, Duration::from_secs(30));
}
}