botstadia-interface 0.2.0

BotStadia's shared contracts: arena and agent WIT worlds, arena declarations, payloads, bundles, the policy shell's ONNX contract, replay archives, metrics files and player messages.
Documentation
package botstadia:agent@0.2.0;

/// What a bot's program may ask of the host during a turn.
interface host {
    /// The fuel left in this turn's budget, and the turn number. Exact on
    /// every machine, for a bot that paces its own search.
    record turn-budget {
        fuel-left: u64,
        turn: u32,
    }

    budget: func() -> turn-budget;

    /// The arena's declaration, JSON-encoded by `botstadia-interface`: the
    /// same bytes the registry stores. Every value's name, type, shape and
    /// bounds, so one program (the policy shell) can serve every arena.
    declaration: func() -> list<u8>;

    /// One tensor, row-major.
    record tensor {
        name: string,
        shape: list<u32>,
        data: list<f32>,
    }

    /// Why an inference call didn't run or didn't finish.
    variant inference-error {
        /// The turn's remaining fuel can't pay the model's charge.
        unaffordable,
        /// The call was cancelled at the backstop.
        cancelled,
        /// The seat's inference has ended for this session.
        unavailable,
        /// The inputs don't match the model.
        bad-input(string),
    }

    /// A tensor a model takes or gives: its name and its fixed shape.
    record tensor-spec {
        name: string,
        shape: list<u32>,
    }

    /// One model in the bundle, in manifest order, as preflight found it.
    record model-info {
        name: string,
        inputs: list<tensor-spec>,
        outputs: list<tensor-spec>,
        /// The fuel one call costs, under this session's budget version.
        charge: u64,
    }

    /// The bundle's models, so a bot (the policy shell among them) knows
    /// exactly what each takes, gives and costs.
    models: func() -> list<model-info>;

    /// Run the bundle's model `model` (its index in the manifest) on `inputs`.
    infer: func(model: u32, inputs: list<tensor>) -> result<list<tensor>, inference-error>;
}

/// A bot: one instance per seat per session.
///
/// Inputs and outputs are opaque bytes in the arena's declared payload layout.
/// Generated code reads and writes them by name.
world agent {
    import host;

    /// Once, before the first turn, under the arena's `init` budget.
    export init: func();

    /// This turn's input in, this turn's output back.
    export on-tick: func(input: list<u8>) -> list<u8>;
}