mod private
{
use std::collections::HashMap;
use serde_json::Value;
pub type ToolResult = Result< String, String >;
pub trait ToolExecutor : Send + Sync
{
fn name( &self ) -> &str;
fn description( &self ) -> &str;
fn parameter_schema( &self ) -> Value
{
serde_json::json!(
{
"type" : "object",
"properties" : {},
"required" : []
})
}
fn execute( &self, params : Value ) -> ToolResult;
fn definition( &self ) -> crate::ToolDefinition
{
crate::ToolDefinition
{
name : self.name().to_string(),
description : self.description().to_string(),
input_schema : self.parameter_schema(),
}
}
}
pub struct ToolRegistry
{
tools : HashMap< String, Box< dyn ToolExecutor > >,
}
impl std::fmt::Debug for ToolRegistry
{
fn fmt( &self, f : &mut std::fmt::Formatter< '_ > ) -> std::fmt::Result
{
f.debug_struct( "ToolRegistry" )
.field( "tool_count", &self.tools.len() )
.finish()
}
}
impl ToolRegistry
{
#[ must_use ]
pub fn new() -> Self
{
Self
{
tools : HashMap::new(),
}
}
pub fn register( &mut self, tool : Box< dyn ToolExecutor > )
{
let name = tool.name().to_string();
self.tools.insert( name, tool );
}
pub fn get( &self, name : &str ) -> Option< &dyn ToolExecutor >
{
self.tools.get( name ).map( | t | &**t )
}
pub fn execute( &self, name : &str, params : Value ) -> ToolResult
{
let tool = self.get( name )
.ok_or_else( || format!( "Tool '{name}' not found in registry" ) )?;
tool.execute( params )
}
#[ must_use ]
pub fn definitions( &self ) -> Vec< crate::ToolDefinition >
{
self.tools
.values()
.map( | tool | tool.definition() )
.collect()
}
#[ must_use ]
pub fn tool_names( &self ) -> Vec< String >
{
self.tools.keys().cloned().collect()
}
#[ must_use ]
pub fn has_tool( &self, name : &str ) -> bool
{
self.tools.contains_key( name )
}
#[ must_use ]
pub fn len( &self ) -> usize
{
self.tools.len()
}
#[ must_use ]
pub fn is_empty( &self ) -> bool
{
self.tools.is_empty()
}
}
impl Default for ToolRegistry
{
fn default() -> Self
{
Self::new()
}
}
#[ must_use ]
pub fn create_tool_definition(
name : impl Into< String >,
description : impl Into< String >,
input_schema : Value,
) -> crate::ToolDefinition
{
crate::ToolDefinition
{
name : name.into(),
description : description.into(),
input_schema,
}
}
#[ must_use ]
pub fn create_parameter_schema(
properties : &Value,
required : &[ String ],
) -> Value
{
serde_json::json!(
{
"type" : "object",
"properties" : properties,
"required" : required
})
}
}
crate::mod_interface!
{
exposed use
{
ToolExecutor,
ToolRegistry,
ToolResult,
create_tool_definition,
create_parameter_schema,
};
}