Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7717232
feat(rust-sdk): add RegisterFunctionOptions struct
guibeira Apr 24, 2026
b0e965f
feat(rust-sdk): re-export RegisterFunctionOptions
guibeira Apr 24, 2026
13babb3
feat(rust-sdk)!: align register_function_with with Node/Python order
guibeira Apr 24, 2026
76f3009
docs(rust-sdk): update register_function_with rustdoc example
guibeira Apr 24, 2026
91bdf34
docs(changelog): align Rust register_function_with signature
guibeira Apr 24, 2026
bdadae3
docs(changelog): fix migration row Rust example
guibeira Apr 24, 2026
659413e
docs: regenerate Rust SDK API reference for register_function_with re…
guibeira Apr 24, 2026
273061f
docs: add RegisterFunctionOptions to rustdoc parser allowlist
guibeira Apr 24, 2026
9a046b1
feat(console-rust)!: migrate to new register_function_with signature
guibeira Apr 25, 2026
1a56631
docs(skills): update Rust register_function_with references
guibeira Apr 25, 2026
4b75193
docs: scan FunctionDoc descriptions/examples in type-reachability filter
guibeira Apr 25, 2026
ceaee1a
refactor(rust-sdk)!: collapse to single register_function entry point
guibeira Apr 30, 2026
ca4b8d6
fix(rust-sdk): migrate iii-worker sandbox_daemon + fmt the workspace
guibeira Apr 30, 2026
c1b8e18
rename(rust-sdk): RegisterFunction::raw -> RegisterFunction::untyped
guibeira Apr 30, 2026
d415ce8
refactor(rust-sdk)!: collapse to 3 constructors, fix handler error to…
guibeira Apr 30, 2026
50365b1
fix(rust-sdk): address CodeRabbit review feedback
guibeira Apr 30, 2026
ee38c81
fix(rust-sdk): more CodeRabbit review fixes
guibeira Apr 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
320 changes: 179 additions & 141 deletions console/packages/console-rust/src/bridge/functions.rs

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion console/packages/console-rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ async fn main() -> Result<()> {
}),
otel: otel_config,
headers: None,
..Default::default()
},
);

Expand Down
84 changes: 53 additions & 31 deletions crates/iii-worker/src/cli/worker_manager_daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use crate::core::{
list as core_list, remove as core_remove, start as core_start, stop as core_stop,
update as core_update,
};
use iii_sdk::{III, InitOptions, OtelConfig, RegisterFunction, WorkerMetadata, register_worker};
use iii_sdk::{
III, IIIError, InitOptions, OtelConfig, RegisterFunction, WorkerMetadata, register_worker,
};
use schemars::{JsonSchema, schema_for};
use serde_json::Value;

Expand Down Expand Up @@ -72,6 +74,18 @@ pub fn bad_request_payload(input_label: &str, e: &serde_json::Error) -> String {
err_payload(&err)
}

fn handler_error(payload: String) -> IIIError {
IIIError::Handler(payload)
}

fn op_error(e: &WorkerOpError) -> IIIError {
handler_error(err_payload(e))
}

fn bad_request_error(input_label: &str, e: &serde_json::Error) -> IIIError {
handler_error(bad_request_payload(input_label, e))
}

