steer_tools/
traits.rs

1use async_trait::async_trait;
2use serde::Serialize;
3use serde_json::Value;
4
5use crate::context::ExecutionContext;
6use crate::error::ToolError;
7use crate::result::{ToolOutput, ToolResult as ToolResultEnum};
8use crate::schema::InputSchema;
9
10/// Type alias for tool execution results
11pub type ToolResult<T> = Result<T, ToolError>;
12
13#[async_trait]
14pub trait Tool: Send + Sync + 'static {
15    /// The concrete output type for this tool
16    type Output: ToolOutput + Serialize;
17
18    /// A unique, stable identifier for the tool (e.g., "bash", "edit_file").
19    fn name(&self) -> &'static str;
20
21    /// A description of what the tool does.
22    fn description(&self) -> String;
23
24    /// The JSON schema defining the tool's expected input parameters.
25    fn input_schema(&self) -> &'static InputSchema;
26
27    /// Executes the tool with the given parameters and execution context.
28    ///
29    /// # Arguments
30    /// * `parameters` - The parameters for the tool call, matching the `input_schema`.
31    /// * `context` - Execution context containing cancellation token, working directory, etc.
32    ///
33    /// # Returns
34    /// A `ToolResult` containing the typed output on success, or a `ToolError` on failure.
35    async fn execute(
36        &self,
37        parameters: Value,
38        context: &ExecutionContext,
39    ) -> ToolResult<Self::Output>;
40
41    /// Indicates if this tool requires user approval before execution.
42    ///
43    /// Tools that modify the filesystem or external state should return true.
44    /// Default implementation returns true (requiring approval).
45    /// Tools should override this to return false if they only read data.
46    fn requires_approval(&self) -> bool {
47        true
48    }
49}
50
51#[async_trait]
52pub trait ExecutableTool: Send + Sync {
53    fn name(&self) -> &'static str;
54    fn description(&self) -> String;
55    fn input_schema(&self) -> &'static InputSchema;
56    async fn run(&self, params: Value, ctx: &ExecutionContext)
57    -> Result<ToolResultEnum, ToolError>;
58    fn requires_approval(&self) -> bool;
59}
60
61#[async_trait]
62impl<T> ExecutableTool for T
63where
64    T: Tool + Send + Sync,
65    T::Output: Into<ToolResultEnum> + Send,
66{
67    fn name(&self) -> &'static str {
68        Tool::name(self)
69    }
70
71    fn description(&self) -> String {
72        Tool::description(self)
73    }
74
75    fn input_schema(&self) -> &'static InputSchema {
76        Tool::input_schema(self)
77    }
78
79    async fn run(&self, p: Value, c: &ExecutionContext) -> Result<ToolResultEnum, ToolError> {
80        Ok(Tool::execute(self, p, c).await?.into())
81    }
82
83    fn requires_approval(&self) -> bool {
84        Tool::requires_approval(self)
85    }
86}