feat(sdk): Context::emit for WIT 1.1 host.emit-event (T1)
Some checks failed
CI / Linux x86_64 (Forgejo) (push) Failing after 1s
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>
This commit is contained in:
parent
98e98e9371
commit
f32dc820b9
9 changed files with 568 additions and 5 deletions
|
|
@ -95,6 +95,13 @@ pub fn fai_module(_attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let sdk_inputs =
|
let sdk_inputs =
|
||||||
::chain_module_sdk::Inputs::__from_pairs(sdk_pairs);
|
::chain_module_sdk::Inputs::__from_pairs(sdk_pairs);
|
||||||
|
|
||||||
|
// Wire Context::emit to the real WIT host import
|
||||||
|
// for the duration of this invocation (WIT 1.1).
|
||||||
|
::chain_module_sdk::__set_emit_hook(|name, payload| {
|
||||||
|
let wit = sdk_payload_to_wit(payload);
|
||||||
|
chain::platform::host::emit_event(name, &wit);
|
||||||
|
});
|
||||||
|
|
||||||
match super::#user_fn_name(sdk_ctx, sdk_inputs) {
|
match super::#user_fn_name(sdk_ctx, sdk_inputs) {
|
||||||
Ok(outputs) => {
|
Ok(outputs) => {
|
||||||
let pairs = outputs.__into_pairs();
|
let pairs = outputs.__into_pairs();
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,23 @@ pub struct Context {
|
||||||
pub capability_name: String,
|
pub capability_name: String,
|
||||||
pub deadline_ms: u64,
|
pub deadline_ms: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
/// Emit an ephemeral progress/stream event during this invocation
|
||||||
|
/// (WIT 1.1 `emit-event`). Delivered live to any client following
|
||||||
|
/// the flow (`SubmitStream`); it is **never** written to the audit
|
||||||
|
/// log. Use it for progress updates or token streaming.
|
||||||
|
///
|
||||||
|
/// `name` is a caller-defined label (e.g. `"progress"`, `"token"`);
|
||||||
|
/// `payload` is the event body. The host enforces per-invocation
|
||||||
|
/// size + rate limits — an over-limit event is dropped, never an
|
||||||
|
/// error. When the module runs outside a hub that supports it (or
|
||||||
|
/// in a unit test) `emit` is a silent no-op.
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// ctx.emit("progress", Payload::Text("50%".into()));
|
||||||
|
/// ```
|
||||||
|
pub fn emit(&self, name: &str, payload: crate::Payload) {
|
||||||
|
crate::emit(name, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
35
crates/chain-module-sdk/src/host.rs
Normal file
35
crates/chain-module-sdk/src/host.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
//! Host-callback plumbing for `Context::emit` (WIT 1.1 `emit-event`).
|
||||||
|
//!
|
||||||
|
//! The WIT host imports (`emit-event`) are only reachable from the
|
||||||
|
//! `wit_bindgen`-generated glue inside the `#[fai_module]` expansion,
|
||||||
|
//! which lives in the module crate — not here. So the macro installs a
|
||||||
|
//! function pointer that reaches the real host import, and
|
||||||
|
//! [`Context::emit`](crate::Context::emit) calls it through this hook.
|
||||||
|
//!
|
||||||
|
//! On a non-wasm host target (unit tests) no hook is installed, so
|
||||||
|
//! `emit` is a silent no-op. The guest is single-threaded, so a
|
||||||
|
//! thread-local cell is sufficient and lock-free.
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
use crate::Payload;
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static EMIT_HOOK: Cell<Option<fn(&str, Payload)>> = const { Cell::new(None) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Install the emit hook. Called by the `#[fai_module]` expansion at
|
||||||
|
/// the start of each invocation. Not part of the stable public API.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn __set_emit_hook(f: fn(&str, Payload)) {
|
||||||
|
EMIT_HOOK.with(|c| c.set(Some(f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Forward an event to the host, if a hook is installed.
|
||||||
|
pub(crate) fn emit(name: &str, payload: Payload) {
|
||||||
|
EMIT_HOOK.with(|c| {
|
||||||
|
if let Some(f) = c.get() {
|
||||||
|
f(name, payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
mod context;
|
mod context;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod host;
|
||||||
mod inputs;
|
mod inputs;
|
||||||
mod outputs;
|
mod outputs;
|
||||||
mod payload;
|
mod payload;
|
||||||
|
|
@ -37,6 +38,12 @@ pub use payload::{BytesValue, FileRef, Payload};
|
||||||
|
|
||||||
pub use chain_module_sdk_macros::fai_module;
|
pub use chain_module_sdk_macros::fai_module;
|
||||||
|
|
||||||
|
// Emit-hook plumbing used by the `#[fai_module]` expansion (wasm32)
|
||||||
|
// so `Context::emit` reaches the WIT `emit-event` host import.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use host::__set_emit_hook;
|
||||||
|
pub(crate) use host::emit;
|
||||||
|
|
||||||
/// Convenience prelude — `use chain_module_sdk::prelude::*;` brings
|
/// Convenience prelude — `use chain_module_sdk::prelude::*;` brings
|
||||||
/// every type a typical module needs into scope.
|
/// every type a typical module needs into scope.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,13 @@ use std::path::PathBuf;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
/// Identical to FROZEN_WIT_SHA256 in
|
/// Identical to FROZEN_WIT_SHA256 in
|
||||||
/// fai/platform :: crates/fai_runtime/tests/wit_freeze.rs.
|
/// fai/chain :: crates/chain_runtime/tests/wit_freeze.rs.
|
||||||
/// Update both repos in lockstep, never one alone.
|
/// Update both repos in lockstep, never one alone.
|
||||||
|
/// 2026-07-05 — WIT 1.0.0 → 1.1.0 (additive: host.emit-event). The SDK
|
||||||
|
/// wit/world.wit is now byte-identical to the platform's, so the two
|
||||||
|
/// frozen hashes match exactly.
|
||||||
const PLATFORM_FROZEN_WIT_SHA256: &str =
|
const PLATFORM_FROZEN_WIT_SHA256: &str =
|
||||||
"6f4e2266a4264832a16fe5a3704622cd978b290b90f3300c3ed236d98b689b5f";
|
"2ba9d6c61c4c77d081679603a9389aef663429ec80f9c386cf9b1ca9d353bf6f";
|
||||||
|
|
||||||
fn world_wit_path() -> PathBuf {
|
fn world_wit_path() -> PathBuf {
|
||||||
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
|
|
|
||||||
439
examples/progress/Cargo.lock
generated
Normal file
439
examples/progress/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,439 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.103"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chain-module-sdk"
|
||||||
|
version = "0.1.2"
|
||||||
|
dependencies = [
|
||||||
|
"chain-module-sdk-macros",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chain-module-sdk-macros"
|
||||||
|
version = "0.1.2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "id-arena"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown 0.17.1",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "leb128"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c83bff1d572d6b9aeef67ddfc8448e4a3737909cb28e81f97c791b9018703e52"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettyplease"
|
||||||
|
version = "0.2.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "progress_example"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chain-module-sdk",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.150"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.15.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spdx"
|
||||||
|
version = "0.10.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3"
|
||||||
|
dependencies = [
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.118"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-encoder"
|
||||||
|
version = "0.220.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e913f9242315ca39eff82aee0e19ee7a372155717ff0eb082c741e435ce25ed1"
|
||||||
|
dependencies = [
|
||||||
|
"leb128",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-metadata"
|
||||||
|
version = "0.220.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "185dfcd27fa5db2e6a23906b54c28199935f71d9a27a1a27b3a88d6fee2afae7"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"spdx",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.220.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d07b6a3b550fefa1a914b6d54fc175dd11c3392da11eee604e6ffc759805d25"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"bitflags",
|
||||||
|
"hashbrown 0.14.5",
|
||||||
|
"indexmap",
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.36.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a2b3e15cd6068f233926e7d8c7c588b2ec4fb7cc7bf3824115e7c7e2a8485a3"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen-rt",
|
||||||
|
"wit-bindgen-rust-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-core"
|
||||||
|
version = "0.36.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b632a5a0fa2409489bd49c9e6d99fcc61bb3d4ce9d1907d44662e75a28c71172"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rt"
|
||||||
|
version = "0.36.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7947d0131c7c9da3f01dfde0ab8bd4c4cf3c5bd49b6dba0ae640f1fa752572ea"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust"
|
||||||
|
version = "0.36.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4329de4186ee30e2ef30a0533f9b3c123c019a237a7c82d692807bf1b3ee2697"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"indexmap",
|
||||||
|
"prettyplease",
|
||||||
|
"syn",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-component",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust-macro"
|
||||||
|
version = "0.36.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "177fb7ee1484d113b4792cc480b1ba57664bbc951b42a4beebe573502135b1fc"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"prettyplease",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-bindgen-rust",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-component"
|
||||||
|
version = "0.220.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b505603761ed400c90ed30261f44a768317348e49f1864e82ecdc3b2744e5627"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bitflags",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wasmparser",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-parser"
|
||||||
|
version = "0.220.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae2a7999ed18efe59be8de2db9cb2b7f84d88b27818c79353dfc53131840fe1a"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"id-arena",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"semver",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"unicode-xid",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.52"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.52"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
21
examples/progress/Cargo.toml
Normal file
21
examples/progress/Cargo.toml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
name = "progress_example"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
publish = false
|
||||||
|
description = "Reference module showing WIT 1.1 host.emit-event via ctx.emit (progress + token streaming)."
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
chain-module-sdk = { path = "../../crates/chain-module-sdk" }
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = "s"
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
strip = "symbols"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
20
examples/progress/src/lib.rs
Normal file
20
examples/progress/src/lib.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
//! Reference module for WIT 1.1 `host.emit-event`.
|
||||||
|
//!
|
||||||
|
//! Echoes the input, but first emits a few ephemeral progress events
|
||||||
|
//! via `ctx.emit`. A client following the flow with `SubmitStream`
|
||||||
|
//! sees them live; they are never written to the audit log.
|
||||||
|
|
||||||
|
use chain_module_sdk::prelude::*;
|
||||||
|
|
||||||
|
#[fai_module]
|
||||||
|
fn invoke(ctx: Context, inputs: Inputs) -> Result<Outputs, ModuleError> {
|
||||||
|
let text = inputs.require_text("input")?;
|
||||||
|
|
||||||
|
for pct in [0u32, 50, 100] {
|
||||||
|
ctx.emit("progress", Payload::Text(format!("{pct}%")));
|
||||||
|
}
|
||||||
|
// A structured event, too.
|
||||||
|
ctx.emit("token", Payload::Text(text.to_string()));
|
||||||
|
|
||||||
|
Ok(Outputs::new().with_text("output", format!("echo: {text}")))
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// FROZEN. Wire contract between hub and modules.
|
// FROZEN. Wire contract between hub and modules.
|
||||||
// =============================================================
|
// =============================================================
|
||||||
//
|
//
|
||||||
// This file is the stable wire contract between the F∆I Hub
|
// This file is the stable wire contract between the Ch∆In Hub
|
||||||
// and any module compiled against it. It is **frozen at v1.0**.
|
// and any module compiled against it. It is **frozen at v1.0**.
|
||||||
//
|
//
|
||||||
// Frozen means:
|
// Frozen means:
|
||||||
|
|
@ -20,11 +20,11 @@
|
||||||
// See `crates/fai_runtime/tests/wit_freeze.rs`.
|
// See `crates/fai_runtime/tests/wit_freeze.rs`.
|
||||||
//
|
//
|
||||||
// Module authors do NOT depend on this file directly. They
|
// Module authors do NOT depend on this file directly. They
|
||||||
// use `fai-module-sdk`, which wraps these bindings behind a
|
// use `chain-module-sdk`, which wraps these bindings behind a
|
||||||
// stable, ergonomic surface. That is what protects modules
|
// stable, ergonomic surface. That is what protects modules
|
||||||
// from any future evolution of this contract.
|
// from any future evolution of this contract.
|
||||||
|
|
||||||
package chain:platform@1.0.0;
|
package chain:platform@1.1.0;
|
||||||
|
|
||||||
/// Types that flow between the host (hub) and modules.
|
/// Types that flow between the host (hub) and modules.
|
||||||
interface types {
|
interface types {
|
||||||
|
|
@ -74,8 +74,19 @@ interface types {
|
||||||
|
|
||||||
/// The host-provided interface that modules can import to talk back.
|
/// The host-provided interface that modules can import to talk back.
|
||||||
interface host {
|
interface host {
|
||||||
|
use types.{payload};
|
||||||
|
|
||||||
/// Log a structured message. Level is "trace", "debug", "info", "warn", "error".
|
/// Log a structured message. Level is "trace", "debug", "info", "warn", "error".
|
||||||
log: func(level: string, message: string);
|
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.
|
/// The core interface every module exports.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue