Skip to main content

sim_lib_agent/
tool_projection.rs

1use std::sync::Arc;
2
3use sim_kernel::{CapabilityName, Cx, Result, ShapeRef, Symbol, Value};
4use sim_lib_server::ServerAddress;
5
6use crate::tools::{Tool, register_tool};
7use crate::util::installed_codecs;
8
9/// Specification for projecting a runtime value into a local [`Tool`].
10pub struct ToolSpec {
11    /// Symbol the tool is registered and dispatched under.
12    pub symbol: Symbol,
13    /// Human-facing description of the tool.
14    pub description: String,
15    /// Shape the tool's arguments must match.
16    pub args_shape: ShapeRef,
17    /// Shape the tool's result is checked against, if any.
18    pub result_shape: Option<ShapeRef>,
19    /// Category symbol grouping the tool.
20    pub category: Symbol,
21    /// Capabilities the tool requires to run.
22    pub capabilities: Vec<CapabilityName>,
23    /// Callable value invoked when the tool runs.
24    pub function: Value,
25}
26
27impl Tool {
28    /// Builds a local tool from a [`ToolSpec`], binding installed codecs.
29    pub fn local(cx: &mut Cx, spec: ToolSpec) -> Self {
30        Self {
31            symbol: spec.symbol,
32            description: spec.description,
33            args_shape: spec.args_shape,
34            result_shape: spec.result_shape,
35            category: spec.category,
36            capabilities: spec.capabilities,
37            function: spec.function,
38            address: ServerAddress::Local,
39            codecs: installed_codecs(cx),
40        }
41    }
42}
43
44/// Installs a tool into the registry, reusing any existing registration.
45pub fn install_tool(cx: &mut Cx, tool: Arc<Tool>) -> Result<Value> {
46    if let Some(existing) = cx.registry().value_by_symbol(&tool.symbol).cloned()
47        && existing.object().downcast_ref::<Tool>().is_some()
48    {
49        return Ok(existing);
50    }
51    let value = cx.factory().opaque(tool.clone())?;
52    register_tool(cx, tool, value.clone())?;
53    Ok(value)
54}