pub struct ToolRouter { /* private fields */ }Expand description
Which client reaches which server.
§Why a plane needs one at all
A ToolId carries a server because two servers may both offer transfer
and they are not the same tool. Nothing enforced that: a plane held exactly
one ToolClient and handed it every id, so a deployment could grant
tool://ledger/read and wire a client connected to a different server —
which then answered, because a transport that never reads the server
component cannot tell the difference. The realistic shape is two servers with
a tool of the same name, where the wrong one runs and reports success.
One client per server, resolved by name, makes that unspellable. A server
nobody registered is ToolError::Unreachable — the honest answer, since
there is no transport that could carry the call.
It is also what lets a plane use more than one kind of tool at once: a
ToolBox of typed in-process tools and an MCP server are two transports,
and a plane routes to both by the server a reference names.
Implementations§
Source§impl ToolRouter
impl ToolRouter
pub fn new() -> Self
Sourcepub fn server(
self,
name: impl Into<String>,
client: Arc<dyn ToolClient>,
) -> Self
pub fn server( self, name: impl Into<String>, client: Arc<dyn ToolClient>, ) -> Self
Route one server’s tools to one client.
§Panics
If the server is already routed. Silently replacing would make registration order decide which transport carries a call, which is the same defect this type exists to remove.
Trait Implementations§
Source§impl Debug for ToolRouter
impl Debug for ToolRouter
Source§impl Default for ToolRouter
impl Default for ToolRouter
Source§impl ToolClient for ToolRouter
impl ToolClient for ToolRouter
Source§fn destination(&self, tool: &ToolId) -> Destination
fn destination(&self, tool: &ToolId) -> Destination
Whatever the routed transport says.
An unrouted server answers Destination::Local rather than refusing:
there is no transport, so there is no destination to grant, and the call
is about to fail as ToolError::Unreachable with the honest reason.
Reporting an egress refusal for a server nobody wired would name the
wrong problem.
Source§fn call<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
tool: &'life1 ToolId,
arguments: &'life2 Value,
provenance: Option<&'life3 Provenance>,
) -> Pin<Box<dyn Future<Output = Result<Value, ToolError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn call<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
tool: &'life1 ToolId,
arguments: &'life2 Value,
provenance: Option<&'life3 Provenance>,
) -> Pin<Box<dyn Future<Output = Result<Value, ToolError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Auto Trait Implementations§
impl !RefUnwindSafe for ToolRouter
impl !UnwindSafe for ToolRouter
impl Freeze for ToolRouter
impl Send for ToolRouter
impl Sync for ToolRouter
impl Unpin for ToolRouter
impl UnsafeUnpin for ToolRouter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more