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}