Skip to content

Latest commit

 

History

History
66 lines (49 loc) · 4.17 KB

File metadata and controls

66 lines (49 loc) · 4.17 KB

Plugin Runtime Lifecycle

PRX owns exactly one PluginRuntime per canonical workspace in a process. Gateway and Channels obtain the same runtime instead of building independent registries, event buses, and adapters.

Generation boundary

A plugin generation contains the compiled registry plus tool, middleware, hook, cron, provider, and storage adapters derived from it. Every long-lived consumer uses a stable proxy that resolves the current generation at execution time, so install, update, enable, disable, and reload never leave an IM channel or CLI holding a stale provider/storage instance.

WASM providers and storage backends are selected explicitly as wasm:<exported-name> in default_provider, model routes, or memory.backend. The explicit prefix prevents a plugin from shadowing a built-in backend. TUI chat, the interactive and one-shot agent CLIs, gateway, standalone channels, and session workers all initialize the workspace plugin runtime before resolving an explicitly selected WASM backend.

The four middleware stages use JSON envelopes and run in the shared agent tool loop: inbound once per admitted turn, llm_request before each provider call, llm_response after each provider response, and outbound before delivery. Consequently the same transformation path covers TUI, CLI, gateway, and every IM channel. Invalid JSON or structurally invalid message replacements are isolated and the original envelope is preserved.

wasm_plugins_manage also exposes direct component probes for operational verification: middleware_test, cron_run, provider_chat, and storage health/store/recall/forget/count actions. These probes use the same current generation as production traffic; they are not separate mock adapters.

POST /api/plugins/{name}/reload performs these steps:

  1. Serialize reloads for the workspace.
  2. Build a complete candidate manager and every derived adapter without changing the active generation.
  3. Verify that the requested plugin is present in the candidate.
  4. Publish the candidate with one atomic generation swap.

Any parse, compile, or target-presence failure leaves the previous generation active. The API reports the published generation number on success. The event bus remains stable across generations, while old subscriber pumps close and unregister when their adapter generation is released.

Event delivery

EventBus queues are bounded. Publishing never waits for a consumer; when a subscriber queue is full, that event is dropped with a warning. Host subscribe is accepted only for hook-capable instances that own an on-event export. A real pump continuously consumes the subscription receiver and delivers (topic, payload) to that guest export. Other plugin capabilities receive an explicit unsupported error.

Native lifecycle names are bridged into the documented prx.lifecycle.* namespace before WASM dispatch (agent_end maps to prx.lifecycle.agent_stop). Hook manifest events accept string arrays and the documented [[capabilities.events]] table form, with exact, prefix-wildcard, global-wildcard, and legacy short-name matching. Status reports per-adapter invocation counters and the last event/error for end-to-end verification.

Middleware, hook, and cron adapters link the same canonical PDK host ABI as tool plugins, including result-bearing KV mutations plus HTTP, memory, events, WebSocket, and WASI imports. Their host state receives the live memory backend when one is configured.

Admission and trust

  • plugin.toml is limited to 256 KiB and cannot be a symlink.
  • A WASM component is limited to 128 MiB, cannot be a symlink, and its manifest path cannot escape the plugin directory.
  • Directory discovery is deterministic and capped at 256 entries.
  • A plugin missing any required sensitive permission is registered with an error status and does not receive a live adapter.

Native hooks

hooks.json reload is content-addressed: parsing and validation finish before one state swap, and an invalid candidate preserves the prior generation. Hook payloads, configuration, stderr, action counts, arguments, environment entries, and timeouts are bounded. Timeout kills and reaps the child, and the restrictive payload tempfile is removed through RAII.