Skip to content

Add plugin support to objectiveai-viewer (let wrappers contribute panels/visuals/events) #173

@WiggidyW

Description

@WiggidyW

Summary

Add a plugin system to objectiveai-viewer so that third-party programs which wrap ObjectiveAI can hook into the viewer and contribute their own features, panels, and visualizations.

Motivating example: WiggidyW/psychological-operations — a wrapper around ObjectiveAI with its own domain-specific concepts. It (and tools like it) should be able to render their own views inside the same viewer the user already has open, instead of forking the viewer or shipping a parallel UI.

Note: the umbrella orchestrator issue (#171) listed "Plugin system / third-party panels" as out of scope to keep that RFC tractable. This issue tracks it as a follow-on, expected to land after the orchestrator's session model and bidirectional channel are in place.

Why

What plugins should be able to do

  • Register custom panels — full-pane views alongside the existing AgentCompletionView, FunctionExecutionView, FunctionInventionRecursiveView.
  • Register custom event channels — the viewer's HTTP receiver currently has 4 hardcoded routes; plugins should be able to add their own (e.g. psyops/operations) with the same HMAC-signed POST contract.
  • Decorate existing views — inline annotations on existing event types (e.g. badge a tool call with wrapper-specific context).
  • Contribute to control surfaces — once Turn objectiveai-viewer into a GUI swarm orchestrator (interactive co-pilot for human + coding agent) #171 lands a control channel, plugins should be able to register actions (buttons, modals, slash commands) that round-trip to the wrapper's own backend.
  • Bring their own schemas — Zod schemas (or JSON Schema) for validating their event payloads, mirroring how the viewer already routes incoming chunks.

Proposed architecture (sketch — open for redesign)

Three pieces:

  1. Plugin manifest — a JSON/TS descriptor declaring channel names, panel components, event schemas, and required permissions.
  2. Loader — at viewer startup, scan a known directory (e.g. $CONFIG_BASE_DIR/.objectiveai/viewer/plugins/) or a configured remote URL list. Each plugin ships as an ES module bundle plus its manifest.
  3. Sandboxed runtime — plugins run in an iframe or web worker with a postMessage bridge to the host. The host enforces which event channels the plugin can read and which Tauri commands (post-Turn objectiveai-viewer into a GUI swarm orchestrator (interactive co-pilot for human + coding agent) #171) it can invoke.

Open question: native (Rust) plugins vs JS-only? JS-only is the obvious starting point (no FFI surface, no WASM dance, no Tauri rebuild per plugin). The HTTP receiver side stays in the host; plugins only contribute UI + schemas.

Scope

In scope

  • Plugin manifest format and loader.
  • Panel registration API (registerPanel({ id, title, component, channels })).
  • Custom event channel registration with HMAC verification reusing the host's existing signature_middleware.
  • Schema-driven event routing so plugins can define and parse their own payloads.
  • Permissions model — plugins declare what they need; user approves on first install.
  • Documentation + a sample plugin (probably from psychological-operations) demonstrating the full surface.

Out of scope

Key technical decisions

  1. Sandbox boundary. Iframe (strong isolation, harder integration) vs web worker (no DOM, harder to render UI) vs same-realm with capability tokens (simplest, weakest). Recommendation: iframe.
  2. Distribution format. ES module + manifest as a directory, vs a single bundled .zip/.tar.gz, vs npm-style package. Recommendation: directory with manifest, signed.
  3. Permissions UX. First-install prompt vs always-on capability tokens vs no-op (trust everything). Recommendation: first-install prompt listing requested channels and actions.
  4. Integration with the host's HMAC. Plugins share the host's VIEWER_SECRET, or each plugin gets its own signature key. Recommendation: shared secret in v1, per-plugin keys when we have a marketplace.

Open questions

  • Should plugins be able to push events to the desktop viewer over HTTP from outside the viewer process (i.e. a wrapper's backend POSTs psyops/operations events directly)? If yes, plugins need to reserve URL paths at the host level — affects routing in objectiveai-viewer/src-tauri/src/run.rs.
  • How does this interact with the shared UI extraction proposed in Add objectiveai-viewer to objectiveai-web (browser/cloud surface in addition to Tauri desktop) #172? The plugin API needs to live in the shared package so both desktop and (eventually) web can host plugins.
  • Versioning: plugin API stability guarantees, deprecation policy.
  • Telemetry: do we let plugins report their own usage, or stay strictly local-first?

Files most likely to be touched

  • objectiveai-viewer/src/App.tsx → add panel registry, plugin loader bootstrap.
  • objectiveai-viewer/src-tauri/src/run.rs → optional dynamic route registration for plugin event channels; permission-gated.
  • New: objectiveai-viewer/src/plugins/ → manifest types, loader, sandbox bridge, registry.
  • New: objectiveai-viewer/docs/plugin-api.md → authoring guide.

Acceptance

  • A plugin authored against the documented API can be dropped into the plugin directory, loaded on viewer start, register a panel, ingest its own event channel, and render correctly without modifying the viewer's source.
  • psychological-operations ships such a plugin as the reference implementation.
  • The viewer functions identically with zero plugins installed.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions