pub type PluginStream = Pin<Box<dyn Stream<Item = Result<StreamingEvent, PluginError>> + Send>>;Expand description
A boxed async stream of streaming events from a plugin.
Each item is a Result, so individual events can fail (e.g., mid-stream
network error) without aborting the stream. The outer Result<PluginStream, _>
returned by the trait methods represents errors that occur before the stream
starts (e.g., invalid config, plugin unavailable).
§'static lifetime requirement
PluginStream is BoxStream<'static, _>, meaning the stream must own
everything it touches. Chat Engine drives the stream to completion after
the trait method returns, so any reference into &self would dangle once
the call frame unwinds.
The compiler error you will see if you violate this is a lifetime mismatch
pointing at the inside of your async_stream::stream! { … },
futures::stream::unfold(…), or async closure — not at the trait
signature. The fix is to detach from &self before entering the stream body:
// ❌ Captures `&self.config` — won't satisfy `'static`.
async fn on_message(&self, ctx: MessagePluginCtx)
-> Result<PluginStream, PluginError>
{
Ok(async_stream::stream! {
let response = self.config.client.send(&ctx.messages).await?;
// ...
}.boxed())
}
// ✅ Clone the bits you need out of `self` first.
async fn on_message(&self, ctx: MessagePluginCtx)
-> Result<PluginStream, PluginError>
{
let client = self.config.client.clone();
Ok(async_stream::stream! {
let response = client.send(&ctx.messages).await?;
// ...
}.boxed())
}
// ✅ Or hold the plugin in an `Arc` and clone the handle.
// (works well if you need many fields and `Clone` on each is awkward)
// self: Arc<MyPlugin> at the call site, then:
let me = Arc::clone(&self);
Ok(async_stream::stream! {
me.do_things(...).await;
}.boxed())For non-streaming responses, prefer stream_from_events — it side-steps
the issue entirely by collecting all events synchronously before returning.
Aliased Type§
pub struct PluginStream { /* private fields */ }