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 methods
    fn lashlang_abilities(&self) -> LashlangAbilities { ... }
    fn lashlang_language_features(&self) -> LashlangLanguageFeatures { ... }
    fn lashlang_resources(&self) -> ResourceCatalog { ... }
}
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§

Source

fn lashlang_abilities(&self) -> LashlangAbilities

Source

fn lashlang_language_features(&self) -> LashlangLanguageFeatures

Source

fn lashlang_resources(&self) -> ResourceCatalog

Host-owned Lashlang catalog entries that code may link against.

This only affects the execution surface. It is intentionally not rendered into prompts automatically; hosts remain responsible for describing their resources through prompt contributions.

Dyn Compatibility§

This trait is dyn compatible.

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

Implementors§