A plugin can ship up to three pieces in one archive:Documentation Index
Fetch the complete documentation index at: https://docs.altnautica.com/llms.txt
Use this file to discover all available pages before exploring further.
- An agent half (Python subprocess on the drone).
- A GCS half (TypeScript bundle in a sandboxed iframe).
- One or more drivers registered by the agent half.
When to ship two halves
Ship two halves when the plugin needs both of:- Hardware or low-level system access on the drone.
- An operator-facing UI in the GCS.
usb.read on the drone (driver half) plus
a video overlay in the GCS.
Do not split work that belongs in one half. If the plugin only
needs telemetry and renders a panel, it is GCS-only. If the
plugin only does background analytics with no operator UI, it is
agent-only.
Lifecycle ordering
Install order is fixed:- Operator drops
.adospluginto the GCS install dialog. - Manifest is parsed (no disk writes).
- Operator approves permissions. Both halves’ permissions appear in one grid.
- Host calls install on both halves in parallel. The agent host unpacks the agent half; the GCS host registers the bundle in the user’s Convex profile.
- On enable, the agent half starts first. The supervisor
waits for
Type=notifyready signal (default 30 s timeout). - Once the agent reports ready, the GCS half mounts. The GCS bridge gates outbound RPC until the agent acknowledges it is listening.
SIGTERM to the agent.
Cross-half communication
The two halves do not speak directly. They speak through the host’s event bus.plg.<id>.* topics:
event.publish and event.subscribe capabilities are sufficient.
Shared manifest
One manifest. Two contributing blocks:id and version. The host treats
them as one install row.
Version compatibility between halves
Both halves ship in the same archive, so they always carry the same version. The supervisor refuses to load mismatched halves; that case can only happen if someone unpacks an archive and hand-edits one side. What can drift across versions:- Topic schemas published from the agent and consumed by the GCS.
Use a
schema_versionfield in your published payload and branch on it in the GCS. - Persistent state on disk written by the agent and read by the
GCS via Convex. Carry a
data_versionin those rows.
Driver halves
Drivers are agent plugins that subclass one of the typed driver base classes (CameraDriver, GimbalDriver, etc.) and register
with the peripheral manager. See driver layer
for the contract.
A plugin can ship multiple drivers. The Thermal Camera plugin
registers a CameraDriver for the FLIR sensor. A multi-sensor
plugin can register a CameraDriver plus a GpsDriver from the
same agent half:
sensor.camera.register, sensor.gps.register). Both must be
declared in the manifest.
Worked example: hybrid plugin skeleton
Failure modes
| Scenario | What the host does |
|---|---|
| Agent half crashes, GCS still running. | GCS half stays mounted; outbound RPC to the agent returns handler_error. The GCS half should render an “offline” state. |
| GCS half fails to load (bundle 404). | Agent half keeps running. The slot orchestrator marks the iframe failed and shows an error tile. |
| Operator revokes a permission used by only one half. | That half’s affected calls return permission_denied; the other half is unaffected. |