Some checks failed
CI / Linux x86_64 (Forgejo) (push) Failing after 1s
Brings the module SDK to WIT 1.1 in lockstep with the platform and
exposes the new host.emit-event as an ergonomic ctx.emit(name,
payload). Modules emit ephemeral progress/stream events (progress,
token streaming) delivered live to a following client and never
persisted.
- wit/world.wit → 1.1.0 (host.emit-event + use types.{payload}).
- host.rs: an emit hook (thread-local fn pointer; guest is
single-threaded). The #[fai_module] expansion installs a closure
reaching the real WIT emit-event import at the start of each
invocation; Context::emit calls through it. Outside a hub (unit
tests) it is a silent no-op.
- examples/progress: reference module emitting progress + token events;
builds clean for wasm32-wasip2, proving the ergonomics end-to-end.
The SDK keeps shielding module authors: emit is the whole surface, no
wit_bindgen in sight.
Signed-off-by: flemming-it <sf@flemming.it>
110 lines
3.5 KiB
Text
110 lines
3.5 KiB
Text
// =============================================================
|
|
// FROZEN. Wire contract between hub and modules.
|
|
// =============================================================
|
|
//
|
|
// This file is the stable wire contract between the Ch∆In Hub
|
|
// and any module compiled against it. It is **frozen at v1.0**.
|
|
//
|
|
// Frozen means:
|
|
//
|
|
// - No removal, rename, or signature change of any existing
|
|
// interface, function, type, field, or variant case.
|
|
// - Additive changes (new types, new variant cases at the end,
|
|
// new fields with stable defaults) require a minor bump
|
|
// (1.0 -> 1.1) and a coordinated review.
|
|
// - Any breaking change requires a major bump (1.0 -> 2.0)
|
|
// and a parallel-world transition plan.
|
|
//
|
|
// The fai_runtime crate ships a snapshot test that fails if
|
|
// this file changes without an intentional, reviewed update.
|
|
// See `crates/fai_runtime/tests/wit_freeze.rs`.
|
|
//
|
|
// Module authors do NOT depend on this file directly. They
|
|
// use `chain-module-sdk`, which wraps these bindings behind a
|
|
// stable, ergonomic surface. That is what protects modules
|
|
// from any future evolution of this contract.
|
|
|
|
package chain:platform@1.1.0;
|
|
|
|
/// Types that flow between the host (hub) and modules.
|
|
interface types {
|
|
/// A typed value passed between the host and a module.
|
|
variant payload {
|
|
/// Plain UTF-8 text.
|
|
text(string),
|
|
/// Arbitrary JSON encoded as a string.
|
|
json(string),
|
|
/// Raw bytes with a MIME type.
|
|
bytes(bytes-value),
|
|
/// A reference to a file, by URI.
|
|
file-ref(file-ref),
|
|
}
|
|
|
|
/// Inline byte content.
|
|
record bytes-value {
|
|
mime-type: string,
|
|
data: list<u8>,
|
|
}
|
|
|
|
/// File reference by URI.
|
|
record file-ref {
|
|
uri: string,
|
|
mime-type: string,
|
|
size-bytes: u64,
|
|
sha256: string,
|
|
}
|
|
|
|
/// Context passed with every invocation.
|
|
record invocation-context {
|
|
invocation-id: string,
|
|
capability-namespace: string,
|
|
capability-name: string,
|
|
deadline-ms: u64,
|
|
}
|
|
|
|
/// Structured error type returned by modules.
|
|
variant invocation-error {
|
|
invalid-input(string),
|
|
permission-denied(string),
|
|
resource-exhausted(string),
|
|
deadline-exceeded,
|
|
internal(string),
|
|
}
|
|
}
|
|
|
|
/// The host-provided interface that modules can import to talk back.
|
|
interface host {
|
|
use types.{payload};
|
|
|
|
/// Log a structured message. Level is "trace", "debug", "info", "warn", "error".
|
|
log: func(level: string, message: string);
|
|
|
|
/// Emit an ephemeral progress/stream event during an invocation.
|
|
/// Added in 1.1. Events are fanned out to any client following this
|
|
/// invocation live (SubmitStream); they are NOT written to the
|
|
/// tamper-evident audit log. `name` is a caller-defined event label
|
|
/// (e.g. "progress", "token"); `payload` is the event body. The host
|
|
/// enforces per-invocation size + rate limits — an event over the
|
|
/// limit is dropped with a warning and never fails the invocation.
|
|
emit-event: func(name: string, payload: payload);
|
|
}
|
|
|
|
/// The core interface every module exports.
|
|
interface invoke {
|
|
use types.{payload, invocation-context, invocation-error};
|
|
|
|
/// Invoke the module with inputs, receive outputs or an error.
|
|
invoke: func(
|
|
ctx: invocation-context,
|
|
inputs: list<tuple<string, payload>>,
|
|
) -> result<list<tuple<string, payload>>, invocation-error>;
|
|
}
|
|
|
|
/// The world a module component targets.
|
|
///
|
|
/// Modules `export` the invoke interface to be callable by the hub.
|
|
/// Modules `import` the host interface to emit logs.
|
|
world module {
|
|
import host;
|
|
export invoke;
|
|
}
|