Skip to main content

golem_rust/
lib.rs

1// Copyright 2024-2026 Golem Cloud
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(test)]
16test_r::enable!();
17
18pub use uuid::Uuid;
19pub use wasip3;
20
21pub mod http;
22
23#[doc(hidden)]
24#[cfg(feature = "export_golem_agentic")]
25pub fn __link_golem_component_exports() {
26    #[cfg(target_arch = "wasm32")]
27    agentic::exports::raw::link();
28}
29
30/// Export the unified Golem guest world without registering an agent, tool, or middleware.
31#[macro_export]
32#[cfg(feature = "export_golem_agentic")]
33macro_rules! export_golem_component {
34    () => {
35        $crate::ctor::__support::ctor_parse!(
36            #[ctor]
37            fn __golem_link_component_exports() {
38                $crate::__link_golem_component_exports();
39            }
40        );
41    };
42}
43
44pub use golem_schema;
45pub use golem_schema::schema;
46pub use golem_schema::schema::wit::direct::{FromWire, IntoWire, WireSchema};
47pub use golem_schema::schema::{
48    FromSchema, IntoSchema, IntoTypedSchemaValue, Quantity, QuantityUnit, Schema,
49    SchemaFingerprintError, SchemaFingerprintV1, SchemaGraph, SchemaType, SchemaValue,
50    TypedSchemaValue, schema_fingerprint_v1,
51};
52#[cfg(feature = "macro")]
53pub use golem_schema::schema::{FromWire, IntoWire, WireSchema};
54pub use golem_schema::{AgentId, ComponentId, EnvironmentId, PromiseId};
55
56pub fn encode_schema_graph(
57    graph: &SchemaGraph,
58) -> Result<schema::wit::wire::SchemaGraph, schema::wit::EncodeError> {
59    schema::wit::encode_graph(graph)
60}
61
62pub fn decode_schema_graph(
63    graph: &schema::wit::wire::SchemaGraph,
64) -> Result<SchemaGraph, schema::wit::DecodeError> {
65    schema::wit::decode_graph(graph)
66}
67
68pub fn encode_schema_value(
69    value: &SchemaValue,
70) -> Result<schema::wit::wire::SchemaValueTree, schema::wit::EncodeError> {
71    schema::wit::encode_value(value)
72}
73
74pub async fn encode_schema_value_async(
75    value: &SchemaValue,
76) -> Result<schema::wit::wire::SchemaValueTree, schema::wit::EncodeError> {
77    schema::wit::encode_value_async(value).await
78}
79
80pub fn decode_schema_value(
81    value: schema::wit::wire::SchemaValueTree,
82) -> Result<SchemaValue, schema::wit::DecodeError> {
83    schema::wit::decode_value(value)
84}
85
86pub fn encode_typed_schema_value(
87    value: &TypedSchemaValue,
88) -> Result<schema::wit::wire::TypedSchemaValue, schema::wit::EncodeError> {
89    schema::wit::encode_typed(value)
90}
91
92pub async fn encode_typed_schema_value_async(
93    value: &TypedSchemaValue,
94) -> Result<schema::wit::wire::TypedSchemaValue, schema::wit::EncodeError> {
95    schema::wit::encode_typed_async(value).await
96}
97
98pub fn decode_typed_schema_value(
99    value: &schema::wit::wire::TypedSchemaValue,
100) -> Result<TypedSchemaValue, schema::wit::DecodeError> {
101    schema::wit::decode_typed(value)
102}
103
104pub fn encode_typed_schema_value_owned(
105    value: TypedSchemaValue,
106) -> Result<schema::wit::wire::TypedSchemaValue, schema::wit::EncodeError> {
107    schema::wit::encode_typed_owned(value)
108}
109
110pub fn decode_typed_schema_value_owned(
111    value: schema::wit::wire::TypedSchemaValue,
112) -> Result<TypedSchemaValue, schema::wit::DecodeError> {
113    schema::wit::decode_typed_owned(value)
114}
115
116// Compatibility shim for the `wasi:clocks` types the Golem WIT interfaces reference
117// (`wasi:clocks/system-clock@0.3.0.{instant}` and
118// `wasi:clocks/types@0.3.0.{duration}`). The `with:` remaps in every
119// `generate!` block point the generated bindings at these modules so the Rust
120// types come from a single source.
121
122/// Public alias for the instant/datetime type used by Golem's scheduling APIs.
123pub type ScheduledTime = wasip3::clocks::system_clock::Instant;
124
125mod wasi_clocks_compat {
126    pub mod system_clock {
127        pub use wasip3::clocks::system_clock::Instant;
128    }
129    pub mod types {
130        pub use wasip3::clocks::types::Duration;
131    }
132}
133
134mod raw_bindings {
135    use wit_bindgen::generate;
136
137    generate!({
138        path: "wit",
139        world: "golem-rust",
140        generate_all,
141        generate_unused_types: true,
142        pub_export_macro: true,
143        with: {
144            "golem:core/types@2.0.0": golem_schema::schema::wit::wire,
145            "golem:tool/common@0.1.0": golem_schema::schema::tool::wit::wire,
146            "wasi:clocks/system-clock@0.3.0": crate::wasi_clocks_compat::system_clock,
147            "wasi:clocks/types@0.3.0": crate::wasi_clocks_compat::types,
148        }
149    });
150}
151
152/// Component Model `stream` constructor generated by `wit_bindgen` for the
153/// primary bindings world. Used by callers that need to hand a writable
154/// `stream<u8>` to host imports such as `wasi:blobstore` outgoing values.
155pub use crate::raw_bindings::wit_stream;
156
157pub mod bindings {
158    pub use crate::raw_bindings::wasi;
159
160    pub mod golem {
161        pub mod api {
162            pub(crate) use crate::raw_bindings::golem::api::host;
163            pub use crate::raw_bindings::golem::api::{context, oplog, retry};
164        }
165
166        pub mod durability {
167            pub(crate) use crate::raw_bindings::golem::durability::durability;
168        }
169
170        pub mod quota {
171            pub(crate) use crate::raw_bindings::golem::quota::types;
172        }
173
174        pub mod secrets {
175            pub use crate::raw_bindings::golem::secrets::{reveal, types};
176        }
177
178        pub mod agent {
179            pub use crate::raw_bindings::golem::agent::{common, durable_streams, host};
180        }
181
182        pub mod permissions {
183            pub(crate) use crate::raw_bindings::golem::permissions::{
184                derive, inspect, kernel_introspection, revoke, types, wallet,
185            };
186        }
187
188        pub mod tool {
189            pub use crate::raw_bindings::golem::tool::{host, streams};
190            pub use crate::schema::tool::wit::wire as common;
191        }
192
193        pub use crate::raw_bindings::golem::{rdbms, websocket};
194    }
195}
196
197#[cfg(feature = "export_load_snapshot")]
198pub mod load_snapshot {
199    use wit_bindgen::generate;
200
201    generate!({
202        path: "wit",
203        world: "golem-rust-load-snapshot",
204        async: ["export:golem:api/load-snapshot@1.5.0#load"],
205        generate_all,
206        generate_unused_types: true,
207        pub_export_macro: true,
208        with: {
209            "golem:core/types@2.0.0": golem_schema::schema::wit::wire,
210            "golem:tool/common@0.1.0": golem_schema::schema::tool::wit::wire,
211            "wasi:clocks/system-clock@0.3.0": crate::wasi_clocks_compat::system_clock,
212            "wasi:clocks/types@0.3.0": crate::wasi_clocks_compat::types,
213
214            "golem:api/host@1.5.0": crate::bindings::golem::api::host,
215            "golem:tool/host@0.1.0": crate::bindings::golem::tool::host,
216            "golem:api/retry@1.5.0": crate::bindings::golem::api::retry,
217            "golem:api/oplog@1.5.0": crate::bindings::golem::api::oplog,
218            "golem:api/context@1.5.0": crate::bindings::golem::api::context,
219            "golem:durability/durability@1.6.0": crate::bindings::golem::durability::durability,
220            "golem:quota/types@1.5.0": crate::bindings::golem::quota::types,
221            "golem:secrets/types@0.1.0": crate::bindings::golem::secrets::types,
222            "golem:secrets/reveal@0.1.0": crate::bindings::golem::secrets::reveal,
223            "golem:permissions/types@0.1.0": crate::bindings::golem::permissions::types,
224            "golem:permissions/derive@0.1.0": crate::bindings::golem::permissions::derive,
225            "golem:permissions/inspect@0.1.0": crate::bindings::golem::permissions::inspect,
226            "golem:permissions/revoke@0.1.0": crate::bindings::golem::permissions::revoke,
227            "golem:permissions/wallet@0.1.0": crate::bindings::golem::permissions::wallet,
228            "golem:permissions/kernel-introspection@0.1.0": crate::bindings::golem::permissions::kernel_introspection,
229            "golem:rdbms/mysql@1.5.0": crate::bindings::golem::rdbms::mysql,
230            "golem:rdbms/postgres@1.5.0": crate::bindings::golem::rdbms::postgres,
231            "golem:rdbms/types@1.5.0": crate::bindings::golem::rdbms::types,
232            "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
233            "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
234            "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
235            "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
236            "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
237            "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
238            "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
239            "wasi:logging/logging": crate::bindings::wasi::logging::logging,
240        }
241    });
242
243    pub use __export_golem_rust_load_snapshot_impl as export_load_snapshot;
244}
245
246#[cfg(feature = "export_save_snapshot")]
247pub mod save_snapshot {
248    use wit_bindgen::generate;
249
250    generate!({
251        path: "wit",
252        world: "golem-rust-save-snapshot",
253        async: ["export:golem:api/save-snapshot@1.5.0#save"],
254        generate_all,
255        generate_unused_types: true,
256        pub_export_macro: true,
257        with: {
258            "golem:core/types@2.0.0": golem_schema::schema::wit::wire,
259            "golem:tool/common@0.1.0": golem_schema::schema::tool::wit::wire,
260            "wasi:clocks/system-clock@0.3.0": crate::wasi_clocks_compat::system_clock,
261            "wasi:clocks/types@0.3.0": crate::wasi_clocks_compat::types,
262
263            "golem:api/host@1.5.0": crate::bindings::golem::api::host,
264            "golem:tool/host@0.1.0": crate::bindings::golem::tool::host,
265            "golem:api/retry@1.5.0": crate::bindings::golem::api::retry,
266            "golem:api/oplog@1.5.0": crate::bindings::golem::api::oplog,
267            "golem:api/context@1.5.0": crate::bindings::golem::api::context,
268            "golem:durability/durability@1.6.0": crate::bindings::golem::durability::durability,
269            "golem:quota/types@1.5.0": crate::bindings::golem::quota::types,
270            "golem:secrets/types@0.1.0": crate::bindings::golem::secrets::types,
271            "golem:secrets/reveal@0.1.0": crate::bindings::golem::secrets::reveal,
272            "golem:permissions/types@0.1.0": crate::bindings::golem::permissions::types,
273            "golem:permissions/derive@0.1.0": crate::bindings::golem::permissions::derive,
274            "golem:permissions/inspect@0.1.0": crate::bindings::golem::permissions::inspect,
275            "golem:permissions/revoke@0.1.0": crate::bindings::golem::permissions::revoke,
276            "golem:permissions/wallet@0.1.0": crate::bindings::golem::permissions::wallet,
277            "golem:permissions/kernel-introspection@0.1.0": crate::bindings::golem::permissions::kernel_introspection,
278            "golem:rdbms/mysql@1.5.0": crate::bindings::golem::rdbms::mysql,
279            "golem:rdbms/postgres@1.5.0": crate::bindings::golem::rdbms::postgres,
280            "golem:rdbms/types@1.5.0": crate::bindings::golem::rdbms::types,
281            "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
282            "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
283            "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
284            "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
285            "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
286            "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
287            "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
288            "wasi:logging/logging": crate::bindings::wasi::logging::logging,
289        }
290    });
291
292    pub use __export_golem_rust_save_snapshot_impl as export_save_snapshot;
293}
294
295#[cfg(feature = "export_golem_agentic")]
296pub mod golem_agentic {
297    use wit_bindgen::generate;
298
299    generate!({
300        path: "wit",
301        world: "golem-agentic",
302        async: [
303            "export:golem:agent/guest@2.0.0#initialize",
304            "export:golem:agent/guest@2.0.0#invoke",
305            "export:golem:tool/guest@0.1.0#invoke",
306            "export:golem:tool/tool-middleware-guest@0.1.0#invoke-tool-middleware",
307        ],
308        generate_all,
309        generate_unused_types: true,
310        pub_export_macro: true,
311
312        with: {
313            "golem:core/types@2.0.0": golem_schema::schema::wit::wire,
314            "golem:tool/common@0.1.0": golem_schema::schema::tool::wit::wire,
315            "wasi:clocks/system-clock@0.3.0": crate::wasi_clocks_compat::system_clock,
316            "wasi:clocks/types@0.3.0": crate::wasi_clocks_compat::types,
317
318            "golem:api/host@1.5.0": crate::bindings::golem::api::host,
319            "golem:api/retry@1.5.0": crate::bindings::golem::api::retry,
320            "golem:api/oplog@1.5.0": crate::bindings::golem::api::oplog,
321            "golem:api/context@1.5.0": crate::bindings::golem::api::context,
322            "golem:durability/durability@1.6.0": crate::bindings::golem::durability::durability,
323            "golem:quota/types@1.5.0": crate::bindings::golem::quota::types,
324            "golem:secrets/types@0.1.0": crate::bindings::golem::secrets::types,
325            "golem:secrets/reveal@0.1.0": crate::bindings::golem::secrets::reveal,
326            "golem:permissions/types@0.1.0": crate::bindings::golem::permissions::types,
327            "golem:permissions/derive@0.1.0": crate::bindings::golem::permissions::derive,
328            "golem:permissions/inspect@0.1.0": crate::bindings::golem::permissions::inspect,
329            "golem:permissions/revoke@0.1.0": crate::bindings::golem::permissions::revoke,
330            "golem:permissions/wallet@0.1.0": crate::bindings::golem::permissions::wallet,
331            "golem:permissions/kernel-introspection@0.1.0": crate::bindings::golem::permissions::kernel_introspection,
332            "golem:rdbms/mysql@1.5.0": crate::bindings::golem::rdbms::mysql,
333            "golem:rdbms/postgres@1.5.0": crate::bindings::golem::rdbms::postgres,
334            "golem:rdbms/types@1.5.0": crate::bindings::golem::rdbms::types,
335            "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
336            "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
337            "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
338            "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
339            "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
340            "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
341            "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
342            "wasi:logging/logging": crate::bindings::wasi::logging::logging,
343            "wasi:config/store@0.2.0-draft": crate::bindings::wasi::config::store,
344        }
345    });
346
347    pub use __export_golem_agentic_impl as export_golem_agentic;
348}
349#[cfg(feature = "export_golem_agentic")]
350pub(crate) use golem_agentic::golem::tool::underlying as tool_underlying_bindings;
351
352#[cfg(feature = "export_golem_agentic")]
353pub use ctor;
354
355#[cfg(feature = "export_golem_agentic")]
356pub use async_trait;
357
358#[cfg(feature = "export_golem_agentic")]
359pub use serde;
360
361#[cfg(feature = "export_golem_agentic")]
362pub use serde_json;
363
364#[cfg(feature = "export_oplog_processor")]
365pub mod oplog_processor {
366    use wit_bindgen::generate;
367
368    pub mod host {
369        pub use crate::raw_bindings::golem::api::host::AgentMetadata;
370    }
371
372    generate!({
373        path: "wit",
374        world: "golem-rust-oplog-processor",
375        generate_all,
376        generate_unused_types: true,
377        pub_export_macro: true,
378        with: {
379            "golem:core/types@2.0.0": golem_schema::schema::wit::wire,
380            "golem:tool/common@0.1.0": golem_schema::schema::tool::wit::wire,
381            "wasi:clocks/system-clock@0.3.0": crate::wasi_clocks_compat::system_clock,
382            "wasi:clocks/types@0.3.0": crate::wasi_clocks_compat::types,
383
384            "golem:api/host@1.5.0": crate::bindings::golem::api::host,
385            "golem:tool/host@0.1.0": crate::bindings::golem::tool::host,
386            "golem:api/retry@1.5.0": crate::bindings::golem::api::retry,
387            "golem:api/oplog@1.5.0": crate::bindings::golem::api::oplog,
388            "golem:api/context@1.5.0": crate::bindings::golem::api::context,
389            "golem:durability/durability@1.6.0": crate::bindings::golem::durability::durability,
390            "golem:quota/types@1.5.0": crate::bindings::golem::quota::types,
391            "golem:secrets/types@0.1.0": crate::bindings::golem::secrets::types,
392            "golem:secrets/reveal@0.1.0": crate::bindings::golem::secrets::reveal,
393            "golem:permissions/types@0.1.0": crate::bindings::golem::permissions::types,
394            "golem:permissions/derive@0.1.0": crate::bindings::golem::permissions::derive,
395            "golem:permissions/inspect@0.1.0": crate::bindings::golem::permissions::inspect,
396            "golem:permissions/revoke@0.1.0": crate::bindings::golem::permissions::revoke,
397            "golem:permissions/wallet@0.1.0": crate::bindings::golem::permissions::wallet,
398            "golem:permissions/kernel-introspection@0.1.0": crate::bindings::golem::permissions::kernel_introspection,
399            "golem:rdbms/mysql@1.5.0": crate::bindings::golem::rdbms::mysql,
400            "golem:rdbms/postgres@1.5.0": crate::bindings::golem::rdbms::postgres,
401            "golem:rdbms/types@1.5.0": crate::bindings::golem::rdbms::types,
402            "wasi:blobstore/blobstore": crate::bindings::wasi::blobstore::blobstore,
403            "wasi:blobstore/container": crate::bindings::wasi::blobstore::container,
404            "wasi:blobstore/types": crate::bindings::wasi::blobstore::types,
405            "wasi:keyvalue/eventual-batch@0.1.0": crate::bindings::wasi::keyvalue::eventual_batch,
406            "wasi:keyvalue/eventual@0.1.0": crate::bindings::wasi::keyvalue::eventual,
407            "wasi:keyvalue/types@0.1.0": crate::bindings::wasi::keyvalue::types,
408            "wasi:keyvalue/wasi-keyvalue-error@0.1.0": crate::bindings::wasi::keyvalue::wasi_keyvalue_error,
409            "wasi:logging/logging": crate::bindings::wasi::logging::logging,
410        }
411    });
412
413    pub use __export_golem_rust_oplog_processor_impl as export_oplog_processor;
414}
415
416#[cfg(feature = "export_golem_agentic")]
417pub mod agentic;
418
419#[cfg(feature = "export_golem_agentic")]
420pub use agentic::reflection::*;
421
422#[cfg(feature = "durability")]
423pub mod durability;
424
425#[cfg(feature = "json")]
426mod json;
427
428#[cfg(feature = "json")]
429pub use json::*;
430
431#[cfg(feature = "json")]
432pub mod durable_streams;
433
434pub mod permissions;
435pub mod quota;
436pub mod secrets;
437pub mod tool;
438mod transaction;
439
440use bindings::golem::api::host as host_api;
441
442pub type OplogIndex = u64;
443
444pub mod websocket;
445pub use quota::*;
446pub use secrets::*;
447pub mod retry;
448pub use transaction::*;
449pub use websocket::{WebSocketCloseInfo, WebSocketError, WebSocketMessage, WebsocketConnection};
450
451#[cfg(feature = "macro")]
452pub use golem_rust_macro::*;
453
454fn schema_uuid_to_wire(value: Uuid) -> schema::wit::wire::Uuid {
455    let (high_bits, low_bits) = value.as_u64_pair();
456    schema::wit::wire::Uuid {
457        high_bits,
458        low_bits,
459    }
460}
461
462fn wire_uuid_to_schema(value: schema::wit::wire::Uuid) -> Uuid {
463    Uuid::from_u64_pair(value.high_bits, value.low_bits)
464}
465
466fn schema_component_id_to_wire(value: ComponentId) -> schema::wit::wire::ComponentId {
467    schema::wit::wire::ComponentId {
468        uuid: schema_uuid_to_wire(value.uuid),
469    }
470}
471
472fn wire_component_id_to_schema(value: schema::wit::wire::ComponentId) -> ComponentId {
473    ComponentId {
474        uuid: wire_uuid_to_schema(value.uuid),
475    }
476}
477
478fn schema_agent_id_to_wire(value: AgentId) -> schema::wit::wire::AgentId {
479    schema::wit::wire::AgentId {
480        component_id: schema_component_id_to_wire(value.component_id),
481        agent_id: value.agent_id,
482    }
483}
484
485fn wire_agent_id_to_schema(value: schema::wit::wire::AgentId) -> AgentId {
486    AgentId {
487        component_id: wire_component_id_to_schema(value.component_id),
488        agent_id: value.agent_id,
489    }
490}
491
492fn schema_promise_id_to_wire(value: &PromiseId) -> schema::wit::wire::PromiseId {
493    schema::wit::wire::PromiseId {
494        agent_id: schema_agent_id_to_wire(value.agent_id.clone()),
495        oplog_idx: value.oplog_idx,
496    }
497}
498
499fn wire_promise_id_to_schema(value: schema::wit::wire::PromiseId) -> PromiseId {
500    PromiseId {
501        agent_id: wire_agent_id_to_schema(value.agent_id),
502        oplog_idx: value.oplog_idx,
503    }
504}
505
506fn schema_environment_id_to_host(value: EnvironmentId) -> host_api::EnvironmentId {
507    host_api::EnvironmentId {
508        uuid: schema_uuid_to_wire(value.uuid),
509    }
510}
511
512fn host_environment_id_to_schema(value: host_api::EnvironmentId) -> EnvironmentId {
513    EnvironmentId {
514        uuid: wire_uuid_to_schema(value.uuid),
515    }
516}
517
518#[derive(
519    Clone, Copy, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema,
520)]
521pub enum UpdateMode {
522    Automatic,
523    SnapshotBased,
524}
525
526impl From<host_api::UpdateMode> for UpdateMode {
527    fn from(value: host_api::UpdateMode) -> Self {
528        match value {
529            host_api::UpdateMode::Automatic => Self::Automatic,
530            host_api::UpdateMode::SnapshotBased => Self::SnapshotBased,
531        }
532    }
533}
534
535impl From<UpdateMode> for host_api::UpdateMode {
536    fn from(value: UpdateMode) -> Self {
537        match value {
538            UpdateMode::Automatic => Self::Automatic,
539            UpdateMode::SnapshotBased => Self::SnapshotBased,
540        }
541    }
542}
543
544#[derive(
545    Clone, Copy, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema,
546)]
547pub enum FilterComparator {
548    Equal,
549    NotEqual,
550    GreaterEqual,
551    Greater,
552    LessEqual,
553    Less,
554}
555
556impl From<host_api::FilterComparator> for FilterComparator {
557    fn from(value: host_api::FilterComparator) -> Self {
558        match value {
559            host_api::FilterComparator::Equal => Self::Equal,
560            host_api::FilterComparator::NotEqual => Self::NotEqual,
561            host_api::FilterComparator::GreaterEqual => Self::GreaterEqual,
562            host_api::FilterComparator::Greater => Self::Greater,
563            host_api::FilterComparator::LessEqual => Self::LessEqual,
564            host_api::FilterComparator::Less => Self::Less,
565        }
566    }
567}
568
569impl From<FilterComparator> for host_api::FilterComparator {
570    fn from(value: FilterComparator) -> Self {
571        match value {
572            FilterComparator::Equal => Self::Equal,
573            FilterComparator::NotEqual => Self::NotEqual,
574            FilterComparator::GreaterEqual => Self::GreaterEqual,
575            FilterComparator::Greater => Self::Greater,
576            FilterComparator::LessEqual => Self::LessEqual,
577            FilterComparator::Less => Self::Less,
578        }
579    }
580}
581
582#[derive(
583    Clone, Copy, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema,
584)]
585pub enum StringFilterComparator {
586    Equal,
587    NotEqual,
588    Like,
589    NotLike,
590    StartsWith,
591}
592
593impl From<host_api::StringFilterComparator> for StringFilterComparator {
594    fn from(value: host_api::StringFilterComparator) -> Self {
595        match value {
596            host_api::StringFilterComparator::Equal => Self::Equal,
597            host_api::StringFilterComparator::NotEqual => Self::NotEqual,
598            host_api::StringFilterComparator::Like => Self::Like,
599            host_api::StringFilterComparator::NotLike => Self::NotLike,
600            host_api::StringFilterComparator::StartsWith => Self::StartsWith,
601        }
602    }
603}
604
605impl From<StringFilterComparator> for host_api::StringFilterComparator {
606    fn from(value: StringFilterComparator) -> Self {
607        match value {
608            StringFilterComparator::Equal => Self::Equal,
609            StringFilterComparator::NotEqual => Self::NotEqual,
610            StringFilterComparator::Like => Self::Like,
611            StringFilterComparator::NotLike => Self::NotLike,
612            StringFilterComparator::StartsWith => Self::StartsWith,
613        }
614    }
615}
616
617#[derive(
618    Clone, Copy, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema,
619)]
620pub enum AgentStatus {
621    Running,
622    Idle,
623    Suspended,
624    Interrupted,
625    Retrying,
626    Failed,
627    Exited,
628}
629
630impl From<host_api::AgentStatus> for AgentStatus {
631    fn from(value: host_api::AgentStatus) -> Self {
632        match value {
633            host_api::AgentStatus::Running => Self::Running,
634            host_api::AgentStatus::Idle => Self::Idle,
635            host_api::AgentStatus::Suspended => Self::Suspended,
636            host_api::AgentStatus::Interrupted => Self::Interrupted,
637            host_api::AgentStatus::Retrying => Self::Retrying,
638            host_api::AgentStatus::Failed => Self::Failed,
639            host_api::AgentStatus::Exited => Self::Exited,
640        }
641    }
642}
643
644impl From<AgentStatus> for host_api::AgentStatus {
645    fn from(value: AgentStatus) -> Self {
646        match value {
647            AgentStatus::Running => Self::Running,
648            AgentStatus::Idle => Self::Idle,
649            AgentStatus::Suspended => Self::Suspended,
650            AgentStatus::Interrupted => Self::Interrupted,
651            AgentStatus::Retrying => Self::Retrying,
652            AgentStatus::Failed => Self::Failed,
653            AgentStatus::Exited => Self::Exited,
654        }
655    }
656}
657
658#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
659pub struct AgentNameFilter {
660    pub comparator: StringFilterComparator,
661    pub value: String,
662}
663
664impl From<host_api::AgentNameFilter> for AgentNameFilter {
665    fn from(value: host_api::AgentNameFilter) -> Self {
666        Self {
667            comparator: Into::into(value.comparator),
668            value: value.value,
669        }
670    }
671}
672
673impl From<AgentNameFilter> for host_api::AgentNameFilter {
674    fn from(value: AgentNameFilter) -> Self {
675        Self {
676            comparator: Into::into(value.comparator),
677            value: value.value,
678        }
679    }
680}
681
682#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
683pub struct AgentStatusFilter {
684    pub comparator: FilterComparator,
685    pub value: AgentStatus,
686}
687
688impl From<host_api::AgentStatusFilter> for AgentStatusFilter {
689    fn from(value: host_api::AgentStatusFilter) -> Self {
690        Self {
691            comparator: Into::into(value.comparator),
692            value: Into::into(value.value),
693        }
694    }
695}
696
697impl From<AgentStatusFilter> for host_api::AgentStatusFilter {
698    fn from(value: AgentStatusFilter) -> Self {
699        Self {
700            comparator: Into::into(value.comparator),
701            value: Into::into(value.value),
702        }
703    }
704}
705
706#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
707pub struct AgentVersionFilter {
708    pub comparator: FilterComparator,
709    pub value: u64,
710}
711
712impl From<host_api::AgentVersionFilter> for AgentVersionFilter {
713    fn from(value: host_api::AgentVersionFilter) -> Self {
714        Self {
715            comparator: Into::into(value.comparator),
716            value: value.value,
717        }
718    }
719}
720
721impl From<AgentVersionFilter> for host_api::AgentVersionFilter {
722    fn from(value: AgentVersionFilter) -> Self {
723        Self {
724            comparator: Into::into(value.comparator),
725            value: value.value,
726        }
727    }
728}
729
730#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
731pub struct AgentCreatedAtFilter {
732    pub comparator: FilterComparator,
733    pub value: u64,
734}
735
736impl From<host_api::AgentCreatedAtFilter> for AgentCreatedAtFilter {
737    fn from(value: host_api::AgentCreatedAtFilter) -> Self {
738        Self {
739            comparator: Into::into(value.comparator),
740            value: value.value,
741        }
742    }
743}
744
745impl From<AgentCreatedAtFilter> for host_api::AgentCreatedAtFilter {
746    fn from(value: AgentCreatedAtFilter) -> Self {
747        Self {
748            comparator: Into::into(value.comparator),
749            value: value.value,
750        }
751    }
752}
753
754#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
755pub struct AgentEnvFilter {
756    pub name: String,
757    pub comparator: StringFilterComparator,
758    pub value: String,
759}
760
761impl From<host_api::AgentEnvFilter> for AgentEnvFilter {
762    fn from(value: host_api::AgentEnvFilter) -> Self {
763        Self {
764            name: value.name,
765            comparator: Into::into(value.comparator),
766            value: value.value,
767        }
768    }
769}
770
771impl From<AgentEnvFilter> for host_api::AgentEnvFilter {
772    fn from(value: AgentEnvFilter) -> Self {
773        Self {
774            name: value.name,
775            comparator: Into::into(value.comparator),
776            value: value.value,
777        }
778    }
779}
780
781#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
782pub struct AgentConfigVarsFilter {
783    pub name: String,
784    pub comparator: StringFilterComparator,
785    pub value: String,
786}
787
788impl From<host_api::AgentConfigVarsFilter> for AgentConfigVarsFilter {
789    fn from(value: host_api::AgentConfigVarsFilter) -> Self {
790        Self {
791            name: value.name,
792            comparator: Into::into(value.comparator),
793            value: value.value,
794        }
795    }
796}
797
798impl From<AgentConfigVarsFilter> for host_api::AgentConfigVarsFilter {
799    fn from(value: AgentConfigVarsFilter) -> Self {
800        Self {
801            name: value.name,
802            comparator: Into::into(value.comparator),
803            value: value.value,
804        }
805    }
806}
807
808#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
809pub enum AgentPropertyFilter {
810    Name(AgentNameFilter),
811    Status(AgentStatusFilter),
812    Version(AgentVersionFilter),
813    CreatedAt(AgentCreatedAtFilter),
814    Env(AgentEnvFilter),
815    Config(AgentConfigVarsFilter),
816}
817
818impl From<host_api::AgentPropertyFilter> for AgentPropertyFilter {
819    fn from(value: host_api::AgentPropertyFilter) -> Self {
820        match value {
821            host_api::AgentPropertyFilter::Name(value) => Self::Name(Into::into(value)),
822            host_api::AgentPropertyFilter::Status(value) => Self::Status(Into::into(value)),
823            host_api::AgentPropertyFilter::Version(value) => Self::Version(Into::into(value)),
824            host_api::AgentPropertyFilter::CreatedAt(value) => Self::CreatedAt(Into::into(value)),
825            host_api::AgentPropertyFilter::Env(value) => Self::Env(Into::into(value)),
826            host_api::AgentPropertyFilter::Config(value) => Self::Config(Into::into(value)),
827        }
828    }
829}
830
831impl From<AgentPropertyFilter> for host_api::AgentPropertyFilter {
832    fn from(value: AgentPropertyFilter) -> Self {
833        match value {
834            AgentPropertyFilter::Name(value) => Self::Name(Into::into(value)),
835            AgentPropertyFilter::Status(value) => Self::Status(Into::into(value)),
836            AgentPropertyFilter::Version(value) => Self::Version(Into::into(value)),
837            AgentPropertyFilter::CreatedAt(value) => Self::CreatedAt(Into::into(value)),
838            AgentPropertyFilter::Env(value) => Self::Env(Into::into(value)),
839            AgentPropertyFilter::Config(value) => Self::Config(Into::into(value)),
840        }
841    }
842}
843
844#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
845pub struct AgentAllFilter {
846    pub filters: Vec<AgentPropertyFilter>,
847}
848
849impl From<host_api::AgentAllFilter> for AgentAllFilter {
850    fn from(value: host_api::AgentAllFilter) -> Self {
851        Self {
852            filters: value.filters.into_iter().map(Into::into).collect(),
853        }
854    }
855}
856
857impl From<AgentAllFilter> for host_api::AgentAllFilter {
858    fn from(value: AgentAllFilter) -> Self {
859        Self {
860            filters: value.filters.into_iter().map(Into::into).collect(),
861        }
862    }
863}
864
865#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
866pub struct AgentAnyFilter {
867    pub filters: Vec<AgentAllFilter>,
868}
869
870impl From<host_api::AgentAnyFilter> for AgentAnyFilter {
871    fn from(value: host_api::AgentAnyFilter) -> Self {
872        Self {
873            filters: value.filters.into_iter().map(Into::into).collect(),
874        }
875    }
876}
877
878impl From<AgentAnyFilter> for host_api::AgentAnyFilter {
879    fn from(value: AgentAnyFilter) -> Self {
880        Self {
881            filters: value.filters.into_iter().map(Into::into).collect(),
882        }
883    }
884}
885
886#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
887pub struct AgentMetadata {
888    pub agent_id: AgentId,
889    pub args: Vec<String>,
890    pub env: Vec<(String, String)>,
891    pub config: Vec<(String, String)>,
892    pub status: AgentStatus,
893    pub component_revision: u64,
894    pub retry_count: u64,
895    pub environment_id: EnvironmentId,
896}
897
898impl From<host_api::AgentMetadata> for AgentMetadata {
899    fn from(value: host_api::AgentMetadata) -> Self {
900        Self {
901            agent_id: wire_agent_id_to_schema(value.agent_id),
902            args: value.args,
903            env: value.env,
904            config: value.config,
905            status: Into::into(value.status),
906            component_revision: value.component_revision,
907            retry_count: value.retry_count,
908            environment_id: host_environment_id_to_schema(value.environment_id),
909        }
910    }
911}
912
913impl From<AgentMetadata> for host_api::AgentMetadata {
914    fn from(value: AgentMetadata) -> Self {
915        Self {
916            agent_id: schema_agent_id_to_wire(value.agent_id),
917            args: value.args,
918            env: value.env,
919            config: value.config,
920            status: Into::into(value.status),
921            component_revision: value.component_revision,
922            retry_count: value.retry_count,
923            environment_id: schema_environment_id_to_host(value.environment_id),
924        }
925    }
926}
927
928pub struct GetAgents {
929    raw: host_api::GetAgents,
930}
931
932pub use host_api::AgentOperationError;
933
934impl GetAgents {
935    pub fn new(component_id: ComponentId, filter: Option<&AgentAnyFilter>, precise: bool) -> Self {
936        let raw_filter = filter.cloned().map(host_api::AgentAnyFilter::from);
937        Self {
938            raw: host_api::GetAgents::new(
939                schema_component_id_to_wire(component_id),
940                raw_filter.as_ref(),
941                precise,
942            ),
943        }
944    }
945
946    pub fn get_next(&self) -> Result<Option<Vec<AgentMetadata>>, AgentOperationError> {
947        self.raw
948            .get_next()
949            .map(|values| values.map(|values| values.into_iter().map(Into::into).collect()))
950    }
951}
952
953#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
954pub struct ForkDetails {
955    pub forked_phantom_id: Uuid,
956}
957
958#[derive(Clone, Debug, Eq, PartialEq, IntoSchema, FromSchema, IntoWire, FromWire, WireSchema)]
959pub enum ForkResult {
960    Original(ForkDetails),
961    Forked(ForkDetails),
962}
963
964impl From<host_api::ForkResult> for ForkResult {
965    fn from(value: host_api::ForkResult) -> Self {
966        match value {
967            host_api::ForkResult::Original(details) => Self::Original(ForkDetails {
968                forked_phantom_id: wire_uuid_to_schema(details.forked_phantom_id),
969            }),
970            host_api::ForkResult::Forked(details) => Self::Forked(ForkDetails {
971                forked_phantom_id: wire_uuid_to_schema(details.forked_phantom_id),
972            }),
973        }
974    }
975}
976
977pub struct PromiseResult {
978    raw: host_api::GetPromiseResult,
979}
980
981impl PromiseResult {
982    /// Awaits the promise result. The agent is suspended until the promise is
983    /// completed; the completed payload is then returned.
984    ///
985    /// On WASI P2 this was a non-blocking `get() -> Option<...>` paired with a
986    /// `subscribe() -> pollable`; the P3 `wasi:io/poll` pollable is gone, so the
987    /// host `get-promise-result.get` is now an `async func` that awaits directly.
988    pub async fn get(&self) -> Vec<u8> {
989        self.raw.get().await
990    }
991}
992
993pub fn create_promise() -> PromiseId {
994    wire_promise_id_to_schema(host_api::create_promise())
995}
996
997pub fn get_promise(promise_id: &PromiseId) -> PromiseResult {
998    PromiseResult {
999        raw: host_api::get_promise(&schema_promise_id_to_wire(promise_id)),
1000    }
1001}
1002
1003pub fn complete_promise(promise_id: &PromiseId, data: &[u8]) -> bool {
1004    host_api::complete_promise(&schema_promise_id_to_wire(promise_id), data)
1005}
1006
1007pub fn oplog_commit(replicas: u8) {
1008    host_api::oplog_commit(replicas)
1009}
1010
1011/// Read full self metadata. Requires view permission on the running agent,
1012/// admitted by the effective permission card and permitted by `initialCard`.
1013/// Stored environment and configuration fields are not filtered by the per-key
1014/// permissions used for WASI reads. Pure initialization does not call this API.
1015/// Permission denials and backend failures remain typed `AgentOperationError`s.
1016pub fn get_self_metadata() -> Result<AgentMetadata, AgentOperationError> {
1017    host_api::get_self_metadata().map(Into::into)
1018}
1019
1020pub fn get_agent_metadata(agent_id: &AgentId) -> Option<AgentMetadata> {
1021    host_api::get_agent_metadata(&schema_agent_id_to_wire(agent_id.clone())).map(Into::into)
1022}
1023
1024pub fn update_agent(
1025    agent_id: &AgentId,
1026    target_revision: u64,
1027    mode: UpdateMode,
1028) -> Result<(), AgentOperationError> {
1029    host_api::update_agent(
1030        &schema_agent_id_to_wire(agent_id.clone()),
1031        target_revision,
1032        Into::into(mode),
1033    )
1034}
1035
1036pub fn resolve_component_id(component_reference: &str) -> Option<ComponentId> {
1037    host_api::resolve_component_id(component_reference).map(wire_component_id_to_schema)
1038}
1039
1040pub fn resolve_agent_id(component_reference: &str, agent_name: &str) -> Option<AgentId> {
1041    host_api::resolve_agent_id(component_reference, agent_name).map(wire_agent_id_to_schema)
1042}
1043
1044pub fn resolve_agent_id_strict(component_reference: &str, agent_name: &str) -> Option<AgentId> {
1045    host_api::resolve_agent_id_strict(component_reference, agent_name).map(wire_agent_id_to_schema)
1046}
1047
1048pub fn fork() -> Result<ForkResult, AgentOperationError> {
1049    host_api::fork().map(Into::into)
1050}
1051
1052/// Awaits a promise blocking the execution of the agent. The agent is going to be
1053/// suspended until the promise is completed.
1054///
1055/// Use `await_promise` for an async version of this function, allowing to interleave
1056/// awaiting of the promise with other operations.
1057pub fn blocking_await_promise(promise_id: &PromiseId) -> Vec<u8> {
1058    let promise = get_promise(promise_id);
1059    wit_bindgen::block_on(async move { promise.get().await })
1060}
1061
1062/// Awaits a promise.
1063///
1064/// If only promises or timeouts are awaited simultaneously, the agent is going to be
1065/// suspended until any of them completes.
1066pub async fn await_promise(promise_id: &PromiseId) -> Vec<u8> {
1067    let promise = get_promise(promise_id);
1068    promise.get().await
1069}
1070
1071/// Generates an idempotency key. This operation will never be replayed —
1072/// i.e. not only is this key generated, but it is persisted and committed, such that the key can be used in third-party systems (e.g. payment processing)
1073/// to introduce idempotence.
1074pub fn generate_idempotency_key() -> uuid::Uuid {
1075    Into::into(host_api::generate_idempotency_key())
1076}