Skip to main content

oino_extension/
lib.rs

1//! Guest SDK for Oino WASM component extensions (`oino:extension@2.0.0`).
2//!
3//! An extension is a type implementing [`Extension`]; [`export_extension!`] turns it into a
4//! component. `init` registers events, tools, commands, shortcuts, flags, services, settings,
5//! renderers and arbiter roles through [`Init`]; handlers are plain async closures or methods
6//! receiving `&'static Self`. Host capabilities are thin typed wrappers over the WIT imports:
7//!
8//! | Module | WIT | Use |
9//! |---|---|---|
10//! | [`session`] | `session` | entries, `append_entry`, `send_message`, sessions index |
11//! | [`control`] | `control` | model, thinking, tools, commands, compaction, command-context ops |
12//! | [`models`] | `models` | completions, streaming, summaries, credentials |
13//! | [`ui`] | `ui`, `registry` | dialogs, slots (panels, widgets, status, turn footers), settings namespaces, editor, OS integration; node trees from [`ui::widgets`] |
14//! | [`agents`] | `agents` | nested agent sessions (subagents) |
15//! | [`process`] | `process` | `exec`, spawn with streaming stdio, signals, process trees |
16//! | [`tasks`] | `tasks` | host background tasks |
17//! | [`http`] | `http` | fetch (streaming), loopback listener |
18//! | [`fs`] | `fs` + WASI | named preopens, atomic writes, locks, watchers |
19//! | [`timers`] | `timers` | `oino_timer` events, `sleep`, wall clock |
20//! | [`kv`] | `kv` | scoped key-value state |
21//! | [`settings`] | `registry` | extension settings reads and writes |
22//! | [`secrets`], [`bus`], [`services`] | same | secrets, pub/sub, inter-extension calls |
23//! | [`host_service`] | `host-service` | embedding-host services (`"browser"`, `"cron"`, …) |
24//! | [`host`] | `host-info`, `log` | platform, workspace, env, logging |
25//! | [`provider`] (feature `provider`) | `provider`, `provider-host` | provider components |
26//!
27//! ```ignore
28//! use oino_extension::prelude::*;
29//!
30//! #[derive(Default)]
31//! struct Hello;
32//!
33//! #[derive(Deserialize, JsonSchema)]
34//! struct Args { name: String }
35//!
36//! impl Extension for Hello {
37//!     async fn init(&'static self, cx: &mut Init<Self>) -> Result<()> {
38//!         cx.tool(Tool::new("hello").description("Greets").args::<Args>()
39//!             .run(|_ext, args: Args, _cx| async move { Ok(ToolResult::text(format!("Hello {}", args.name))) }));
40//!         cx.on(EventKind::AgentEnd, |_ext, _ev, cx| async move {
41//!             session::append_entry("hello.seen", Some(&json!({"session": cx.session_id()})))?;
42//!             Ok(())
43//!         });
44//!         Ok(())
45//!     }
46//! }
47//!
48//! oino_extension::export_extension!(Hello);
49//! ```
50
51//!
52//! # Errors
53//!
54//! Every wrapper returning [`Result`] fails only with the `host-error` of its WIT import
55//! (permission denied, stale context, invalid argument, …) or a JSON decoding error, surfaced
56//! as [`Error`]. Individual functions therefore do not repeat an `# Errors` section.
57
58#![allow(
59    clippy::missing_errors_doc,
60    reason = "errors are documented once at crate level"
61)]
62#![cfg_attr(not(target_arch = "wasm32"), allow(dead_code, unused_imports))]
63
64#[allow(
65    unsafe_code,
66    clippy::all,
67    clippy::pedantic,
68    missing_docs,
69    unreachable_pub,
70    reason = "generated by wit-bindgen"
71)]
72#[doc(hidden)]
73pub mod bindings {
74    #[cfg(feature = "provider")]
75    wit_bindgen::generate!({
76        path: "wit/oino-extension",
77        world: "provider-extension",
78        generate_all,
79        pub_export_macro: true,
80        export_macro_name: "export_guest",
81        default_bindings_module: "oino_extension::bindings",
82    });
83    #[cfg(not(feature = "provider"))]
84    wit_bindgen::generate!({
85        path: "wit/oino-extension",
86        world: "extension",
87        generate_all,
88        pub_export_macro: true,
89        export_macro_name: "export_guest",
90        default_bindings_module: "oino_extension::bindings",
91    });
92}
93
94pub mod agents;
95pub mod bus;
96pub mod command;
97pub mod context;
98pub mod control;
99mod error;
100pub mod events;
101pub mod fs;
102pub mod host;
103pub mod host_service;
104pub mod http;
105mod init;
106pub mod kv;
107pub mod models;
108pub mod process;
109#[cfg(feature = "provider")]
110pub mod provider;
111#[doc(hidden)]
112pub mod rt;
113pub mod secrets;
114pub mod services;
115pub mod session;
116pub mod settings;
117pub mod sync;
118pub mod tasks;
119pub mod timers;
120pub mod tool;
121pub mod ui;
122
123/// Raw generated WIT types (escape hatch).
124pub use bindings::oino::extension as wit;
125pub use error::{Error, Result};
126pub use futures;
127pub use init::{Extension, Init};
128pub use oino_ai;
129pub use oino_extension_macros::tool;
130pub use schemars;
131pub use serde;
132pub use serde_json;
133pub use wit_bindgen;
134
135/// Everything an extension usually needs.
136pub mod prelude {
137    pub use crate::command::{Command, Flag, Shortcut};
138    pub use crate::context::{CommandCtx, Ctx, ToolCtx};
139    pub use crate::events::{Event, EventKind};
140    pub use crate::tool::{Tool, ToolKind, ToolResult};
141    pub use crate::{
142        Error, Extension, Init, Result, agents, bus, control, fs, host, http, kv, models, process,
143        secrets, services, session, tasks, timers, ui,
144    };
145    pub use schemars::JsonSchema;
146    pub use serde::{Deserialize, Serialize};
147    pub use serde_json::{Value, json};
148}
149
150/// Exports an [`Extension`] type as the component's guest implementation.
151///
152/// ```ignore
153/// oino_extension::export_extension!(MyExtension);
154/// ```
155#[macro_export]
156macro_rules! export_extension {
157    ($ty:ty) => {
158        #[doc(hidden)]
159        type __OinoExtensionShim = $crate::rt::Shim<$ty>;
160        $crate::bindings::export_guest!(__OinoExtensionShim with_types_in $crate::bindings);
161    };
162}