Component

Trait Component 

Source
pub trait Component: Send + 'static {
    // Required method
    fn serve(
        self,
        client: impl Component,
    ) -> impl Future<Output = Result<(), Error>> + Send;

    // Provided method
    fn into_server(
        self,
    ) -> (Channel, Pin<Box<dyn Future<Output = Result<(), Error>> + Send>>)
       where Self: Sized { ... }
}
Expand description

Re-export component types from sacp A component that can participate in the Agent-Client Protocol.

This trait represents anything that can communicate via JSON-RPC messages over channels - agents, proxies, in-process connections, or any ACP-speaking component.

§Component Types

The trait is implemented by several built-in types representing different communication patterns:

  • ByteStreams: A component communicating over byte streams (stdin/stdout, sockets, etc.)
  • Channel: A component communicating via in-process message channels (for testing or direct connections)
  • AcpAgent: An external agent running in a separate process with stdio communication
  • Custom components: Proxies, transformers, or any ACP-aware service

§Two Ways to Serve

Components can be used in two ways:

  1. serve(client) - Serve by forwarding to another component (most components implement this)
  2. into_server() - Convert into a channel endpoint and server future (base cases implement this)

Most components only need to implement serve(client) - the into_server() method has a default implementation that creates an intermediate channel and calls serve.

§Implementation Example

use sacp::Component;

struct MyProxy {
    config: ProxyConfig,
}

impl Component for MyProxy {
    async fn serve(self, client: impl Component) -> Result<(), sacp::Error> {
        // Set up handler chain that forwards to client
        sacp::JrHandlerChain::new()
            .name("my-proxy")
            .on_receive_request(async |req: MyRequest, cx| {
                // Transform and forward request
                cx.respond(MyResponse { status: "ok".into() })
            })
            .serve(client)
            .await
    }
}

§Heterogeneous Collections

For storing different component types in the same collection, use DynComponent:

let components: Vec<DynComponent> = vec![
    DynComponent::new(proxy1),
    DynComponent::new(proxy2),
    DynComponent::new(agent),
];

Required Methods§

Source

fn serve( self, client: impl Component, ) -> impl Future<Output = Result<(), Error>> + Send

Serve this component by forwarding to a client component.

Most components implement this method to set up their handler chain and forward messages to the provided client.

§Arguments
  • client - The component to forward messages to
§Returns

A future that resolves when the component stops serving, either successfully or with an error. The future must be Send.

Provided Methods§

Source

fn into_server( self, ) -> (Channel, Pin<Box<dyn Future<Output = Result<(), Error>> + Send>>)
where Self: Sized,

Convert this component into a channel endpoint and server future.

This method returns:

  • A Channel that can be used to communicate with this component
  • A BoxFuture that runs the component’s server logic

The default implementation creates an intermediate channel pair and calls serve on one endpoint while returning the other endpoint for the caller to use.

Base cases like Channel and ByteStreams override this to avoid unnecessary copying.

§Returns

A tuple of (Channel, BoxFuture) where the channel is for the caller to use and the future must be spawned to run the server.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl Component for DynComponent

Source§

impl Component for Channel

Source§

impl<OB, IB> Component for ByteStreams<OB, IB>
where OB: AsyncWrite + Send + 'static, IB: AsyncRead + Send + 'static,