1use std::{future::Future, pin::Pin};
2
3use crate::{
4 ToolError,
5 execution::{ToolHandlerInput, ToolHandlerOutput},
6 sources::{local, mcp},
7};
8
9pub trait ToolHandlerBackend: Send + 'static {
18 fn step(
28 &mut self,
29 input: ToolHandlerInput,
30 ) -> impl Future<Output = Result<ToolHandlerOutput, ToolError>> + Send + '_;
31}
32
33pub struct ToolHandler {
42 inner: InnerToolHandler,
43}
44
45enum InnerToolHandler {
46 Local(local::handler::LocalToolHandler),
47 Mcp(mcp::handler::McpToolHandler),
48 Extension(Box<dyn ErasedToolHandlerBackend>),
49}
50
51impl ToolHandler {
52 pub(crate) fn from_local(handler: local::handler::LocalToolHandler) -> Self {
53 Self {
54 inner: InnerToolHandler::Local(handler),
55 }
56 }
57
58 pub(crate) fn from_mcp(handler: mcp::handler::McpToolHandler) -> Self {
59 Self {
60 inner: InnerToolHandler::Mcp(handler),
61 }
62 }
63
64 pub(crate) fn from_extension<B: ToolHandlerBackend>(backend: B) -> Self {
65 Self {
66 inner: InnerToolHandler::Extension(Box::new(backend)),
67 }
68 }
69}
70
71impl std::fmt::Debug for ToolHandler {
72 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 formatter
74 .debug_struct("ToolHandler")
75 .finish_non_exhaustive()
76 }
77}
78
79trait ErasedToolHandlerBackend: Send {
80 fn step_erased(
81 &mut self,
82 input: ToolHandlerInput,
83 ) -> Pin<Box<dyn Future<Output = Result<ToolHandlerOutput, ToolError>> + Send + '_>>;
84}
85
86impl<B: ToolHandlerBackend> ErasedToolHandlerBackend for B {
87 fn step_erased(
88 &mut self,
89 input: ToolHandlerInput,
90 ) -> Pin<Box<dyn Future<Output = Result<ToolHandlerOutput, ToolError>> + Send + '_>> {
91 Box::pin(self.step(input))
92 }
93}
94
95impl ToolHandlerBackend for InnerToolHandler {
96 async fn step(&mut self, input: ToolHandlerInput) -> Result<ToolHandlerOutput, ToolError> {
97 match self {
98 Self::Local(handler) => handler.step(input).await,
99 Self::Mcp(handler) => handler.step(input).await,
100 Self::Extension(handler) => handler.step_erased(input).await,
101 }
102 }
103}
104
105impl ToolHandlerBackend for ToolHandler {
106 fn step(
107 &mut self,
108 input: ToolHandlerInput,
109 ) -> impl Future<Output = Result<ToolHandlerOutput, ToolError>> + Send + '_ {
110 self.inner.step(input)
111 }
112}