Skip to main content

PluginFactory

Trait PluginFactory 

Source
pub trait PluginFactory: Send + Sync {
    // Required methods
    fn id(&self) -> &'static str;
    fn build(
        &self,
        ctx: &PluginSessionContext,
    ) -> Result<Arc<dyn SessionPlugin>, PluginError>;

    // Provided method
    fn extension_contributions(&self) -> Vec<PluginExtensionContribution> { ... }
}
Expand description

Registers a plugin with the runtime and produces a per-session SessionPlugin instance for each new session.

§Cheap-build / stateful-factory contract

build(ctx) must be cheap. It runs on the hot path every time a new session is created (including subagents, forked children, and compaction children) and any latency here is paid per session.

Specifically, build must not:

  • perform any I/O (disk reads, HTTP calls, DB queries),
  • compile regexes, templates, or schemas,
  • open network connections or initialize connection pools,
  • load models, parse large config files, or allocate large buffers,
  • block the current thread for non-trivial work.

Expensive state belongs on the PluginFactory struct itself, wrapped in Arc so it can be cheaply cloned into per-session closures. The PluginFactory is constructed once by the embedder and held in the RuntimeEnvironment; its fields outlive every session. Hooks captured into a PluginSpec are closures that clone the Arcs off self and reference the shared state directly, so every session sees the same pool / cache / compiled artifact without rebuilding it.

The typical shape is:

pub struct MyFactory {
    pool: Arc<ConnectionPool>,          // expensive, built once
    compiled: Arc<Regex>,               // expensive, built once
}

impl PluginFactory for MyFactory {
    fn id(&self) -> &'static str { "my_plugin" }

    fn build(&self, _ctx: &PluginSessionContext)
        -> Result<Arc<dyn SessionPlugin>, PluginError>
    {
        // Cheap: clone Arcs, assemble spec, wrap in SpecPlugin.
        let pool = Arc::clone(&self.pool);
        let spec = PluginSpec::new().with_before_turn(Arc::new(move |_ctx| {
            let pool = Arc::clone(&pool);
            Box::pin(async move { /* use pool */ Ok(vec![]) })
        }));
        Ok(Arc::new(SpecPluginFromSpec::new("my_plugin", spec)))
    }
}

Required Methods§

Source

fn id(&self) -> &'static str

Source

fn build( &self, ctx: &PluginSessionContext, ) -> Result<Arc<dyn SessionPlugin>, PluginError>

Produce a session-scoped plugin. Must be cheap — see the trait-level docs for the full contract.

Provided Methods§

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl PluginFactory for StandardProtocolPluginFactory

Source§

fn id(&self) -> &'static str

Source§

fn build( &self, _ctx: &PluginSessionContext, ) -> Result<Arc<dyn SessionPlugin>, PluginError>

Implementors§