Skip to main content
@altnautica/plugin-sdk (v1.0.0, GPL-3.0-or-later) is the GCS browser-half SDK: the package a plugin’s Mission Control side imports. It is one of three SDKs an ADOS plugin can use. The other two are the agent half, which runs on the companion: the Python SDK (ados.sdk) and the Rust SDK (the ados-sdk crate). A plugin’s GCS half always uses this one; its agent half picks Python or Rust. This SDK hides the postMessage envelope shape and gives you a typed PluginContext instead.

Install

The standalone npm publish lands with the hosted registry. Until then the supported workflow is to develop your plugin inside the altnautica/ADOSExtensions monorepo as a pnpm workspace member; the SDK resolves via workspace:^ against the in-tree packages/plugin-sdk. The Quickstart walks through the clone and scaffold flow. The package is a peer of the host iframe runtime. It has no runtime dependencies and ships ESM only.

definePlugin

The single entry point:
mount is awaited; if it throws, the host receives a handler_error envelope and surfaces it in the install dialog. info is optional. Most plugins write async mount(ctx) and ignore it; the second argument carries the host build version, the plugin’s resolved permission set, and the operator-edited config. The same pattern applies to unmount.

PluginContext

The argument the SDK hands to mount:
Each domain group is small on purpose. Plugins drop down to ctx.client.request(method, capability, args) for any RPC the helpers do not expose. definePlugin builds this context for you. If you need one outside the lifecycle (in a test, or to wire it by hand), construct it with createPluginContext:
The events group subscribes to one-way host pushes that have no request and response round-trip: video-overlay host props, an agent plugin’s state read-back, and any other topic the host forwards to the iframe. subscribe returns an unsubscribe function.

PluginClient

The lower-level RPC client:
Methods:
  • request(method, capability, args, options?): send a request and await the response. Default timeout 5s.
  • on(method, handler): subscribe to host-pushed events.
  • subscribeTelemetry(topic, handler): convenience that does both request("telemetry.subscribe", ...) and on("telemetry.<topic>", ...).
  • dispose(): tear down listeners and reject in-flight RPCs.

HostError

Thrown by client.request when the host returns an error envelope:
The code field is the machine-readable error code from the envelope. The message is human-readable; do not branch on it.

Test harness

The harness:
  • mounts the plugin against an in-memory transport (no real iframe);
  • captures every RPC in harness.calls, grouped helpers in harness.notifications and harness.recordingMarks;
  • accepts pushTelemetry, pushEvent, pushConfig, pushTheme;
  • supports failNext(method, code, message) to simulate host failures;
  • mirrors the real bridge’s capability gate.
This means you can validate a plugin end-to-end inside Vitest without running Mission Control or a real drone.

Building the bundle

The SDK does not ship a build step. Plugin repos use esbuild, Vite, or any other bundler that emits ESM. The create-ados-plugin template uses esbuild for zero-config builds:
Output goes to gcs/plugin.bundle.js. The manifest’s gcs.entrypoint field points at the same path. The bundle is not hashed in the manifest; its integrity is bound by the canonical payload hash that the signing step writes into the separate SIGNATURE file.
This SDK is the GCS browser half only. For the companion-side plugin half, see the Python SDK (ados.sdk) or the Rust SDK (the ados-sdk crate). A hybrid plugin ships both halves from a single manifest.yaml.