Skip to main content

MatchDispatchFrom

Struct MatchDispatchFrom 

Source
pub struct MatchDispatchFrom<Counterpart: Role> { /* private fields */ }
Expand description

Role-aware helper for pattern-matching on untyped JSON-RPC requests.

Prefer this over implementing HandleDispatchFrom directly. This provides a more ergonomic API for matching on message types in connection handlers.

Use this when you need peer-aware transforms (e.g., unwrapping proxy envelopes) before parsing messages. For simple parsing without peer awareness (e.g., inside a callback), use MatchDispatch instead.

This wraps MatchDispatch and applies peer-specific message transformations via remote_style().handle_incoming_dispatch() before delegating to MatchDispatch for the actual parsing.

§Example

MatchDispatchFrom::new(message, cx)
    .if_request(|req: InitializeRequest, responder: agent_client_protocol::Responder<InitializeResponse>| async move {
        // Handle initialization
        let response = InitializeResponse::new(req.protocol_version)
            .agent_capabilities(AgentCapabilities::new());
        responder.respond(response)
    })
    .await
    .if_request(|_req: PromptRequest, responder: agent_client_protocol::Responder<PromptResponse>| async move {
        // Handle prompts
        responder.respond(PromptResponse::new(StopReason::EndTurn))
    })
    .await
    .otherwise(|message| async move {
        // Fallback for unrecognized messages
        match message {
            Dispatch::Request(_, responder) => responder.respond_with_error(agent_client_protocol::util::internal_error("unknown method")),
            Dispatch::Notification(_) | Dispatch::Response(_, _) => Ok(()),
        }
    })
    .await

Implementations§

Source§

impl<Counterpart: Role> MatchDispatchFrom<Counterpart>

Source

pub fn new(message: Dispatch, cx: &ConnectionTo<Counterpart>) -> Self

Create a new pattern matcher for the given untyped request message.

Source

pub async fn if_request<Req: JsonRpcRequest, H>( self, op: impl AsyncFnOnce(Req, Responder<Req::Response>) -> Result<H, Error>, ) -> Self
where Counterpart: HasPeer<Counterpart>, H: IntoHandled<(Req, Responder<Req::Response>)>,

Try to handle the message as a request of type Req.

If the message can be parsed as Req, the handler op is called with the parsed request and a typed request context. If parsing fails or the message was already handled by a previous handle_if, this call has no effect.

The handler can return either () (which becomes Handled::Yes) or an explicit Handled value to control whether the message should be passed to the next handler.

Returns self to allow chaining multiple handle_if calls.

Source

pub async fn if_request_from<Peer: Role, Req: JsonRpcRequest, H>( self, peer: Peer, op: impl AsyncFnOnce(Req, Responder<Req::Response>) -> Result<H, Error>, ) -> Self
where Counterpart: HasPeer<Peer>, H: IntoHandled<(Req, Responder<Req::Response>)>,

Try to handle the message as a request of type Req from a specific peer.

This is similar to if_request, but first applies peer-specific message transformation (e.g., unwrapping SuccessorMessage envelopes when receiving from an agent via a proxy).

§Parameters
  • peer - The peer the message is expected to come from
  • op - The handler to call if the message matches
Source

pub async fn if_notification<N: JsonRpcNotification, H>( self, op: impl AsyncFnOnce(N) -> Result<H, Error>, ) -> Self
where Counterpart: HasPeer<Counterpart>, H: IntoHandled<N>,

Try to handle the message as a notification of type N.

If the message can be parsed as N, the handler op is called with the parsed notification and connection context. If parsing fails or the message was already handled by a previous handle_if, this call has no effect.

The handler can return either () (which becomes Handled::Yes) or an explicit Handled value to control whether the message should be passed to the next handler.

Returns self to allow chaining multiple handle_if calls.

Source

pub async fn if_notification_from<Peer: Role, N: JsonRpcNotification, H>( self, peer: Peer, op: impl AsyncFnOnce(N) -> Result<H, Error>, ) -> Self
where Counterpart: HasPeer<Peer>, H: IntoHandled<N>,

Try to handle the message as a notification of type N from a specific peer.

This is similar to if_notification, but first applies peer-specific message transformation (e.g., unwrapping SuccessorMessage envelopes when receiving from an agent via a proxy).

§Parameters
  • peer - The peer the message is expected to come from
  • op - The handler to call if the message matches
Source

pub async fn if_message_from<Peer: Role, Req: JsonRpcRequest, N: JsonRpcNotification, H>( self, peer: Peer, op: impl AsyncFnOnce(Dispatch<Req, N>) -> Result<H, Error>, ) -> Self
where Counterpart: HasPeer<Peer>, H: IntoHandled<Dispatch<Req, N>>,

Try to handle the message as a typed Dispatch<Req, N> from a specific peer.

This is similar to MatchDispatch::if_message, but first applies peer-specific message transformation (e.g., unwrapping SuccessorMessage envelopes).

§Parameters
  • peer - The peer the message is expected to come from
  • op - The handler to call if the message matches
Source

pub async fn if_response_to<Req: JsonRpcRequest, H>( self, op: impl AsyncFnOnce(Result<Req::Response, Error>, ResponseRouter<Req::Response>) -> Result<H, Error>, ) -> Self

Try to handle the message as a response to a request of type Req.

If the message is a Response variant and the method matches Req, the handler is called with the result (which may be Ok or Err) and a typed response context.

Unlike requests and notifications, responses don’t need peer-specific transforms (they don’t have the SuccessorMessage envelope structure), so this method delegates directly to MatchDispatch::if_response_to.

Source

pub async fn if_ok_response_to<Req: JsonRpcRequest, H>( self, op: impl AsyncFnOnce(Req::Response, ResponseRouter<Req::Response>) -> Result<H, Error>, ) -> Self
where Counterpart: HasPeer<Counterpart>, H: IntoHandled<(Req::Response, ResponseRouter<Req::Response>)>,

Try to handle the message as a successful response to a request of type Req.

If the message is a Response variant with an Ok result and the method matches Req, the handler is called with the parsed response and a typed response context. Error responses are passed through without calling the handler.

This is a convenience wrapper around if_response_to.

Source

pub async fn if_response_to_from<Req: JsonRpcRequest, Peer: Role, H>( self, peer: Peer, op: impl AsyncFnOnce(Result<Req::Response, Error>, ResponseRouter<Req::Response>) -> Result<H, Error>, ) -> Self
where Counterpart: HasPeer<Peer>, H: IntoHandled<(Result<Req::Response, Error>, ResponseRouter<Req::Response>)>,

Try to handle the message as a response to a request of type Req from a specific peer.

If the message is a Response variant, the method matches Req, and the role_id matches the expected peer, the handler is called with the result and a typed response context.

This is used to filter responses by the peer they came from, which is important in proxy scenarios where responses might arrive from multiple peers.

Source

pub async fn if_ok_response_to_from<Req: JsonRpcRequest, Peer: Role, H>( self, peer: Peer, op: impl AsyncFnOnce(Req::Response, ResponseRouter<Req::Response>) -> Result<H, Error>, ) -> Self
where Counterpart: HasPeer<Peer>, H: IntoHandled<(Req::Response, ResponseRouter<Req::Response>)>,

Try to handle the message as a successful response to a request of type Req from a specific peer.

This is a convenience wrapper around if_response_to_from for the common case where you only care about successful responses.

Source

pub fn done(self) -> Result<Handled<Dispatch>, Error>

Complete matching, returning Handled::No if no match was found.

Source

pub async fn otherwise( self, op: impl AsyncFnOnce(Dispatch) -> Result<(), Error>, ) -> Result<(), Error>

Handle messages that didn’t match any previous handle_if call.

This is the fallback handler that receives the original untyped message if none of the typed handlers matched. You must call this method to complete the pattern matching chain and get the final result.

Source

pub async fn otherwise_delegate( self, handler: impl HandleDispatchFrom<Counterpart>, ) -> Result<Handled<Dispatch>, Error>

Handle messages that didn’t match any previous handle_if call.

This is the fallback handler that receives the original untyped message if none of the typed handlers matched. You must call this method to complete the pattern matching chain and get the final result.

Trait Implementations§

Source§

impl<Counterpart: Debug + Role> Debug for MatchDispatchFrom<Counterpart>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<Counterpart> Freeze for MatchDispatchFrom<Counterpart>
where Counterpart: Freeze,

§

impl<Counterpart> !RefUnwindSafe for MatchDispatchFrom<Counterpart>

§

impl<Counterpart> Send for MatchDispatchFrom<Counterpart>

§

impl<Counterpart> !Sync for MatchDispatchFrom<Counterpart>

§

impl<Counterpart> Unpin for MatchDispatchFrom<Counterpart>
where Counterpart: Unpin,

§

impl<Counterpart> UnsafeUnpin for MatchDispatchFrom<Counterpart>
where Counterpart: UnsafeUnpin,

§

impl<Counterpart> !UnwindSafe for MatchDispatchFrom<Counterpart>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoMaybeUndefined<T> for T

Source§

impl<T> IntoOption<T> for T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more