act_runtime/sessions.rs
1//! Host-side typed handles for the generated `act:sessions/session-provider`
2//! bindings.
3//!
4//! `act-world` declares `session-provider` as an export, but it is opt-in:
5//! stateless components do not export it. The host therefore binds it through
6//! a per-interface `GuestIndices::new` lookup that is allowed to fail —
7//! `instantiate_component` turns that failure into `None`, so components
8//! without session-provider instantiate fine.
9//!
10//! `Session`, `Error` and `Metadata` come straight from the generated
11//! bindings (the same `act:core/types` records the tool-provider uses, shared
12//! via the single `act-world` bindgen invocation).
13
14use wasmtime::component::TypedFunc;
15
16use super::exports::act::sessions::session_provider::Guest;
17// `act:sessions@0.2.0` moved the `session` record into `act:sessions/types`;
18// `error` / `metadata` resolve through `act:core/types`. Only the `Guest`
19// (and its typed-func accessors) still live in `session_provider`.
20use super::act::core::types::{Error, Metadata};
21
22/// `act:sessions/types.session` — re-exported from the generated bindings so
23/// callers keep referring to `sessions::Session`.
24pub use super::act::sessions::types::Session;
25
26// ── Typed function aliases (matching the WIT signatures) ───────────────────
27
28/// `get-open-session-args-schema(metadata) -> result<string, error>`
29type GetOpenSessionArgsSchemaFn = TypedFunc<(Metadata,), (Result<String, Error>,)>;
30
31/// `open-session(args: metadata, metadata: metadata) -> result<session, error>`
32type OpenSessionFn = TypedFunc<(Metadata, Metadata), (Result<Session, Error>,)>;
33
34/// `close-session(session-id: string)`
35type CloseSessionFn = TypedFunc<(String,), ()>;
36
37/// Typed handles to the three session-provider functions of one component
38/// instance, derived from the generated session `Guest`.
39#[derive(Clone)]
40pub struct SessionProvider {
41 pub get_open_session_args_schema: GetOpenSessionArgsSchemaFn,
42 pub open_session: OpenSessionFn,
43 pub close_session: CloseSessionFn,
44}
45
46impl SessionProvider {
47 /// Build typed handles from the generated session-provider `Guest`.
48 pub fn from_guest(guest: &Guest) -> Self {
49 Self {
50 get_open_session_args_schema: guest.func_get_open_session_args_schema(),
51 open_session: guest.func_open_session(),
52 // `close-session` is a sync WIT func, so bindgen types its accessor
53 // `TypedFunc<(&str,), ()>`. `call_concurrent` (used to drive it
54 // through the async store, like the other two) rejects that because
55 // its params must be `'static`. Re-type the same underlying `Func`
56 // to owned `(String,)`; the lowering is identical (both lower a
57 // `string`), which is what makes the `new_unchecked` sound.
58 close_session: unsafe { TypedFunc::new_unchecked(*guest.func_close_session().func()) },
59 }
60 }
61}