diff --git a/acp/Cargo.lock b/acp/Cargo.lock index 08e3424d3..83a62ccd4 100644 --- a/acp/Cargo.lock +++ b/acp/Cargo.lock @@ -685,9 +685,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -706,9 +706,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/acp/Cargo.toml b/acp/Cargo.toml index b38ee9a4e..5fc03b56e 100644 --- a/acp/Cargo.toml +++ b/acp/Cargo.toml @@ -23,7 +23,7 @@ name = "iii-acp" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" tokio = { version = "1", features = ["macros", "rt-multi-thread", "io-std", "io-util", "sync", "time", "signal"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/acp/src/handler.rs b/acp/src/handler.rs index ec39c9c98..1217f9c1e 100644 --- a/acp/src/handler.rs +++ b/acp/src/handler.rs @@ -704,6 +704,9 @@ fn register_event_subscriber( function_id: fn_id, config: json!({ "stream_name": AGENT_EVENTS_STREAM }), metadata: None, + // Resolve the trigger's target in this worker's namespace so it matches + // where the function was registered (None => engine default). + namespace: iii.namespace(), }) { Ok(t) => Some(t), Err(e) => { diff --git a/approval-gate/Cargo.lock b/approval-gate/Cargo.lock index 6101c32c9..f0308f505 100644 --- a/approval-gate/Cargo.lock +++ b/approval-gate/Cargo.lock @@ -806,9 +806,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -827,9 +827,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/approval-gate/Cargo.toml b/approval-gate/Cargo.toml index 8b3cb2609..8277d30f0 100644 --- a/approval-gate/Cargo.toml +++ b/approval-gate/Cargo.toml @@ -15,7 +15,7 @@ name = "approval_gate" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.2" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/approval-gate/src/configuration.rs b/approval-gate/src/configuration.rs index b753e837b..85b1687f4 100644 --- a/approval-gate/src/configuration.rs +++ b/approval-gate/src/configuration.rs @@ -128,6 +128,7 @@ pub fn bind_hook(iii: &IIIClient) { "on_error": HOOK_ON_ERROR, }), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!( trigger_type = "harness::hook::pre-trigger", @@ -157,6 +158,7 @@ pub fn bind_filesystem_access_watch_hook(iii: &IIIClient) { "on_error": FILESYSTEM_ACCESS_WATCH_ON_ERROR, }), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!( trigger_type = "harness::hook::post-trigger", @@ -262,6 +264,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/approval-gate/src/events.rs b/approval-gate/src/events.rs index a6290a52b..fdc6d094c 100644 --- a/approval-gate/src/events.rs +++ b/approval-gate/src/events.rs @@ -253,15 +253,36 @@ impl Emitter { ) { for binding in set.snapshot() { if binding_matches(&binding.filter, session_id, session_metadata) { - let res = self - .iii - .trigger(TriggerRequest { - function_id: binding.function_id.clone(), - payload: payload.clone(), - action: Some(TriggerAction::Void), - timeout_ms: None, - }) - .await; + let request = TriggerRequest { + function_id: binding.function_id.clone(), + payload: payload.clone(), + action: Some(TriggerAction::Void), + timeout_ms: None, + }; + let route_ns = self.iii.namespace().filter(|_| { + !matches!( + binding.function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let res = match route_ns { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; if let Err(e) = res { tracing::warn!( function_id = %binding.function_id, @@ -314,6 +335,7 @@ mod tests { function_id: function_id.into(), config, metadata: None, + namespace: None, } } diff --git a/approval-gate/src/harness.rs b/approval-gate/src/harness.rs index 601a59e21..1c7d0a153 100644 --- a/approval-gate/src/harness.rs +++ b/approval-gate/src/harness.rs @@ -10,13 +10,16 @@ use iii_sdk::IIIClient; use serde_json::{json, Value}; pub async fn function_resolve(iii: &IIIClient, payload: Value) -> Result { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: "harness::function::resolve".into(), payload, action: None, timeout_ms: None, - }) - .await + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } } fn parse_roots(reply: &Value) -> Vec { @@ -36,14 +39,16 @@ fn parse_roots(reply: &Value) -> Vec { /// error on "no grants" — only on transport/RPC failure, e.g. an older /// harness that doesn't implement this control plane yet). pub async fn filesystem_grants(iii: &IIIClient, session_id: &str) -> Result, Error> { - let reply = iii - .trigger(TriggerRequest { - function_id: "harness::filesystem::grants".into(), - payload: json!({ "session_id": session_id }), - action: None, - timeout_ms: None, - }) - .await?; + let request = TriggerRequest { + function_id: "harness::filesystem::grants".into(), + payload: json!({ "session_id": session_id }), + action: None, + timeout_ms: None, + }; + let reply = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; Ok(parse_roots(&reply)) } @@ -55,13 +60,15 @@ pub async fn filesystem_grant( session_id: &str, root: &str, ) -> Result, Error> { - let reply = iii - .trigger(TriggerRequest { - function_id: "harness::filesystem::grant".into(), - payload: json!({ "session_id": session_id, "root": root }), - action: None, - timeout_ms: None, - }) - .await?; + let request = TriggerRequest { + function_id: "harness::filesystem::grant".into(), + payload: json!({ "session_id": session_id, "root": root }), + action: None, + timeout_ms: None, + }; + let reply = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; Ok(parse_roots(&reply)) } diff --git a/approval-gate/src/main.rs b/approval-gate/src/main.rs index b7670398a..ecff0d3cd 100644 --- a/approval-gate/src/main.rs +++ b/approval-gate/src/main.rs @@ -86,6 +86,7 @@ fn bind_best_effort( function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }); match res { Ok(_) => tracing::info!(trigger_type, function_id, "trigger binding requested"), diff --git a/approval-gate/src/session.rs b/approval-gate/src/session.rs index 979ad5b33..ed34a3fea 100644 --- a/approval-gate/src/session.rs +++ b/approval-gate/src/session.rs @@ -6,11 +6,14 @@ use iii_sdk::IIIClient; use serde_json::{json, Value}; pub async fn get(iii: &IIIClient, session_id: &str) -> Result { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: "session::get".into(), payload: json!({ "session_id": session_id }), action: None, timeout_ms: None, - }) - .await + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } } diff --git a/approval-gate/src/testkit/engine.rs b/approval-gate/src/testkit/engine.rs index a14eafb2c..2ea578679 100644 --- a/approval-gate/src/testkit/engine.rs +++ b/approval-gate/src/testkit/engine.rs @@ -459,6 +459,7 @@ pub async fn boot(engine: &Engine, opts: BootOpts) -> TestStack { function_id: "recorder::on_created".to_string(), config: json!({}), metadata: None, + namespace: iii.namespace(), }) .expect("bind pending_created"); iii.register_trigger(RegisterTriggerInput { @@ -466,6 +467,7 @@ pub async fn boot(engine: &Engine, opts: BootOpts) -> TestStack { function_id: "recorder::on_resolved".to_string(), config: json!({}), metadata: None, + namespace: iii.namespace(), }) .expect("bind pending_resolved"); diff --git a/bridge/Cargo.lock b/bridge/Cargo.lock index 323a1b714..c4874ac61 100644 --- a/bridge/Cargo.lock +++ b/bridge/Cargo.lock @@ -660,9 +660,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -681,9 +681,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/bridge/Cargo.toml b/bridge/Cargo.toml index 62f434836..e2570af6a 100644 --- a/bridge/Cargo.toml +++ b/bridge/Cargo.toml @@ -18,7 +18,7 @@ name = "bridge" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" async-trait = "0.1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } diff --git a/bridge/src/boot.rs b/bridge/src/boot.rs index c45598fa1..9603d1306 100644 --- a/bridge/src/boot.rs +++ b/bridge/src/boot.rs @@ -122,7 +122,7 @@ pub async fn start(iii: Arc, config: BridgeConfig) -> anyhow::Result< /// `bridge.invoke` + `bridge.invoke_async` on the local engine — exact /// function ids and descriptions from the builtin (mod.rs:96-191). /// -/// Both use `new_async_with_bad_request` with the typed [`functions:: +/// Both use `new_async` with the typed [`functions:: /// InvokeInput`]: the SDK auto-extracts a real request schema instead of the /// permissive `AnyValue` a `Value` closure param would emit, while /// [`functions::invoke_bad_request`] keeps owning the `deserialization_error` @@ -133,33 +133,27 @@ pub fn register_bridge_functions(iii: &Arc, remote: RemoteCell) { let caller = caller.clone(); iii.register_function( functions::INVOKE_FN, - RegisterFunction::new_async_with_bad_request( - move |req: functions::InvokeInput| { - let caller = caller.clone(); - async move { - functions::handle_invoke_typed(caller.as_ref(), req) - .await - .map_err(Error::from) - } - }, - functions::invoke_bad_request, - ) - .description("Invoke a function on the remote III instance"), - ); - } - iii.register_function( - functions::INVOKE_ASYNC_FN, - RegisterFunction::new_async_with_bad_request( - move |req: functions::InvokeInput| { + RegisterFunction::new_async(move |req: functions::InvokeInput| { let caller = caller.clone(); async move { - functions::handle_invoke_async_typed(caller.as_ref(), req) + functions::handle_invoke_typed(caller.as_ref(), req) .await .map_err(Error::from) } - }, - functions::invoke_bad_request, - ) + }) + .description("Invoke a function on the remote III instance"), + ); + } + iii.register_function( + functions::INVOKE_ASYNC_FN, + RegisterFunction::new_async(move |req: functions::InvokeInput| { + let caller = caller.clone(); + async move { + functions::handle_invoke_async_typed(caller.as_ref(), req) + .await + .map_err(Error::from) + } + }) .description("Fire-and-forget invoke on the remote III instance"), ); } diff --git a/bridge/src/configuration.rs b/bridge/src/configuration.rs index ed63b1b7c..248ccdafc 100644 --- a/bridge/src/configuration.rs +++ b/bridge/src/configuration.rs @@ -205,6 +205,7 @@ pub async fn register_config_trigger(iii: &Arc, boot: &BootHandle) -> "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/browser/Cargo.lock b/browser/Cargo.lock index a7b6eae4e..e1861c7da 100644 --- a/browser/Cargo.lock +++ b/browser/Cargo.lock @@ -822,9 +822,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -843,9 +843,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/browser/Cargo.toml b/browser/Cargo.toml index a8818f6cd..ab165f9aa 100644 --- a/browser/Cargo.toml +++ b/browser/Cargo.toml @@ -15,7 +15,7 @@ name = "browser" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" iii-console-ui = { path = "../crates/console-ui" } arc-swap = "1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time", "process"] } diff --git a/browser/src/configuration.rs b/browser/src/configuration.rs index 7bef16766..750952f89 100644 --- a/browser/src/configuration.rs +++ b/browser/src/configuration.rs @@ -92,6 +92,7 @@ pub fn register_config_trigger(iii: &IIIClient, config: SharedConfig) -> Result< function_id: CONFIG_FN_ID.to_string(), config: json!({ "configuration_id": CONFIG_ID, "event_types": ["configuration:updated"] }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/browser/src/events.rs b/browser/src/events.rs index c396150aa..3d6f927d7 100644 --- a/browser/src/events.rs +++ b/browser/src/events.rs @@ -440,6 +440,7 @@ mod tests { function_id: "console::on-event".to_string(), config, metadata: None, + namespace: None, } } @@ -494,6 +495,7 @@ mod tests { function_id: "fn::match".to_string(), config: json!({ "session_id": "b1" }), metadata: None, + namespace: None, }) .unwrap(); set.add(TriggerConfig { @@ -501,6 +503,7 @@ mod tests { function_id: "fn::other".to_string(), config: json!({ "session_id": "b2" }), metadata: None, + namespace: None, }) .unwrap(); diff --git a/claude-code/package.json b/claude-code/package.json index 02ccad33d..14b3a6a22 100644 --- a/claude-code/package.json +++ b/claude-code/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.3.173", - "iii-sdk": "^0.21.6", + "iii-sdk": "0.22.0-alpha.3", "yaml": "^2.6.0", "zod": "^4.0.0" }, diff --git a/claude-code/pnpm-lock.yaml b/claude-code/pnpm-lock.yaml index 29c788680..1a4c03c91 100644 --- a/claude-code/pnpm-lock.yaml +++ b/claude-code/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^0.3.173 version: 0.3.173(@anthropic-ai/sdk@0.104.1(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3) iii-sdk: - specifier: ^0.21.6 - version: 0.21.6 + specifier: 0.22.0-alpha.3 + version: 0.22.0-alpha.3 yaml: specifier: ^2.6.0 version: 2.9.0 @@ -630,8 +630,8 @@ packages: peerDependencies: hono: ^4 - '@iii-dev/helpers@0.21.6': - resolution: {integrity: sha512-UkiIqC5Ob41xc9uYx1SRt4LXLKrzAMzOCq6Kwo4hCak7Qj4Q1tP0GW0nYP7UpgYHsQnzf+2sspb2yD/DVa2ePA==} + '@iii-dev/helpers@0.22.0-alpha.3': + resolution: {integrity: sha512-zwilMTMq2MgVFu/aOEbtrPDpB+AVcdcqKBVAGc4vXv4XT2sK5eAXpdyzPcNgf8bGRKcRGZJ0ZJ8dA8WDVlSlaw==} '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -1178,8 +1178,8 @@ packages: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} - iii-sdk@0.21.6: - resolution: {integrity: sha512-D9NGtcGWdY8tqXRIjvRDqNqKRI2qJcQguSDWuUEPXaYyIHSn1jp3PIVF34cCY6C+f3Bby8fjptxpfzWYQUOg2A==} + iii-sdk@0.22.0-alpha.3: + resolution: {integrity: sha512-S6dH8ssbZsuuh8m6k0gG//D5K11w/wTkUviRMQ0sP3NNQh4ZhxZz0TbGlhROpwCYdJb1Rgl8dAHgeXbhyoIUXg==} import-in-the-middle@1.15.0: resolution: {integrity: sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==} @@ -1919,7 +1919,7 @@ snapshots: dependencies: hono: 4.12.25 - '@iii-dev/helpers@0.21.6': + '@iii-dev/helpers@0.22.0-alpha.3': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.57.2 @@ -2530,9 +2530,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - iii-sdk@0.21.6: + iii-sdk@0.22.0-alpha.3: dependencies: - '@iii-dev/helpers': 0.21.6 + '@iii-dev/helpers': 0.22.0-alpha.3 '@opentelemetry/api': 1.9.1 ws: 8.21.0 transitivePeerDependencies: diff --git a/claude-code/src/index.ts b/claude-code/src/index.ts index 95648844b..3624f78dd 100644 --- a/claude-code/src/index.ts +++ b/claude-code/src/index.ts @@ -39,7 +39,13 @@ const bootConfig: Config = { claude_executable: resolveClaudeExecutable(seed.claude_executable), }; -const iii = registerWorker(url, { workerName: 'claude-code' }); +// namespace: explicit III_NAMESPACE so the worker registers under a namespace +// when one is set (the SDK also reads it, passed here for visibility). Absent, +// the engine applies its default namespace. +const iii = registerWorker(url, { + workerName: 'claude-code', + namespace: process.env.III_NAMESPACE, +}); // Best-effort: a configuration-worker hiccup at boot must not stop the worker // from registering claude::*; it falls back to the seed via fetchRuntime. diff --git a/codex/Cargo.lock b/codex/Cargo.lock index 9b00e2047..ce357f675 100644 --- a/codex/Cargo.lock +++ b/codex/Cargo.lock @@ -672,9 +672,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -693,9 +693,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/codex/Cargo.toml b/codex/Cargo.toml index 52298ac37..12c758131 100644 --- a/codex/Cargo.toml +++ b/codex/Cargo.toml @@ -15,8 +15,8 @@ name = "codex" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" +iii-helpers = "=0.22.0-alpha.3" schemars = { version = "0.8", features = ["uuid1"] } tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "process", "time", "io-util"] } serde = { version = "1", features = ["derive"] } diff --git a/codex/src/configuration.rs b/codex/src/configuration.rs index b617140d1..cd5d2d53c 100644 --- a/codex/src/configuration.rs +++ b/codex/src/configuration.rs @@ -106,6 +106,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/console/Cargo.lock b/console/Cargo.lock index 6131fbdb1..9b2f018ec 100644 --- a/console/Cargo.lock +++ b/console/Cargo.lock @@ -778,9 +778,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -799,9 +799,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/console/Cargo.toml b/console/Cargo.toml index fb5d172ae..d1d89f3c6 100644 --- a/console/Cargo.toml +++ b/console/Cargo.toml @@ -14,7 +14,7 @@ path = "src/main.rs" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.2" # Worker-side injectable console UI (content function + console:script/style # triggers + hot-reload watcher) — the console dogfoods its own protocol to # ship the injectable-UI toggle form. Direct link, never published. diff --git a/console/src/configuration.rs b/console/src/configuration.rs index ab6213ae1..ade9044b3 100644 --- a/console/src/configuration.rs +++ b/console/src/configuration.rs @@ -222,6 +222,7 @@ pub async fn start_injectable_ui_sync(iii: &Arc, control: UiControl) "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), }) { tracing::warn!( error = %e, diff --git a/console/src/ui_assets.rs b/console/src/ui_assets.rs index 059d96ccf..fe29507db 100644 --- a/console/src/ui_assets.rs +++ b/console/src/ui_assets.rs @@ -1077,6 +1077,7 @@ mod tests { function_id: function_id.to_string(), config: json!({ "path": path }), metadata: None, + namespace: None, } } @@ -1086,6 +1087,7 @@ mod tests { function_id: function_id.to_string(), config: json!({}), metadata: None, + namespace: None, } } diff --git a/context-manager/Cargo.lock b/context-manager/Cargo.lock index 6c0102cf2..b1d403ab8 100644 --- a/context-manager/Cargo.lock +++ b/context-manager/Cargo.lock @@ -939,9 +939,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -960,9 +960,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/context-manager/Cargo.toml b/context-manager/Cargo.toml index 1d1903e8a..f924e16c9 100644 --- a/context-manager/Cargo.toml +++ b/context-manager/Cargo.toml @@ -15,7 +15,7 @@ name = "context_manager" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/context-manager/src/adapters/cache.rs b/context-manager/src/adapters/cache.rs index 6bbee1f5f..d9ee60780 100644 --- a/context-manager/src/adapters/cache.rs +++ b/context-manager/src/adapters/cache.rs @@ -138,6 +138,7 @@ pub fn register_models_changed_flush(iii: &IIIClient, cache: Arc self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; + let resp = match budget_result { Ok(resp) => resp, Err(err) if is_unroutable(&err) => { // Rolling upgrades may briefly run a context-manager newer than // the router. Preserve the former, conservative behavior until // `models::budget` is registered instead of dropping all the way // to the 8k fallback model. - let response = self - .iii - .trigger(TriggerRequest { - function_id: "router::models::get".to_string(), - payload, - action: None, - timeout_ms: Some(MODELS_GET_TIMEOUT_MS), - }) - .await - .map_err(|e| e.to_string())?; + let request = TriggerRequest { + function_id: "router::models::get".to_string(), + payload, + action: None, + timeout_ms: Some(MODELS_GET_TIMEOUT_MS), + }; + let response = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + } + .map_err(|e| e.to_string())?; if response.is_null() { return Ok(None); } @@ -188,15 +190,16 @@ impl Summarizer for RouterSummarizer { // Read the outer budget from the live snapshot so a // summarizer_timeout_ms change takes effect without a restart. let timeout_ms = self.config.read().await.summarizer_timeout_ms; - let trigger_result = self - .iii - .trigger(TriggerRequest { - function_id: "router::chat".to_string(), - payload, - action: None, - timeout_ms: Some(timeout_ms), - }) - .await; + let request = TriggerRequest { + function_id: "router::chat".to_string(), + payload, + action: None, + timeout_ms: Some(timeout_ms), + }; + let trigger_result = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; // The terminal event precedes the trigger response; give the // socket a short drain window, then stop reading either way. diff --git a/context-manager/src/configuration.rs b/context-manager/src/configuration.rs index 120fff985..5dbae944b 100644 --- a/context-manager/src/configuration.rs +++ b/context-manager/src/configuration.rs @@ -166,6 +166,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/crates/console-ui/Cargo.toml b/crates/console-ui/Cargo.toml index d9c92bf9f..f24ac304d 100644 --- a/crates/console-ui/Cargo.toml +++ b/crates/console-ui/Cargo.toml @@ -15,7 +15,7 @@ publish = false [dependencies] # Same exact pin the workers carry — path-linking this crate must never be # what drags a worker onto a different SDK build. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt", "sync", "time", "fs"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/crates/console-ui/src/lib.rs b/crates/console-ui/src/lib.rs index 27831c43a..24f30cbd5 100644 --- a/crates/console-ui/src/lib.rs +++ b/crates/console-ui/src/lib.rs @@ -386,6 +386,7 @@ fn register_asset_trigger( function_id: function_id.to_string(), config: serde_json::json!({ "path": path }), metadata: None, + namespace: iii.namespace(), }) } diff --git a/cron/Cargo.lock b/cron/Cargo.lock index cc763a9a5..500c07bed 100644 --- a/cron/Cargo.lock +++ b/cron/Cargo.lock @@ -773,9 +773,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -794,9 +794,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/cron/Cargo.toml b/cron/Cargo.toml index c1836a647..87d264cbb 100644 --- a/cron/Cargo.toml +++ b/cron/Cargo.toml @@ -18,7 +18,7 @@ name = "cron" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" async-trait = "0.1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } diff --git a/cron/src/configuration.rs b/cron/src/configuration.rs index 16efd1353..d9be0bb51 100644 --- a/cron/src/configuration.rs +++ b/cron/src/configuration.rs @@ -96,6 +96,7 @@ pub fn register_config_trigger(iii: &Arc, parts: BootParts) -> Result "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/cron/src/trigger.rs b/cron/src/trigger.rs index 2ad0d9cfb..9c999a948 100644 --- a/cron/src/trigger.rs +++ b/cron/src/trigger.rs @@ -101,6 +101,7 @@ mod tests { function_id: "backend".to_string(), config: cfg, metadata: None, + namespace: None, } } diff --git a/cron/tests/e2e_schedule.rs b/cron/tests/e2e_schedule.rs index a4758f10a..b6b0f2bff 100644 --- a/cron/tests/e2e_schedule.rs +++ b/cron/tests/e2e_schedule.rs @@ -46,6 +46,7 @@ async fn cron_trigger_fires_bound_function_with_parity_payload() { function_id: "e2e::cron-backend".to_string(), config: serde_json::json!({"expression": "*/1 * * * * *"}), metadata: None, + namespace: iii.namespace(), }) .expect("trigger registration"); diff --git a/database/Cargo.lock b/database/Cargo.lock index 7a5338091..f0a61594e 100644 --- a/database/Cargo.lock +++ b/database/Cargo.lock @@ -1282,9 +1282,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -1303,9 +1303,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/database/Cargo.toml b/database/Cargo.toml index f2c7084f4..effea1b24 100644 --- a/database/Cargo.toml +++ b/database/Cargo.toml @@ -14,8 +14,8 @@ path = "src/main.rs" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.2" +iii-helpers = "=0.22.0-alpha.2" iii-console-ui = { path = "../crates/console-ui" } tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } diff --git a/database/src/configuration.rs b/database/src/configuration.rs index 2f49d8870..40a6e334e 100644 --- a/database/src/configuration.rs +++ b/database/src/configuration.rs @@ -152,6 +152,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/devin/Cargo.lock b/devin/Cargo.lock index 1498bb769..2942356f0 100644 --- a/devin/Cargo.lock +++ b/devin/Cargo.lock @@ -670,9 +670,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -691,9 +691,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/devin/Cargo.toml b/devin/Cargo.toml index 80b170b20..190c628aa 100644 --- a/devin/Cargo.toml +++ b/devin/Cargo.toml @@ -15,8 +15,8 @@ name = "devin" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" +iii-helpers = "=0.22.0-alpha.3" schemars = { version = "0.8", features = ["uuid1"] } tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "process", "time", "io-util"] } reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } diff --git a/devin/src/configuration.rs b/devin/src/configuration.rs index 6aed77cd8..5dfde4b22 100644 --- a/devin/src/configuration.rs +++ b/devin/src/configuration.rs @@ -105,6 +105,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/email/Cargo.lock b/email/Cargo.lock index 1c85cf138..278700a76 100644 --- a/email/Cargo.lock +++ b/email/Cargo.lock @@ -1204,9 +1204,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -1225,9 +1225,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/email/Cargo.toml b/email/Cargo.toml index 0f7e56581..5b8164f30 100644 --- a/email/Cargo.toml +++ b/email/Cargo.toml @@ -16,7 +16,7 @@ path = "src/main.rs" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time", "io-util", "net"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/email/src/handlers/send.rs b/email/src/handlers/send.rs index 426a8e2dd..e0ec392c2 100644 --- a/email/src/handlers/send.rs +++ b/email/src/handlers/send.rs @@ -94,14 +94,16 @@ pub fn register(iii: &Arc, cfg: &Arc) { } } - let cred = iii - .trigger(TriggerRequest { - function_id: "auth::get_token".to_string(), - payload: json!({ "provider": format!("email::{}", req.account) }), - action: None, - timeout_ms: Some(5_000), - }) - .await + let request = TriggerRequest { + function_id: "auth::get_token".to_string(), + payload: json!({ "provider": format!("email::{}", req.account) }), + action: None, + timeout_ms: Some(5_000), + }; + let cred = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } .map_err(|e| { Error::Handler( json!({ diff --git a/email/src/provider/imap/connection.rs b/email/src/provider/imap/connection.rs index 22be9b948..f5b385672 100644 --- a/email/src/provider/imap/connection.rs +++ b/email/src/provider/imap/connection.rs @@ -192,20 +192,22 @@ async fn fetch_credential(account: &str) -> Result { "internal: iii handle not initialized for credential fetch", ) })?; - let cred = iii - .trigger(TriggerRequest { - function_id: "auth::get_token".to_string(), - payload: json!({ "provider": format!("email::{}", account) }), - action: None, - timeout_ms: Some(5_000), - }) - .await - .map_err(|e| { - handler_err( - "E606", - &format!("auth::get_token failed for `email::{account}`: {e}"), - ) - })?; + let request = TriggerRequest { + function_id: "auth::get_token".to_string(), + payload: json!({ "provider": format!("email::{}", account) }), + action: None, + timeout_ms: Some(5_000), + }; + let cred = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } + .map_err(|e| { + handler_err( + "E606", + &format!("auth::get_token failed for `email::{account}`: {e}"), + ) + })?; if cred.is_null() { return Err(handler_err( "E607", diff --git a/email/src/triggers/dispatcher.rs b/email/src/triggers/dispatcher.rs index 00d4d4edb..5923d7bed 100644 --- a/email/src/triggers/dispatcher.rs +++ b/email/src/triggers/dispatcher.rs @@ -53,7 +53,31 @@ impl EventDispatcher for EngineDispatcher { timeout_ms: Some(sub.handler_timeout_ms), }; let bound = Duration::from_millis(sub.handler_timeout_ms.saturating_add(1_000)); - match timeout(bound, self.iii.trigger(req)).await { + let route_ns = self.iii.namespace().filter(|_| { + !matches!( + sub.function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let result = match route_ns { + Some(ns) => timeout(bound, self.iii.trigger(req.namespace(ns))).await, + None => timeout(bound, self.iii.trigger(req)).await, + }; + match result { Ok(Ok(_)) => {} Ok(Err(e)) => { tracing::warn!( diff --git a/fp/Cargo.lock b/fp/Cargo.lock index d4720fd34..7a88196ee 100644 --- a/fp/Cargo.lock +++ b/fp/Cargo.lock @@ -645,9 +645,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/fp/Cargo.toml b/fp/Cargo.toml index ddf419b77..39fa6a20c 100644 --- a/fp/Cargo.toml +++ b/fp/Cargo.toml @@ -17,7 +17,7 @@ name = "fp" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" # Must stay on the same schemars major as iii-sdk so the derived schemas line up. schemars = "0.8" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal"] } diff --git a/fp/src/guidance.rs b/fp/src/guidance.rs index 4d6a10976..091b1b58b 100644 --- a/fp/src/guidance.rs +++ b/fp/src/guidance.rs @@ -170,6 +170,7 @@ fn bind(iii: &IIIClient, trigger_type: &str, function_id: &str, config: Value) - function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }) { Ok(handle) => { tracing::info!(trigger_type, function_id, "trigger binding requested"); diff --git a/github/Cargo.lock b/github/Cargo.lock index 73c8535ae..4dfe8571c 100644 --- a/github/Cargo.lock +++ b/github/Cargo.lock @@ -680,9 +680,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -701,9 +701,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/github/Cargo.toml b/github/Cargo.toml index ccc22797d..0dbdd3a9b 100644 --- a/github/Cargo.toml +++ b/github/Cargo.toml @@ -17,7 +17,7 @@ name = "github" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" iii-console-ui = { path = "../crates/console-ui" } # Must stay on the same schemars major as iii-sdk so the derived schemas line up. schemars = "0.8" diff --git a/github/src/configuration.rs b/github/src/configuration.rs index ab1f1a379..12a65c027 100644 --- a/github/src/configuration.rs +++ b/github/src/configuration.rs @@ -105,6 +105,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/grok/Cargo.lock b/grok/Cargo.lock index c0bcbe627..3bf074467 100644 --- a/grok/Cargo.lock +++ b/grok/Cargo.lock @@ -671,9 +671,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -692,9 +692,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/grok/Cargo.toml b/grok/Cargo.toml index 685d2dff4..88ce3b2f1 100644 --- a/grok/Cargo.toml +++ b/grok/Cargo.toml @@ -15,8 +15,8 @@ name = "grok" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" +iii-helpers = "=0.22.0-alpha.3" schemars = { version = "0.8", features = ["uuid1"] } tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "process", "time", "io-util"] } serde = { version = "1", features = ["derive"] } diff --git a/grok/src/configuration.rs b/grok/src/configuration.rs index c8e13d7c7..a31830ebb 100644 --- a/grok/src/configuration.rs +++ b/grok/src/configuration.rs @@ -106,6 +106,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/harness/Cargo.lock b/harness/Cargo.lock index e472f7aa2..5089dffc1 100644 --- a/harness/Cargo.lock +++ b/harness/Cargo.lock @@ -508,8 +508,8 @@ dependencies = [ "async-trait", "clap", "globset", - "iii-helpers", - "iii-sdk", + "iii-helpers 0.22.0-alpha.2", + "iii-sdk 0.22.0-alpha.2", "jsonschema", "schemars", "serde", @@ -530,7 +530,7 @@ dependencies = [ "anyhow", "clap", "harness", - "iii-sdk", + "iii-sdk 0.21.8", "serde", "serde_json", "tokio", @@ -545,7 +545,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "iii-sdk", + "iii-sdk 0.21.8", "jsonschema", "nix", "regex", @@ -823,6 +823,27 @@ dependencies = [ "uuid", ] +[[package]] +name = "iii-helpers" +version = "0.22.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +dependencies = [ + "futures-util", + "opentelemetry", + "opentelemetry-http", + "opentelemetry_sdk", + "reqwest", + "schemars", + "serde", + "serde_json", + "sysinfo", + "tokio", + "tokio-tungstenite", + "tracing", + "uuid", +] + [[package]] name = "iii-sdk" version = "0.21.8" @@ -832,7 +853,28 @@ dependencies = [ "async-trait", "futures-util", "hostname", - "iii-helpers", + "iii-helpers 0.21.8", + "reqwest", + "schemars", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "uuid", +] + +[[package]] +name = "iii-sdk" +version = "0.22.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +dependencies = [ + "async-trait", + "futures-util", + "hostname", + "iii-helpers 0.22.0-alpha.2", "reqwest", "schemars", "serde", diff --git a/harness/Cargo.toml b/harness/Cargo.toml index 8e08f82d6..ea2a06f4d 100644 --- a/harness/Cargo.toml +++ b/harness/Cargo.toml @@ -19,12 +19,12 @@ path = "src/lib.rs" [dependencies] # 0.21.8 adds the reconnect reattach handshake. Older SDKs can lose this # worker's registrations when the engine reloads another worker. -iii-sdk = "=0.21.8" +iii-sdk = "=0.22.0-alpha.2" # Re-exports the same `opentelemetry` the SDK uses, so we can carry the active # OTel context across `tokio::spawn` boundaries (shared `Context` global). # 0.21.5 adds the live span-start push (`LiveSpanStartProcessor`), so the # console renders `harness::turn step` while it runs instead of on close. -iii-helpers = "=0.21.8" +iii-helpers = "=0.22.0-alpha.2" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/harness/src/clients/context.rs b/harness/src/clients/context.rs index 78863ac8f..28c6721db 100644 --- a/harness/src/clients/context.rs +++ b/harness/src/clients/context.rs @@ -104,15 +104,16 @@ impl ContextClient { payload["system_prompt"] = json!(sp); } - let resp = self - .iii - .trigger(TriggerRequest { - function_id: "context::assemble".into(), - payload, - action: None, - timeout_ms: Some(self.timeout_ms), - }) - .await; + let request = TriggerRequest { + function_id: "context::assemble".into(), + payload, + action: None, + timeout_ms: Some(self.timeout_ms), + }; + let resp = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; match resp { Ok(v) => serde_json::from_value::(v) @@ -139,15 +140,16 @@ impl ContextClient { payload["system_prompt"] = json!(sp); } - let resp = self - .iii - .trigger(TriggerRequest { - function_id: "context::count-tokens".into(), - payload, - action: None, - timeout_ms: Some(self.timeout_ms), - }) - .await; + let request = TriggerRequest { + function_id: "context::count-tokens".into(), + payload, + action: None, + timeout_ms: Some(self.timeout_ms), + }; + let resp = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; match resp { Ok(v) => serde_json::from_value::(v) diff --git a/harness/src/clients/router.rs b/harness/src/clients/router.rs index 3344a9c9c..8239c5091 100644 --- a/harness/src/clients/router.rs +++ b/harness/src/clients/router.rs @@ -161,13 +161,16 @@ impl RouterClient { let parent_cx = iii_helpers::observability::opentelemetry::Context::current(); let mut trigger = tokio::spawn( async move { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: "router::chat".into(), payload, action: None, timeout_ms: Some(timeout_ms), - }) - .await + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } } .with_context(parent_cx), ); @@ -407,15 +410,16 @@ impl RouterClient { /// Abort an in-flight stream by `request_id` (best-effort). pub async fn abort(&self, request_id: &str) -> bool { - let res = self - .iii - .trigger(TriggerRequest { - function_id: "router::abort".into(), - payload: json!({ "request_id": request_id }), - action: None, - timeout_ms: Some(self.timeout_ms), - }) - .await; + let request = TriggerRequest { + function_id: "router::abort".into(), + payload: json!({ "request_id": request_id }), + action: None, + timeout_ms: Some(self.timeout_ms), + }; + let res = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; match res { Ok(v) => v.get("aborted").and_then(Value::as_bool).unwrap_or(false), Err(e) => { @@ -434,16 +438,17 @@ impl RouterClient { if let Some(p) = provider { payload["provider"] = json!(p); } - let resp = self - .iii - .trigger(TriggerRequest { - function_id: "router::system_prompt::get".into(), - payload, - action: None, - timeout_ms: Some(self.timeout_ms), - }) - .await - .ok()?; + let request = TriggerRequest { + function_id: "router::system_prompt::get".into(), + payload, + action: None, + timeout_ms: Some(self.timeout_ms), + }; + let resp = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + } + .ok()?; resp.get("system_prompt") .and_then(Value::as_str) .filter(|s| !s.is_empty()) @@ -457,16 +462,17 @@ impl RouterClient { if let Some(p) = provider { payload["provider"] = json!(p); } - let resp = self - .iii - .trigger(TriggerRequest { - function_id: "router::models::get".into(), - payload, - action: None, - timeout_ms: Some(self.timeout_ms), - }) - .await - .ok()?; + let request = TriggerRequest { + function_id: "router::models::get".into(), + payload, + action: None, + timeout_ms: Some(self.timeout_ms), + }; + let resp = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + } + .ok()?; if resp.is_null() { return None; } @@ -480,15 +486,16 @@ impl RouterClient { /// Whether `model` supports a capability (false when the router is absent /// or the model is unknown — the caller falls back). pub async fn models_supports(&self, provider: &str, id: &str, capability: &str) -> bool { - let resp = self - .iii - .trigger(TriggerRequest { - function_id: "router::models::supports".into(), - payload: json!({ "provider": provider, "id": id, "capability": capability }), - action: None, - timeout_ms: Some(self.timeout_ms), - }) - .await; + let request = TriggerRequest { + function_id: "router::models::supports".into(), + payload: json!({ "provider": provider, "id": id, "capability": capability }), + action: None, + timeout_ms: Some(self.timeout_ms), + }; + let resp = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; match resp { Ok(v) => v.get("supported").and_then(Value::as_bool).unwrap_or(false), Err(_) => false, diff --git a/harness/src/clients/session.rs b/harness/src/clients/session.rs index e9f7f848c..d0449d389 100644 --- a/harness/src/clients/session.rs +++ b/harness/src/clients/session.rs @@ -71,15 +71,17 @@ impl SessionClient { } async fn call(&self, function_id: &str, payload: Value) -> Result { - self.iii - .trigger(TriggerRequest { - function_id: function_id.to_string(), - payload, - action: None, - timeout_ms: Some(self.timeout_ms), - }) - .await - .map_err(|e| HarnessError::Dependency(format!("{function_id}: {e}"))) + let request = TriggerRequest { + function_id: function_id.to_string(), + payload, + action: None, + timeout_ms: Some(self.timeout_ms), + }; + let res = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; + res.map_err(|e| HarnessError::Dependency(format!("{function_id}: {e}"))) } /// Best-effort session title from `session::get` — `None` when the diff --git a/harness/src/configuration.rs b/harness/src/configuration.rs index 198212234..b079d47a2 100644 --- a/harness/src/configuration.rs +++ b/harness/src/configuration.rs @@ -198,6 +198,7 @@ fn bind(iii: &IIIClient, trigger_type: &str, function_id: &str, config: Value) - function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }) { Ok(handle) => { tracing::info!(trigger_type, function_id, "trigger binding requested"); @@ -290,6 +291,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/harness/src/discovery.rs b/harness/src/discovery.rs index 5bd6e9d95..7159e585f 100644 --- a/harness/src/discovery.rs +++ b/harness/src/discovery.rs @@ -270,6 +270,7 @@ pub fn register_functions_trigger(iii: &Arc, cell: FunctionsCell, tim function_id: FUNCTIONS_FN_ID.to_string(), config: json!({}), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!( trigger_type = FUNCTIONS_TRIGGER_TYPE, diff --git a/harness/src/events.rs b/harness/src/events.rs index 84e7cde69..5e6fb86ed 100644 --- a/harness/src/events.rs +++ b/harness/src/events.rs @@ -533,9 +533,34 @@ impl TurnEvents { action: Some(TriggerAction::Void), timeout_ms: None, }; - let res = match metadata { - Some(m) => self.iii.trigger(request.metadata(m)).await, - None => self.iii.trigger(request).await, + // A dynamic target may be an engine builtin (a hook wired to + // `state::set`) or a sibling worker's function — route to the + // worker's namespace only when it is NOT a builtin. + let route_ns = self.iii.namespace().filter(|_| { + !matches!( + binding.function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let res = match (metadata, route_ns) { + (Some(m), Some(ns)) => self.iii.trigger(request.metadata(m).namespace(ns)).await, + (Some(m), None) => self.iii.trigger(request.metadata(m)).await, + (None, Some(ns)) => self.iii.trigger(request.namespace(ns)).await, + (None, None) => self.iii.trigger(request).await, }; if let Err(e) = res { tracing::warn!(trigger_type, function_id = %binding.function_id, error = %e, "turn-event fan-out failed"); diff --git a/harness/src/functions/react.rs b/harness/src/functions/react.rs index b86f63750..fc705436f 100644 --- a/harness/src/functions/react.rs +++ b/harness/src/functions/react.rs @@ -1137,16 +1137,40 @@ async fn dispatch_call( &[], crate::filesystem_scope::FilesystemBoundary::ConfiguredRoots, ); - match deps - .iii - .trigger(TriggerRequest { - function_id: call.function_id.clone(), - payload, - action: None, - timeout_ms: Some(CALL_TIMEOUT_MS), - }) - .await - { + let request = TriggerRequest { + function_id: call.function_id.clone(), + payload, + action: None, + timeout_ms: Some(CALL_TIMEOUT_MS), + }; + // The call target is a runtime function_id: an engine builtin (e.g. + // `state::set`) stays in the default namespace; a sibling worker's + // function routes to the worker's namespace. + let route_ns = deps.iii.namespace().filter(|_| { + !matches!( + call.function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let res = match route_ns { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + }; + match res { Ok(_) => { tracing::info!( function_id = %call.function_id, @@ -1439,16 +1463,16 @@ fn parent_anchor(event: &Value, spec: &ReactSpec) -> Option { async fn resolve_root(deps: &Deps, session_id: &str) -> String { let mut current = session_id.to_string(); for _ in 0..32 { - let resp = match deps - .iii - .trigger(TriggerRequest { - function_id: "session::get".to_string(), - payload: json!({ "session_id": current }), - action: None, - timeout_ms: None, - }) - .await - { + let request = TriggerRequest { + function_id: "session::get".to_string(), + payload: json!({ "session_id": current }), + action: None, + timeout_ms: None, + }; + let resp = match match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + } { Ok(v) => v, Err(_) => break, }; @@ -1626,15 +1650,17 @@ pub const MAX_REACTIVE_DEPTH: u32 = 8; /// unreachable (callers fail OPEN on `None` — a router blip must not block /// registrations or reactions; a definitively unknown id must). async fn known_model_ids(iii: &iii_sdk::IIIClient) -> Option> { - let resp = iii - .trigger(TriggerRequest { - function_id: "router::models::list".to_string(), - payload: json!({}), - action: None, - timeout_ms: Some(5_000), - }) - .await - .ok()?; + let request = TriggerRequest { + function_id: "router::models::list".to_string(), + payload: json!({}), + action: None, + timeout_ms: Some(5_000), + }; + let resp = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } + .ok()?; Some(parse_model_ids(&resp)) } diff --git a/harness/src/functions/subscribe.rs b/harness/src/functions/subscribe.rs index 74c1114a6..d2b192d3f 100644 --- a/harness/src/functions/subscribe.rs +++ b/harness/src/functions/subscribe.rs @@ -184,17 +184,18 @@ fn parent_filter_join_advisory(req: &SubscribeRequest) -> Option { /// 0/N forever. Fail-open: a lookup error produces no note. async fn session_filter_advisory(deps: &Deps, req: &SubscribeRequest) -> Option { let sid = turn_event_session_filter(req)?; - let exists = deps - .iii - .trigger(TriggerRequest { - function_id: "session::get".to_string(), - payload: json!({ "session_id": sid }), - action: None, - timeout_ms: None, - }) - .await - .map(|v| v.get("meta").is_some()) - .unwrap_or(true); + let request = TriggerRequest { + function_id: "session::get".to_string(), + payload: json!({ "session_id": sid }), + action: None, + timeout_ms: None, + }; + let exists = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + } + .map(|v| v.get("meta").is_some()) + .unwrap_or(true); if exists { return None; } diff --git a/harness/src/hooks/runner.rs b/harness/src/hooks/runner.rs index cba626acb..250b942fb 100644 --- a/harness/src/hooks/runner.rs +++ b/harness/src/hooks/runner.rs @@ -272,14 +272,42 @@ impl HookRegistry { ("iii.tag.kind", "harness.hook"), ("iii.hook.point", point.as_str()), ]; + let request = TriggerRequest { + function_id: binding.function_id.clone(), + payload: input, + action: None, + timeout_ms: Some(binding.timeout_ms), + }; + // A hook's target function_id is a runtime value: an engine builtin + // (e.g. a hook wired to `state::set`) stays in the default namespace; + // a sibling worker's function routes to the worker's namespace. + let route_ns = self.iii.namespace().filter(|_| { + !matches!( + binding.function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let request: iii_sdk::protocol::TriggerRequestWithMetadata = match route_ns { + Some(ns) => request.namespace(ns), + None => request.into(), + }; let fut = iii_helpers::observability::run_with_baggage( &baggage, - self.iii.trigger(TriggerRequest { - function_id: binding.function_id.clone(), - payload: input, - action: None, - timeout_ms: Some(binding.timeout_ms), - }), + self.iii.trigger(request), ); let bounded = tokio::time::timeout( Duration::from_millis(binding.timeout_ms.saturating_add(1_000)), diff --git a/harness/src/turn_loop.rs b/harness/src/turn_loop.rs index 22523279f..708569e95 100644 --- a/harness/src/turn_loop.rs +++ b/harness/src/turn_loop.rs @@ -142,17 +142,19 @@ pub async fn enqueue_step( } let mut last_error = String::new(); for attempt in 1..=ENQUEUE_ATTEMPTS { - match iii - .trigger(TriggerRequest { - function_id: "harness::turn".to_string(), - payload: payload.clone(), - action: Some(TriggerAction::Enqueue { - queue: TURN_QUEUE.to_string(), - }), - timeout_ms: None, - }) - .await - { + let request = TriggerRequest { + function_id: "harness::turn".to_string(), + payload: payload.clone(), + action: Some(TriggerAction::Enqueue { + queue: TURN_QUEUE.to_string(), + }), + timeout_ms: None, + }; + let res = match iii.namespace() { + Some(namespace) => iii.trigger(request.namespace(namespace)).await, + None => iii.trigger(request).await, + }; + match res { Ok(_) => return Ok(()), Err(e) => { last_error = e.to_string(); diff --git a/hermes/pyproject.toml b/hermes/pyproject.toml index efe921d5f..048a08e9d 100644 --- a/hermes/pyproject.toml +++ b/hermes/pyproject.toml @@ -10,8 +10,8 @@ authors = [{ name = "iii" }] license = "Apache-2.0" requires-python = ">=3.11" dependencies = [ - "iii-sdk==0.21.6", - "iii-helpers==0.21.6", + "iii-sdk==0.22.0a3", + "iii-helpers==0.22.0a3", "opentelemetry-api", "opentelemetry-sdk", "pyyaml", diff --git a/hermes/src/main.py b/hermes/src/main.py index 0799b9f54..a7be27f7b 100644 --- a/hermes/src/main.py +++ b/hermes/src/main.py @@ -129,9 +129,15 @@ def _print_connected(state: str, url: str) -> None: def main() -> None: cfg = load_config() url = os.environ.get("III_URL") or cfg["engine_url"] + # namespace: register under III_NAMESPACE when set (the SDK also resolves the + # env; passed explicitly for visibility). Absent -> the engine's default. iii = register_worker( address=url, - options=InitOptions(worker_name="hermes", otel={"enabled": True, "service_name": "hermes"}), + options=InitOptions( + worker_name="hermes", + namespace=os.environ.get("III_NAMESPACE"), + otel={"enabled": True, "service_name": "hermes"}, + ), ) logging.basicConfig(level=logging.INFO) logger = logging.getLogger("hermes") diff --git a/http/Cargo.lock b/http/Cargo.lock index 3592fe84b..4c16795d7 100644 --- a/http/Cargo.lock +++ b/http/Cargo.lock @@ -795,9 +795,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -847,9 +847,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/http/Cargo.toml b/http/Cargo.toml index 2ef6722ba..6a3353460 100644 --- a/http/Cargo.toml +++ b/http/Cargo.toml @@ -18,12 +18,12 @@ name = "http" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" # Direct dep for W3C trace-context propagation helpers # (`observability::extract_context` + the re-exported `opentelemetry` crate). # Pinned to the version `iii-sdk` already resolves so the `opentelemetry` types # line up across both crates. -iii-helpers = "=0.21.6" +iii-helpers = "=0.22.0-alpha.3" # W3C trace-context parent propagation on `tracing::Span` (`OpenTelemetrySpanExt`). # 0.32 pairs with opentelemetry 0.31 (same as the engine). tracing-opentelemetry = "0.32" diff --git a/http/src/configuration.rs b/http/src/configuration.rs index 0250d6fff..e97f21d34 100644 --- a/http/src/configuration.rs +++ b/http/src/configuration.rs @@ -190,6 +190,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/http/src/trigger.rs b/http/src/trigger.rs index e4bd15d67..8a4ffe27c 100644 --- a/http/src/trigger.rs +++ b/http/src/trigger.rs @@ -412,6 +412,7 @@ mod tests { function_id: function_id.to_string(), config, metadata: None, + namespace: None, } } diff --git a/http/tests/common/backend.rs b/http/tests/common/backend.rs index 4371ad629..05f257cfb 100644 --- a/http/tests/common/backend.rs +++ b/http/tests/common/backend.rs @@ -43,6 +43,7 @@ pub async fn register_echo_backend(iii: &Arc, api_path: &str, http_me function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger"); } @@ -89,6 +90,7 @@ pub async fn register_trace_capturing_backend( function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger"); @@ -121,6 +123,7 @@ pub async fn register_removable_echo_backend( function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger") } @@ -163,6 +166,7 @@ pub async fn register_echo_backend_with_middleware( "middleware_function_ids": middleware_function_ids, }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger with middleware"); } @@ -250,6 +254,7 @@ pub async fn register_echo_backend_with_condition( "condition_function_id": condition_function_id, }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger with condition"); } @@ -301,6 +306,7 @@ pub async fn register_slow_backend( function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger"); } @@ -333,6 +339,7 @@ pub async fn register_sleep_backend( function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger"); } @@ -360,6 +367,7 @@ pub async fn register_erroring_backend(iii: &Arc, api_path: &str, htt function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger"); } diff --git a/http/tests/e2e_condition.rs b/http/tests/e2e_condition.rs index 5dce52ce4..24ffaea61 100644 --- a/http/tests/e2e_condition.rs +++ b/http/tests/e2e_condition.rs @@ -58,6 +58,7 @@ async fn register_counting_backend_with_condition( "condition_function_id": condition_function_id, }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger with condition"); } diff --git a/http/tests/e2e_request_body.rs b/http/tests/e2e_request_body.rs index 314b8755b..93cb08427 100644 --- a/http/tests/e2e_request_body.rs +++ b/http/tests/e2e_request_body.rs @@ -80,6 +80,7 @@ async fn register_request_body_echo_backend( function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger for request-body echo backend"); } diff --git a/http/tests/e2e_streaming.rs b/http/tests/e2e_streaming.rs index b56e00457..3f227f5e5 100644 --- a/http/tests/e2e_streaming.rs +++ b/http/tests/e2e_streaming.rs @@ -50,6 +50,7 @@ async fn register_stream_backend(iii: &Arc, api_path: &str, http_meth function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger for stream backend"); } @@ -94,6 +95,7 @@ async fn register_late_stream_backend(iii: &Arc, api_path: &str, http function_id, config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) .expect("register http trigger for late stream backend"); } diff --git a/iii-directory/Cargo.lock b/iii-directory/Cargo.lock index e7ec8cbef..38dac7a4f 100644 --- a/iii-directory/Cargo.lock +++ b/iii-directory/Cargo.lock @@ -1090,9 +1090,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -1111,9 +1111,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/iii-directory/Cargo.toml b/iii-directory/Cargo.toml index 79cbf9b56..90111b8fc 100644 --- a/iii-directory/Cargo.toml +++ b/iii-directory/Cargo.toml @@ -15,7 +15,7 @@ name = "iii_directory" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.2" arc-swap = "1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time", "fs", "process"] } serde = { version = "1", features = ["derive"] } diff --git a/iii-directory/src/configuration.rs b/iii-directory/src/configuration.rs index 302947284..f09fc04b6 100644 --- a/iii-directory/src/configuration.rs +++ b/iii-directory/src/configuration.rs @@ -173,6 +173,7 @@ pub fn register_config_trigger(iii: &IIIClient, state: SharedState) -> Result<() "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/iii-directory/src/functions/skills.rs b/iii-directory/src/functions/skills.rs index 3f7e8bcff..8ea8fa794 100644 --- a/iii-directory/src/functions/skills.rs +++ b/iii-directory/src/functions/skills.rs @@ -300,14 +300,16 @@ impl RegisteredWorkersCache { /// Fetch `worker::list` from the engine WITHOUT holding the lock, /// then store the result (or fall back to the stale set on error). async fn fetch_and_store(&self, iii: &IIIClient) -> Option> { - let result = iii - .trigger(TriggerRequest { - function_id: "worker::list".to_string(), - payload: json!({}), - action: None, - timeout_ms: Some(5_000), - }) - .await; + let request = TriggerRequest { + function_id: "worker::list".to_string(), + payload: json!({}), + action: None, + timeout_ms: Some(5_000), + }; + let result = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + }; // Re-acquire the lock and store or fall back. let mut lock = self.inner.lock().await; diff --git a/iii-directory/src/main.rs b/iii-directory/src/main.rs index 53885a513..39c7b58e1 100644 --- a/iii-directory/src/main.rs +++ b/iii-directory/src/main.rs @@ -256,6 +256,7 @@ fn setup_auto_download( "stages": ["done"] }), metadata: None, + namespace: iii_sub.namespace(), }); match result { Ok(_) => { @@ -356,14 +357,16 @@ async fn reconcile_one( async fn fetch_worker_list_with_retry(iii: &IIIClient) -> Option> { const MAX_ATTEMPTS: u32 = 6; for attempt in 1..=MAX_ATTEMPTS { - let result = iii - .trigger(TriggerRequest { - function_id: "worker::list".to_string(), - payload: json!({}), - action: None, - timeout_ms: Some(10_000), - }) - .await; + let request = TriggerRequest { + function_id: "worker::list".to_string(), + payload: json!({}), + action: None, + timeout_ms: Some(10_000), + }; + let result = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + }; match result { Ok(val) => { diff --git a/iii-directory/src/trigger_types.rs b/iii-directory/src/trigger_types.rs index ee9b6b437..36a40c0e5 100644 --- a/iii-directory/src/trigger_types.rs +++ b/iii-directory/src/trigger_types.rs @@ -87,14 +87,36 @@ pub async fn dispatch(iii: &IIIClient, subscribers: &SubscriberSet, payload: Val for function_id in targets { let fid = function_id.clone(); let payload_copy = payload.clone(); - let res = iii - .trigger(TriggerRequest { - function_id: fid, - payload: payload_copy, - action: Some(TriggerAction::Void), - timeout_ms: None, - }) - .await; + let request = TriggerRequest { + function_id: fid, + payload: payload_copy, + action: Some(TriggerAction::Void), + timeout_ms: None, + }; + let route_ns = iii.namespace().filter(|_| { + !matches!( + function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let res = match route_ns { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + }; if let Err(e) = res { tracing::warn!( function_id = %function_id, @@ -180,6 +202,7 @@ mod tests { function_id: function_id.to_string(), config: json!({}), metadata: None, + namespace: None, } } diff --git a/image-resize/Cargo.lock b/image-resize/Cargo.lock index 27add8049..5ca0a78ab 100644 --- a/image-resize/Cargo.lock +++ b/image-resize/Cargo.lock @@ -697,9 +697,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -718,9 +718,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/image-resize/Cargo.toml b/image-resize/Cargo.toml index 064699189..fe00144c4 100644 --- a/image-resize/Cargo.toml +++ b/image-resize/Cargo.toml @@ -11,7 +11,7 @@ name = "image-resize" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" image = { version = "0.25", default-features = false, features = ["jpeg", "png", "webp"] } kamadak-exif = "0.6" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal"] } diff --git a/image-resize/src/main.rs b/image-resize/src/main.rs index e7e9608b4..8b61affab 100644 --- a/image-resize/src/main.rs +++ b/image-resize/src/main.rs @@ -17,6 +17,11 @@ struct Cli { /// WebSocket URL of the III engine (port 49134 = engine main WS, not StreamModule 3112) #[arg(long, env = "III_URL", default_value = "ws://127.0.0.1:49134")] url: String, + + /// Namespace to register under. Absent uses the engine's default namespace. + /// Falls back to the III_NAMESPACE env var. + #[arg(long, env = "III_NAMESPACE")] + namespace: Option, } #[tokio::main] @@ -49,9 +54,15 @@ async fn main() -> Result<()> { let config = Arc::new(resize_config); - tracing::info!(url = %cli.url, "connecting to III engine"); + tracing::info!(url = %cli.url, namespace = ?cli.namespace, "connecting to III engine"); - let iii = register_worker(&cli.url, InitOptions::default()); + let iii = register_worker( + &cli.url, + InitOptions { + namespace: cli.namespace.clone(), + ..Default::default() + }, + ); let resize_handler = handler::build_handler(cli.url.clone(), config); diff --git a/llm-router/Cargo.lock b/llm-router/Cargo.lock index 59df666cf..359a0fd22 100644 --- a/llm-router/Cargo.lock +++ b/llm-router/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/llm-router/Cargo.toml b/llm-router/Cargo.toml index 9748a340e..466e2118d 100644 --- a/llm-router/Cargo.toml +++ b/llm-router/Cargo.toml @@ -18,12 +18,12 @@ path = "src/main.rs" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" # Re-exports the same `opentelemetry` the SDK uses, so we can carry the active # OTel context across `tokio::spawn` boundaries (shared `Context` global). # 0.21.5 adds the live span-start push, so `router::chat` renders in the # console while it streams instead of on close. -iii-helpers = "=0.21.6" +iii-helpers = "=0.22.0-alpha.3" serde = { version = "1", features = ["derive"] } serde_json = "1" # Must stay on the same schemars major as iii-sdk so the derived diff --git a/llm-router/src/provider_scaffold/router_client.rs b/llm-router/src/provider_scaffold/router_client.rs index c098a5222..d6eb71323 100644 --- a/llm-router/src/provider_scaffold/router_client.rs +++ b/llm-router/src/provider_scaffold/router_client.rs @@ -10,13 +10,18 @@ use iii_sdk::IIIClient; use serde_json::{json, Value}; pub async fn call(iii: &IIIClient, function_id: &str, payload: Value) -> Result { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: function_id.into(), payload, action: None, timeout_ms: Some(15_000), - }) - .await + }; + // Route the cross-worker call to this worker's namespace so it reaches the + // router registered in the same namespace (None => the engine's default). + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } } /// `router::provider::resolve` — credential + effective settings. diff --git a/llm-router/src/register.rs b/llm-router/src/register.rs index bc02e7d23..33d4681a0 100644 --- a/llm-router/src/register.rs +++ b/llm-router/src/register.rs @@ -35,7 +35,6 @@ use crate::registry::resolve::{make_provider_resolve, make_update_credential}; use crate::registry::store::RegistryStore; use crate::surface; use crate::triggers::RouterEvents; -use crate::types::errors::invalid_request_from_serde; use crate::types::router::ConfigChangedEvent; /// `metadata.internal = true` keeps a registration out of the default @@ -93,30 +92,24 @@ pub async fn register_router(iii: IIIClient) -> Result { let (iii_for_chat, pipeline) = (iii.clone(), pipeline.clone()); iii.register_function( surface::CHAT_ID, - RegisterFunction::new_async_with_bad_request( - move |input: ChatFnInput| { - let (iii, pipeline) = (iii_for_chat.clone(), pipeline.clone()); - async move { - let sink = open_sink(&iii, &input.writer_ref).await?; - let result = pipeline.run(input.call, sink.clone()).await; - sink.close(); // the handler owns closing the caller's channel - result - } - }, - invalid_request_from_serde, - ) + RegisterFunction::new_async(move |input: ChatFnInput| { + let (iii, pipeline) = (iii_for_chat.clone(), pipeline.clone()); + async move { + let sink = open_sink(&iii, &input.writer_ref).await?; + let result = pipeline.run(input.call, sink.clone()).await; + sink.close(); // the handler owns closing the caller's channel + result + } + }) .description(surface::CHAT_DESC) .metadata(internal_meta()), ); } iii.register_function( surface::COMPLETE_ID, - RegisterFunction::new_async_with_bad_request( - make_complete(iii.clone(), pipeline.clone()), - invalid_request_from_serde, - ) - .description(surface::COMPLETE_DESC) - .metadata(internal_meta()), + RegisterFunction::new_async(make_complete(iii.clone(), pipeline.clone())) + .description(surface::COMPLETE_DESC) + .metadata(internal_meta()), ); iii.register_function( surface::ABORT_ID, @@ -181,16 +174,13 @@ pub async fn register_router(iii: IIIClient) -> Result { ); iii.register_function( surface::PROVIDER_REGISTER_ID, - RegisterFunction::new_async_with_bad_request( - make_provider_register( - iii.clone(), - registry.clone(), - catalog.clone(), - entry_lock.clone(), - events.clone(), - ), - invalid_request_from_serde, - ) + RegisterFunction::new_async(make_provider_register( + iii.clone(), + registry.clone(), + catalog.clone(), + entry_lock.clone(), + events.clone(), + )) .description(surface::PROVIDER_REGISTER_DESC) .metadata(internal_meta()), ); @@ -213,10 +203,11 @@ pub async fn register_router(iii: IIIClient) -> Result { ); iii.register_function( surface::MODELS_RECONCILE_ID, - RegisterFunction::new_async_with_bad_request( - make_models_reconcile(registry.clone(), catalog.clone(), events.clone()), - invalid_request_from_serde, - ) + RegisterFunction::new_async(make_models_reconcile( + registry.clone(), + catalog.clone(), + events.clone(), + )) .description(surface::MODELS_RECONCILE_DESC) .metadata(internal_meta()), ); @@ -255,6 +246,7 @@ pub async fn register_router(iii: IIIClient) -> Result { function_id: surface::ON_CONFIG_CHANGED_ID.into(), config: json!({ "configuration_id": "llm-router", "event_types": ["configuration:updated"] }), metadata: None, + namespace: iii.namespace(), })?; // Close the boot race between the initial fetch and trigger binding by diff --git a/llm-router/src/triggers.rs b/llm-router/src/triggers.rs index eead0cbc6..a7fc8a39d 100644 --- a/llm-router/src/triggers.rs +++ b/llm-router/src/triggers.rs @@ -224,12 +224,14 @@ mod tests { function_id: "probe::on_ready".into(), config: Value::Object(serde_json::Map::new()), metadata: None, + namespace: None, }); set.insert(TriggerConfig { id: "sub-2".into(), function_id: "other::recv".into(), config: Value::Object(serde_json::Map::new()), metadata: None, + namespace: None, }); let mut fns = set.function_ids(); fns.sort(); diff --git a/llm-router/tests/integration.rs b/llm-router/tests/integration.rs index ed8a010b1..80a0edc8c 100644 --- a/llm-router/tests/integration.rs +++ b/llm-router/tests/integration.rs @@ -1050,6 +1050,7 @@ async fn models_changed_event_reaches_a_trigger_subscriber() { function_id: "probe::on_models_changed".into(), config: json!({}), metadata: None, + namespace: probe.namespace(), }) .expect("router::models::changed trigger registered"); diff --git a/lsp/Cargo.lock b/lsp/Cargo.lock index 5d0e697c6..b77a4ebcb 100644 --- a/lsp/Cargo.lock +++ b/lsp/Cargo.lock @@ -481,9 +481,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -712,9 +712,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -733,9 +733,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", @@ -754,12 +754,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -794,13 +794,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -2053,9 +2052,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -2066,9 +2065,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.67" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -2076,9 +2075,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2086,9 +2085,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", @@ -2099,9 +2098,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] @@ -2142,9 +2141,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.94" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/lsp/Cargo.toml b/lsp/Cargo.toml index 311749d7a..162071048 100644 --- a/lsp/Cargo.toml +++ b/lsp/Cargo.toml @@ -13,7 +13,7 @@ name = "lsp" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" tower-lsp-server = "0.23" tree-sitter = "0.24" tree-sitter-typescript = "0.23" diff --git a/mcp/Cargo.lock b/mcp/Cargo.lock index 0915f38d7..146953d90 100644 --- a/mcp/Cargo.lock +++ b/mcp/Cargo.lock @@ -887,9 +887,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -908,9 +908,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/mcp/Cargo.toml b/mcp/Cargo.toml index 920e93971..5a434d45a 100644 --- a/mcp/Cargo.toml +++ b/mcp/Cargo.toml @@ -15,8 +15,8 @@ name = "iii_mcp" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" +iii-helpers = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/mcp/src/main.rs b/mcp/src/main.rs index a3ab6c556..ac063ee48 100644 --- a/mcp/src/main.rs +++ b/mcp/src/main.rs @@ -87,6 +87,7 @@ async fn main() -> Result<()> { "http_method": "POST", }), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!( function_id = functions::FUNCTION_ID, diff --git a/mcp/tests/common/engine.rs b/mcp/tests/common/engine.rs index 90cb323f5..8bba2317d 100644 --- a/mcp/tests/common/engine.rs +++ b/mcp/tests/common/engine.rs @@ -106,6 +106,7 @@ async fn register_bridge(iii: &Arc) { "http_method": "POST", }), metadata: None, + namespace: iii.namespace(), }) { eprintln!( "[warn] mcp BDD harness failed to register HTTP trigger at {api_path}: {e}; \ diff --git a/memory-consolidate/Cargo.lock b/memory-consolidate/Cargo.lock index f4517b366..0978a1438 100644 --- a/memory-consolidate/Cargo.lock +++ b/memory-consolidate/Cargo.lock @@ -642,9 +642,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -663,9 +663,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.3" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6455e06a9357696d8aa7cf7ba6d6b30ce8803036d85ea53a51de76178b867ec" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/memory-consolidate/Cargo.toml b/memory-consolidate/Cargo.toml index 6e7f72554..5f4554a4b 100644 --- a/memory-consolidate/Cargo.toml +++ b/memory-consolidate/Cargo.toml @@ -15,7 +15,7 @@ name = "memory_consolidate" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.3" +iii-sdk = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/memory-consolidate/src/configuration.rs b/memory-consolidate/src/configuration.rs index d3046ccf1..c328e97d4 100644 --- a/memory-consolidate/src/configuration.rs +++ b/memory-consolidate/src/configuration.rs @@ -117,6 +117,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/memory-consolidate/src/consolidate.rs b/memory-consolidate/src/consolidate.rs index 0f9c6cb40..2ff068a02 100644 --- a/memory-consolidate/src/consolidate.rs +++ b/memory-consolidate/src/consolidate.rs @@ -171,13 +171,16 @@ fn group_by(rows: &[MemoryRow], key: fn(&str) -> String, report_only: bool) -> V } async fn call(iii: &IIIClient, function_id: &str, payload: Value) -> Result { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: function_id.to_string(), payload, action: None, timeout_ms: Some(CALL_TIMEOUT_MS), - }) - .await + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } .map_err(|e| format!("{function_id}: {e}")) } diff --git a/memory-consolidate/src/llm.rs b/memory-consolidate/src/llm.rs index 6900ad619..82ecd63e9 100644 --- a/memory-consolidate/src/llm.rs +++ b/memory-consolidate/src/llm.rs @@ -146,15 +146,17 @@ async fn resolve_model(iii: &IIIClient, configured: &str) -> Result iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } + .map_err(|e| format!("router::models::list: {e}"))?; reply .get("models") .and_then(Value::as_array) @@ -172,24 +174,26 @@ pub async fn judge( prompt: String, ) -> Result { let model = resolve_model(iii, configured_model).await?; - let reply = iii - .trigger(TriggerRequest { - function_id: "router::complete".into(), - payload: json!({ - "model": model, - "system_prompt": JUDGE_SYSTEM, - "messages": [{ - "role": "user", - "content": [{ "type": "text", "text": prompt }], - "timestamp": now_ms() as i64, - }], - "max_output_tokens": 1_024, - }), - action: None, - timeout_ms: Some(LLM_TIMEOUT_MS), - }) - .await - .map_err(|e| format!("router::complete: {e}"))?; + let request = TriggerRequest { + function_id: "router::complete".into(), + payload: json!({ + "model": model, + "system_prompt": JUDGE_SYSTEM, + "messages": [{ + "role": "user", + "content": [{ "type": "text", "text": prompt }], + "timestamp": now_ms() as i64, + }], + "max_output_tokens": 1_024, + }), + action: None, + timeout_ms: Some(LLM_TIMEOUT_MS), + }; + let reply = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } + .map_err(|e| format!("router::complete: {e}"))?; let text = reply .pointer("/message/content") .and_then(Value::as_array) diff --git a/memory-consolidate/src/main.rs b/memory-consolidate/src/main.rs index 4851524c9..58d7b8efa 100644 --- a/memory-consolidate/src/main.rs +++ b/memory-consolidate/src/main.rs @@ -88,6 +88,7 @@ fn bind_schedule(iii: Arc, deps: Arc) { function_id: functions::TICK_ID.to_string(), config: serde_json::json!({ "expression": CRON_EXPRESSION }), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => { tracing::info!(expression = CRON_EXPRESSION, "cron heartbeat bound"); @@ -200,6 +201,7 @@ async fn main() -> Result<()> { function_id: spec.function_id.to_string(), config: serde_json::json!({ "api_path": api_path, "http_method": "POST" }), metadata: None, + namespace: iii.namespace(), }) { tracing::debug!(error = %e, function_id = spec.function_id, "http trigger registration failed"); } diff --git a/memory/Cargo.lock b/memory/Cargo.lock index c0e2a65b6..819b7e410 100644 --- a/memory/Cargo.lock +++ b/memory/Cargo.lock @@ -660,9 +660,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.8" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84bdc7bbc3abfde934a62cdc5d3045adf52914dfc1ed6c20f8af691fc561dc55" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -681,9 +681,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/memory/Cargo.toml b/memory/Cargo.toml index dc9703ac2..374b5a793 100644 --- a/memory/Cargo.toml +++ b/memory/Cargo.toml @@ -18,7 +18,7 @@ path = "src/lib.rs" # Bumped from =0.21.3 to match the `iii-console-ui` crate's exact pin: both are # `=` requirements so they must resolve to a single version, and the injectable # UI helper must never drag a worker onto a different SDK build. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" # Worker-side injectable console UI (content function + console:script/style # triggers + hot-reload watcher) — direct path link, never published. iii-console-ui = { path = "../crates/console-ui" } diff --git a/memory/src/configuration.rs b/memory/src/configuration.rs index c1ed99fe0..cae7e5983 100644 --- a/memory/src/configuration.rs +++ b/memory/src/configuration.rs @@ -151,6 +151,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/memory/src/embed_client.rs b/memory/src/embed_client.rs index 4f5c40294..1765537af 100644 --- a/memory/src/embed_client.rs +++ b/memory/src/embed_client.rs @@ -31,15 +31,17 @@ pub async fn embed_texts( if !model.trim().is_empty() { payload["model"] = json!(model); } - let reply = iii - .trigger(TriggerRequest { - function_id: "router::embed".into(), - payload, - action: None, - timeout_ms: Some(timeout_ms), - }) - .await - .ok()?; + let request = TriggerRequest { + function_id: "router::embed".into(), + payload, + action: None, + timeout_ms: Some(timeout_ms), + }; + let reply = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } + .ok()?; let embeddings: Vec> = serde_json::from_value(reply.get("embeddings").cloned().unwrap_or(Value::Null)).ok()?; if embeddings.len() == texts.len() { diff --git a/memory/src/events.rs b/memory/src/events.rs index b4532ca2c..7c7cccf9d 100644 --- a/memory/src/events.rs +++ b/memory/src/events.rs @@ -206,15 +206,36 @@ impl Emitter { if !matches { continue; } - let res = self - .iii - .trigger(TriggerRequest { - function_id: binding.function_id.clone(), - payload: payload.clone(), - action: Some(TriggerAction::Void), - timeout_ms: None, - }) - .await; + let request = TriggerRequest { + function_id: binding.function_id.clone(), + payload: payload.clone(), + action: Some(TriggerAction::Void), + timeout_ms: None, + }; + let route_ns = self.iii.namespace().filter(|_| { + !matches!( + binding.function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let res = match route_ns { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; if let Err(e) = res { tracing::warn!(function_id = %binding.function_id, error = %e, "void fan-out failed"); } diff --git a/memory/src/extract.rs b/memory/src/extract.rs index f74b778d7..7effcebc7 100644 --- a/memory/src/extract.rs +++ b/memory/src/extract.rs @@ -107,14 +107,16 @@ fn merge_learned(existing: &str, additions: &[String]) -> (String, usize) { /// `None` — injecting or writing the default bank when the session's real /// bank is unknown would leak across contexts. pub async fn resolve_bank(iii: &IIIClient, session_id: &str, default_bank: &str) -> Option { - let reply = iii - .trigger(TriggerRequest { - function_id: "session::get".into(), - payload: json!({ "session_id": session_id }), - action: None, - timeout_ms: Some(5_000), - }) - .await; + let request = TriggerRequest { + function_id: "session::get".into(), + payload: json!({ "session_id": session_id }), + action: None, + timeout_ms: Some(5_000), + }; + let reply = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + }; match reply { Ok(v) => { let from_meta = v @@ -163,25 +165,26 @@ pub async fn try_run(deps: &Deps, session_id: &str) -> Result<(), String> { } let model = resolve_model(&deps.iii, &cfg.extraction_model).await?; - let reply = deps - .iii - .trigger(TriggerRequest { - function_id: "router::complete".into(), - payload: json!({ - "model": model, - "system_prompt": EXTRACT_SYSTEM, - "messages": [{ - "role": "user", - "content": [{ "type": "text", "text": transcript }], - "timestamp": now_ms() as i64, - }], - "max_output_tokens": 1024, - }), - action: None, - timeout_ms: Some(cfg.extraction_timeout_ms), - }) - .await - .map_err(|e| format!("router::complete: {e}"))?; + let request = TriggerRequest { + function_id: "router::complete".into(), + payload: json!({ + "model": model, + "system_prompt": EXTRACT_SYSTEM, + "messages": [{ + "role": "user", + "content": [{ "type": "text", "text": transcript }], + "timestamp": now_ms() as i64, + }], + "max_output_tokens": 1024, + }), + action: None, + timeout_ms: Some(cfg.extraction_timeout_ms), + }; + let reply = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + } + .map_err(|e| format!("router::complete: {e}"))?; let text = assistant_text(&reply); let items = parse_items(&text)?; @@ -407,15 +410,17 @@ async fn fetch_transcript_since( if let Some(c) = &cursor { payload["cursor"] = json!(c); } - let reply = iii - .trigger(TriggerRequest { - function_id: "session::messages".into(), - payload, - action: None, - timeout_ms: Some(10_000), - }) - .await - .map_err(|e| format!("session::messages: {e}"))?; + let request = TriggerRequest { + function_id: "session::messages".into(), + payload, + action: None, + timeout_ms: Some(10_000), + }; + let reply = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } + .map_err(|e| format!("session::messages: {e}"))?; if let Some(items) = reply.get("messages").and_then(Value::as_array) { for item in items { let entry_id = item @@ -507,15 +512,17 @@ async fn resolve_model(iii: &IIIClient, configured: &str) -> Result iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } + .map_err(|e| format!("router::models::list: {e}"))?; let first = reply .get("models") .and_then(Value::as_array) diff --git a/memory/src/functions/ops.rs b/memory/src/functions/ops.rs index 298d45bc4..929a7c61a 100644 --- a/memory/src/functions/ops.rs +++ b/memory/src/functions/ops.rs @@ -117,15 +117,16 @@ async fn roundtrip_check(deps: &Deps) -> DoctorCheck { } async fn sibling_check(deps: &Deps, name: &str, function_id: &str, why: &str) -> DoctorCheck { - let res = deps - .iii - .trigger(TriggerRequest { - function_id: function_id.into(), - payload: json!({}), - action: None, - timeout_ms: Some(3_000), - }) - .await; + let request = TriggerRequest { + function_id: function_id.into(), + payload: json!({}), + action: None, + timeout_ms: Some(3_000), + }; + let res = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + }; match res { Ok(_) => DoctorCheck { name: name.into(), diff --git a/memory/src/main.rs b/memory/src/main.rs index b33a9fb17..5d08e5392 100644 --- a/memory/src/main.rs +++ b/memory/src/main.rs @@ -80,6 +80,7 @@ fn bind_best_effort( function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }); match res { Ok(_) => tracing::info!(trigger_type, function_id, "trigger binding requested"), @@ -241,6 +242,7 @@ async fn main() -> Result<()> { function_id: spec.function_id.to_string(), config: json!({ "api_path": api_path, "http_method": "POST" }), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::debug!( function_id = spec.function_id, diff --git a/opencode/package.json b/opencode/package.json index 6c225ab73..8e596f2df 100644 --- a/opencode/package.json +++ b/opencode/package.json @@ -23,7 +23,7 @@ "opencode-worker": "./dist/index.js" }, "dependencies": { - "iii-sdk": "^0.21.6", + "iii-sdk": "0.22.0-alpha.3", "yaml": "^2.6.0", "zod": "^4.0.0" }, diff --git a/opencode/pnpm-lock.yaml b/opencode/pnpm-lock.yaml index 580ee5b98..4c8823a5b 100644 --- a/opencode/pnpm-lock.yaml +++ b/opencode/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: iii-sdk: - specifier: ^0.21.6 - version: 0.21.6 + specifier: 0.22.0-alpha.3 + version: 0.22.0-alpha.3 yaml: specifier: ^2.6.0 version: 2.9.0 @@ -560,8 +560,8 @@ packages: cpu: [x64] os: [win32] - '@iii-dev/helpers@0.21.6': - resolution: {integrity: sha512-UkiIqC5Ob41xc9uYx1SRt4LXLKrzAMzOCq6Kwo4hCak7Qj4Q1tP0GW0nYP7UpgYHsQnzf+2sspb2yD/DVa2ePA==} + '@iii-dev/helpers@0.22.0-alpha.3': + resolution: {integrity: sha512-zwilMTMq2MgVFu/aOEbtrPDpB+AVcdcqKBVAGc4vXv4XT2sK5eAXpdyzPcNgf8bGRKcRGZJ0ZJ8dA8WDVlSlaw==} '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -936,8 +936,8 @@ packages: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} - iii-sdk@0.21.6: - resolution: {integrity: sha512-D9NGtcGWdY8tqXRIjvRDqNqKRI2qJcQguSDWuUEPXaYyIHSn1jp3PIVF34cCY6C+f3Bby8fjptxpfzWYQUOg2A==} + iii-sdk@0.22.0-alpha.3: + resolution: {integrity: sha512-S6dH8ssbZsuuh8m6k0gG//D5K11w/wTkUviRMQ0sP3NNQh4ZhxZz0TbGlhROpwCYdJb1Rgl8dAHgeXbhyoIUXg==} import-in-the-middle@1.15.0: resolution: {integrity: sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==} @@ -1440,7 +1440,7 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@iii-dev/helpers@0.21.6': + '@iii-dev/helpers@0.22.0-alpha.3': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.57.2 @@ -1839,9 +1839,9 @@ snapshots: dependencies: function-bind: 1.1.2 - iii-sdk@0.21.6: + iii-sdk@0.22.0-alpha.3: dependencies: - '@iii-dev/helpers': 0.21.6 + '@iii-dev/helpers': 0.22.0-alpha.3 '@opentelemetry/api': 1.9.1 ws: 8.21.0 transitivePeerDependencies: diff --git a/opencode/src/index.ts b/opencode/src/index.ts index c3bb9eae3..5b283240d 100644 --- a/opencode/src/index.ts +++ b/opencode/src/index.ts @@ -37,7 +37,12 @@ const bootConfig: Config = { opencode_executable: resolveOpencodeExecutable(seed.opencode_executable), }; -const iii = registerWorker(url, { workerName: 'opencode' }); +// namespace: register under III_NAMESPACE when set (the SDK also reads it, +// passed here for visibility). Absent, the engine's default namespace is used. +const iii = registerWorker(url, { + workerName: 'opencode', + namespace: process.env.III_NAMESPACE, +}); try { await registerOpencodeConfig(iii, bootConfig); diff --git a/pi/package.json b/pi/package.json index 689c01195..468f7a2bc 100644 --- a/pi/package.json +++ b/pi/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@earendil-works/pi-coding-agent": "^0.79.0", - "iii-sdk": "^0.21.6", + "iii-sdk": "0.22.0-alpha.3", "yaml": "^2.6.0", "zod": "^4.0.0" }, diff --git a/pi/pnpm-lock.yaml b/pi/pnpm-lock.yaml index 067568fb6..e53a8d163 100644 --- a/pi/pnpm-lock.yaml +++ b/pi/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^0.79.0 version: 0.79.10(ws@8.21.0)(zod@4.4.3) iii-sdk: - specifier: ^0.21.6 - version: 0.21.6 + specifier: 0.22.0-alpha.3 + version: 0.22.0-alpha.3 yaml: specifier: ^2.6.0 version: 2.9.0 @@ -704,8 +704,8 @@ packages: '@modelcontextprotocol/sdk': optional: true - '@iii-dev/helpers@0.21.6': - resolution: {integrity: sha512-UkiIqC5Ob41xc9uYx1SRt4LXLKrzAMzOCq6Kwo4hCak7Qj4Q1tP0GW0nYP7UpgYHsQnzf+2sspb2yD/DVa2ePA==} + '@iii-dev/helpers@0.22.0-alpha.3': + resolution: {integrity: sha512-zwilMTMq2MgVFu/aOEbtrPDpB+AVcdcqKBVAGc4vXv4XT2sK5eAXpdyzPcNgf8bGRKcRGZJ0ZJ8dA8WDVlSlaw==} '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -1301,8 +1301,8 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} - iii-sdk@0.21.6: - resolution: {integrity: sha512-D9NGtcGWdY8tqXRIjvRDqNqKRI2qJcQguSDWuUEPXaYyIHSn1jp3PIVF34cCY6C+f3Bby8fjptxpfzWYQUOg2A==} + iii-sdk@0.22.0-alpha.3: + resolution: {integrity: sha512-S6dH8ssbZsuuh8m6k0gG//D5K11w/wTkUviRMQ0sP3NNQh4ZhxZz0TbGlhROpwCYdJb1Rgl8dAHgeXbhyoIUXg==} import-in-the-middle@1.15.0: resolution: {integrity: sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==} @@ -2246,7 +2246,7 @@ snapshots: - supports-color - utf-8-validate - '@iii-dev/helpers@0.21.6': + '@iii-dev/helpers@0.22.0-alpha.3': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.57.2 @@ -2865,9 +2865,9 @@ snapshots: ignore@7.0.5: {} - iii-sdk@0.21.6: + iii-sdk@0.22.0-alpha.3: dependencies: - '@iii-dev/helpers': 0.21.6 + '@iii-dev/helpers': 0.22.0-alpha.3 '@opentelemetry/api': 1.9.1 ws: 8.21.0 transitivePeerDependencies: diff --git a/pi/src/index.ts b/pi/src/index.ts index 172a02301..22af501ce 100644 --- a/pi/src/index.ts +++ b/pi/src/index.ts @@ -32,7 +32,12 @@ const url = values.url : (process.env.III_URL ?? process.env.III_ENGINE_URL ?? seed.engine_url); const bootConfig: Config = { ...seed, engine_url: url }; -const iii = registerWorker(url, { workerName: 'pi' }); +// namespace: register under III_NAMESPACE when set (the SDK also reads it, +// passed here for visibility). Absent, the engine's default namespace is used. +const iii = registerWorker(url, { + workerName: 'pi', + namespace: process.env.III_NAMESPACE, +}); // Best-effort: a configuration-worker hiccup at boot must not stop the worker // from registering pi::*; it falls back to the seed via fetchRuntime. diff --git a/provider-anthropic/Cargo.lock b/provider-anthropic/Cargo.lock index d4ee34a95..e298cffda 100644 --- a/provider-anthropic/Cargo.lock +++ b/provider-anthropic/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/provider-anthropic/Cargo.toml b/provider-anthropic/Cargo.toml index e55a38f08..15a5b26ed 100644 --- a/provider-anthropic/Cargo.toml +++ b/provider-anthropic/Cargo.toml @@ -22,7 +22,7 @@ path = "src/lib.rs" llm-router = { path = "../llm-router" } # Must match llm-router's pin (one iii-sdk per graph). 0.21.5 brings the # live span-start push: `provider::anthropic::stream` renders while streaming. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" serde = { version = "1", features = ["derive"] } serde_json = "1" # Must stay on the same schemars major as iii-sdk so the derived diff --git a/provider-anthropic/src/register.rs b/provider-anthropic/src/register.rs index d2cff315e..f3f33530f 100644 --- a/provider-anthropic/src/register.rs +++ b/provider-anthropic/src/register.rs @@ -2,7 +2,6 @@ //! declare-with-backoff loop (spec § Registration lifecycle). use crate::config::{DEFAULT_API_URL, DEFAULT_MAX_TOKENS}; use crate::discovery::{make_refresh_models, refresh_models}; -use crate::errors::invalid_request_from_serde; use crate::stream_fn::make_stream; use crate::surface; use crate::{router_client, state, PROVIDER_ID}; @@ -145,21 +144,20 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { iii.register_function( surface::STREAM_ID, - RegisterFunction::new_async_with_bad_request( - make_stream(iii.clone(), http.clone(), cache.clone(), aborts.clone()), - invalid_request_from_serde, - ) + RegisterFunction::new_async(make_stream( + iii.clone(), + http.clone(), + cache.clone(), + aborts.clone(), + )) .description(surface::STREAM_DESC) .metadata(json!({ "internal": true })), ); iii.register_function( surface::ABORT_ID, - RegisterFunction::new_async_with_bad_request( - make_abort(aborts), - invalid_request_from_serde, - ) - .description(surface::ABORT_DESC) - .metadata(json!({ "internal": true })), + RegisterFunction::new_async(make_abort(aborts)) + .description(surface::ABORT_DESC) + .metadata(json!({ "internal": true })), ); iii.register_function( surface::REFRESH_MODELS_ID, @@ -192,6 +190,7 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { function_id: surface::ON_ROUTER_READY_ID.into(), config: json!({}), metadata: None, + namespace: iii.namespace(), }); // Boot declare, off the boot path (a missing router must not block boot). diff --git a/provider-kimi/Cargo.lock b/provider-kimi/Cargo.lock index 914580f85..2986b043f 100644 --- a/provider-kimi/Cargo.lock +++ b/provider-kimi/Cargo.lock @@ -628,9 +628,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -649,9 +649,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", @@ -717,7 +717,7 @@ checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "llm-router" -version = "1.3.2" +version = "1.4.0" dependencies = [ "async-trait", "clap", diff --git a/provider-kimi/Cargo.toml b/provider-kimi/Cargo.toml index bb8e8f746..ee4b3c806 100644 --- a/provider-kimi/Cargo.toml +++ b/provider-kimi/Cargo.toml @@ -18,7 +18,7 @@ path = "src/lib.rs" [dependencies] llm-router = { path = "../llm-router" } # Must match llm-router's pin so the provider and router share one IIIClient type. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" serde = { version = "1", features = ["derive"] } serde_json = "1" # Must stay on the same schemars major as iii-sdk so the derived diff --git a/provider-kimi/src/register.rs b/provider-kimi/src/register.rs index 66954902e..51f6dfd92 100644 --- a/provider-kimi/src/register.rs +++ b/provider-kimi/src/register.rs @@ -2,7 +2,6 @@ //! declare-with-backoff loop (spec § Registration lifecycle). use crate::config::{DEFAULT_API_URL, DEFAULT_MAX_TOKENS}; use crate::discovery::{make_refresh_models, refresh_models}; -use crate::errors::invalid_request_from_serde; use crate::stream_fn::make_stream; use crate::surface; use crate::{router_client, state, PROVIDER_ID}; @@ -124,22 +123,16 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { iii.register_function( surface::STREAM_ID, - RegisterFunction::new_async_with_bad_request( - make_stream(iii.clone(), http.clone(), aborts.clone()), - invalid_request_from_serde, - ) - .description(surface::STREAM_DESC), + RegisterFunction::new_async(make_stream(iii.clone(), http.clone(), aborts.clone())) + .description(surface::STREAM_DESC), ); iii.register_function( surface::ABORT_ID, - RegisterFunction::new_async_with_bad_request( - make_abort(aborts), - invalid_request_from_serde, - ) - .description(surface::ABORT_DESC) - // Control-plane callback (router::abort fan-out) — hide from the - // agent-facing catalog like the other providers' abort functions. - .metadata(serde_json::json!({ "internal": true })), + RegisterFunction::new_async(make_abort(aborts)) + .description(surface::ABORT_DESC) + // Control-plane callback (router::abort fan-out) — hide from the + // agent-facing catalog like the other providers' abort functions. + .metadata(serde_json::json!({ "internal": true })), ); iii.register_function( surface::REFRESH_MODELS_ID, @@ -168,6 +161,7 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { function_id: surface::ON_ROUTER_READY_ID.into(), config: json!({}), metadata: None, + namespace: iii.namespace(), }); // Boot declare, off the boot path (a missing router must not block boot). diff --git a/provider-kimi/src/router_client.rs b/provider-kimi/src/router_client.rs index 6cd49b7ae..610e2a92d 100644 --- a/provider-kimi/src/router_client.rs +++ b/provider-kimi/src/router_client.rs @@ -9,13 +9,18 @@ use llm_router::types::router::ProviderResolveResponse; use serde_json::{json, Value}; async fn call(iii: &IIIClient, function_id: &str, payload: Value) -> Result { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: function_id.into(), payload, action: None, timeout_ms: Some(15_000), - }) - .await + }; + // Route the cross-worker call to this worker's namespace so it reaches the + // router registered in the same namespace (None => the engine's default). + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } } /// `router::provider::resolve` — credential + effective settings. diff --git a/provider-llamacpp/Cargo.lock b/provider-llamacpp/Cargo.lock index b9e2683af..efbca72ec 100644 --- a/provider-llamacpp/Cargo.lock +++ b/provider-llamacpp/Cargo.lock @@ -649,9 +649,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -670,9 +670,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", @@ -738,7 +738,7 @@ checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "llm-router" -version = "1.3.2" +version = "1.4.0" dependencies = [ "async-trait", "clap", diff --git a/provider-llamacpp/Cargo.toml b/provider-llamacpp/Cargo.toml index 618333e1b..197a56b04 100644 --- a/provider-llamacpp/Cargo.toml +++ b/provider-llamacpp/Cargo.toml @@ -19,7 +19,7 @@ path = "src/lib.rs" llm-router = { path = "../llm-router" } # Must match llm-router's pin (one iii-sdk per graph). 0.21.5 brings the # live span-start push: `provider::llamacpp::stream` renders while streaming. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" serde = { version = "1", features = ["derive"] } serde_json = "1" # Must stay on the same schemars major as iii-sdk so the derived diff --git a/provider-llamacpp/src/register.rs b/provider-llamacpp/src/register.rs index 75326acca..4df71a632 100644 --- a/provider-llamacpp/src/register.rs +++ b/provider-llamacpp/src/register.rs @@ -2,7 +2,6 @@ //! declare-with-backoff loop (spec § Registration lifecycle). use crate::config::{DEFAULT_API_URL, DEFAULT_MAX_TOKENS}; use crate::discovery::{make_refresh_models, refresh_models}; -use crate::errors::invalid_request_from_serde; use crate::stream_fn::make_stream; use crate::surface; use crate::{router_client, state, PROVIDER_ID}; @@ -134,20 +133,19 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { iii.register_function( surface::STREAM_ID, - RegisterFunction::new_async_with_bad_request( - make_stream(iii.clone(), http.clone(), cache.clone(), aborts.clone()), - invalid_request_from_serde, - ) + RegisterFunction::new_async(make_stream( + iii.clone(), + http.clone(), + cache.clone(), + aborts.clone(), + )) .description(surface::STREAM_DESC), ); iii.register_function( surface::ABORT_ID, - RegisterFunction::new_async_with_bad_request( - make_abort(aborts), - invalid_request_from_serde, - ) - .description(surface::ABORT_DESC) - .metadata(json!({ "internal": true })), + RegisterFunction::new_async(make_abort(aborts)) + .description(surface::ABORT_DESC) + .metadata(json!({ "internal": true })), ); iii.register_function( surface::REFRESH_MODELS_ID, @@ -195,6 +193,7 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { function_id: surface::ON_ROUTER_READY_ID.into(), config: json!({}), metadata: None, + namespace: iii.namespace(), }); // Boot declare, off the boot path (a missing router must not block boot). diff --git a/provider-openai-codex/Cargo.lock b/provider-openai-codex/Cargo.lock index 80e96068b..42a02a44b 100644 --- a/provider-openai-codex/Cargo.lock +++ b/provider-openai-codex/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/provider-openai-codex/Cargo.toml b/provider-openai-codex/Cargo.toml index abbf5f93d..1c3f78ade 100644 --- a/provider-openai-codex/Cargo.toml +++ b/provider-openai-codex/Cargo.toml @@ -19,7 +19,7 @@ path = "src/lib.rs" llm-router = { path = "../llm-router" } # Must match llm-router's pin (one iii-sdk per graph). 0.21.5 brings the # live span-start push: `provider::openai-codex::stream` renders while streaming. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" serde = { version = "1", features = ["derive"] } serde_json = "1" # Must stay on the same schemars major as iii-sdk so the derived diff --git a/provider-openai-codex/src/register.rs b/provider-openai-codex/src/register.rs index 6779ecc8c..cbee0a5df 100644 --- a/provider-openai-codex/src/register.rs +++ b/provider-openai-codex/src/register.rs @@ -4,7 +4,6 @@ use crate::config::{DEFAULT_API_URL, DEFAULT_MAX_TOKENS}; use crate::discovery::{ make_refresh_models, refresh_models, refresh_models_periodically, CatalogRefreshState, }; -use crate::errors::invalid_request_from_serde; use crate::stream_fn::make_stream; use crate::surface; use crate::{auth, router_client, state, PROVIDER_ID}; @@ -147,21 +146,20 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { iii.register_function( surface::STREAM_ID, - RegisterFunction::new_async_with_bad_request( - make_stream(iii.clone(), http.clone(), cache.clone(), aborts.clone()), - invalid_request_from_serde, - ) + RegisterFunction::new_async(make_stream( + iii.clone(), + http.clone(), + cache.clone(), + aborts.clone(), + )) .description(surface::STREAM_DESC) .metadata(json!({ "internal": true })), ); iii.register_function( surface::ABORT_ID, - RegisterFunction::new_async_with_bad_request( - make_abort(aborts), - invalid_request_from_serde, - ) - .description(surface::ABORT_DESC) - .metadata(json!({ "internal": true })), + RegisterFunction::new_async(make_abort(aborts)) + .description(surface::ABORT_DESC) + .metadata(json!({ "internal": true })), ); iii.register_function( surface::REFRESH_MODELS_ID, @@ -202,6 +200,7 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { function_id: surface::ON_ROUTER_READY_ID.into(), config: json!({}), metadata: None, + namespace: iii.namespace(), }); tokio::spawn(declare_and_refresh( diff --git a/provider-openai/Cargo.lock b/provider-openai/Cargo.lock index 6e63c86d9..b510537e4 100644 --- a/provider-openai/Cargo.lock +++ b/provider-openai/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/provider-openai/Cargo.toml b/provider-openai/Cargo.toml index f590ede5c..07b85c38a 100644 --- a/provider-openai/Cargo.toml +++ b/provider-openai/Cargo.toml @@ -22,7 +22,7 @@ path = "src/lib.rs" llm-router = { path = "../llm-router" } # Must match llm-router's pin (one iii-sdk per graph). 0.21.5 brings the # live span-start push: `provider::openai::stream` renders while streaming. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" serde = { version = "1", features = ["derive"] } serde_json = "1" # Must stay on the same schemars major as iii-sdk so the derived diff --git a/provider-openai/src/register.rs b/provider-openai/src/register.rs index d6a00cd7e..a7fdbbcb1 100644 --- a/provider-openai/src/register.rs +++ b/provider-openai/src/register.rs @@ -2,7 +2,6 @@ //! declare-with-backoff loop (spec § Registration lifecycle). use crate::config::{DEFAULT_API_URL, DEFAULT_MAX_TOKENS}; use crate::discovery::{make_refresh_models, refresh_models}; -use crate::errors::invalid_request_from_serde; use crate::stream_fn::make_stream; use crate::surface; use crate::{router_client, state, PROVIDER_ID}; @@ -143,21 +142,20 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { iii.register_function( surface::STREAM_ID, - RegisterFunction::new_async_with_bad_request( - make_stream(iii.clone(), http.clone(), cache.clone(), aborts.clone()), - invalid_request_from_serde, - ) + RegisterFunction::new_async(make_stream( + iii.clone(), + http.clone(), + cache.clone(), + aborts.clone(), + )) .description(surface::STREAM_DESC) .metadata(json!({ "internal": true })), ); iii.register_function( surface::ABORT_ID, - RegisterFunction::new_async_with_bad_request( - make_abort(aborts), - invalid_request_from_serde, - ) - .description(surface::ABORT_DESC) - .metadata(json!({ "internal": true })), + RegisterFunction::new_async(make_abort(aborts)) + .description(surface::ABORT_DESC) + .metadata(json!({ "internal": true })), ); iii.register_function( surface::REFRESH_MODELS_ID, @@ -205,6 +203,7 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { function_id: surface::ON_ROUTER_READY_ID.into(), config: json!({}), metadata: None, + namespace: iii.namespace(), }); // Boot declare, off the boot path (a missing router must not block boot). diff --git a/provider-xai/Cargo.lock b/provider-xai/Cargo.lock index a836bf22e..11570dd73 100644 --- a/provider-xai/Cargo.lock +++ b/provider-xai/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", @@ -776,7 +776,7 @@ checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "llm-router" -version = "1.3.2" +version = "1.4.0" dependencies = [ "async-trait", "clap", diff --git a/provider-xai/Cargo.toml b/provider-xai/Cargo.toml index f684a071d..64d8b547b 100644 --- a/provider-xai/Cargo.toml +++ b/provider-xai/Cargo.toml @@ -22,7 +22,7 @@ path = "src/lib.rs" llm-router = { path = "../llm-router" } # Must match llm-router's pin (one iii-sdk per graph). 0.21.5 brings the # live span-start push: `provider::xai::stream` renders while streaming. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" serde = { version = "1", features = ["derive"] } serde_json = "1" # Must stay on the same schemars major as iii-sdk so the derived diff --git a/provider-xai/src/configuration.rs b/provider-xai/src/configuration.rs index 609a484b0..04f590ca9 100644 --- a/provider-xai/src/configuration.rs +++ b/provider-xai/src/configuration.rs @@ -101,6 +101,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/provider-xai/src/register.rs b/provider-xai/src/register.rs index 5cfb8c62b..341885d16 100644 --- a/provider-xai/src/register.rs +++ b/provider-xai/src/register.rs @@ -2,7 +2,6 @@ //! declare-with-backoff loop (spec § Registration lifecycle). use crate::config::{DEFAULT_API_URL, DEFAULT_MAX_TOKENS}; use crate::discovery::{make_refresh_models, refresh_models}; -use crate::errors::invalid_request_from_serde; use crate::stream_fn::make_stream; use crate::surface; use crate::{router_client, state, PROVIDER_ID}; @@ -176,27 +175,21 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { iii.register_function( surface::STREAM_ID, - RegisterFunction::new_async_with_bad_request( - make_stream( - iii.clone(), - http.clone(), - cell.clone(), - cache.clone(), - aborts.clone(), - ), - invalid_request_from_serde, - ) + RegisterFunction::new_async(make_stream( + iii.clone(), + http.clone(), + cell.clone(), + cache.clone(), + aborts.clone(), + )) .description(surface::STREAM_DESC) .metadata(json!({ "internal": true })), ); iii.register_function( surface::ABORT_ID, - RegisterFunction::new_async_with_bad_request( - make_abort(aborts), - invalid_request_from_serde, - ) - .description(surface::ABORT_DESC) - .metadata(json!({ "internal": true })), + RegisterFunction::new_async(make_abort(aborts)) + .description(surface::ABORT_DESC) + .metadata(json!({ "internal": true })), ); iii.register_function( surface::REFRESH_MODELS_ID, @@ -229,6 +222,7 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { function_id: surface::ON_ROUTER_READY_ID.into(), config: json!({}), metadata: None, + namespace: iii.namespace(), }); // Boot declare, off the boot path (a missing router must not block boot). diff --git a/provider-zai/Cargo.lock b/provider-zai/Cargo.lock index 813f5cfce..2b259c8d1 100644 --- a/provider-zai/Cargo.lock +++ b/provider-zai/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/provider-zai/Cargo.toml b/provider-zai/Cargo.toml index a2ea054e2..ccff3091a 100644 --- a/provider-zai/Cargo.toml +++ b/provider-zai/Cargo.toml @@ -19,7 +19,7 @@ path = "src/lib.rs" llm-router = { path = "../llm-router" } # Must match llm-router's pin (one iii-sdk per graph). 0.21.5 brings the # live span-start push: `provider::zai::stream` renders while streaming. -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" serde = { version = "1", features = ["derive"] } serde_json = "1" # Must stay on the same schemars major as iii-sdk so the derived diff --git a/provider-zai/src/register.rs b/provider-zai/src/register.rs index d21e96c28..520f23da0 100644 --- a/provider-zai/src/register.rs +++ b/provider-zai/src/register.rs @@ -2,7 +2,6 @@ //! declare-with-backoff loop (spec § Registration lifecycle). use crate::config::{DEFAULT_API_URL, DEFAULT_MAX_TOKENS}; use crate::discovery::{make_refresh_models, refresh_models}; -use crate::errors::invalid_request_from_serde; use crate::stream_fn::make_stream; use crate::surface; use crate::{router_client, state, PROVIDER_ID}; @@ -146,21 +145,20 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { iii.register_function( surface::STREAM_ID, - RegisterFunction::new_async_with_bad_request( - make_stream(iii.clone(), http.clone(), cache.clone(), aborts.clone()), - invalid_request_from_serde, - ) + RegisterFunction::new_async(make_stream( + iii.clone(), + http.clone(), + cache.clone(), + aborts.clone(), + )) .description(surface::STREAM_DESC) .metadata(json!({ "internal": true })), ); iii.register_function( surface::ABORT_ID, - RegisterFunction::new_async_with_bad_request( - make_abort(aborts), - invalid_request_from_serde, - ) - .description(surface::ABORT_DESC) - .metadata(json!({ "internal": true })), + RegisterFunction::new_async(make_abort(aborts)) + .description(surface::ABORT_DESC) + .metadata(json!({ "internal": true })), ); iii.register_function( surface::REFRESH_MODELS_ID, @@ -192,6 +190,7 @@ pub async fn register_provider(iii: IIIClient) -> Result<(), Error> { function_id: surface::ON_ROUTER_READY_ID.into(), config: json!({}), metadata: None, + namespace: iii.namespace(), }); // Boot declare, off the boot path (a missing router must not block boot). diff --git a/pubsub/Cargo.lock b/pubsub/Cargo.lock index d02b9eac5..e0bf93771 100644 --- a/pubsub/Cargo.lock +++ b/pubsub/Cargo.lock @@ -696,9 +696,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -737,9 +737,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/pubsub/Cargo.toml b/pubsub/Cargo.toml index 9d7a5f578..406bc9f41 100644 --- a/pubsub/Cargo.toml +++ b/pubsub/Cargo.toml @@ -18,7 +18,7 @@ name = "pubsub" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" async-trait = "0.1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } diff --git a/pubsub/src/configuration.rs b/pubsub/src/configuration.rs index 605dae2f0..70f09f1ae 100644 --- a/pubsub/src/configuration.rs +++ b/pubsub/src/configuration.rs @@ -140,6 +140,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/pubsub/src/trigger.rs b/pubsub/src/trigger.rs index 49c3c21fd..93a7c9399 100644 --- a/pubsub/src/trigger.rs +++ b/pubsub/src/trigger.rs @@ -84,6 +84,7 @@ mod tests { function_id: "test::listener".to_string(), config: cfg, metadata: None, + namespace: None, } } diff --git a/pubsub/tests/e2e_pubsub.rs b/pubsub/tests/e2e_pubsub.rs index 5f015e8a0..bafebdcdf 100644 --- a/pubsub/tests/e2e_pubsub.rs +++ b/pubsub/tests/e2e_pubsub.rs @@ -47,6 +47,7 @@ async fn publish_fans_out_raw_data_to_subscribe_triggers() { function_id: fn_id.to_string(), config: json!({"topic": "e2e.orders"}), metadata: None, + namespace: iii.namespace(), }) .expect("trigger registration"); } diff --git a/queue/Cargo.lock b/queue/Cargo.lock index 2c0ed4a6e..7f891ad99 100644 --- a/queue/Cargo.lock +++ b/queue/Cargo.lock @@ -1217,9 +1217,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -1263,9 +1263,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/queue/Cargo.toml b/queue/Cargo.toml index 56e9c4b85..a1c562e78 100644 --- a/queue/Cargo.toml +++ b/queue/Cargo.toml @@ -27,8 +27,8 @@ rabbitmq = ["dep:lapin"] test-adapters = [] [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" +iii-helpers = "=0.22.0-alpha.3" async-trait = "0.1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } diff --git a/queue/src/configuration.rs b/queue/src/configuration.rs index 483ee863a..500a823de 100644 --- a/queue/src/configuration.rs +++ b/queue/src/configuration.rs @@ -102,6 +102,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/queue/src/trigger.rs b/queue/src/trigger.rs index 321ec8e77..541bf277e 100644 --- a/queue/src/trigger.rs +++ b/queue/src/trigger.rs @@ -453,6 +453,7 @@ mod tests { function_id: function_id.to_string(), config, metadata: None, + namespace: None, } } diff --git a/queue/tests/e2e_durability.rs b/queue/tests/e2e_durability.rs index e032ede18..a279a76ca 100644 --- a/queue/tests/e2e_durability.rs +++ b/queue/tests/e2e_durability.rs @@ -81,6 +81,7 @@ fn register_subscriber_with_config( function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }) .expect("register durable subscriber trigger"); } diff --git a/rbac-proxy/Cargo.lock b/rbac-proxy/Cargo.lock index 7b06d7363..b770a0f6e 100644 --- a/rbac-proxy/Cargo.lock +++ b/rbac-proxy/Cargo.lock @@ -692,9 +692,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -713,9 +713,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/rbac-proxy/Cargo.toml b/rbac-proxy/Cargo.toml index c7c0b9700..a37084107 100644 --- a/rbac-proxy/Cargo.toml +++ b/rbac-proxy/Cargo.toml @@ -15,7 +15,7 @@ name = "rbac_proxy" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "net", "io-util", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/rbac-proxy/src/configuration.rs b/rbac-proxy/src/configuration.rs index 9ae76e60e..dd12db53a 100644 --- a/rbac-proxy/src/configuration.rs +++ b/rbac-proxy/src/configuration.rs @@ -171,6 +171,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } @@ -248,6 +249,7 @@ pub fn bind_catalog_refresh(iii: &Arc, catalog: Arc) { function_id: FUNCTIONS_AVAILABLE_FN_ID.to_string(), config: json!({}), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!("bound catalog-refresh trigger (engine::functions-available)"), Err(e) => { diff --git a/scrapling/pyproject.toml b/scrapling/pyproject.toml index 5f89bb57f..aafb89fcb 100644 --- a/scrapling/pyproject.toml +++ b/scrapling/pyproject.toml @@ -13,7 +13,8 @@ authors = [{ name = "iii" }] license = "Apache-2.0" requires-python = ">=3.11" dependencies = [ - "iii-sdk==0.21.6", + "iii-sdk==0.22.0a3", + "iii-helpers==0.22.0a3", # transitive iii-sdk dep; pinned so uv allows the pre-release "scrapling[fetchers]==0.4.9", "markdownify", # scrapling's HTML→Markdown backend (only in its [shell]/[ai] extras) "pillow", # screenshot downscale/tiling so images fit model input limits diff --git a/scrapling/src/main.py b/scrapling/src/main.py index ff6227a4c..ddc9b1c4f 100644 --- a/scrapling/src/main.py +++ b/scrapling/src/main.py @@ -61,7 +61,15 @@ def main() -> None: idle_timeout=cfg.get("session_idle_timeout_s") or None, ) - iii = register_worker(address=url, options=InitOptions(worker_name="scrapling")) + # namespace: register under III_NAMESPACE when set (the SDK also resolves the + # env; passed explicitly for visibility). Absent -> the engine's default. + iii = register_worker( + address=url, + options=InitOptions( + worker_name="scrapling", + namespace=os.environ.get("III_NAMESPACE"), + ), + ) handlers = create_handlers(load_config, iii=iii) for spec in FUNCTIONS: diff --git a/session-manager/Cargo.lock b/session-manager/Cargo.lock index cde75e50a..c4c445dfb 100644 --- a/session-manager/Cargo.lock +++ b/session-manager/Cargo.lock @@ -914,9 +914,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -935,9 +935,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/session-manager/Cargo.toml b/session-manager/Cargo.toml index 4702d23ee..fc52a9709 100644 --- a/session-manager/Cargo.toml +++ b/session-manager/Cargo.toml @@ -15,10 +15,10 @@ name = "session_manager" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" # `run_with_baggage` for call-site span hiding (`iii.tag.hidden` on the # session-event fan-out — see src/events.rs `IiiDeliverer`). -iii-helpers = "=0.21.6" +iii-helpers = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/session-manager/src/configuration.rs b/session-manager/src/configuration.rs index a3defb874..a51ba4bf0 100644 --- a/session-manager/src/configuration.rs +++ b/session-manager/src/configuration.rs @@ -363,6 +363,7 @@ pub fn register_config_trigger(iii: &IIIClient, state: AppState) -> Result<(), E "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/session-manager/src/events.rs b/session-manager/src/events.rs index d502aaa62..db89dbcd5 100644 --- a/session-manager/src/events.rs +++ b/session-manager/src/events.rs @@ -992,6 +992,7 @@ pub fn attach_bridge_relay(remote: &Arc, local_emitter: Arc) function_id: relay_id.clone(), config: serde_json::json!({}), metadata: None, + namespace: remote.namespace(), }) { Ok(_) => tracing::info!(relay = %relay_id, "attached to the main instance's event feed"), Err(e) => tracing::warn!( @@ -1284,6 +1285,7 @@ mod tests { function_id: "ui::recv".into(), config: json!({}), metadata: None, + namespace: None, }) .unwrap(); @@ -1312,6 +1314,7 @@ mod tests { function_id: "ui::recv".into(), config: json!({ "session_id": "s_1", "roles": ["assistant"] }), metadata: None, + namespace: None, }) .unwrap(); assert_eq!(set.len(), 1); @@ -1321,6 +1324,7 @@ mod tests { function_id: "ui::recv".into(), config: json!({ "bogus": true }), metadata: None, + namespace: None, }); assert!(err.is_err()); assert_eq!(set.len(), 1); diff --git a/session-manager/src/resync.rs b/session-manager/src/resync.rs index c0c50b0fd..2f2ab4590 100644 --- a/session-manager/src/resync.rs +++ b/session-manager/src/resync.rs @@ -200,6 +200,7 @@ mod tests { function_id: "test::recv".to_string(), config: json!({}), metadata: None, + namespace: None, }) .unwrap(); } diff --git a/session-manager/tests/steps/binding_steps.rs b/session-manager/tests/steps/binding_steps.rs index 50f7a338b..8564dea8f 100644 --- a/session-manager/tests/steps/binding_steps.rs +++ b/session-manager/tests/steps/binding_steps.rs @@ -31,6 +31,7 @@ fn add_binding( function_id: function_id.to_string(), config, metadata: None, + namespace: None, }) } diff --git a/session-manager/tests/steps/bridge_steps.rs b/session-manager/tests/steps/bridge_steps.rs index 37d70b556..d3bddaa2e 100644 --- a/session-manager/tests/steps/bridge_steps.rs +++ b/session-manager/tests/steps/bridge_steps.rs @@ -72,6 +72,7 @@ async fn bridge_local_binding( function_id, config, metadata: None, + namespace: None, }) .expect("bridge-local binding config must be valid"); } diff --git a/session-manager/tests/steps/engine_steps.rs b/session-manager/tests/steps/engine_steps.rs index 7aacf66d3..a13d19d27 100644 --- a/session-manager/tests/steps/engine_steps.rs +++ b/session-manager/tests/steps/engine_steps.rs @@ -176,6 +176,7 @@ async fn engine_subscriber( function_id: function_id.clone(), config, metadata: None, + namespace: iii.namespace(), }) .expect("register engine trigger"); // And a beat for the registration to round-trip to our handler. diff --git a/shell/Cargo.lock b/shell/Cargo.lock index e35d05b70..fdb19d74b 100644 --- a/shell/Cargo.lock +++ b/shell/Cargo.lock @@ -893,9 +893,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -914,9 +914,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/shell/Cargo.toml b/shell/Cargo.toml index ec7772ba8..f67228cc0 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -11,8 +11,8 @@ name = "shell" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" +iii-helpers = "=0.22.0-alpha.3" schemars = { version = "0.8", features = ["uuid1"] } libc = "0.2" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "process", "time", "io-util", "fs"] } diff --git a/shell/src/configuration.rs b/shell/src/configuration.rs index d1e12eba1..c25bb9251 100644 --- a/shell/src/configuration.rs +++ b/shell/src/configuration.rs @@ -364,6 +364,7 @@ pub fn register_config_trigger(iii: &IIIClient, state: AppState) -> Result<(), E "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/slack/Cargo.lock b/slack/Cargo.lock index d03da3e72..3776dd224 100644 --- a/slack/Cargo.lock +++ b/slack/Cargo.lock @@ -657,9 +657,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -678,9 +678,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/slack/Cargo.toml b/slack/Cargo.toml index f7f1d0816..bfdcf8428 100644 --- a/slack/Cargo.toml +++ b/slack/Cargo.toml @@ -15,7 +15,7 @@ name = "slack" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/slack/src/clients/approval.rs b/slack/src/clients/approval.rs index 1e861d6af..8647ca5a9 100644 --- a/slack/src/clients/approval.rs +++ b/slack/src/clients/approval.rs @@ -12,7 +12,7 @@ pub async fn resolve( allow: bool, timeout_ms: u64, ) -> Result<(), Error> { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: "approval::resolve".into(), payload: json!({ "session_id": session_id, @@ -21,8 +21,11 @@ pub async fn resolve( }), action: None, timeout_ms: Some(timeout_ms), - }) - .await?; + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; Ok(()) } @@ -32,12 +35,15 @@ pub async fn approve_always( function_id: &str, timeout_ms: u64, ) -> Result<(), Error> { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: "approval::approve-always".into(), payload: json!({ "session_id": session_id, "function_id": function_id }), action: None, timeout_ms: Some(timeout_ms), - }) - .await?; + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; Ok(()) } diff --git a/slack/src/clients/harness.rs b/slack/src/clients/harness.rs index 9ef0ee943..614ce7704 100644 --- a/slack/src/clients/harness.rs +++ b/slack/src/clients/harness.rs @@ -50,25 +50,30 @@ pub async fn send( req: SendRequest, timeout_ms: u64, ) -> Result { - let value = iii - .trigger(TriggerRequest { - function_id: "harness::send".into(), - payload: serde_json::to_value(&req).unwrap_or(Value::Null), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await?; + let request = TriggerRequest { + function_id: "harness::send".into(), + payload: serde_json::to_value(&req).unwrap_or(Value::Null), + action: None, + timeout_ms: Some(timeout_ms), + }; + let value = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; serde_json::from_value(value).map_err(|e| Error::Handler(format!("harness::send: {e}"))) } pub async fn stop(iii: &IIIClient, session_id: &str, timeout_ms: u64) -> Result<(), Error> { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: "harness::stop".into(), payload: json!({ "session_id": session_id }), action: None, timeout_ms: Some(timeout_ms), - }) - .await?; + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; Ok(()) } diff --git a/slack/src/clients/router.rs b/slack/src/clients/router.rs index 0789251e9..970124a81 100644 --- a/slack/src/clients/router.rs +++ b/slack/src/clients/router.rs @@ -21,14 +21,16 @@ struct ModelsListResponse { } pub async fn list_models(iii: &IIIClient, timeout_ms: u64) -> Result, Error> { - let value = iii - .trigger(TriggerRequest { - function_id: "router::models::list".into(), - payload: json!({ "capability": "tools" }), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await?; + let request = TriggerRequest { + function_id: "router::models::list".into(), + payload: json!({ "capability": "tools" }), + action: None, + timeout_ms: Some(timeout_ms), + }; + let value = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; let resp: ModelsListResponse = serde_json::from_value(value) .map_err(|e| Error::Handler(format!("router::models::list: {e}")))?; Ok(resp.models) diff --git a/slack/src/configuration.rs b/slack/src/configuration.rs index 7ba69373d..ec0326f8f 100644 --- a/slack/src/configuration.rs +++ b/slack/src/configuration.rs @@ -132,6 +132,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/slack/src/functions/bindings.rs b/slack/src/functions/bindings.rs index fd1efd539..bac07d1ab 100644 --- a/slack/src/functions/bindings.rs +++ b/slack/src/functions/bindings.rs @@ -219,6 +219,7 @@ fn bind_best_effort( function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!(trigger_type, function_id, "trigger bound"), Err(e) => { diff --git a/slack/src/ingress.rs b/slack/src/ingress.rs index a506f7c7c..bf40ba473 100644 --- a/slack/src/ingress.rs +++ b/slack/src/ingress.rs @@ -112,5 +112,6 @@ fn register_route(iii: &IIIClient, function_id: &str, api_path: &str) -> Result< function_id: function_id.to_string(), config: json!({ "api_path": api_path, "http_method": "POST" }), metadata: None, + namespace: iii.namespace(), }) } diff --git a/state/Cargo.lock b/state/Cargo.lock index 5509e937b..7c19baa71 100644 --- a/state/Cargo.lock +++ b/state/Cargo.lock @@ -752,9 +752,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -773,9 +773,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/state/Cargo.toml b/state/Cargo.toml index f25c875f8..8f37d9d50 100644 --- a/state/Cargo.toml +++ b/state/Cargo.toml @@ -18,10 +18,10 @@ name = "state" path = "src/main.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" # UpdateOp / StreamSetResult / StreamUpdateResult / UpdateOpError / MergePath — # the exact types the builtin used; pinned to the version iii-sdk resolves. -iii-helpers = "=0.21.6" +iii-helpers = "=0.22.0-alpha.3" # Worker-side injectable console UI (content function + console:script/style # triggers + hot-reload watcher) — direct link, never published. iii-console-ui = { path = "../crates/console-ui" } diff --git a/state/src/configuration.rs b/state/src/configuration.rs index a322c33d2..1bcbda4b8 100644 --- a/state/src/configuration.rs +++ b/state/src/configuration.rs @@ -151,6 +151,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/state/src/trigger.rs b/state/src/trigger.rs index 76220c0dc..96dc4ab74 100644 --- a/state/src/trigger.rs +++ b/state/src/trigger.rs @@ -107,6 +107,7 @@ mod tests { function_id: "backend".to_string(), config: cfg, metadata: None, + namespace: None, } } diff --git a/state/tests/e2e_state.rs b/state/tests/e2e_state.rs index 8f66a35a9..b3950206c 100644 --- a/state/tests/e2e_state.rs +++ b/state/tests/e2e_state.rs @@ -377,6 +377,7 @@ async fn state_trigger_fires_with_event_payload() { function_id: "e2e::on_state".to_string(), config: json!({"scope": scope}), metadata: None, + namespace: iii.namespace(), }) .expect("register state trigger"); wait_for_trigger_count(&boot.triggers, 1).await; @@ -488,6 +489,7 @@ async fn condition_false_blocks_null_passes() { function_id: "e2e::backend_false".to_string(), config: json!({"scope": scope, "condition_function_id": "e2e::cond_false"}), metadata: None, + namespace: iii.namespace(), }) .expect("register false-condition trigger"); iii.register_trigger(RegisterTriggerInput { @@ -495,6 +497,7 @@ async fn condition_false_blocks_null_passes() { function_id: "e2e::backend_null".to_string(), config: json!({"scope": scope, "condition_function_id": "e2e::cond_null"}), metadata: None, + namespace: iii.namespace(), }) .expect("register null-condition trigger"); wait_for_trigger_count(&boot.triggers, 2).await; @@ -555,6 +558,7 @@ async fn max_value_bytes_rejects_oversized_set() { function_id: "e2e::on_state_cfg".to_string(), config: json!({"scope": scope}), metadata: None, + namespace: iii.namespace(), }) .expect("register state trigger"); wait_for_trigger_count(&boot.triggers, 1).await; diff --git a/storage/Cargo.lock b/storage/Cargo.lock index 9b4afca82..83e660058 100644 --- a/storage/Cargo.lock +++ b/storage/Cargo.lock @@ -1922,9 +1922,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -1943,9 +1943,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/storage/Cargo.toml b/storage/Cargo.toml index 4a9d15655..fbd9355a1 100644 --- a/storage/Cargo.toml +++ b/storage/Cargo.toml @@ -14,7 +14,7 @@ path = "src/main.rs" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time", "process", "io-util", "net"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/storage/src/configuration.rs b/storage/src/configuration.rs index 7335cf124..9e8d2d7fb 100644 --- a/storage/src/configuration.rs +++ b/storage/src/configuration.rs @@ -168,6 +168,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/telegram-bot/Cargo.lock b/telegram-bot/Cargo.lock index c28cfdbce..4380aa29b 100644 --- a/telegram-bot/Cargo.lock +++ b/telegram-bot/Cargo.lock @@ -679,9 +679,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/telegram-bot/Cargo.toml b/telegram-bot/Cargo.toml index 1e2dcc776..02438db8b 100644 --- a/telegram-bot/Cargo.toml +++ b/telegram-bot/Cargo.toml @@ -15,8 +15,8 @@ name = "telegram_bot" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" +iii-helpers = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/telegram-bot/src/approval_gate.rs b/telegram-bot/src/approval_gate.rs index 143b01c89..5567b4eb3 100644 --- a/telegram-bot/src/approval_gate.rs +++ b/telegram-bot/src/approval_gate.rs @@ -123,6 +123,7 @@ pub fn start_watch( "stages": ["done"] }), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => { tracing::info!("subscribed to worker trigger for approval-gate presence"); diff --git a/telegram-bot/src/clients/approval.rs b/telegram-bot/src/clients/approval.rs index 74927bb3d..b4623bfac 100644 --- a/telegram-bot/src/clients/approval.rs +++ b/telegram-bot/src/clients/approval.rs @@ -43,14 +43,16 @@ pub async fn resolve( req: ResolveRequest, timeout_ms: u64, ) -> Result { - let value = iii - .trigger(TriggerRequest { - function_id: "approval::resolve".into(), - payload: serde_json::to_value(&req).unwrap_or(json!({})), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await?; + let request = TriggerRequest { + function_id: "approval::resolve".into(), + payload: serde_json::to_value(&req).unwrap_or(json!({})), + action: None, + timeout_ms: Some(timeout_ms), + }; + let value = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; serde_json::from_value(value).map_err(|e| Error::Handler(format!("approval::resolve: {e}"))) } @@ -60,7 +62,7 @@ pub async fn approve_always( function_id: &str, timeout_ms: u64, ) -> Result<(), Error> { - iii.trigger(TriggerRequest { + let request = TriggerRequest { function_id: "approval::approve-always".into(), payload: json!({ "session_id": session_id, @@ -68,8 +70,11 @@ pub async fn approve_always( }), action: None, timeout_ms: Some(timeout_ms), - }) - .await?; + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; Ok(()) } @@ -78,14 +83,16 @@ pub async fn list_pending( session_id: &str, timeout_ms: u64, ) -> Result, Error> { - let value = iii - .trigger(TriggerRequest { - function_id: "approval::list-pending".into(), - payload: json!({ "session_id": session_id }), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await?; + let request = TriggerRequest { + function_id: "approval::list-pending".into(), + payload: json!({ "session_id": session_id }), + action: None, + timeout_ms: Some(timeout_ms), + }; + let value = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; let resp: ListPendingResponse = serde_json::from_value(value) .map_err(|e| Error::Handler(format!("approval::list-pending: {e}")))?; Ok(resp.pending) diff --git a/telegram-bot/src/clients/harness.rs b/telegram-bot/src/clients/harness.rs index 65e7432f3..151094341 100644 --- a/telegram-bot/src/clients/harness.rs +++ b/telegram-bot/src/clients/harness.rs @@ -100,14 +100,16 @@ pub async fn send( req: HarnessSendRequest, timeout_ms: u64, ) -> Result { - let value = iii - .trigger(TriggerRequest { - function_id: "harness::send".into(), - payload: serde_json::to_value(&req).unwrap_or(Value::Null), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await?; + let request = TriggerRequest { + function_id: "harness::send".into(), + payload: serde_json::to_value(&req).unwrap_or(Value::Null), + action: None, + timeout_ms: Some(timeout_ms), + }; + let value = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; serde_json::from_value(value).map_err(|e| Error::Handler(format!("harness::send: {e}"))) } @@ -116,14 +118,16 @@ pub async fn stop( session_id: &str, timeout_ms: u64, ) -> Result { - let value = iii - .trigger(TriggerRequest { - function_id: "harness::stop".into(), - payload: json!({ "session_id": session_id }), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await?; + let request = TriggerRequest { + function_id: "harness::stop".into(), + payload: json!({ "session_id": session_id }), + action: None, + timeout_ms: Some(timeout_ms), + }; + let value = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; serde_json::from_value(value).map_err(|e| Error::Handler(format!("harness::stop: {e}"))) } @@ -132,14 +136,16 @@ pub async fn status_active( session_id: &str, timeout_ms: u64, ) -> Result { - let v = iii - .trigger(TriggerRequest { - function_id: "harness::status".into(), - payload: json!({ "session_id": session_id }), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await?; + let request = TriggerRequest { + function_id: "harness::status".into(), + payload: json!({ "session_id": session_id }), + action: None, + timeout_ms: Some(timeout_ms), + }; + let v = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; Ok(!v.is_null()) } diff --git a/telegram-bot/src/clients/router.rs b/telegram-bot/src/clients/router.rs index 855627626..db7bb06e7 100644 --- a/telegram-bot/src/clients/router.rs +++ b/telegram-bot/src/clients/router.rs @@ -27,14 +27,16 @@ pub struct ModelsListResponse { } pub async fn list_models(iii: &IIIClient, timeout_ms: u64) -> Result, Error> { - let value = iii - .trigger(TriggerRequest { - function_id: "router::models::list".into(), - payload: json!({ "capability": "tools" }), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await?; + let request = TriggerRequest { + function_id: "router::models::list".into(), + payload: json!({ "capability": "tools" }), + action: None, + timeout_ms: Some(timeout_ms), + }; + let value = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await?, + None => iii.trigger(request).await?, + }; let resp: ModelsListResponse = serde_json::from_value(value) .map_err(|e| Error::Handler(format!("router::models::list: {e}")))?; Ok(resp.models) diff --git a/telegram-bot/src/configuration.rs b/telegram-bot/src/configuration.rs index 16eb60dfe..65f56602d 100644 --- a/telegram-bot/src/configuration.rs +++ b/telegram-bot/src/configuration.rs @@ -137,6 +137,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/telegram-bot/src/functions/mod.rs b/telegram-bot/src/functions/mod.rs index d746d9984..88c02b1f3 100644 --- a/telegram-bot/src/functions/mod.rs +++ b/telegram-bot/src/functions/mod.rs @@ -113,6 +113,7 @@ pub fn bind_http_triggers(iii: &Arc) { function_id: function_id.to_string(), config: json!({ "api_path": api_path, "http_method": http_method }), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!(function_id, api_path, "http trigger registered"), Err(e) => tracing::warn!(error = %e, function_id, "failed to register http trigger"), @@ -130,6 +131,7 @@ pub fn register_webhook_trigger(iii: &IIIClient) -> Result { function_id: WEBHOOK_ID.to_string(), config: json!({ "api_path": crate::config::WEBHOOK_API_PATH, "http_method": "POST" }), metadata: None, + namespace: iii.namespace(), }) } @@ -144,6 +146,7 @@ fn bind_best_effort( function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!(trigger_type, function_id, "trigger binding requested"), Err(e) => tracing::warn!( diff --git a/web/Cargo.lock b/web/Cargo.lock index d210687ac..31ad66cbc 100644 --- a/web/Cargo.lock +++ b/web/Cargo.lock @@ -758,9 +758,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -779,9 +779,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/web/Cargo.toml b/web/Cargo.toml index e1e0861bb..460baf8a0 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -15,7 +15,7 @@ name = "web" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" arc-swap = "1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time", "net"] } serde = { version = "1", features = ["derive"] } diff --git a/web/src/configuration.rs b/web/src/configuration.rs index 338d7d811..7414df1e5 100644 --- a/web/src/configuration.rs +++ b/web/src/configuration.rs @@ -32,6 +32,7 @@ fn bind(iii: &IIIClient, trigger_type: &str, function_id: &str, config: Value) - function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }) { Ok(handle) => { tracing::info!(trigger_type, function_id, "trigger binding requested"); @@ -138,6 +139,7 @@ pub fn register_config_trigger(iii: &IIIClient, state: SharedState) -> Result<() function_id: CONFIG_FN_ID.to_string(), config: json!({ "configuration_id": CONFIG_ID, "event_types": ["configuration:updated"] }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/workflow/Cargo.lock b/workflow/Cargo.lock index afb980d1b..5d9599abb 100644 --- a/workflow/Cargo.lock +++ b/workflow/Cargo.lock @@ -621,9 +621,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -642,9 +642,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/workflow/Cargo.toml b/workflow/Cargo.toml index 6b854bd00..22311acf5 100644 --- a/workflow/Cargo.toml +++ b/workflow/Cargo.toml @@ -15,8 +15,8 @@ name = "workflow" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" -iii-helpers = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" +iii-helpers = "=0.22.0-alpha.3" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/workflow/src/configuration.rs b/workflow/src/configuration.rs index f34ee28ae..9877d9833 100644 --- a/workflow/src/configuration.rs +++ b/workflow/src/configuration.rs @@ -96,6 +96,7 @@ fn bind(iii: &IIIClient, trigger_type: &str, function_id: &str, config: Value) - function_id: function_id.to_string(), config, metadata: None, + namespace: iii.namespace(), }) { Ok(handle) => { tracing::info!(trigger_type, function_id, "trigger binding requested"); @@ -242,6 +243,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/workflow/src/events.rs b/workflow/src/events.rs index 327f2b816..c080403a2 100644 --- a/workflow/src/events.rs +++ b/workflow/src/events.rs @@ -16,15 +16,16 @@ pub async fn emit_run_completed( deps: &crate::functions::Deps, record: &crate::types::WorkflowRunRecord, ) { - let _ = deps - .iii - .trigger(iii_sdk::protocol::TriggerRequest { - function_id: "workflow::run-completed".into(), - payload: completed_payload(record), - action: Some(iii_sdk::TriggerAction::Void), - timeout_ms: None, - }) - .await; // best-effort fire-and-forget + let request = iii_sdk::protocol::TriggerRequest { + function_id: "workflow::run-completed".into(), + payload: completed_payload(record), + action: Some(iii_sdk::TriggerAction::Void), + timeout_ms: None, + }; + let _ = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + }; // best-effort fire-and-forget } /// Fire the caller-supplied completion callback, if the run carries one. The @@ -46,15 +47,36 @@ pub async fn emit_notify(deps: &crate::functions::Deps, record: &crate::types::W .queue .clone() .unwrap_or_else(|| "default".to_string()); - let _ = deps - .iii - .trigger(iii_sdk::protocol::TriggerRequest { - function_id: notify.function_id.clone(), - payload: completed_payload(record), - action: Some(iii_sdk::TriggerAction::Enqueue { queue }), - timeout_ms: None, - }) - .await; // best-effort; durable retry is the queue's job + let request = iii_sdk::protocol::TriggerRequest { + function_id: notify.function_id.clone(), + payload: completed_payload(record), + action: Some(iii_sdk::TriggerAction::Enqueue { queue }), + timeout_ms: None, + }; + let route_ns = deps.iii.namespace().filter(|_| { + !matches!( + notify.function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let _ = match route_ns { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + }; // best-effort; durable retry is the queue's job } /// Build the `harness::send` payload that posts the run outcome into the @@ -132,15 +154,16 @@ pub async fn emit_reply(deps: &crate::functions::Deps, record: &crate::types::Wo if payload.is_null() { return; } - let _ = deps - .iii - .trigger(iii_sdk::protocol::TriggerRequest { - function_id: "harness::send".into(), - payload, - action: None, - timeout_ms: None, - }) - .await; // best-effort; deterministic idempotency_key makes re-fire safe + let request = iii_sdk::protocol::TriggerRequest { + function_id: "harness::send".into(), + payload, + action: None, + timeout_ms: None, + }; + let _ = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + }; // best-effort; deterministic idempotency_key makes re-fire safe } #[cfg(test)] diff --git a/workflow/src/functions/mod.rs b/workflow/src/functions/mod.rs index 4076d2172..0b70a2b82 100644 --- a/workflow/src/functions/mod.rs +++ b/workflow/src/functions/mod.rs @@ -41,15 +41,16 @@ impl Deps { /// `harness::stop` is a no-op for a session with no live turn, so this is safe to /// call on an already-finished session. pub(crate) async fn harness_stop_session(deps: &Deps, session_id: &str, dispatch_timeout_ms: u64) { - let _ = deps - .iii - .trigger(iii_sdk::protocol::TriggerRequest { - function_id: "harness::stop".into(), - payload: serde_json::json!({ "session_id": session_id }), - action: None, - timeout_ms: Some(dispatch_timeout_ms), - }) - .await; + let request = iii_sdk::protocol::TriggerRequest { + function_id: "harness::stop".into(), + payload: serde_json::json!({ "session_id": session_id }), + action: None, + timeout_ms: Some(dispatch_timeout_ms), + }; + let _ = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + }; } /// Stop the live session of every node still `Running`. Workflow nodes are diff --git a/workflow/src/functions/start.rs b/workflow/src/functions/start.rs index 1de496915..c903baa4a 100644 --- a/workflow/src/functions/start.rs +++ b/workflow/src/functions/start.rs @@ -761,16 +761,17 @@ pub fn unknown_models(def: &WorkflowDef, registered: &BTreeSet<(String, String)> /// `result_error` remains the backstop. async fn fetch_registered_models(deps: &Deps) -> Option> { let timeout_ms = deps.cfg().await.dispatch_timeout_ms; - let resp = deps - .iii - .trigger(iii_sdk::protocol::TriggerRequest { - function_id: "router::models::list".into(), - payload: json!({}), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await - .ok()?; + let request = iii_sdk::protocol::TriggerRequest { + function_id: "router::models::list".into(), + payload: json!({}), + action: None, + timeout_ms: Some(timeout_ms), + }; + let resp = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + } + .ok()?; let set: BTreeSet<(String, String)> = resp .get("models")? @@ -823,15 +824,18 @@ pub async fn enqueue_tick( run_id: &str, step: u64, ) -> Result<(), WorkflowError> { - iii.trigger(iii_sdk::protocol::TriggerRequest { + let request = iii_sdk::protocol::TriggerRequest { function_id: "workflow::tick".into(), payload: json!({"run_id": run_id, "step": step}), action: Some(iii_sdk::TriggerAction::Enqueue { queue: "default".into(), }), timeout_ms: None, - }) - .await + }; + match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + } .map_err(|e| WorkflowError::Trigger(e.to_string()))?; Ok(()) } diff --git a/workflow/src/functions/tick.rs b/workflow/src/functions/tick.rs index 50b3d4bba..6a124a45c 100644 --- a/workflow/src/functions/tick.rs +++ b/workflow/src/functions/tick.rs @@ -246,16 +246,17 @@ pub(crate) async fn fire_node( } send_payload["session"] = session_init; - let resp = deps - .iii - .trigger(iii_sdk::protocol::TriggerRequest { - function_id: "harness::send".into(), - payload: send_payload, - action: None, - timeout_ms: Some(dispatch_timeout_ms), - }) - .await - .map_err(|e| WorkflowError::Trigger(e.to_string()))?; + let request = iii_sdk::protocol::TriggerRequest { + function_id: "harness::send".into(), + payload: send_payload, + action: None, + timeout_ms: Some(dispatch_timeout_ms), + }; + let resp = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + } + .map_err(|e| WorkflowError::Trigger(e.to_string()))?; let turn_id = resp .get("turn_id") diff --git a/workflow/src/reconcile.rs b/workflow/src/reconcile.rs index ee56836f1..04833f584 100644 --- a/workflow/src/reconcile.rs +++ b/workflow/src/reconcile.rs @@ -107,16 +107,17 @@ pub async fn reconcile_run( // abort reconciliation of the rest of the run (which previously bubbled up, // failed the whole tick, and dead-lettered). Log and move on — the node // stays Running and is re-polled next tick; the timeout sweep is the backstop. - let resp = match deps - .iii - .trigger(iii_sdk::protocol::TriggerRequest { - function_id: "harness::status".into(), - payload: json!({ "session_id": session_id }), - action: None, - timeout_ms: Some(timeout_ms), - }) - .await - { + let request = iii_sdk::protocol::TriggerRequest { + function_id: "harness::status".into(), + payload: json!({ "session_id": session_id }), + action: None, + timeout_ms: Some(timeout_ms), + }; + let result = match deps.iii.namespace() { + Some(ns) => deps.iii.trigger(request.namespace(ns)).await, + None => deps.iii.trigger(request).await, + }; + let resp = match result { Ok(resp) => resp, Err(e) => { tracing::warn!( diff --git a/worktree/Cargo.lock b/worktree/Cargo.lock index 33d9414aa..326397e92 100644 --- a/worktree/Cargo.lock +++ b/worktree/Cargo.lock @@ -683,9 +683,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.21.6" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "d990b866c3ef708290e1160f5640721130a8ebc28afa65b387551ee358f0a616" dependencies = [ "futures-util", "opentelemetry", @@ -704,9 +704,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.21.6" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", @@ -776,9 +776,9 @@ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libredox" -version = "0.1.18" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ "libc", ] diff --git a/worktree/Cargo.toml b/worktree/Cargo.toml index 51086362c..5c1a90cba 100644 --- a/worktree/Cargo.toml +++ b/worktree/Cargo.toml @@ -15,7 +15,7 @@ name = "worktree" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.21.6" +iii-sdk = "=0.22.0-alpha.3" # Worker-side injectable console UI (content function + console:script/style # triggers + hot-reload watcher) — direct path link, never published. iii-console-ui = { path = "../crates/console-ui" } diff --git a/worktree/src/configuration.rs b/worktree/src/configuration.rs index 29b836589..2ae4ceeb0 100644 --- a/worktree/src/configuration.rs +++ b/worktree/src/configuration.rs @@ -105,6 +105,7 @@ impl CronSlot { function_id: "worktree::prune".to_string(), config: json!({ "expression": schedule }), metadata: None, + namespace: iii.namespace(), }) { Ok(trigger) => { tracing::info!(schedule, "prune cron binding registered"); @@ -180,6 +181,7 @@ pub fn register_config_trigger( "event_types": ["configuration:updated"], }), metadata: None, + namespace: iii.namespace(), })?; Ok(()) } diff --git a/worktree/src/events.rs b/worktree/src/events.rs index e9ce44304..32ffe64ce 100644 --- a/worktree/src/events.rs +++ b/worktree/src/events.rs @@ -367,14 +367,36 @@ impl EventDeliverer for IiiDeliverer { let trigger_type = trigger_type.to_string(); let function_id = function_id.to_string(); tokio::spawn(async move { - let res = iii - .trigger(TriggerRequest { - function_id: function_id.clone(), - payload, - action: Some(TriggerAction::Void), - timeout_ms: None, - }) - .await; + let request = TriggerRequest { + function_id: function_id.clone(), + payload, + action: Some(TriggerAction::Void), + timeout_ms: None, + }; + let route_ns = iii.namespace().filter(|_| { + !matches!( + function_id.split("::").next(), + Some( + "state" + | "stream" + | "queue" + | "pubsub" + | "configuration" + | "cron" + | "http" + | "engine" + | "sandbox" + | "log" + | "secret" + | "kv" + | "iii" + ) + ) + }); + let res = match route_ns { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + }; if let Err(e) = res { tracing::warn!(trigger_type, function_id, error = %e, "event fan-out failed"); } @@ -470,6 +492,7 @@ mod tests { function_id: "ui::recv".into(), config: json!({ "sesion_id": "typo" }), metadata: None, + namespace: None, }) .unwrap_err(); assert!(err.contains("invalid worktree::created config")); @@ -484,6 +507,7 @@ mod tests { function_id: "ui::recv".into(), config: Value::Null, metadata: None, + namespace: None, }) .unwrap(); set.add(TriggerConfig { @@ -491,6 +515,7 @@ mod tests { function_id: "ui::recv".into(), config: json!({}), metadata: None, + namespace: None, }) .unwrap(); assert_eq!(set.snapshot().len(), 2); @@ -522,6 +547,7 @@ mod tests { function_id: "recv::all".into(), config: json!({}), metadata: None, + namespace: None, }) .unwrap(); sets.for_kind(EventKind::Landed) @@ -530,6 +556,7 @@ mod tests { function_id: "recv::other".into(), config: json!({ "repo_path": "/other" }), metadata: None, + namespace: None, }) .unwrap(); let deliverer = Arc::new(RecordingDeliverer { diff --git a/worktree/src/land/mod.rs b/worktree/src/land/mod.rs index 2b663b26f..eeb55eced 100644 --- a/worktree/src/land/mod.rs +++ b/worktree/src/land/mod.rs @@ -54,18 +54,20 @@ impl IiiEnqueuer { #[async_trait] impl Enqueuer for IiiEnqueuer { async fn enqueue(&self, queue: &str, function_id: &str, payload: Value) -> Result<(), WError> { - self.iii - .trigger(TriggerRequest { - function_id: function_id.to_string(), - payload, - action: Some(TriggerAction::Enqueue { - queue: queue.to_string(), - }), - timeout_ms: None, - }) - .await - .map(|_| ()) - .map_err(|e| WError::new(codes::ENQUEUE_FAILED, format!("enqueue to {queue:?}: {e}"))) + let request = TriggerRequest { + function_id: function_id.to_string(), + payload, + action: Some(TriggerAction::Enqueue { + queue: queue.to_string(), + }), + timeout_ms: None, + }; + match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + } + .map(|_| ()) + .map_err(|e| WError::new(codes::ENQUEUE_FAILED, format!("enqueue to {queue:?}: {e}"))) } } diff --git a/worktree/src/land/test_gate.rs b/worktree/src/land/test_gate.rs index 5f089bcab..3a6393ffe 100644 --- a/worktree/src/land/test_gate.rs +++ b/worktree/src/land/test_gate.rs @@ -55,20 +55,21 @@ impl TestRunner for ShellExecRunner { worktree_path: &str, timeout_ms: u64, ) -> Result { - let result = self - .iii - .trigger(TriggerRequest { - function_id: "shell::exec".into(), - payload: json!({ - "command": cmd, - "cwd": worktree_path, - "fs_scope": { "root": worktree_path, "grants": [] }, - "timeout_ms": timeout_ms, - }), - action: None, - timeout_ms: Some(timeout_ms.saturating_add(TRIGGER_MARGIN_MS)), - }) - .await; + let request = TriggerRequest { + function_id: "shell::exec".into(), + payload: json!({ + "command": cmd, + "cwd": worktree_path, + "fs_scope": { "root": worktree_path, "grants": [] }, + "timeout_ms": timeout_ms, + }), + action: None, + timeout_ms: Some(timeout_ms.saturating_add(TRIGGER_MARGIN_MS)), + }; + let result = match self.iii.namespace() { + Some(ns) => self.iii.trigger(request.namespace(ns)).await, + None => self.iii.trigger(request).await, + }; match result { Ok(v) => { let timed_out = v["timed_out"].as_bool().unwrap_or(false); diff --git a/worktree/src/main.rs b/worktree/src/main.rs index 05d6b6548..a885e15ae 100644 --- a/worktree/src/main.rs +++ b/worktree/src/main.rs @@ -153,6 +153,7 @@ async fn main() -> Result<()> { function_id: function_id.to_string(), config: serde_json::json!({ "api_path": api_path, "http_method": "POST" }), metadata: None, + namespace: iii.namespace(), }) { Ok(_) => tracing::info!(function_id, api_path, "http trigger registered"), Err(e) => { diff --git a/worktree/tests/support/mod.rs b/worktree/tests/support/mod.rs index 8d065439d..41481601c 100644 --- a/worktree/tests/support/mod.rs +++ b/worktree/tests/support/mod.rs @@ -241,6 +241,7 @@ pub fn recording_emitter() -> (Arc, Arc) { function_id: "test::recv".into(), config: json!({}), metadata: None, + namespace: None, }) .unwrap(); }