fn schema_for_value<T: JsonSchema>() -> Option<Value> {
serde_json::to_value(schema_for!(T)).ok()
}
Expand Down Expand Up @@ -130,9 +144,10 @@ struct SchemaResponse {

fn register_schema(iii: &III) {
let _ = iii.register_function(
RegisterFunction::new_async("worker::schema", |payload: Value| async move {
"worker::schema",
RegisterFunction::new_async(|payload: Value| async move {
let req: SchemaRequest = serde_json::from_value(payload)
.map_err(|e| bad_request_payload("worker::schema", &e))?;
.map_err(|e| bad_request_error("worker::schema", &e))?;
let all = vec![
(
"worker::add",
Expand Down Expand Up @@ -199,7 +214,7 @@ fn register_schema(iii: &III) {
}
})
.collect();
Ok::<_, String>(SchemaResponse { schemas })
Ok::<_, IIIError>(SchemaResponse { schemas })
})
.description(
"Introspect request/response schemas for worker::* triggers. \
Expand All @@ -210,12 +225,13 @@ fn register_schema(iii: &III) {

fn register_add(iii: &III, project_root: PathBuf) {
let _ = iii.register_function(
RegisterFunction::new_async("worker::add", move |payload: Value| {
"worker::add",
RegisterFunction::new_async(move |payload: Value| {
let project_root = project_root.clone();
async move {
let opts: AddOptions = serde_json::from_value(payload)
.map_err(|e| bad_request_payload("worker::add", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| err_payload(&e))?;
.map_err(|e| bad_request_error("worker::add", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| op_error(&e))?;
core_add::run(
opts,
&ctx,
Expand All @@ -224,7 +240,7 @@ fn register_add(iii: &III, project_root: PathBuf) {
core_add::CallerMode::Trigger,
)
.await
.map_err(|e| err_payload(&e))
.map_err(|e| op_error(&e))
}
})
.description("Install a worker from registry name or OCI ref"),
Expand All @@ -233,15 +249,16 @@ fn register_add(iii: &III, project_root: PathBuf) {

fn register_remove(iii: &III, project_root: PathBuf) {
let _ = iii.register_function(
RegisterFunction::new_async("worker::remove", move |payload: Value| {
"worker::remove",
RegisterFunction::new_async(move |payload: Value| {
let project_root = project_root.clone();
async move {
let opts: RemoveOptions = serde_json::from_value(payload)
.map_err(|e| bad_request_payload("worker::remove", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| err_payload(&e))?;
.map_err(|e| bad_request_error("worker::remove", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| op_error(&e))?;
core_remove::run(opts, &ctx, &NullSink, &CliHostShim)
.await
.map_err(|e| err_payload(&e))
.map_err(|e| op_error(&e))
}
})
.description("Uninstall workers and clear their artifacts"),
Expand All @@ -250,15 +267,16 @@ fn register_remove(iii: &III, project_root: PathBuf) {

fn register_update(iii: &III, project_root: PathBuf) {
let _ = iii.register_function(
RegisterFunction::new_async("worker::update", move |payload: Value| {
"worker::update",
RegisterFunction::new_async(move |payload: Value| {
let project_root = project_root.clone();
async move {
let opts: UpdateOptions = serde_json::from_value(payload)
.map_err(|e| bad_request_payload("worker::update", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| err_payload(&e))?;
.map_err(|e| bad_request_error("worker::update", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| op_error(&e))?;
core_update::run(opts, &ctx, &NullSink, &CliHostShim)
.await
.map_err(|e| err_payload(&e))
.map_err(|e| op_error(&e))
}
})
.description("Reinstall workers preserving config"),
Expand All @@ -267,15 +285,16 @@ fn register_update(iii: &III, project_root: PathBuf) {

fn register_start(iii: &III, project_root: PathBuf) {
let _ = iii.register_function(
RegisterFunction::new_async("worker::start", move |payload: Value| {
"worker::start",
RegisterFunction::new_async(move |payload: Value| {
let project_root = project_root.clone();
async move {
let opts: StartOptions = serde_json::from_value(payload)
.map_err(|e| bad_request_payload("worker::start", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| err_payload(&e))?;
.map_err(|e| bad_request_error("worker::start", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| op_error(&e))?;
core_start::run(opts, &ctx, &NullSink, &CliHostShim)
.await
.map_err(|e| err_payload(&e))
.map_err(|e| op_error(&e))
}
})
.description("Start a configured worker"),
Expand All @@ -284,15 +303,16 @@ fn register_start(iii: &III, project_root: PathBuf) {

fn register_stop(iii: &III, project_root: PathBuf) {
let _ = iii.register_function(
RegisterFunction::new_async("worker::stop", move |payload: Value| {
"worker::stop",
RegisterFunction::new_async(move |payload: Value| {
let project_root = project_root.clone();
async move {
let opts: StopOptions = serde_json::from_value(payload)
.map_err(|e| bad_request_payload("worker::stop", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| err_payload(&e))?;
.map_err(|e| bad_request_error("worker::stop", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| op_error(&e))?;
core_stop::run(opts, &ctx, &NullSink, &CliHostShim)
.await
.map_err(|e| err_payload(&e))
.map_err(|e| op_error(&e))
}
})
.description("Stop a running worker"),
Expand All @@ -301,7 +321,8 @@ fn register_stop(iii: &III, project_root: PathBuf) {

fn register_list(iii: &III, project_root: PathBuf) {
let _ = iii.register_function(
RegisterFunction::new_async("worker::list", move |payload: Value| {
"worker::list",
RegisterFunction::new_async(move |payload: Value| {
let project_root = project_root.clone();
async move {
// Lenient default only for null or empty object. Other shapes
Expand All @@ -311,12 +332,12 @@ fn register_list(iii: &III, project_root: PathBuf) {
Value::Null => ListOptions::default(),
Value::Object(map) if map.is_empty() => ListOptions::default(),
_ => serde_json::from_value(payload)
.map_err(|e| bad_request_payload("worker::list", &e))?,
.map_err(|e| bad_request_error("worker::list", &e))?,
};
let ctx = ProjectCtx::open_unlocked(project_root);
core_list::run(opts, &ctx, &NullSink, &CliHostShim)
.await
.map_err(|e| err_payload(&e))
.map_err(|e| op_error(&e))
}
})
.description("List installed workers"),
Expand All @@ -325,15 +346,16 @@ fn register_list(iii: &III, project_root: PathBuf) {

fn register_clear(iii: &III, project_root: PathBuf) {
let _ = iii.register_function(
RegisterFunction::new_async("worker::clear", move |payload: Value| {
"worker::clear",
RegisterFunction::new_async(move |payload: Value| {
let project_root = project_root.clone();
async move {
let opts: ClearOptions = serde_json::from_value(payload)
.map_err(|e| bad_request_payload("worker::clear", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| err_payload(&e))?;
.map_err(|e| bad_request_error("worker::clear", &e))?;
let ctx = ProjectCtx::open(project_root).map_err(|e| op_error(&e))?;
core_clear::run(opts, &ctx, &NullSink, &CliHostShim)
.await
.map_err(|e| err_payload(&e))
.map_err(|e| op_error(&e))
}
})
.description("Wipe worker artifacts"),
Expand Down
16 changes: 5 additions & 11 deletions crates/iii-worker/src/sandbox_daemon/fs/chmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;

use iii_sdk::{IIIError, RegisterFunctionMessage};
use iii_sdk::IIIError;
use iii_shell_proto::{FsOp, FsResult};
use serde::{Deserialize, Serialize};
use serde_json::Value;
Expand Down Expand Up @@ -91,16 +91,10 @@ pub(super) fn register(
}
}) as Pin<Box<dyn Future<Output = Result<Value, IIIError>> + Send>>
};
let _ = iii.register_function_with(
RegisterFunctionMessage {
id: "sandbox::fs::chmod".to_string(),
description: Some("Change file permissions inside a sandbox".to_string()),
request_format: None,
response_format: None,
metadata: None,
invocation: None,
},
handler,
let _ = iii.register_function(
"sandbox::fs::chmod",
iii_sdk::RegisterFunction::new_async(handler)
.description("Change file permissions inside a sandbox".to_string()),
);
}

Expand Down
16 changes: 5 additions & 11 deletions crates/iii-worker/src/sandbox_daemon/fs/grep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;

use iii_sdk::{IIIError, RegisterFunctionMessage};
use iii_sdk::IIIError;
use iii_shell_proto::{FsMatch, FsOp, FsResult};
use serde::{Deserialize, Serialize};
use serde_json::Value;
Expand Down Expand Up @@ -111,16 +111,10 @@ pub(super) fn register(
}
}) as Pin<Box<dyn Future<Output = Result<Value, IIIError>> + Send>>
};
let _ = iii.register_function_with(
RegisterFunctionMessage {
id: "sandbox::fs::grep".to_string(),
description: Some("Search for a pattern in files inside a sandbox".to_string()),
request_format: None,
response_format: None,
metadata: None,
invocation: None,
},
handler,
let _ = iii.register_function(
"sandbox::fs::grep",
iii_sdk::RegisterFunction::new_async(handler)
.description("Search for a pattern in files inside a sandbox".to_string()),
);
}

Expand Down
16 changes: 5 additions & 11 deletions crates/iii-worker/src/sandbox_daemon/fs/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;

use iii_sdk::{IIIError, RegisterFunctionMessage};
use iii_sdk::IIIError;
use iii_shell_proto::{FsEntry, FsOp, FsResult};
use serde::{Deserialize, Serialize};
use serde_json::Value;
Expand Down Expand Up @@ -75,16 +75,10 @@ pub(super) fn register(
}
}) as Pin<Box<dyn Future<Output = Result<Value, IIIError>> + Send>>
};
let _ = iii.register_function_with(
RegisterFunctionMessage {
id: "sandbox::fs::ls".to_string(),
description: Some("List directory contents inside a sandbox".to_string()),
request_format: None,
response_format: None,
metadata: None,
invocation: None,
},
handler,
let _ = iii.register_function(
"sandbox::fs::ls",
iii_sdk::RegisterFunction::new_async(handler)
.description("List directory contents inside a sandbox".to_string()),
);
}

Expand Down
16 changes: 5 additions & 11 deletions crates/iii-worker/src/sandbox_daemon/fs/mkdir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;

use iii_sdk::{IIIError, RegisterFunctionMessage};
use iii_sdk::IIIError;
use iii_shell_proto::{FsOp, FsResult};
use serde::{Deserialize, Serialize};
use serde_json::Value;
Expand Down Expand Up @@ -90,16 +90,10 @@ pub(super) fn register(
}
}) as Pin<Box<dyn Future<Output = Result<Value, IIIError>> + Send>>
};
let _ = iii.register_function_with(
RegisterFunctionMessage {
id: "sandbox::fs::mkdir".to_string(),
description: Some("Create a directory inside a sandbox".to_string()),
request_format: None,
response_format: None,
metadata: None,
invocation: None,
},
handler,
let _ = iii.register_function(
"sandbox::fs::mkdir",
iii_sdk::RegisterFunction::new_async(handler)
.description("Create a directory inside a sandbox".to_string()),
);
}

Expand Down
16 changes: 5 additions & 11 deletions crates/iii-worker/src/sandbox_daemon/fs/mv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;

use iii_sdk::{IIIError, RegisterFunctionMessage};
use iii_sdk::IIIError;
use iii_shell_proto::{FsOp, FsResult};
use serde::{Deserialize, Serialize};
use serde_json::Value;
Expand Down Expand Up @@ -85,16 +85,10 @@ pub(super) fn register(
}
}) as Pin<Box<dyn Future<Output = Result<Value, IIIError>> + Send>>
};
let _ = iii.register_function_with(
RegisterFunctionMessage {
id: "sandbox::fs::mv".to_string(),
description: Some("Move or rename a path inside a sandbox".to_string()),
request_format: None,
response_format: None,
metadata: None,
invocation: None,
},
handler,
let _ = iii.register_function(
"sandbox::fs::mv",
iii_sdk::RegisterFunction::new_async(handler)
.description("Move or rename a path inside a sandbox".to_string()),
);
}

Expand Down
16 changes: 5 additions & 11 deletions crates/iii-worker/src/sandbox_daemon/fs/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;

use iii_sdk::IIIError;
use iii_sdk::channels::StreamChannelRef;
use iii_sdk::{IIIError, RegisterFunctionMessage};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use tokio::io::AsyncReadExt;
Expand Down Expand Up @@ -149,16 +149,10 @@ pub(super) fn register(
}
}) as Pin<Box<dyn Future<Output = Result<Value, IIIError>> + Send>>
};
let _ = iii.register_function_with(
RegisterFunctionMessage {
id: "sandbox::fs::read".to_string(),
description: Some("Stream-download a file from a sandbox".to_string()),
request_format: None,
response_format: None,
metadata: None,
invocation: None,
},
handler,
let _ = iii.register_function(
"sandbox::fs::read",
iii_sdk::RegisterFunction::new_async(handler)
.description("Stream-download a file from a sandbox".to_string()),
);
}

Expand Down
Loading
Loading