ados-protocol 0.106.2

Wire contracts for the ADOS Drone Agent: length-prefixed IPC framing, plugin RPC envelope and capability tokens, the vision frame bus, MSP and MAVLink helpers.
Documentation
// @generated by ados-capabilities-codegen from capabilities.toml. Do not edit by hand.
//! Generated plugin RPC dispatch table.
//!
//! Maps every wire method to the dispatch-level capability the plugin IPC
//! server requires before routing it. The source of truth is the
//! `[[method]]` section of `capabilities.toml`; regenerate with
//! `cargo run -p ados-capabilities-codegen`.
//!
//! `required_cap` is `None` for the ungated methods (the event surface and
//! `ping`) and for the methods gated inline by their handler from the
//! request payload; `inline` distinguishes the two so an open method cannot
//! be mistaken for an inline-gated one.

/// One row of the dispatch table: a wire method and its dispatch-level gate.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DispatchMethod {
    pub method: &'static str,
    pub required_cap: Option<&'static str>,
    pub inline: bool,
}

/// Every plugin RPC method, with the capability the dispatch loop requires
/// before routing it.
#[rustfmt::skip]
pub const DISPATCH_METHODS: &[DispatchMethod] = &[
    DispatchMethod { method: "event.publish", required_cap: None, inline: false },
    DispatchMethod { method: "event.subscribe", required_cap: None, inline: false },
    DispatchMethod { method: "ping", required_cap: None, inline: false },
    DispatchMethod { method: "tool.invoke", required_cap: Some("mcp.expose"), inline: false },
    DispatchMethod { method: "telemetry.subscribe", required_cap: Some("telemetry.read"), inline: false },
    DispatchMethod { method: "telemetry.extend", required_cap: Some("telemetry.extend"), inline: false },
    DispatchMethod { method: "mission.read", required_cap: Some("mission.read"), inline: false },
    DispatchMethod { method: "mission.write", required_cap: Some("mission.write"), inline: false },
    DispatchMethod { method: "recording.start", required_cap: Some("recording.write"), inline: false },
    DispatchMethod { method: "recording.stop", required_cap: Some("recording.write"), inline: false },
    DispatchMethod { method: "mavlink.subscribe", required_cap: Some("mavlink.read"), inline: false },
    DispatchMethod { method: "mavlink.send", required_cap: Some("mavlink.write"), inline: false },
    DispatchMethod { method: "msp.subscribe", required_cap: Some("msp.read"), inline: false },
    DispatchMethod { method: "msp.send", required_cap: Some("msp.write"), inline: false },
    DispatchMethod { method: "mavlink.tunnel.send", required_cap: Some("mavlink.tunnel"), inline: false },
    DispatchMethod { method: "mavlink.register_component", required_cap: None, inline: true },
    DispatchMethod { method: "peripheral.register_driver", required_cap: None, inline: true },
    DispatchMethod { method: "peripheral.unregister_driver", required_cap: None, inline: true },
    DispatchMethod { method: "camera.claim", required_cap: Some("sensor.camera.register"), inline: false },
    DispatchMethod { method: "camera.release", required_cap: Some("sensor.camera.register"), inline: false },
    DispatchMethod { method: "camera.get_frame", required_cap: Some("sensor.camera.register"), inline: false },
    DispatchMethod { method: "video.source.set", required_cap: Some("video.source.set"), inline: false },
    DispatchMethod { method: "video.whep.offer", required_cap: Some("video.whep.relay"), inline: false },
    DispatchMethod { method: "video.whep.close", required_cap: Some("video.whep.relay"), inline: false },
    DispatchMethod { method: "sensors.rig.write", required_cap: Some("sensors.rig.write"), inline: false },
    DispatchMethod { method: "camera.control.set", required_cap: Some("camera.control.write"), inline: false },
    DispatchMethod { method: "config.get", required_cap: None, inline: false },
    DispatchMethod { method: "config.set", required_cap: None, inline: false },
    DispatchMethod { method: "process.spawn", required_cap: Some("process.spawn"), inline: false },
    DispatchMethod { method: "vision.subscribe_frames", required_cap: Some("vision.frame.read"), inline: false },
    DispatchMethod { method: "vision.register_model", required_cap: Some("vision.model.register"), inline: false },
    DispatchMethod { method: "vision.read_model", required_cap: Some("vision.model.read"), inline: false },
    DispatchMethod { method: "vision.infer", required_cap: Some("vision.model.register"), inline: false },
    DispatchMethod { method: "vision.publish_detection", required_cap: Some("vision.detection.publish"), inline: false },
    DispatchMethod { method: "vision.subscribe_detections", required_cap: Some("vision.detection.subscribe"), inline: false },
    DispatchMethod { method: "vision.designate_track", required_cap: Some("vision.track.designate"), inline: false },
    DispatchMethod { method: "display.page.set", required_cap: Some("display.oled.page"), inline: false },
    DispatchMethod { method: "display.zone.subscribe", required_cap: Some("display.oled.page"), inline: false },
    DispatchMethod { method: "button.subscribe", required_cap: Some("button.subscribe"), inline: false },
    DispatchMethod { method: "gpio.output.set", required_cap: Some("hardware.gpio_out"), inline: false },
    DispatchMethod { method: "gpio.buzzer.beep", required_cap: Some("hardware.gpio_out"), inline: false },
    DispatchMethod { method: "flight.guided_setpoint.send", required_cap: Some("flight.guided_setpoint"), inline: false },
    DispatchMethod { method: "flight.rate_setpoint.send", required_cap: Some("flight.rate_setpoint"), inline: false },
    DispatchMethod { method: "radio.aux_stream.open", required_cap: Some("radio.aux_stream"), inline: false },
    DispatchMethod { method: "radio.aux_stream.close", required_cap: Some("radio.aux_stream"), inline: false },
    DispatchMethod { method: "radio.aux_stream.send", required_cap: Some("radio.aux_stream"), inline: false },
    DispatchMethod { method: "radio.aux_stream.subscribe", required_cap: Some("radio.aux_stream"), inline: false },
    DispatchMethod { method: "cloud.publish", required_cap: Some("cloud.publish"), inline: false },
    DispatchMethod { method: "cloud.records.put", required_cap: Some("cloud.records"), inline: false },
    DispatchMethod { method: "offload.advertise", required_cap: Some("vision.offload.advertise"), inline: false },
    DispatchMethod { method: "node.info", required_cap: Some("node.info.read"), inline: false },
    DispatchMethod { method: "mdns.advertise", required_cap: Some("network.listen"), inline: false },
    DispatchMethod { method: "mdns.browse", required_cap: Some("network.outbound"), inline: false },
];

/// Look up the dispatch-level required capability for a wire method.
/// Returns `Some(None)` for a known ungated/inline method and `None` for an
/// unknown method, so a caller can tell the two apart.
pub fn required_cap_for(method: &str) -> Option<Option<&'static str>> {
    DISPATCH_METHODS
        .iter()
        .find(|m| m.method == method)
        .map(|m| m.required_cap)
}

/// True if `method` is a known dispatch method.
pub fn is_known_method(method: &str) -> bool {
    DISPATCH_METHODS.iter().any(|m| m.method == method)
}