From 1116bf9ea84d24746c1bd352310dc144445961b5 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 19:46:43 -0300 Subject: [PATCH 01/75] feat(image-resize): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to the 0.22.0-alpha.2 namespace release and adopt namespace registration: a --namespace flag (III_NAMESPACE env fallback) is threaded into InitOptions so the worker can register under a namespace. Absent, it keeps the engine's default namespace, so existing deploys are unchanged. Verified at runtime: the worker connects and image_resize::resize resolves in the declared namespace via engine::functions::list. --- image-resize/Cargo.lock | 8 ++++---- image-resize/Cargo.toml | 2 +- image-resize/src/main.rs | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/image-resize/Cargo.lock b/image-resize/Cargo.lock index 27add8049..7b78b40cf 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/image-resize/Cargo.toml b/image-resize/Cargo.toml index 064699189..2b69898ca 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.2" 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); From d68bd3f62f8d806907d01951fa1268c24fe66f43 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 19:49:02 -0300 Subject: [PATCH 02/75] feat(claude-code): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to the 0.22.0-alpha.2 namespace release and pass III_NAMESPACE through registerWorker so claude::* register under a namespace when one is set (the SDK also resolves the env; passed explicitly for visibility). Absent, the engine's default namespace is used. Verified at runtime: all six claude::* functions resolve in the declared namespace via engine::functions::list. --- claude-code/package.json | 2 +- claude-code/pnpm-lock.yaml | 18 +++++++++--------- claude-code/src/index.ts | 8 +++++++- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/claude-code/package.json b/claude-code/package.json index 02ccad33d..b7d251b8a 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.2", "yaml": "^2.6.0", "zod": "^4.0.0" }, diff --git a/claude-code/pnpm-lock.yaml b/claude-code/pnpm-lock.yaml index 29c788680..71f011094 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.2 + version: 0.22.0-alpha.2 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.2': + resolution: {integrity: sha512-NhmwybfpPmjlL4yKNxAVevkWIzu4SIhHFPh1bCMKEpy5oLTCSx/oHHF2ruUhQEyKwB79LqrrJ21SM93klujZJg==} '@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.2: + resolution: {integrity: sha512-mdILi3R+MeTXpEmUPmqMyjGY35DWddia+7DoIDaXXm/xop4gAeSARqqpZggzcAzSMQek0XACTKKKypUm4uA8PA==} 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.2': 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.2: dependencies: - '@iii-dev/helpers': 0.21.6 + '@iii-dev/helpers': 0.22.0-alpha.2 '@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. From 5697a57b75727e6af3a0cb643cd94efed7a93728 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 19:50:47 -0300 Subject: [PATCH 03/75] feat(hermes): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk and iii-helpers to the 0.22.0a2 namespace release and pass III_NAMESPACE through InitOptions so hermes::* register under a namespace when one is set (the SDK also resolves the env; passed explicitly for visibility). Absent, the engine's default namespace is used. Verified at runtime: all seven hermes::* functions resolve in the declared namespace via engine::functions::list. --- hermes/pyproject.toml | 4 ++-- hermes/src/main.py | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/hermes/pyproject.toml b/hermes/pyproject.toml index efe921d5f..e1e679239 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.0a2", + "iii-helpers==0.22.0a2", "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") From 892ab138b2905a30723a9ae0efaeb7c7bdba7bf2 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:08:24 -0300 Subject: [PATCH 04/75] feat(acp): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to the 0.22.0-alpha.2 namespace release. The SDK made RegisterTriggerInput.namespace required; pass iii.namespace() so the ACP event subscriber resolves its target in the worker's namespace (None => engine default, unchanged). Namespace itself is env-driven (III_NAMESPACE) via the SDK. Build-verified; runtime registration is driven by an ACP stdio client, so the functions::list smoke does not apply to this worker. --- acp/Cargo.lock | 8 ++++---- acp/Cargo.toml | 2 +- acp/src/handler.rs | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/acp/Cargo.lock b/acp/Cargo.lock index 08e3424d3..5f506431a 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/acp/Cargo.toml b/acp/Cargo.toml index b38ee9a4e..ec8f3858e 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.2" 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) => { From a5aba7231abca706e947e012b59c3b067b390a94 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:10:18 -0300 Subject: [PATCH 05/75] feat(opencode): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2 and pass III_NAMESPACE through registerWorker so opencode::* register under a namespace when one is set (SDK also resolves the env). Absent, the engine's default namespace is used. Smoke-verified: all seven opencode::* functions resolve in the declared namespace. --- opencode/package.json | 2 +- opencode/pnpm-lock.yaml | 18 +++++++++--------- opencode/src/index.ts | 7 ++++++- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/opencode/package.json b/opencode/package.json index 6c225ab73..0e2341e2f 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.2", "yaml": "^2.6.0", "zod": "^4.0.0" }, diff --git a/opencode/pnpm-lock.yaml b/opencode/pnpm-lock.yaml index 580ee5b98..15f92adfb 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.2 + version: 0.22.0-alpha.2 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.2': + resolution: {integrity: sha512-NhmwybfpPmjlL4yKNxAVevkWIzu4SIhHFPh1bCMKEpy5oLTCSx/oHHF2ruUhQEyKwB79LqrrJ21SM93klujZJg==} '@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.2: + resolution: {integrity: sha512-mdILi3R+MeTXpEmUPmqMyjGY35DWddia+7DoIDaXXm/xop4gAeSARqqpZggzcAzSMQek0XACTKKKypUm4uA8PA==} 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.2': 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.2: dependencies: - '@iii-dev/helpers': 0.21.6 + '@iii-dev/helpers': 0.22.0-alpha.2 '@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); From 4e65a74fd9dbf35ab78976fa12b7f9b2c1b8502e Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:10:38 -0300 Subject: [PATCH 06/75] feat(pi): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2 and pass III_NAMESPACE through registerWorker so pi::* register under a namespace when one is set (SDK also resolves the env). Absent, the engine's default namespace is used. Smoke-verified: all nine pi::* functions resolve in the declared namespace. --- pi/package.json | 2 +- pi/pnpm-lock.yaml | 18 +++++++++--------- pi/src/index.ts | 7 ++++++- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/pi/package.json b/pi/package.json index 689c01195..5e913dc5e 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.2", "yaml": "^2.6.0", "zod": "^4.0.0" }, diff --git a/pi/pnpm-lock.yaml b/pi/pnpm-lock.yaml index 067568fb6..38d64802a 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.2 + version: 0.22.0-alpha.2 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.2': + resolution: {integrity: sha512-NhmwybfpPmjlL4yKNxAVevkWIzu4SIhHFPh1bCMKEpy5oLTCSx/oHHF2ruUhQEyKwB79LqrrJ21SM93klujZJg==} '@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.2: + resolution: {integrity: sha512-mdILi3R+MeTXpEmUPmqMyjGY35DWddia+7DoIDaXXm/xop4gAeSARqqpZggzcAzSMQek0XACTKKKypUm4uA8PA==} 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.2': 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.2: dependencies: - '@iii-dev/helpers': 0.21.6 + '@iii-dev/helpers': 0.22.0-alpha.2 '@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. From d5a21dfc8875c693dc61e062939a74da0d63c989 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:12:13 -0300 Subject: [PATCH 07/75] feat(scrapling): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0a2 and pass III_NAMESPACE through InitOptions so scrapling::* register under a namespace when one is set (SDK also resolves the env). Pin iii-helpers==0.22.0a2 (transitive iii-sdk dep) so uv resolves the pre-release. Absent a namespace, the engine's default is used. Smoke-verified: all 19 scrapling::* functions resolve in the declared namespace. --- scrapling/pyproject.toml | 3 ++- scrapling/src/main.py | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/scrapling/pyproject.toml b/scrapling/pyproject.toml index 5f89bb57f..cf42504a2 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.0a2", + "iii-helpers==0.22.0a2", # 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: From 46c103655f8fa56845882781a9963627e4d8526c Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:58 -0300 Subject: [PATCH 08/75] feat(approval-gate): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- approval-gate/Cargo.lock | 8 ++++---- approval-gate/Cargo.toml | 2 +- approval-gate/src/configuration.rs | 3 +++ approval-gate/src/main.rs | 1 + approval-gate/src/testkit/engine.rs | 2 ++ 5 files changed, 11 insertions(+), 5 deletions(-) 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/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/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"); From 4a51ec2ae4f17eacbebf99f6cc60cc53c6fa2d49 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 09/75] feat(bridge): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Smoke-verified: functions register in the declared namespace. --- bridge/Cargo.lock | 8 ++++---- bridge/Cargo.toml | 2 +- bridge/src/boot.rs | 40 ++++++++++++++++--------------------- bridge/src/configuration.rs | 1 + 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/bridge/Cargo.lock b/bridge/Cargo.lock index 323a1b714..20be21e57 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/bridge/Cargo.toml b/bridge/Cargo.toml index 62f434836..20767028b 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.2" 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(()) } From 40c29943efedaaa49f7855fcfaa5d0cb317dca32 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 10/75] feat(browser): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- browser/Cargo.lock | 8 ++++---- browser/Cargo.toml | 2 +- browser/src/configuration.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/browser/Cargo.lock b/browser/Cargo.lock index a7b6eae4e..f3511a08f 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/browser/Cargo.toml b/browser/Cargo.toml index a8818f6cd..18b1849e2 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.2" 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(()) } From 122904853db4ab2ba8d1e1001c34512ee6dda983 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 11/75] feat(codex): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- codex/Cargo.lock | 8 ++++---- codex/Cargo.toml | 4 ++-- codex/src/configuration.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/codex/Cargo.lock b/codex/Cargo.lock index 9b00e2047..e425bd6ee 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -693,9 +693,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/codex/Cargo.toml b/codex/Cargo.toml index 52298ac37..078999feb 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.2" +iii-helpers = "=0.22.0-alpha.2" 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(()) } From eb43c91ea8ea74e14555c5b17785039d86bac90f Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 12/75] feat(context-manager): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- context-manager/Cargo.lock | 8 ++++---- context-manager/Cargo.toml | 2 +- context-manager/src/adapters/cache.rs | 1 + context-manager/src/configuration.rs | 1 + 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/context-manager/Cargo.lock b/context-manager/Cargo.lock index 6c0102cf2..9fc377643 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/context-manager/Cargo.toml b/context-manager/Cargo.toml index 1d1903e8a..f7afcbacf 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.2" 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 Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 13/75] feat(cron): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- cron/Cargo.lock | 8 ++++---- cron/Cargo.toml | 2 +- cron/src/configuration.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cron/Cargo.lock b/cron/Cargo.lock index cc763a9a5..7b74fc57d 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/cron/Cargo.toml b/cron/Cargo.toml index c1836a647..93b3bee41 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.2" 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(()) } From eb68ebaea39b31b767fd095fea60fdd2919e81e4 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 14/75] feat(database): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- database/Cargo.lock | 8 ++++---- database/Cargo.toml | 4 ++-- database/src/configuration.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) 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(()) } From d5975466ffe402ae531dd4de998ee4ed5af9c5f1 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 15/75] feat(devin): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- devin/Cargo.lock | 8 ++++---- devin/Cargo.toml | 4 ++-- devin/src/configuration.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/devin/Cargo.lock b/devin/Cargo.lock index 1498bb769..86d155c62 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -691,9 +691,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/devin/Cargo.toml b/devin/Cargo.toml index 80b170b20..f965e5fc3 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.2" +iii-helpers = "=0.22.0-alpha.2" 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(()) } From 5cc7eee31483c8f9b8c42df12c0dc06da74067a0 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 16/75] feat(fp): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- fp/Cargo.lock | 8 ++++---- fp/Cargo.toml | 2 +- fp/src/guidance.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fp/Cargo.lock b/fp/Cargo.lock index d4720fd34..3a6b1a68b 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/fp/Cargo.toml b/fp/Cargo.toml index ddf419b77..88072f604 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.2" # 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"); From df2ce7bc402d485132f15d5fac27a99bd44437ed Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 17/75] feat(github): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- github/Cargo.lock | 8 ++++---- github/Cargo.toml | 2 +- github/src/configuration.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/github/Cargo.lock b/github/Cargo.lock index 73c8535ae..3cad7f5f0 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/github/Cargo.toml b/github/Cargo.toml index ccc22797d..a16f84d84 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.2" 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(()) } From 76ecd202e536d1f70bae44c5037e71283a18327f Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 18/75] feat(grok): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- grok/Cargo.lock | 8 ++++---- grok/Cargo.toml | 4 ++-- grok/src/configuration.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/grok/Cargo.lock b/grok/Cargo.lock index c0bcbe627..04d2e6850 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -692,9 +692,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/grok/Cargo.toml b/grok/Cargo.toml index 685d2dff4..a81bc4079 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.2" +iii-helpers = "=0.22.0-alpha.2" 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(()) } From 3c890a736ab2626fccddcd8480a7aa0b41366e50 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 19/75] feat(harness): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- harness/Cargo.lock | 52 ++++++++++++++++++++++++++++++++---- harness/Cargo.toml | 4 +-- harness/src/configuration.rs | 2 ++ harness/src/discovery.rs | 1 + 4 files changed, 52 insertions(+), 7 deletions(-) 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/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, From 92ffdfc0dcaebe82afda54d8915516900bf6052a Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 20/75] feat(http): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- http/Cargo.lock | 8 ++++---- http/Cargo.toml | 4 ++-- http/src/configuration.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/http/Cargo.lock b/http/Cargo.lock index 3592fe84b..5d9cbafd6 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -847,9 +847,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/http/Cargo.toml b/http/Cargo.toml index 2ef6722ba..5509f7809 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.2" # 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.2" # 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(()) } From 6b9e907167976c3ee9fa26ab73f0c9ecf10aca61 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 21/75] feat(iii-directory): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- iii-directory/Cargo.lock | 8 ++++---- iii-directory/Cargo.toml | 2 +- iii-directory/src/configuration.rs | 1 + iii-directory/src/main.rs | 1 + 4 files changed, 7 insertions(+), 5 deletions(-) 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/main.rs b/iii-directory/src/main.rs index 53885a513..a3d305d18 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(_) => { From b55bba824b522836a32c90f771ac84a3efd98f07 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 22/75] feat(llm-router): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Smoke-verified: functions register in the declared namespace. --- llm-router/Cargo.lock | 8 +++--- llm-router/Cargo.toml | 4 +-- llm-router/src/register.rs | 58 ++++++++++++++++---------------------- 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/llm-router/Cargo.lock b/llm-router/Cargo.lock index 59df666cf..2caa4329d 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,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/llm-router/Cargo.toml b/llm-router/Cargo.toml index 9748a340e..8fd998f8f 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.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, 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.2" 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/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 From d3f676ff9315f66f8d8ede179d6742e0bebba5ef Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 23/75] feat(mcp): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- mcp/Cargo.lock | 8 ++++---- mcp/Cargo.toml | 4 ++-- mcp/src/main.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mcp/Cargo.lock b/mcp/Cargo.lock index 0915f38d7..b4ee1c080 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -908,9 +908,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/mcp/Cargo.toml b/mcp/Cargo.toml index 920e93971..df8aa6e2b 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.2" +iii-helpers = "=0.22.0-alpha.2" 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, From adaa47d6bc3c46b03d3984dc87ddeed0d353a9de Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 24/75] feat(memory): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- crates/console-ui/Cargo.toml | 2 +- crates/console-ui/src/lib.rs | 1 + memory/Cargo.lock | 8 ++++---- memory/Cargo.toml | 2 +- memory/src/configuration.rs | 1 + memory/src/main.rs | 2 ++ 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/console-ui/Cargo.toml b/crates/console-ui/Cargo.toml index d9c92bf9f..9e3d93233 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.2" 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/memory/Cargo.lock b/memory/Cargo.lock index c0e2a65b6..4eb1315e1 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/memory/Cargo.toml b/memory/Cargo.toml index dc9703ac2..270271d97 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.2" # 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/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, From d7709cd83d906a6950352b226edd824486f640d2 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 25/75] feat(memory-consolidate): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- memory-consolidate/Cargo.lock | 8 ++++---- memory-consolidate/Cargo.toml | 2 +- memory-consolidate/src/configuration.rs | 1 + memory-consolidate/src/main.rs | 2 ++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/memory-consolidate/Cargo.lock b/memory-consolidate/Cargo.lock index f4517b366..b6bf21231 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6455e06a9357696d8aa7cf7ba6d6b30ce8803036d85ea53a51de76178b867ec" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/memory-consolidate/Cargo.toml b/memory-consolidate/Cargo.toml index 6e7f72554..5e7bdfd24 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.2" 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/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"); } From e3c5c75d863bd6e10c13812d5935b63b6d1f5ad9 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:36:59 -0300 Subject: [PATCH 26/75] feat(provider-anthropic): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Build- and connect-verified; full registration needs external creds/deps or a driver. --- provider-anthropic/Cargo.lock | 8 ++++---- provider-anthropic/Cargo.toml | 2 +- provider-anthropic/src/register.rs | 21 ++++++++++----------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/provider-anthropic/Cargo.lock b/provider-anthropic/Cargo.lock index d4ee34a95..b08d68a39 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,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/provider-anthropic/Cargo.toml b/provider-anthropic/Cargo.toml index e55a38f08..c6830afbb 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.2" 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). From 5f71fd27398fe05d976840bce221cf3774b45f5a Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 27/75] feat(provider-kimi): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Smoke-verified: functions register in the declared namespace. --- provider-kimi/Cargo.lock | 8 ++++---- provider-kimi/Cargo.toml | 2 +- provider-kimi/src/register.rs | 22 ++++++++-------------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/provider-kimi/Cargo.lock b/provider-kimi/Cargo.lock index 914580f85..92001591e 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -649,9 +649,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/provider-kimi/Cargo.toml b/provider-kimi/Cargo.toml index bb8e8f746..4cc775d35 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.2" 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). From 984b783da85617d68e501982f0349e4988a35c23 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 28/75] feat(provider-llamacpp): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Smoke-verified: functions register in the declared namespace. --- provider-llamacpp/Cargo.lock | 8 ++++---- provider-llamacpp/Cargo.toml | 2 +- provider-llamacpp/src/register.rs | 21 ++++++++++----------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/provider-llamacpp/Cargo.lock b/provider-llamacpp/Cargo.lock index b9e2683af..3bc627784 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -670,9 +670,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/provider-llamacpp/Cargo.toml b/provider-llamacpp/Cargo.toml index 618333e1b..e50991b0f 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.2" 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). From 5ee7d55b4397be93815f24147c5fa9e3e0ac606d Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 29/75] feat(provider-openai): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Build- and connect-verified; full registration needs external creds/deps or a driver. --- provider-openai/Cargo.lock | 8 ++++---- provider-openai/Cargo.toml | 2 +- provider-openai/src/register.rs | 21 ++++++++++----------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/provider-openai/Cargo.lock b/provider-openai/Cargo.lock index 6e63c86d9..a686b989b 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,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/provider-openai/Cargo.toml b/provider-openai/Cargo.toml index f590ede5c..762177ca1 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.2" 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). From f056a1f54c9e5e62140e98b7b3ab0e9a10a4fdf8 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 30/75] feat(provider-openai-codex): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Build- and connect-verified; full registration needs external creds/deps or a driver. --- provider-openai-codex/Cargo.lock | 8 ++++---- provider-openai-codex/Cargo.toml | 2 +- provider-openai-codex/src/register.rs | 21 ++++++++++----------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/provider-openai-codex/Cargo.lock b/provider-openai-codex/Cargo.lock index 80e96068b..1ea9cab68 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,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/provider-openai-codex/Cargo.toml b/provider-openai-codex/Cargo.toml index abbf5f93d..006a7b68e 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.2" 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( From 49c534c4fa7a82b02142d2cc96de29a0dc7c0710 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 31/75] feat(provider-xai): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Build- and connect-verified; full registration needs external creds/deps or a driver. --- provider-xai/Cargo.lock | 8 ++++---- provider-xai/Cargo.toml | 2 +- provider-xai/src/configuration.rs | 1 + provider-xai/src/register.rs | 28 +++++++++++----------------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/provider-xai/Cargo.lock b/provider-xai/Cargo.lock index a836bf22e..ead0c5741 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,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/provider-xai/Cargo.toml b/provider-xai/Cargo.toml index f684a071d..02faaa66e 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.2" 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). From aa7ada8cfd2dcc09073a08ddb22ed0e1abefe2d6 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 32/75] feat(provider-zai): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Also migrate off the removed new_async_with_bad_request (#1966) to new_async, dropping the custom bad-request mapper. Build- and connect-verified; full registration needs external creds/deps or a driver. --- provider-zai/Cargo.lock | 8 ++++---- provider-zai/Cargo.toml | 2 +- provider-zai/src/register.rs | 21 ++++++++++----------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/provider-zai/Cargo.lock b/provider-zai/Cargo.lock index 813f5cfce..24ac82955 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,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/provider-zai/Cargo.toml b/provider-zai/Cargo.toml index a2ea054e2..a6a64b54f 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.2" 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). From a0e4121851c843bce734d52586ee6798de1ca118 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 33/75] feat(pubsub): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- pubsub/Cargo.lock | 8 ++++---- pubsub/Cargo.toml | 2 +- pubsub/src/configuration.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pubsub/Cargo.lock b/pubsub/Cargo.lock index d02b9eac5..deff8d117 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/pubsub/Cargo.toml b/pubsub/Cargo.toml index 9d7a5f578..d396ddc56 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.2" 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(()) } From 02691d5f530ced8ce5515b118a948c190c9392a7 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 34/75] feat(queue): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- queue/Cargo.lock | 8 ++++---- queue/Cargo.toml | 4 ++-- queue/src/configuration.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/queue/Cargo.lock b/queue/Cargo.lock index 2c0ed4a6e..e1f739d2f 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -1263,9 +1263,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/queue/Cargo.toml b/queue/Cargo.toml index 56e9c4b85..f3c3299d2 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.2" +iii-helpers = "=0.22.0-alpha.2" 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(()) } From ed05ae15fdadaaa58f7ef1023617bdc92ee5e7e1 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 35/75] feat(rbac-proxy): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- rbac-proxy/Cargo.lock | 8 ++++---- rbac-proxy/Cargo.toml | 2 +- rbac-proxy/src/configuration.rs | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/rbac-proxy/Cargo.lock b/rbac-proxy/Cargo.lock index 7b06d7363..4e4389d79 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/rbac-proxy/Cargo.toml b/rbac-proxy/Cargo.toml index c7c0b9700..17aa86cd3 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.2" 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) => { From c6612dbab5ab36d1584823eadf1de742ddd7aeb9 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 36/75] feat(session-manager): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- session-manager/Cargo.lock | 8 ++++---- session-manager/Cargo.toml | 4 ++-- session-manager/src/configuration.rs | 1 + session-manager/src/events.rs | 1 + 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/session-manager/Cargo.lock b/session-manager/Cargo.lock index cde75e50a..05d154827 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -935,9 +935,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/session-manager/Cargo.toml b/session-manager/Cargo.toml index 4702d23ee..ea6b3a449 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.2" # `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.2" 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..cb78933aa 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!( From 6d813fe01cb73ad96477501fedd719b4b8b0d3ec Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 37/75] feat(shell): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- shell/Cargo.lock | 8 ++++---- shell/Cargo.toml | 4 ++-- shell/src/configuration.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/shell/Cargo.lock b/shell/Cargo.lock index e35d05b70..47420696a 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -914,9 +914,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/shell/Cargo.toml b/shell/Cargo.toml index ec7772ba8..d611c6bce 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.2" +iii-helpers = "=0.22.0-alpha.2" 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(()) } From f90f61b642ab2149fd11c34a2dac423a8a2e4e89 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 38/75] feat(slack): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Build- and connect-verified; full registration needs external creds/deps or a driver. --- slack/Cargo.lock | 8 ++++---- slack/Cargo.toml | 2 +- slack/src/configuration.rs | 1 + slack/src/functions/bindings.rs | 1 + slack/src/ingress.rs | 1 + 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/slack/Cargo.lock b/slack/Cargo.lock index d03da3e72..fa8771c8e 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/slack/Cargo.toml b/slack/Cargo.toml index f7f1d0816..3bf40dc2a 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.2" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time"] } serde = { version = "1", features = ["derive"] } serde_json = "1" 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(), }) } From daf184f5a7398670e98c8c4213c05845efa644ba Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 39/75] feat(state): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- state/Cargo.lock | 8 ++++---- state/Cargo.toml | 4 ++-- state/src/configuration.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/state/Cargo.lock b/state/Cargo.lock index 5509e937b..5e6b507a8 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -773,9 +773,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/state/Cargo.toml b/state/Cargo.toml index f25c875f8..a567cec5f 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.2" # 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.2" # 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(()) } From a34ed2e0342dfb8bb69435187ff5dfb6958da8af Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 40/75] feat(storage): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- storage/Cargo.lock | 8 ++++---- storage/Cargo.toml | 2 +- storage/src/configuration.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/storage/Cargo.lock b/storage/Cargo.lock index 9b4afca82..83b8e8737 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/storage/Cargo.toml b/storage/Cargo.toml index 4a9d15655..6f104d3ff 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.2" 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(()) } From 90a8f445f7efa5f81c9d6a228bc601d05406ccbb Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 41/75] feat(telegram-bot): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Build- and connect-verified; full registration needs external creds/deps or a driver. --- telegram-bot/Cargo.lock | 8 ++++---- telegram-bot/Cargo.toml | 4 ++-- telegram-bot/src/approval_gate.rs | 1 + telegram-bot/src/configuration.rs | 1 + telegram-bot/src/functions/mod.rs | 3 +++ 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/telegram-bot/Cargo.lock b/telegram-bot/Cargo.lock index c28cfdbce..ae8a6f4a2 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -700,9 +700,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/telegram-bot/Cargo.toml b/telegram-bot/Cargo.toml index 1e2dcc776..85d67aa72 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.2" +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/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/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!( From e47f217397daf9461ce332422f1acfdc8deef6b8 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 42/75] feat(web): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- web/Cargo.lock | 8 ++++---- web/Cargo.toml | 2 +- web/src/configuration.rs | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/web/Cargo.lock b/web/Cargo.lock index d210687ac..7a988b564 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/web/Cargo.toml b/web/Cargo.toml index e1e0861bb..6bdfd0a87 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.2" 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(()) } From fad4f91d0fc839fbc7406c593d26317e3c15a3fd Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 43/75] feat(workflow): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- workflow/Cargo.lock | 8 ++++---- workflow/Cargo.toml | 4 ++-- workflow/src/configuration.rs | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/workflow/Cargo.lock b/workflow/Cargo.lock index afb980d1b..b7f4ec295 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d84d5c149ae4404365a79feca28aa66f6a7dbed56423b4b8c4e2421e0b5add" +checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" dependencies = [ "futures-util", "opentelemetry", @@ -642,9 +642,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/workflow/Cargo.toml b/workflow/Cargo.toml index 6b854bd00..7b9e93452 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.2" +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/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(()) } From b3ca385789d9acacbe204fc90fd906cdbea28d28 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 44/75] feat(worktree): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- worktree/Cargo.lock | 8 ++++---- worktree/Cargo.toml | 2 +- worktree/src/configuration.rs | 2 ++ worktree/src/main.rs | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/worktree/Cargo.lock b/worktree/Cargo.lock index 33d9414aa..4e1111433 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/worktree/Cargo.toml b/worktree/Cargo.toml index 51086362c..950494817 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.2" # 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/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) => { From 6fc4073ba243a8a2c1222559c0fa054448393609 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 45/75] feat(console): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Build- and connect-verified; full registration needs external creds/deps or a driver. --- console/Cargo.lock | 8 ++++---- console/Cargo.toml | 2 +- console/src/configuration.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) 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, From 5b0384760de383d1badfbdf33ffc3861bbd94e5a Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 46/75] feat(email): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Smoke-verified: functions register in the declared namespace. --- email/Cargo.lock | 8 ++++---- email/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/email/Cargo.lock b/email/Cargo.lock index 1c85cf138..3e0ec1e2f 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/email/Cargo.toml b/email/Cargo.toml index 0f7e56581..841cd849d 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.2" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "signal", "time", "io-util", "net"] } serde = { version = "1", features = ["derive"] } serde_json = "1" From 0e73bc5e910de885e45de72b1b8d9f1772c9a230 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:37:00 -0300 Subject: [PATCH 47/75] feat(lsp): migrate to iii-sdk 0.22.0-alpha.2 with namespace support Bump iii-sdk to 0.22.0-alpha.2. Namespace is env-driven (III_NAMESPACE via the SDK); the now-required RegisterTriggerInput.namespace is threaded to the worker's namespace so triggers resolve where functions register. Build- and connect-verified; full registration needs external creds/deps or a driver. --- lsp/Cargo.lock | 8 ++++---- lsp/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lsp/Cargo.lock b/lsp/Cargo.lock index 5d0e697c6..c2834c1ba 100644 --- a/lsp/Cargo.lock +++ b/lsp/Cargo.lock @@ -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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd060fddcc9153b0dd07c038a14cf172ce15ce1d4edb98155563ed55b2caba" +checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" dependencies = [ "async-trait", "futures-util", diff --git a/lsp/Cargo.toml b/lsp/Cargo.toml index 311749d7a..219cbbcf2 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.2" tower-lsp-server = "0.23" tree-sitter = "0.24" tree-sitter-typescript = "0.23" From acef881f6bfc499416b267e14e828f9c8af5d0c0 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:57:51 -0300 Subject: [PATCH 48/75] fix(llm-router): route provider->router calls to the worker's namespace The provider_scaffold router client issued router::provider::register (and resolve/reconcile/models_get) on a TriggerRequest with no namespace, so a provider running in a namespace called the router in default and never registered. Route the call to the worker's own namespace via iii.namespace() (None => engine default). Verified with a multi-worker smoke: llm-router + provider run in the same namespace and the provider's surface registers there. --- llm-router/src/provider_scaffold/router_client.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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. From 614699bd67e5ba43e77f829bc0f237d9f53d5b01 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 20:57:51 -0300 Subject: [PATCH 49/75] fix(provider-kimi): route router calls to the worker's namespace provider-kimi has its own copy of the scaffold call() helper; apply the same namespace routing so its router::provider::register reaches llm-router in the worker's namespace instead of default. Multi-worker smoke-verified. --- provider-kimi/src/router_client.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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. From 29e188ab49d6b1bdd8666ce26f8b787b94959648 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:54 -0300 Subject: [PATCH 50/75] fix(approval-gate): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- approval-gate/src/events.rs | 19 +++++++-------- approval-gate/src/harness.rs | 45 +++++++++++++++++++++--------------- approval-gate/src/session.rs | 9 +++++--- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/approval-gate/src/events.rs b/approval-gate/src/events.rs index a6290a52b..2d13bf3eb 100644 --- a/approval-gate/src/events.rs +++ b/approval-gate/src/events.rs @@ -253,15 +253,16 @@ 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 res = match self.iii.namespace() { + 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, 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/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, + } } From 39e11d88384a50fb88bad70f330ba5a82c8a334c Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:54 -0300 Subject: [PATCH 51/75] fix(context-manager): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- context-manager/src/adapters/router.rs | 61 ++++++++++++++------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/context-manager/src/adapters/router.rs b/context-manager/src/adapters/router.rs index 0d3b765bd..e9451d28e 100644 --- a/context-manager/src/adapters/router.rs +++ b/context-manager/src/adapters/router.rs @@ -53,32 +53,34 @@ impl ModelResolver for RouterModelResolver { if let Some(p) = provider { payload["provider"] = json!(p); } - let resp = match self - .iii - .trigger(TriggerRequest { - function_id: "router::models::budget".to_string(), - payload: payload.clone(), - action: None, - timeout_ms: Some(MODELS_GET_TIMEOUT_MS), - }) - .await - { + let request = TriggerRequest { + function_id: "router::models::budget".to_string(), + payload: payload.clone(), + action: None, + timeout_ms: Some(MODELS_GET_TIMEOUT_MS), + }; + let budget_result = match self.iii.namespace() { + Some(ns) => 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. From 3c26bbd4532827cfdad78d136dad342bb19f9976 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:54 -0300 Subject: [PATCH 52/75] fix(email): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- email/src/handlers/send.rs | 18 +++++++++------- email/src/provider/imap/connection.rs | 30 ++++++++++++++------------- email/src/triggers/dispatcher.rs | 6 +++++- 3 files changed, 31 insertions(+), 23 deletions(-) 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..69746fa96 100644 --- a/email/src/triggers/dispatcher.rs +++ b/email/src/triggers/dispatcher.rs @@ -53,7 +53,11 @@ 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 result = match self.iii.namespace() { + 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!( From 5504339ceba86faa6a8fe2a638610b5e20f6a1e5 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:55 -0300 Subject: [PATCH 53/75] fix(harness): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- harness/src/clients/context.rs | 38 +++++++------ harness/src/clients/router.rs | 89 ++++++++++++++++-------------- harness/src/clients/session.rs | 20 ++++--- harness/src/functions/react.rs | 40 +++++++------- harness/src/functions/subscribe.rs | 23 ++++---- harness/src/turn_loop.rs | 24 ++++---- 6 files changed, 125 insertions(+), 109 deletions(-) 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/functions/react.rs b/harness/src/functions/react.rs index b86f63750..476ac274d 100644 --- a/harness/src/functions/react.rs +++ b/harness/src/functions/react.rs @@ -1439,16 +1439,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 +1626,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/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(); From 837996e12ff26e0be2cd5e7d0d64cff2fb164721 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:55 -0300 Subject: [PATCH 54/75] fix(iii-directory): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- iii-directory/src/functions/skills.rs | 18 ++++++++++-------- iii-directory/src/main.rs | 18 ++++++++++-------- iii-directory/src/trigger_types.rs | 18 ++++++++++-------- 3 files changed, 30 insertions(+), 24 deletions(-) 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 a3d305d18..39c7b58e1 100644 --- a/iii-directory/src/main.rs +++ b/iii-directory/src/main.rs @@ -357,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..ef3d0ace7 100644 --- a/iii-directory/src/trigger_types.rs +++ b/iii-directory/src/trigger_types.rs @@ -87,14 +87,16 @@ 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 res = match iii.namespace() { + Some(ns) => iii.trigger(request.namespace(ns)).await, + None => iii.trigger(request).await, + }; if let Err(e) = res { tracing::warn!( function_id = %function_id, From 6745436db6c6d7df96d06d58bb536be03ecacc6b Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:55 -0300 Subject: [PATCH 55/75] fix(memory): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- memory/src/embed_client.rs | 20 ++++---- memory/src/events.rs | 19 ++++---- memory/src/extract.rs | 97 ++++++++++++++++++++----------------- memory/src/functions/ops.rs | 19 ++++---- 4 files changed, 83 insertions(+), 72 deletions(-) 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..c9c56b2d5 100644 --- a/memory/src/events.rs +++ b/memory/src/events.rs @@ -206,15 +206,16 @@ 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 res = match self.iii.namespace() { + 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(), From d00c5630f3b1ce03d95c75828721da962f814d48 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:55 -0300 Subject: [PATCH 56/75] fix(memory-consolidate): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- memory-consolidate/src/consolidate.rs | 9 +++-- memory-consolidate/src/llm.rs | 58 ++++++++++++++------------- 2 files changed, 37 insertions(+), 30 deletions(-) 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) From cd49cdacf77479fff766ccc0802a868f6fd0cebf Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:55 -0300 Subject: [PATCH 57/75] fix(slack): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- slack/src/clients/approval.rs | 18 ++++++++++++------ slack/src/clients/harness.rs | 27 ++++++++++++++++----------- slack/src/clients/router.rs | 18 ++++++++++-------- 3 files changed, 38 insertions(+), 25 deletions(-) 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) From 776c6aa7cae0fcb6c5f384874e2dbcab4f46a01c Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:55 -0300 Subject: [PATCH 58/75] fix(telegram-bot): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- telegram-bot/src/clients/approval.rs | 45 +++++++++++++---------- telegram-bot/src/clients/harness.rs | 54 +++++++++++++++------------- telegram-bot/src/clients/router.rs | 18 +++++----- 3 files changed, 66 insertions(+), 51 deletions(-) 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) From 6c6bb7d7ad3735582acfebe1358feffe4d8972be Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:55 -0300 Subject: [PATCH 59/75] fix(workflow): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- workflow/src/events.rs | 57 +++++++++++++++++---------------- workflow/src/functions/mod.rs | 19 +++++------ workflow/src/functions/start.rs | 30 +++++++++-------- workflow/src/functions/tick.rs | 21 ++++++------ workflow/src/reconcile.rs | 21 ++++++------ 5 files changed, 79 insertions(+), 69 deletions(-) diff --git a/workflow/src/events.rs b/workflow/src/events.rs index 327f2b816..a134571b6 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,16 @@ 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 _ = match deps.iii.namespace() { + 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 +134,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!( From 4ceea053c77e591495de7b27e4519c5735c10208 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 21:29:55 -0300 Subject: [PATCH 60/75] fix(worktree): route cross-worker calls to the worker's namespace Non-builtin cross-worker trigger calls (e.g. router::/harness::/approval::/session::/context::/shell::/workflow:: and this worker's own functions) issued a TriggerRequest with no namespace, so a worker running in a namespace called those targets in default and missed them. Route each to the worker's namespace via iii.namespace() (None => engine default). Builtin targets (state::/stream::/queue::/pubsub::/configuration::/cron::/http::/engine::/...) intentionally stay in default. --- worktree/src/events.rs | 18 ++++++++++-------- worktree/src/land/mod.rs | 26 ++++++++++++++------------ worktree/src/land/test_gate.rs | 29 +++++++++++++++-------------- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/worktree/src/events.rs b/worktree/src/events.rs index e9ce44304..ba0fe9994 100644 --- a/worktree/src/events.rs +++ b/worktree/src/events.rs @@ -367,14 +367,16 @@ 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 res = match iii.namespace() { + 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"); } 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); From c672f593b4718a87131982e0f5f9007339f5babe Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 22:05:49 -0300 Subject: [PATCH 61/75] fix(harness): gate dynamic fan-out namespacing on the builtin check Dynamic subscriber/hook/notify targets carry a runtime function_id that can be either a builtin (e.g. state::set) or another worker's function. Route these to the worker's namespace ONLY when the target is NOT a builtin prefix; builtins keep default routing so a builtin subscribed to an event still resolves. Literal cross-worker targets are unchanged. --- harness/src/events.rs | 31 +++++++++++++++++++++--- harness/src/functions/react.rs | 44 ++++++++++++++++++++++++++-------- harness/src/hooks/runner.rs | 40 ++++++++++++++++++++++++++----- 3 files changed, 96 insertions(+), 19 deletions(-) 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 476ac274d..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, 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)), From d362a3df1093289b946e496c0e7e2e2d9acdaed0 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 22:05:49 -0300 Subject: [PATCH 62/75] fix(email): gate dynamic fan-out namespacing on the builtin check Dynamic subscriber/hook/notify targets carry a runtime function_id that can be either a builtin (e.g. state::set) or another worker's function. Route these to the worker's namespace ONLY when the target is NOT a builtin prefix; builtins keep default routing so a builtin subscribed to an event still resolves. Literal cross-worker targets are unchanged. --- email/src/triggers/dispatcher.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/email/src/triggers/dispatcher.rs b/email/src/triggers/dispatcher.rs index 69746fa96..5923d7bed 100644 --- a/email/src/triggers/dispatcher.rs +++ b/email/src/triggers/dispatcher.rs @@ -53,7 +53,27 @@ impl EventDispatcher for EngineDispatcher { timeout_ms: Some(sub.handler_timeout_ms), }; let bound = Duration::from_millis(sub.handler_timeout_ms.saturating_add(1_000)); - let result = match self.iii.namespace() { + 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, }; From db701d97197a7f62ccaa6e25987affaf5136d480 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 22:05:49 -0300 Subject: [PATCH 63/75] fix(workflow): gate dynamic fan-out namespacing on the builtin check Dynamic subscriber/hook/notify targets carry a runtime function_id that can be either a builtin (e.g. state::set) or another worker's function. Route these to the worker's namespace ONLY when the target is NOT a builtin prefix; builtins keep default routing so a builtin subscribed to an event still resolves. Literal cross-worker targets are unchanged. --- workflow/src/events.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/workflow/src/events.rs b/workflow/src/events.rs index a134571b6..c080403a2 100644 --- a/workflow/src/events.rs +++ b/workflow/src/events.rs @@ -53,7 +53,27 @@ pub async fn emit_notify(deps: &crate::functions::Deps, record: &crate::types::W action: Some(iii_sdk::TriggerAction::Enqueue { queue }), timeout_ms: None, }; - let _ = match deps.iii.namespace() { + 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 From 73c2077fe7f3e3dfafca33a80df2993992957293 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 22:05:49 -0300 Subject: [PATCH 64/75] fix(worktree): gate dynamic fan-out namespacing on the builtin check Dynamic subscriber/hook/notify targets carry a runtime function_id that can be either a builtin (e.g. state::set) or another worker's function. Route these to the worker's namespace ONLY when the target is NOT a builtin prefix; builtins keep default routing so a builtin subscribed to an event still resolves. Literal cross-worker targets are unchanged. --- worktree/src/events.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/worktree/src/events.rs b/worktree/src/events.rs index ba0fe9994..75a67d13b 100644 --- a/worktree/src/events.rs +++ b/worktree/src/events.rs @@ -373,7 +373,27 @@ impl EventDeliverer for IiiDeliverer { action: Some(TriggerAction::Void), timeout_ms: None, }; - let res = match iii.namespace() { + 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, }; From 549d1dc8c3ca2e22fc6dc682eebdb839f5ad7653 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 22:05:49 -0300 Subject: [PATCH 65/75] fix(memory): gate dynamic fan-out namespacing on the builtin check Dynamic subscriber/hook/notify targets carry a runtime function_id that can be either a builtin (e.g. state::set) or another worker's function. Route these to the worker's namespace ONLY when the target is NOT a builtin prefix; builtins keep default routing so a builtin subscribed to an event still resolves. Literal cross-worker targets are unchanged. --- memory/src/events.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/memory/src/events.rs b/memory/src/events.rs index c9c56b2d5..7c7cccf9d 100644 --- a/memory/src/events.rs +++ b/memory/src/events.rs @@ -212,7 +212,27 @@ impl Emitter { action: Some(TriggerAction::Void), timeout_ms: None, }; - let res = match self.iii.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 res = match route_ns { Some(ns) => self.iii.trigger(request.namespace(ns)).await, None => self.iii.trigger(request).await, }; From df9d9e3bde2a88801936529c18e159d9a43e9608 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 22:05:49 -0300 Subject: [PATCH 66/75] fix(approval-gate): gate dynamic fan-out namespacing on the builtin check Dynamic subscriber/hook/notify targets carry a runtime function_id that can be either a builtin (e.g. state::set) or another worker's function. Route these to the worker's namespace ONLY when the target is NOT a builtin prefix; builtins keep default routing so a builtin subscribed to an event still resolves. Literal cross-worker targets are unchanged. --- approval-gate/src/events.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/approval-gate/src/events.rs b/approval-gate/src/events.rs index 2d13bf3eb..8e21b44b9 100644 --- a/approval-gate/src/events.rs +++ b/approval-gate/src/events.rs @@ -259,7 +259,27 @@ impl Emitter { action: Some(TriggerAction::Void), timeout_ms: None, }; - let res = match self.iii.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 res = match route_ns { Some(ns) => self.iii.trigger(request.namespace(ns)).await, None => self.iii.trigger(request).await, }; From 19a2cdfd4764a62404534a80a21a8d5786fc600e Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sat, 25 Jul 2026 22:05:49 -0300 Subject: [PATCH 67/75] fix(iii-directory): gate dynamic fan-out namespacing on the builtin check Dynamic subscriber/hook/notify targets carry a runtime function_id that can be either a builtin (e.g. state::set) or another worker's function. Route these to the worker's namespace ONLY when the target is NOT a builtin prefix; builtins keep default routing so a builtin subscribed to an event still resolves. Literal cross-worker targets are unchanged. --- iii-directory/src/trigger_types.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/iii-directory/src/trigger_types.rs b/iii-directory/src/trigger_types.rs index ef3d0ace7..8144df4ab 100644 --- a/iii-directory/src/trigger_types.rs +++ b/iii-directory/src/trigger_types.rs @@ -93,7 +93,27 @@ pub async fn dispatch(iii: &IIIClient, subscribers: &SubscriberSet, payload: Val action: Some(TriggerAction::Void), timeout_ms: None, }; - let res = match iii.namespace() { + 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, }; From 2423745e4bbb1fb36341db6e4477f021e1e80f7e Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sun, 26 Jul 2026 13:09:45 -0300 Subject: [PATCH 68/75] chore(state): bump iii-sdk and iii-helpers to 0.22.0-alpha.3 Picks up the namespace review fixes shipped in the 0.22.0-alpha.3 SDK release. Build-verified against the published crates. --- crates/console-ui/Cargo.toml | 2 +- state/Cargo.lock | 8 ++++---- state/Cargo.toml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/console-ui/Cargo.toml b/crates/console-ui/Cargo.toml index 9e3d93233..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.22.0-alpha.2" +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/state/Cargo.lock b/state/Cargo.lock index 5e6b507a8..7c19baa71 100644 --- a/state/Cargo.lock +++ b/state/Cargo.lock @@ -752,9 +752,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -773,9 +773,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/state/Cargo.toml b/state/Cargo.toml index a567cec5f..8f37d9d50 100644 --- a/state/Cargo.toml +++ b/state/Cargo.toml @@ -18,10 +18,10 @@ name = "state" path = "src/main.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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.22.0-alpha.2" +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" } From bd0e02aac4b8493eb4ae7cd7681a29f294b291ec Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Sun, 26 Jul 2026 13:09:45 -0300 Subject: [PATCH 69/75] chore(http): bump iii-sdk and iii-helpers to 0.22.0-alpha.3 Picks up the namespace review fixes shipped in the 0.22.0-alpha.3 SDK release. Build-verified against the published crates. --- http/Cargo.lock | 8 ++++---- http/Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/http/Cargo.lock b/http/Cargo.lock index 5d9cbafd6..4c16795d7 100644 --- a/http/Cargo.lock +++ b/http/Cargo.lock @@ -795,9 +795,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -847,9 +847,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/http/Cargo.toml b/http/Cargo.toml index 5509f7809..6a3353460 100644 --- a/http/Cargo.toml +++ b/http/Cargo.toml @@ -18,12 +18,12 @@ name = "http" path = "src/main.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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.22.0-alpha.2" +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" From 15cc3a5a5cb527b1dcadaac19c1c08dd01f1073f Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Mon, 27 Jul 2026 08:47:55 -0300 Subject: [PATCH 70/75] chore(pubsub): bump iii-sdk and iii-helpers to 0.22.0-alpha.3 Picks up the namespace review fixes in the 0.22.0-alpha.3 SDK release. --- pubsub/Cargo.lock | 4 ++-- pubsub/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubsub/Cargo.lock b/pubsub/Cargo.lock index deff8d117..e0bf93771 100644 --- a/pubsub/Cargo.lock +++ b/pubsub/Cargo.lock @@ -737,9 +737,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/pubsub/Cargo.toml b/pubsub/Cargo.toml index d396ddc56..406bc9f41 100644 --- a/pubsub/Cargo.toml +++ b/pubsub/Cargo.toml @@ -18,7 +18,7 @@ name = "pubsub" path = "src/main.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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"] } From 7239c548495b6fdf0d461da9e85f03ab710bf481 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Mon, 27 Jul 2026 08:47:55 -0300 Subject: [PATCH 71/75] chore(cron): bump iii-sdk and iii-helpers to 0.22.0-alpha.3 Picks up the namespace review fixes in the 0.22.0-alpha.3 SDK release. --- cron/Cargo.lock | 4 ++-- cron/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cron/Cargo.lock b/cron/Cargo.lock index 7b74fc57d..500c07bed 100644 --- a/cron/Cargo.lock +++ b/cron/Cargo.lock @@ -794,9 +794,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/cron/Cargo.toml b/cron/Cargo.toml index 93b3bee41..87d264cbb 100644 --- a/cron/Cargo.toml +++ b/cron/Cargo.toml @@ -18,7 +18,7 @@ name = "cron" path = "src/main.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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"] } From 914f017192ce001ad4cccb21dd879152d76932c2 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Mon, 27 Jul 2026 08:47:55 -0300 Subject: [PATCH 72/75] chore(queue): bump iii-sdk and iii-helpers to 0.22.0-alpha.3 Picks up the namespace review fixes in the 0.22.0-alpha.3 SDK release. --- queue/Cargo.lock | 8 ++++---- queue/Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/queue/Cargo.lock b/queue/Cargo.lock index e1f739d2f..7f891ad99 100644 --- a/queue/Cargo.lock +++ b/queue/Cargo.lock @@ -1217,9 +1217,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -1263,9 +1263,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/queue/Cargo.toml b/queue/Cargo.toml index f3c3299d2..a1c562e78 100644 --- a/queue/Cargo.toml +++ b/queue/Cargo.toml @@ -27,8 +27,8 @@ rabbitmq = ["dep:lapin"] test-adapters = [] [dependencies] -iii-sdk = "=0.22.0-alpha.2" -iii-helpers = "=0.22.0-alpha.2" +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"] } From 40dcdae302893c5b26ac7f712e4906312e754379 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Mon, 27 Jul 2026 09:59:57 -0300 Subject: [PATCH 73/75] chore: bump iii-sdk dependencies to 0.22.0-alpha.3 --- acp/Cargo.lock | 4 +-- acp/Cargo.toml | 2 +- bridge/Cargo.lock | 4 +-- bridge/Cargo.toml | 2 +- browser/Cargo.lock | 4 +-- browser/Cargo.toml | 2 +- claude-code/package.json | 2 +- claude-code/pnpm-lock.yaml | 18 ++++++------- codex/Cargo.lock | 8 +++--- codex/Cargo.toml | 4 +-- context-manager/Cargo.lock | 4 +-- context-manager/Cargo.toml | 2 +- devin/Cargo.lock | 8 +++--- devin/Cargo.toml | 4 +-- email/Cargo.lock | 4 +-- email/Cargo.toml | 2 +- fp/Cargo.lock | 4 +-- fp/Cargo.toml | 2 +- github/Cargo.lock | 4 +-- github/Cargo.toml | 2 +- grok/Cargo.lock | 8 +++--- grok/Cargo.toml | 4 +-- hermes/pyproject.toml | 4 +-- image-resize/Cargo.lock | 4 +-- image-resize/Cargo.toml | 2 +- llm-router/Cargo.lock | 8 +++--- llm-router/Cargo.toml | 4 +-- lsp/Cargo.lock | 43 ++++++++++++++++---------------- lsp/Cargo.toml | 2 +- mcp/Cargo.lock | 8 +++--- mcp/Cargo.toml | 4 +-- memory-consolidate/Cargo.lock | 4 +-- memory-consolidate/Cargo.toml | 2 +- memory/Cargo.lock | 4 +-- memory/Cargo.toml | 2 +- opencode/package.json | 2 +- opencode/pnpm-lock.yaml | 18 ++++++------- pi/package.json | 2 +- pi/pnpm-lock.yaml | 18 ++++++------- provider-anthropic/Cargo.lock | 8 +++--- provider-anthropic/Cargo.toml | 2 +- provider-kimi/Cargo.lock | 10 ++++---- provider-kimi/Cargo.toml | 2 +- provider-llamacpp/Cargo.lock | 10 ++++---- provider-llamacpp/Cargo.toml | 2 +- provider-openai-codex/Cargo.lock | 8 +++--- provider-openai-codex/Cargo.toml | 2 +- provider-openai/Cargo.lock | 8 +++--- provider-openai/Cargo.toml | 2 +- provider-xai/Cargo.lock | 10 ++++---- provider-xai/Cargo.toml | 2 +- provider-zai/Cargo.lock | 8 +++--- provider-zai/Cargo.toml | 2 +- rbac-proxy/Cargo.lock | 4 +-- rbac-proxy/Cargo.toml | 2 +- scrapling/pyproject.toml | 4 +-- session-manager/Cargo.lock | 8 +++--- session-manager/Cargo.toml | 4 +-- shell/Cargo.lock | 8 +++--- shell/Cargo.toml | 4 +-- slack/Cargo.lock | 4 +-- slack/Cargo.toml | 2 +- storage/Cargo.lock | 4 +-- storage/Cargo.toml | 2 +- telegram-bot/Cargo.lock | 8 +++--- telegram-bot/Cargo.toml | 4 +-- web/Cargo.lock | 4 +-- web/Cargo.toml | 2 +- workflow/Cargo.lock | 8 +++--- workflow/Cargo.toml | 4 +-- worktree/Cargo.lock | 8 +++--- worktree/Cargo.toml | 2 +- 72 files changed, 195 insertions(+), 196 deletions(-) diff --git a/acp/Cargo.lock b/acp/Cargo.lock index 5f506431a..83a62ccd4 100644 --- a/acp/Cargo.lock +++ b/acp/Cargo.lock @@ -706,9 +706,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/acp/Cargo.toml b/acp/Cargo.toml index ec8f3858e..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.22.0-alpha.2" +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/bridge/Cargo.lock b/bridge/Cargo.lock index 20be21e57..c4874ac61 100644 --- a/bridge/Cargo.lock +++ b/bridge/Cargo.lock @@ -681,9 +681,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/bridge/Cargo.toml b/bridge/Cargo.toml index 20767028b..e2570af6a 100644 --- a/bridge/Cargo.toml +++ b/bridge/Cargo.toml @@ -18,7 +18,7 @@ name = "bridge" path = "src/main.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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/browser/Cargo.lock b/browser/Cargo.lock index f3511a08f..e1861c7da 100644 --- a/browser/Cargo.lock +++ b/browser/Cargo.lock @@ -843,9 +843,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/browser/Cargo.toml b/browser/Cargo.toml index 18b1849e2..ab165f9aa 100644 --- a/browser/Cargo.toml +++ b/browser/Cargo.toml @@ -15,7 +15,7 @@ name = "browser" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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/claude-code/package.json b/claude-code/package.json index b7d251b8a..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.22.0-alpha.2", + "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 71f011094..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.22.0-alpha.2 - version: 0.22.0-alpha.2 + 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.22.0-alpha.2': - resolution: {integrity: sha512-NhmwybfpPmjlL4yKNxAVevkWIzu4SIhHFPh1bCMKEpy5oLTCSx/oHHF2ruUhQEyKwB79LqrrJ21SM93klujZJg==} + '@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.22.0-alpha.2: - resolution: {integrity: sha512-mdILi3R+MeTXpEmUPmqMyjGY35DWddia+7DoIDaXXm/xop4gAeSARqqpZggzcAzSMQek0XACTKKKypUm4uA8PA==} + 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.22.0-alpha.2': + '@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.22.0-alpha.2: + iii-sdk@0.22.0-alpha.3: dependencies: - '@iii-dev/helpers': 0.22.0-alpha.2 + '@iii-dev/helpers': 0.22.0-alpha.3 '@opentelemetry/api': 1.9.1 ws: 8.21.0 transitivePeerDependencies: diff --git a/codex/Cargo.lock b/codex/Cargo.lock index e425bd6ee..ce357f675 100644 --- a/codex/Cargo.lock +++ b/codex/Cargo.lock @@ -672,9 +672,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -693,9 +693,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/codex/Cargo.toml b/codex/Cargo.toml index 078999feb..12c758131 100644 --- a/codex/Cargo.toml +++ b/codex/Cargo.toml @@ -15,8 +15,8 @@ name = "codex" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" -iii-helpers = "=0.22.0-alpha.2" +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/context-manager/Cargo.lock b/context-manager/Cargo.lock index 9fc377643..b1d403ab8 100644 --- a/context-manager/Cargo.lock +++ b/context-manager/Cargo.lock @@ -960,9 +960,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/context-manager/Cargo.toml b/context-manager/Cargo.toml index f7afcbacf..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.22.0-alpha.2" +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/devin/Cargo.lock b/devin/Cargo.lock index 86d155c62..2942356f0 100644 --- a/devin/Cargo.lock +++ b/devin/Cargo.lock @@ -670,9 +670,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -691,9 +691,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/devin/Cargo.toml b/devin/Cargo.toml index f965e5fc3..190c628aa 100644 --- a/devin/Cargo.toml +++ b/devin/Cargo.toml @@ -15,8 +15,8 @@ name = "devin" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" -iii-helpers = "=0.22.0-alpha.2" +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/email/Cargo.lock b/email/Cargo.lock index 3e0ec1e2f..278700a76 100644 --- a/email/Cargo.lock +++ b/email/Cargo.lock @@ -1225,9 +1225,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/email/Cargo.toml b/email/Cargo.toml index 841cd849d..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.22.0-alpha.2" +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/fp/Cargo.lock b/fp/Cargo.lock index 3a6b1a68b..7a88196ee 100644 --- a/fp/Cargo.lock +++ b/fp/Cargo.lock @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/fp/Cargo.toml b/fp/Cargo.toml index 88072f604..39fa6a20c 100644 --- a/fp/Cargo.toml +++ b/fp/Cargo.toml @@ -17,7 +17,7 @@ name = "fp" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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/github/Cargo.lock b/github/Cargo.lock index 3cad7f5f0..4dfe8571c 100644 --- a/github/Cargo.lock +++ b/github/Cargo.lock @@ -701,9 +701,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/github/Cargo.toml b/github/Cargo.toml index a16f84d84..0dbdd3a9b 100644 --- a/github/Cargo.toml +++ b/github/Cargo.toml @@ -17,7 +17,7 @@ name = "github" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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/grok/Cargo.lock b/grok/Cargo.lock index 04d2e6850..3bf074467 100644 --- a/grok/Cargo.lock +++ b/grok/Cargo.lock @@ -671,9 +671,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -692,9 +692,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/grok/Cargo.toml b/grok/Cargo.toml index a81bc4079..88ce3b2f1 100644 --- a/grok/Cargo.toml +++ b/grok/Cargo.toml @@ -15,8 +15,8 @@ name = "grok" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" -iii-helpers = "=0.22.0-alpha.2" +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/hermes/pyproject.toml b/hermes/pyproject.toml index e1e679239..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.22.0a2", - "iii-helpers==0.22.0a2", + "iii-sdk==0.22.0a3", + "iii-helpers==0.22.0a3", "opentelemetry-api", "opentelemetry-sdk", "pyyaml", diff --git a/image-resize/Cargo.lock b/image-resize/Cargo.lock index 7b78b40cf..5ca0a78ab 100644 --- a/image-resize/Cargo.lock +++ b/image-resize/Cargo.lock @@ -718,9 +718,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/image-resize/Cargo.toml b/image-resize/Cargo.toml index 2b69898ca..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.22.0-alpha.2" +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/llm-router/Cargo.lock b/llm-router/Cargo.lock index 2caa4329d..359a0fd22 100644 --- a/llm-router/Cargo.lock +++ b/llm-router/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/llm-router/Cargo.toml b/llm-router/Cargo.toml index 8fd998f8f..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.22.0-alpha.2" +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.22.0-alpha.2" +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/lsp/Cargo.lock b/lsp/Cargo.lock index c2834c1ba..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" @@ -733,9 +733,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +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 219cbbcf2..162071048 100644 --- a/lsp/Cargo.toml +++ b/lsp/Cargo.toml @@ -13,7 +13,7 @@ name = "lsp" path = "src/main.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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 b4ee1c080..146953d90 100644 --- a/mcp/Cargo.lock +++ b/mcp/Cargo.lock @@ -887,9 +887,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -908,9 +908,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/mcp/Cargo.toml b/mcp/Cargo.toml index df8aa6e2b..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.22.0-alpha.2" -iii-helpers = "=0.22.0-alpha.2" +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/memory-consolidate/Cargo.lock b/memory-consolidate/Cargo.lock index b6bf21231..0978a1438 100644 --- a/memory-consolidate/Cargo.lock +++ b/memory-consolidate/Cargo.lock @@ -663,9 +663,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/memory-consolidate/Cargo.toml b/memory-consolidate/Cargo.toml index 5e7bdfd24..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.22.0-alpha.2" +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/Cargo.lock b/memory/Cargo.lock index 4eb1315e1..819b7e410 100644 --- a/memory/Cargo.lock +++ b/memory/Cargo.lock @@ -681,9 +681,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/memory/Cargo.toml b/memory/Cargo.toml index 270271d97..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.22.0-alpha.2" +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/opencode/package.json b/opencode/package.json index 0e2341e2f..8e596f2df 100644 --- a/opencode/package.json +++ b/opencode/package.json @@ -23,7 +23,7 @@ "opencode-worker": "./dist/index.js" }, "dependencies": { - "iii-sdk": "0.22.0-alpha.2", + "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 15f92adfb..4c8823a5b 100644 --- a/opencode/pnpm-lock.yaml +++ b/opencode/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: iii-sdk: - specifier: 0.22.0-alpha.2 - version: 0.22.0-alpha.2 + 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.22.0-alpha.2': - resolution: {integrity: sha512-NhmwybfpPmjlL4yKNxAVevkWIzu4SIhHFPh1bCMKEpy5oLTCSx/oHHF2ruUhQEyKwB79LqrrJ21SM93klujZJg==} + '@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.22.0-alpha.2: - resolution: {integrity: sha512-mdILi3R+MeTXpEmUPmqMyjGY35DWddia+7DoIDaXXm/xop4gAeSARqqpZggzcAzSMQek0XACTKKKypUm4uA8PA==} + 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.22.0-alpha.2': + '@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.22.0-alpha.2: + iii-sdk@0.22.0-alpha.3: dependencies: - '@iii-dev/helpers': 0.22.0-alpha.2 + '@iii-dev/helpers': 0.22.0-alpha.3 '@opentelemetry/api': 1.9.1 ws: 8.21.0 transitivePeerDependencies: diff --git a/pi/package.json b/pi/package.json index 5e913dc5e..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.22.0-alpha.2", + "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 38d64802a..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.22.0-alpha.2 - version: 0.22.0-alpha.2 + 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.22.0-alpha.2': - resolution: {integrity: sha512-NhmwybfpPmjlL4yKNxAVevkWIzu4SIhHFPh1bCMKEpy5oLTCSx/oHHF2ruUhQEyKwB79LqrrJ21SM93klujZJg==} + '@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.22.0-alpha.2: - resolution: {integrity: sha512-mdILi3R+MeTXpEmUPmqMyjGY35DWddia+7DoIDaXXm/xop4gAeSARqqpZggzcAzSMQek0XACTKKKypUm4uA8PA==} + 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.22.0-alpha.2': + '@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.22.0-alpha.2: + iii-sdk@0.22.0-alpha.3: dependencies: - '@iii-dev/helpers': 0.22.0-alpha.2 + '@iii-dev/helpers': 0.22.0-alpha.3 '@opentelemetry/api': 1.9.1 ws: 8.21.0 transitivePeerDependencies: diff --git a/provider-anthropic/Cargo.lock b/provider-anthropic/Cargo.lock index b08d68a39..e298cffda 100644 --- a/provider-anthropic/Cargo.lock +++ b/provider-anthropic/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/provider-anthropic/Cargo.toml b/provider-anthropic/Cargo.toml index c6830afbb..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.22.0-alpha.2" +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/Cargo.lock b/provider-kimi/Cargo.lock index 92001591e..2986b043f 100644 --- a/provider-kimi/Cargo.lock +++ b/provider-kimi/Cargo.lock @@ -628,9 +628,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -649,9 +649,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +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 4cc775d35..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.22.0-alpha.2" +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/Cargo.lock b/provider-llamacpp/Cargo.lock index 3bc627784..efbca72ec 100644 --- a/provider-llamacpp/Cargo.lock +++ b/provider-llamacpp/Cargo.lock @@ -649,9 +649,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -670,9 +670,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +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 e50991b0f..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.22.0-alpha.2" +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/Cargo.lock b/provider-openai-codex/Cargo.lock index 1ea9cab68..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.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/provider-openai-codex/Cargo.toml b/provider-openai-codex/Cargo.toml index 006a7b68e..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.22.0-alpha.2" +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/Cargo.lock b/provider-openai/Cargo.lock index a686b989b..b510537e4 100644 --- a/provider-openai/Cargo.lock +++ b/provider-openai/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/provider-openai/Cargo.toml b/provider-openai/Cargo.toml index 762177ca1..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.22.0-alpha.2" +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/Cargo.lock b/provider-xai/Cargo.lock index ead0c5741..11570dd73 100644 --- a/provider-xai/Cargo.lock +++ b/provider-xai/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +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 02faaa66e..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.22.0-alpha.2" +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/Cargo.lock b/provider-zai/Cargo.lock index 24ac82955..2b259c8d1 100644 --- a/provider-zai/Cargo.lock +++ b/provider-zai/Cargo.lock @@ -669,9 +669,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/provider-zai/Cargo.toml b/provider-zai/Cargo.toml index a6a64b54f..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.22.0-alpha.2" +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/rbac-proxy/Cargo.lock b/rbac-proxy/Cargo.lock index 4e4389d79..b770a0f6e 100644 --- a/rbac-proxy/Cargo.lock +++ b/rbac-proxy/Cargo.lock @@ -713,9 +713,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/rbac-proxy/Cargo.toml b/rbac-proxy/Cargo.toml index 17aa86cd3..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.22.0-alpha.2" +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/scrapling/pyproject.toml b/scrapling/pyproject.toml index cf42504a2..aafb89fcb 100644 --- a/scrapling/pyproject.toml +++ b/scrapling/pyproject.toml @@ -13,8 +13,8 @@ authors = [{ name = "iii" }] license = "Apache-2.0" requires-python = ">=3.11" dependencies = [ - "iii-sdk==0.22.0a2", - "iii-helpers==0.22.0a2", # transitive iii-sdk dep; pinned so uv allows the pre-release + "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/session-manager/Cargo.lock b/session-manager/Cargo.lock index 05d154827..c4c445dfb 100644 --- a/session-manager/Cargo.lock +++ b/session-manager/Cargo.lock @@ -914,9 +914,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -935,9 +935,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/session-manager/Cargo.toml b/session-manager/Cargo.toml index ea6b3a449..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.22.0-alpha.2" +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.22.0-alpha.2" +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/shell/Cargo.lock b/shell/Cargo.lock index 47420696a..fdb19d74b 100644 --- a/shell/Cargo.lock +++ b/shell/Cargo.lock @@ -893,9 +893,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -914,9 +914,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/shell/Cargo.toml b/shell/Cargo.toml index d611c6bce..f67228cc0 100644 --- a/shell/Cargo.toml +++ b/shell/Cargo.toml @@ -11,8 +11,8 @@ name = "shell" path = "src/main.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" -iii-helpers = "=0.22.0-alpha.2" +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/slack/Cargo.lock b/slack/Cargo.lock index fa8771c8e..3776dd224 100644 --- a/slack/Cargo.lock +++ b/slack/Cargo.lock @@ -678,9 +678,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/slack/Cargo.toml b/slack/Cargo.toml index 3bf40dc2a..bfdcf8428 100644 --- a/slack/Cargo.toml +++ b/slack/Cargo.toml @@ -15,7 +15,7 @@ name = "slack" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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/storage/Cargo.lock b/storage/Cargo.lock index 83b8e8737..83e660058 100644 --- a/storage/Cargo.lock +++ b/storage/Cargo.lock @@ -1943,9 +1943,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/storage/Cargo.toml b/storage/Cargo.toml index 6f104d3ff..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.22.0-alpha.2" +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/telegram-bot/Cargo.lock b/telegram-bot/Cargo.lock index ae8a6f4a2..4380aa29b 100644 --- a/telegram-bot/Cargo.lock +++ b/telegram-bot/Cargo.lock @@ -679,9 +679,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/telegram-bot/Cargo.toml b/telegram-bot/Cargo.toml index 85d67aa72..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.22.0-alpha.2" -iii-helpers = "=0.22.0-alpha.2" +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/web/Cargo.lock b/web/Cargo.lock index 7a988b564..31ad66cbc 100644 --- a/web/Cargo.lock +++ b/web/Cargo.lock @@ -779,9 +779,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/web/Cargo.toml b/web/Cargo.toml index 6bdfd0a87..460baf8a0 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -15,7 +15,7 @@ name = "web" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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/workflow/Cargo.lock b/workflow/Cargo.lock index b7f4ec295..5d9599abb 100644 --- a/workflow/Cargo.lock +++ b/workflow/Cargo.lock @@ -621,9 +621,9 @@ dependencies = [ [[package]] name = "iii-helpers" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5559b662390e53fa7fcac83451ae1667306e94c44a97f6c617f1e3023f1dfd" +checksum = "5090e8ba42874e09f8fa82419a0ef9f150eae4301eb64272cd0a184b548812fc" dependencies = [ "futures-util", "opentelemetry", @@ -642,9 +642,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +checksum = "89e2b076a2227fea8175522eb184c3623af102841a641ec2ff90a8936215d982" dependencies = [ "async-trait", "futures-util", diff --git a/workflow/Cargo.toml b/workflow/Cargo.toml index 7b9e93452..22311acf5 100644 --- a/workflow/Cargo.toml +++ b/workflow/Cargo.toml @@ -15,8 +15,8 @@ name = "workflow" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" -iii-helpers = "=0.22.0-alpha.2" +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/worktree/Cargo.lock b/worktree/Cargo.lock index 4e1111433..326397e92 100644 --- a/worktree/Cargo.lock +++ b/worktree/Cargo.lock @@ -704,9 +704,9 @@ dependencies = [ [[package]] name = "iii-sdk" -version = "0.22.0-alpha.2" +version = "0.22.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743c738975e139d6c5ee0e0635699308e9f85969da11003bc123712f45b48def" +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 950494817..5c1a90cba 100644 --- a/worktree/Cargo.toml +++ b/worktree/Cargo.toml @@ -15,7 +15,7 @@ name = "worktree" path = "src/lib.rs" [dependencies] -iii-sdk = "=0.22.0-alpha.2" +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" } From b255e85e3d9f3cee7e0382ef198c82c1c18d37e4 Mon Sep 17 00:00:00 2001 From: Guilherme Beira Date: Mon, 27 Jul 2026 10:20:42 -0300 Subject: [PATCH 74/75] fix: add namespaces to trigger test fixtures --- approval-gate/src/events.rs | 1 + browser/src/events.rs | 3 +++ console/src/ui_assets.rs | 2 ++ cron/src/trigger.rs | 1 + cron/tests/e2e_schedule.rs | 1 + http/src/trigger.rs | 1 + http/tests/common/backend.rs | 8 ++++++++ http/tests/e2e_condition.rs | 1 + http/tests/e2e_request_body.rs | 1 + http/tests/e2e_streaming.rs | 2 ++ iii-directory/src/trigger_types.rs | 1 + llm-router/src/triggers.rs | 2 ++ llm-router/tests/integration.rs | 1 + mcp/tests/common/engine.rs | 1 + pubsub/src/trigger.rs | 1 + pubsub/tests/e2e_pubsub.rs | 1 + queue/src/trigger.rs | 1 + queue/tests/e2e_durability.rs | 1 + session-manager/src/events.rs | 3 +++ session-manager/src/resync.rs | 1 + session-manager/tests/steps/binding_steps.rs | 1 + session-manager/tests/steps/bridge_steps.rs | 1 + session-manager/tests/steps/engine_steps.rs | 1 + state/src/trigger.rs | 1 + state/tests/e2e_state.rs | 4 ++++ worktree/src/events.rs | 5 +++++ worktree/tests/support/mod.rs | 1 + 27 files changed, 48 insertions(+) diff --git a/approval-gate/src/events.rs b/approval-gate/src/events.rs index 8e21b44b9..fdc6d094c 100644 --- a/approval-gate/src/events.rs +++ b/approval-gate/src/events.rs @@ -335,6 +335,7 @@ mod tests { function_id: function_id.into(), config, metadata: None, + namespace: None, } } 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/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/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/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/src/trigger_types.rs b/iii-directory/src/trigger_types.rs index 8144df4ab..36a40c0e5 100644 --- a/iii-directory/src/trigger_types.rs +++ b/iii-directory/src/trigger_types.rs @@ -202,6 +202,7 @@ mod tests { function_id: function_id.to_string(), config: json!({}), metadata: None, + namespace: None, } } 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/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/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/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/session-manager/src/events.rs b/session-manager/src/events.rs index cb78933aa..db89dbcd5 100644 --- a/session-manager/src/events.rs +++ b/session-manager/src/events.rs @@ -1285,6 +1285,7 @@ mod tests { function_id: "ui::recv".into(), config: json!({}), metadata: None, + namespace: None, }) .unwrap(); @@ -1313,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); @@ -1322,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/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/worktree/src/events.rs b/worktree/src/events.rs index 75a67d13b..32ffe64ce 100644 --- a/worktree/src/events.rs +++ b/worktree/src/events.rs @@ -492,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")); @@ -506,6 +507,7 @@ mod tests { function_id: "ui::recv".into(), config: Value::Null, metadata: None, + namespace: None, }) .unwrap(); set.add(TriggerConfig { @@ -513,6 +515,7 @@ mod tests { function_id: "ui::recv".into(), config: json!({}), metadata: None, + namespace: None, }) .unwrap(); assert_eq!(set.snapshot().len(), 2); @@ -544,6 +547,7 @@ mod tests { function_id: "recv::all".into(), config: json!({}), metadata: None, + namespace: None, }) .unwrap(); sets.for_kind(EventKind::Landed) @@ -552,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/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(); } From 52473697bc0f462eb336ddac6e2f388eca30b0b4 Mon Sep 17 00:00:00 2001 From: guibeira Date: Wed, 5 Aug 2026 10:28:28 -0300 Subject: [PATCH 75/75] feat: a worker is told which configuration entry is its own MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A worker hardcodes its configuration id, which turns that id into a global scarce name. Two instances of one worker share a single entry: the second overwrites the first, and every write wakes both, because the id each watches is the id being written. Two `state` workers cannot hold different settings, and two `http` workers cannot bind different ports. `III_CONFIG_NAME` names the entry a supervisor resolved for this instance, so the id it reads is the one it was given rather than the one it was compiled with. The built-in name remains the default, and an empty or blank value falls back to it, so a worker started by hand — or by a supervisor that does not set it — behaves exactly as before. Nothing here changes what is read, only where it is read from. The format strings that interpolated the id take it as a named argument. A positional one would have shifted the other placeholders in every macro that had more than one. --- approval-gate/src/configuration.rs | 28 ++++++++++++++++++---- bridge/src/configuration.rs | 28 ++++++++++++++++++---- bridge/tests/e2e_reload.rs | 2 +- browser/src/configuration.rs | 26 ++++++++++++++++---- codex/src/configuration.rs | 26 ++++++++++++++++---- console/src/configuration.rs | 28 ++++++++++++++++++---- context-manager/src/configuration.rs | 28 ++++++++++++++++++---- cron/src/configuration.rs | 28 ++++++++++++++++++---- database/src/configuration.rs | 28 ++++++++++++++++++---- devin/src/configuration.rs | 26 ++++++++++++++++---- editor/src/configuration.rs | 28 ++++++++++++++++++---- github/src/configuration.rs | 26 ++++++++++++++++---- grok/src/configuration.rs | 26 ++++++++++++++++---- harness/src/configuration.rs | 32 +++++++++++++++++++------ http/src/configuration.rs | 28 ++++++++++++++++++---- http/tests/e2e_reload.rs | 6 ++--- iii-directory/src/configuration.rs | 28 ++++++++++++++++++---- memory-consolidate/src/configuration.rs | 28 ++++++++++++++++++---- memory/src/configuration.rs | 28 ++++++++++++++++++---- provider-xai/src/configuration.rs | 26 ++++++++++++++++---- pubsub/src/configuration.rs | 28 ++++++++++++++++++---- queue/src/configuration.rs | 31 +++++++++++++++++++----- rbac-proxy/src/configuration.rs | 28 ++++++++++++++++++---- session-manager/src/configuration.rs | 28 ++++++++++++++++++---- shell/src/configuration.rs | 28 ++++++++++++++++++---- slack/src/configuration.rs | 26 ++++++++++++++++---- state/src/configuration.rs | 28 ++++++++++++++++++---- state/tests/e2e_state.rs | 6 ++--- storage/src/configuration.rs | 28 ++++++++++++++++++---- telegram-bot/src/configuration.rs | 28 ++++++++++++++++++---- web/src/configuration.rs | 26 ++++++++++++++++---- workflow/src/configuration.rs | 28 ++++++++++++++++++---- worktree/src/configuration.rs | 28 ++++++++++++++++++---- 33 files changed, 693 insertions(+), 152 deletions(-) diff --git a/approval-gate/src/configuration.rs b/approval-gate/src/configuration.rs index 85b1687f4..afcd782f1 100644 --- a/approval-gate/src/configuration.rs +++ b/approval-gate/src/configuration.rs @@ -29,7 +29,25 @@ use crate::config::WorkerConfig; /// whole-snapshot replaces the inner `Arc` under the write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "approval-gate"; +pub const DEFAULT_CONFIG_ID: &str = "approval-gate"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "approval::on-config-change"; const CONFIG_RETRIES: u32 = 3; /// Base backoff between configuration RPC retries; multiplied by the @@ -59,7 +77,7 @@ const FILESYSTEM_ACCESS_WATCH_ON_ERROR: &str = "fail_open"; /// value, so this is safe to call every boot). pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Approval Gate", "description": "Policy and decision surface settings: the deployment \ approval defaults (permission mode for new sessions \ @@ -98,14 +116,14 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// Returns `Ok(None)` when the entry does not exist. The engine's /// missing-entry codes vary in case (`function_not_found`, /// `STATEMENT_NOT_FOUND`, `NOT_FOUND`), so match case-insensitively. async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.to_ascii_uppercase().contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -260,7 +278,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/bridge/src/configuration.rs b/bridge/src/configuration.rs index 248ccdafc..61a6c0ee5 100644 --- a/bridge/src/configuration.rs +++ b/bridge/src/configuration.rs @@ -73,7 +73,25 @@ pub type ConfigCell = Arc>>; /// Apply lock to serialize overlapping configuration change runs. pub type ApplyLock = Arc>; -pub const CONFIG_ID: &str = "bridge"; +pub const DEFAULT_CONFIG_ID: &str = "bridge"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "bridge::on-config-change"; const CONFIG_RETRIES: u32 = 3; const CONFIG_RETRY_BACKOFF_MS: u64 = 250; @@ -87,7 +105,7 @@ const CONFIG_BUS_TIMEOUT_MS: u64 = 10_000; /// restarts. pub async fn register_config(iii: &IIIClient, seed: Option<&BridgeConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Bridge", "description": "Bridge to a remote iii instance — remote WebSocket URL, functions exposed to the remote engine, and remote functions forwarded locally.", "schema": BridgeConfig::json_schema(), @@ -113,7 +131,7 @@ pub async fn fetch_config(iii: &IIIClient) -> Result { match try_get_config_value(iii).await? { Some(value) if !value.is_null() => BridgeConfig::from_json(&value), _ => { - tracing::info!("no `{CONFIG_ID}` configuration value stored; using built-in default"); + tracing::info!("no `{config_entry}` configuration value stored; using built-in default", config_entry = config_id()); Ok(BridgeConfig::default()) } } @@ -130,7 +148,7 @@ async fn try_get_config_value(iii: &IIIClient) -> Result, String> match trigger_with_retry( iii, "configuration::get", - json!({ "id": CONFIG_ID }), + json!({ "id": config_id() }), CONFIG_BUS_TIMEOUT_MS, ) .await @@ -201,7 +219,7 @@ pub async fn register_config_trigger(iii: &Arc, boot: &BootHandle) -> trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/bridge/tests/e2e_reload.rs b/bridge/tests/e2e_reload.rs index 53f93e01f..780dfeaf1 100644 --- a/bridge/tests/e2e_reload.rs +++ b/bridge/tests/e2e_reload.rs @@ -40,7 +40,7 @@ fn echo_fn() -> RegisterFunction { async fn set_bridge_config(iii: &Arc, value: Value) { iii.trigger(TriggerRequest { function_id: "configuration::set".to_string(), - payload: json!({ "id": configuration::CONFIG_ID, "value": value }), + payload: json!({ "id": configuration::config_id(), "value": value }), action: None, timeout_ms: Some(10_000), }) diff --git a/browser/src/configuration.rs b/browser/src/configuration.rs index 750952f89..bf535c378 100644 --- a/browser/src/configuration.rs +++ b/browser/src/configuration.rs @@ -13,14 +13,32 @@ use serde_json::{json, Value}; use crate::config::{SharedConfig, WorkerConfig}; -pub const CONFIG_ID: &str = "browser"; +pub const DEFAULT_CONFIG_ID: &str = "browser"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "browser::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "browser", "description": "Session limits, buffers, timeouts, viewport, and executable for the browser worker.", "schema": WorkerConfig::json_schema(), @@ -53,7 +71,7 @@ async fn should_seed_default(iii: &IIIClient) -> Result { } async fn try_get_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -90,7 +108,7 @@ pub fn register_config_trigger(iii: &IIIClient, config: SharedConfig) -> Result< iii.register_trigger(RegisterTriggerInput { trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), - config: json!({ "configuration_id": CONFIG_ID, "event_types": ["configuration:updated"] }), + config: json!({ "configuration_id": config_id(), "event_types": ["configuration:updated"] }), metadata: None, namespace: iii.namespace(), })?; diff --git a/codex/src/configuration.rs b/codex/src/configuration.rs index cd5d2d53c..34bf75951 100644 --- a/codex/src/configuration.rs +++ b/codex/src/configuration.rs @@ -21,7 +21,25 @@ use crate::config::Config; /// the inner `Arc` under the write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "codex"; +pub const DEFAULT_CONFIG_ID: &str = "codex"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "codex::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -31,7 +49,7 @@ const CONFIG_RETRIES: u32 = 3; /// only when no stored value exists yet. pub async fn register_config(iii: &IIIClient, seed: Option<&Config>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Codex", "description": "OpenAI Codex worker: per-turn defaults (model, sandbox mode, approval policy, reasoning effort, working directory), the agent::events / codex::events stream names, the codex CLI path, an optional API base URL, and whether to inject the iii runtime context as developer_instructions.", "schema": Config::json_schema(), @@ -65,7 +83,7 @@ async fn should_seed_default(iii: &IIIClient) -> Result { /// `Ok(None)` when the entry does not exist (`NOT_FOUND`). async fn try_get_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -102,7 +120,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/console/src/configuration.rs b/console/src/configuration.rs index ade9044b3..5e1d6a46e 100644 --- a/console/src/configuration.rs +++ b/console/src/configuration.rs @@ -28,7 +28,25 @@ use serde_json::{json, Value}; use crate::ui_assets::UiControl; -pub const CONFIG_ID: &str = "console"; +pub const DEFAULT_CONFIG_ID: &str = "console"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; const CONFIG_RETRY_BACKOFF_MS: u64 = 250; @@ -140,7 +158,7 @@ pub async fn register_console_config(iii: &IIIClient) { }; let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Console", "description": "Console UI preferences — Traces V2 saved views \ (grouping, filters, display settings, hidden functions), \ @@ -153,7 +171,7 @@ pub async fn register_console_config(iii: &IIIClient) { } match trigger_with_retry(iii, "configuration::register", payload).await { - Ok(_) => tracing::info!(id = CONFIG_ID, "console configuration registered"), + Ok(_) => tracing::info!(id = config_id(), "console configuration registered"), Err(e) => tracing::warn!( error = %e, "console configuration registration failed; skipping \ @@ -218,7 +236,7 @@ pub async fn start_injectable_ui_sync(iii: &Arc, control: UiControl) trigger_type: "configuration".to_string(), function_id: CONFIG_CHANGE_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, @@ -268,7 +286,7 @@ pub struct ConfigChangeRequest {} /// `Ok(None)` when the entry does not exist or holds `null`. async fn existing_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").filter(|v| !v.is_null()).cloned()), Err(e) if e.to_ascii_uppercase().contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), diff --git a/context-manager/src/configuration.rs b/context-manager/src/configuration.rs index 5dbae944b..dc1377e93 100644 --- a/context-manager/src/configuration.rs +++ b/context-manager/src/configuration.rs @@ -36,7 +36,25 @@ use crate::ports::{LeaseCell, LeaseStore}; /// whole-snapshot replaces the inner `Arc` under the write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "context-manager"; +pub const DEFAULT_CONFIG_ID: &str = "context-manager"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "context::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -51,7 +69,7 @@ const CONFIG_RETRY_BACKOFF_MS: u64 = 250; /// value, so this is safe to call every boot). pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Context Manager", "description": "Model-ready context assembly tuning: token-budget reserves, \ function-result prune thresholds, compaction tail size, the \ @@ -89,14 +107,14 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// Returns `Ok(None)` when the entry does not exist. The engine's /// missing-entry codes vary in case (`function_not_found`, /// `STATEMENT_NOT_FOUND`, `NOT_FOUND`), so match case-insensitively. async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.to_ascii_uppercase().contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -162,7 +180,7 @@ pub fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/cron/src/configuration.rs b/cron/src/configuration.rs index d9be0bb51..1bcf16cd9 100644 --- a/cron/src/configuration.rs +++ b/cron/src/configuration.rs @@ -13,7 +13,25 @@ use crate::config::CronConfig; use crate::locks; use crate::scheduler::Scheduler; -pub const CONFIG_ID: &str = "cron"; +pub const DEFAULT_CONFIG_ID: &str = "cron"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "cron::on-config-change"; const CONFIG_RETRIES: u32 = 3; const CONFIG_RETRY_BACKOFF_MS: u64 = 250; @@ -21,7 +39,7 @@ const CONFIG_BUS_TIMEOUT_MS: u64 = 10_000; pub async fn register_config(iii: &IIIClient, seed: Option<&CronConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Cron", "description": "Cron scheduler settings - lock backend for multi-instance mutual exclusion (local or redis).", "schema": CronConfig::json_schema(), @@ -44,7 +62,7 @@ pub async fn fetch_config(iii: &IIIClient) -> Result { match try_get_config_value(iii).await? { Some(value) if !value.is_null() => CronConfig::from_json(&value), _ => { - tracing::info!("no `{CONFIG_ID}` configuration value stored; using built-in default"); + tracing::info!("no `{config_entry}` configuration value stored; using built-in default", config_entry = config_id()); Ok(CronConfig::default()) } } @@ -61,7 +79,7 @@ async fn try_get_config_value(iii: &IIIClient) -> Result, String> match trigger_with_retry( iii, "configuration::get", - json!({ "id": CONFIG_ID }), + json!({ "id": config_id() }), CONFIG_BUS_TIMEOUT_MS, ) .await @@ -92,7 +110,7 @@ pub fn register_config_trigger(iii: &Arc, parts: BootParts) -> Result trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/database/src/configuration.rs b/database/src/configuration.rs index 40a6e334e..7f73f0a9c 100644 --- a/database/src/configuration.rs +++ b/database/src/configuration.rs @@ -11,7 +11,25 @@ use serde_json::{json, Value}; use std::collections::HashMap; use std::time::Duration; -pub const CONFIG_ID: &str = "database"; +pub const DEFAULT_CONFIG_ID: &str = "database"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "database::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -21,7 +39,7 @@ const CONFIG_RETRIES: u32 = 3; /// built-in defaults are seeded only when no stored value exists yet. pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Database", "description": "Connection pools for PostgreSQL, MySQL, and SQLite.", "schema": WorkerConfig::json_schema(), @@ -56,12 +74,12 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// Returns `Ok(None)` when the entry does not exist (`NOT_FOUND`). async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -148,7 +166,7 @@ pub fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/devin/src/configuration.rs b/devin/src/configuration.rs index 5dfde4b22..5facf319d 100644 --- a/devin/src/configuration.rs +++ b/devin/src/configuration.rs @@ -20,7 +20,25 @@ use crate::config::Config; /// the inner `Arc` under the write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "devin"; +pub const DEFAULT_CONFIG_ID: &str = "devin"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "devin::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -30,7 +48,7 @@ const CONFIG_RETRIES: u32 = 3; /// only when no stored value exists yet. pub async fn register_config(iii: &IIIClient, seed: Option<&Config>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Devin", "description": "Devin worker: the API bearer token and organization id, the Devin REST base URL and request timeout, the agent::events / devin::events stream names, the devin CLI path and extra args, and whether to inject the iii runtime context into a devin::run prompt.", "schema": Config::json_schema(), @@ -64,7 +82,7 @@ async fn should_seed_default(iii: &IIIClient) -> Result { /// `Ok(None)` when the entry does not exist (`NOT_FOUND`). async fn try_get_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -101,7 +119,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/editor/src/configuration.rs b/editor/src/configuration.rs index 7b4d2954c..7bfd44232 100644 --- a/editor/src/configuration.rs +++ b/editor/src/configuration.rs @@ -28,7 +28,25 @@ use crate::config::WorkerConfig; /// write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "editor"; +pub const DEFAULT_CONFIG_ID: &str = "editor"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "editor::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -55,7 +73,7 @@ pub fn cell(cfg: WorkerConfig) -> ConfigCell { /// this on every boot never overwrites an operator's edit. pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Editor", "description": "Editor workspace limits: diff size and context, file-finder and \ content-search caps, the largest file an open will pull back, and \ @@ -77,7 +95,7 @@ pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Re pub async fn fetch_config(iii: &IIIClient) -> Result { let value = try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found"))?; + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id()))?; if value.is_null() { tracing::info!("no stored configuration; using built-in defaults"); return Ok(WorkerConfig::default()); @@ -96,7 +114,7 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { /// `Ok(None)` when the entry does not exist. The engine's missing-entry codes /// vary in case (`function_not_found`, `NOT_FOUND`), so match case-insensitively. async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.to_ascii_uppercase().contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -277,7 +295,7 @@ pub async fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/github/src/configuration.rs b/github/src/configuration.rs index 12a65c027..8f5cb76c3 100644 --- a/github/src/configuration.rs +++ b/github/src/configuration.rs @@ -20,7 +20,25 @@ use crate::config::Config; /// the inner `Arc` under the write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "github"; +pub const DEFAULT_CONFIG_ID: &str = "github"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "github::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -30,7 +48,7 @@ const CONFIG_RETRIES: u32 = 3; /// only when no stored value exists yet. pub async fn register_config(iii: &IIIClient, seed: Option<&Config>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "GitHub", "description": "GitHub worker: the gh binary path, the GH_TOKEN credential injected into child gh processes, and the timeout / output-capture limits applied to every gh invocation.", "schema": Config::json_schema(), @@ -64,7 +82,7 @@ async fn should_seed_default(iii: &IIIClient) -> Result { /// `Ok(None)` when the entry does not exist (`NOT_FOUND`). async fn try_get_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -101,7 +119,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/grok/src/configuration.rs b/grok/src/configuration.rs index a31830ebb..e280d235e 100644 --- a/grok/src/configuration.rs +++ b/grok/src/configuration.rs @@ -21,7 +21,25 @@ use crate::config::Config; /// the inner `Arc` under the write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "grok"; +pub const DEFAULT_CONFIG_ID: &str = "grok"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "grok::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -31,7 +49,7 @@ const CONFIG_RETRIES: u32 = 3; /// only when no stored value exists yet. pub async fn register_config(iii: &IIIClient, seed: Option<&Config>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Grok", "description": "xAI Grok CLI worker: per-turn defaults (model, working directory, auto-approve), the agent::events / grok::events stream names, the grok CLI path, and whether to inject the iii runtime context into the prompt.", "schema": Config::json_schema(), @@ -65,7 +83,7 @@ async fn should_seed_default(iii: &IIIClient) -> Result { /// `Ok(None)` when the entry does not exist (`NOT_FOUND`). async fn try_get_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -102,7 +120,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/harness/src/configuration.rs b/harness/src/configuration.rs index b079d47a2..eb8bcac07 100644 --- a/harness/src/configuration.rs +++ b/harness/src/configuration.rs @@ -33,7 +33,25 @@ use crate::subscriptions::ON_SESSION_DELETED_ID; /// Hot-swappable config snapshot shared with every handler. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "harness"; +pub const DEFAULT_CONFIG_ID: &str = "harness"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "harness::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -46,7 +64,7 @@ pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Re discard_legacy_harness_config_if_needed(iii).await?; let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Harness", "description": "Durable turn-loop settings: default turn cap and pending-call timeout, \ sub-agent depth/fan-out budgets, output-contract validation retries, the \ @@ -85,12 +103,12 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// Returns `Ok(None)` when the entry does not exist (codes vary in case). async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.to_ascii_uppercase().contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -145,7 +163,7 @@ async fn discard_legacy_harness_config_if_needed(iii: &IIIClient) -> Result<(), iii, "configuration::register", json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Harness", "description": "Legacy harness configuration placeholder (discarding pre-Rust entry).", "schema": { @@ -160,7 +178,7 @@ async fn discard_legacy_harness_config_if_needed(iii: &IIIClient) -> Result<(), iii, "configuration::set", json!({ - "id": CONFIG_ID, + "id": config_id(), "value": WorkerConfig::default().to_json(), }), ) @@ -287,7 +305,7 @@ pub fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/http/src/configuration.rs b/http/src/configuration.rs index e97f21d34..d6d50a0df 100644 --- a/http/src/configuration.rs +++ b/http/src/configuration.rs @@ -60,7 +60,25 @@ pub type ConfigCell = Arc>>; /// (`engine/src/workers/rest_api/api_core.rs`). pub type ApplyLock = Arc>; -pub const CONFIG_ID: &str = "http"; +pub const DEFAULT_CONFIG_ID: &str = "http"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "http::on-config-change"; const CONFIG_RETRIES: u32 = 3; const CONFIG_RETRY_BACKOFF_MS: u64 = 250; @@ -78,7 +96,7 @@ pub fn new_cell(config: RestApiConfig) -> ConfigCell { /// only when nothing is stored yet, so runtime edits survive restarts. pub async fn register_config(iii: &IIIClient, seed: Option<&RestApiConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "HTTP", "description": "HTTP server settings — host/port binding, CORS, request timeout, concurrency limit, and global middleware.", "schema": RestApiConfig::json_schema(), @@ -104,7 +122,7 @@ pub async fn fetch_config(iii: &IIIClient) -> Result { match try_get_config_value(iii).await? { Some(value) if !value.is_null() => RestApiConfig::from_json(&value), _ => { - tracing::info!("no `{CONFIG_ID}` configuration value stored; using built-in default"); + tracing::info!("no `{config_entry}` configuration value stored; using built-in default", config_entry = config_id()); Ok(RestApiConfig::default()) } } @@ -121,7 +139,7 @@ async fn try_get_config_value(iii: &IIIClient) -> Result, String> match trigger_with_retry( iii, "configuration::get", - json!({ "id": CONFIG_ID }), + json!({ "id": config_id() }), CONFIG_BUS_TIMEOUT_MS, ) .await @@ -186,7 +204,7 @@ pub fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/http/tests/e2e_reload.rs b/http/tests/e2e_reload.rs index 7995b1e0a..91ef48376 100644 --- a/http/tests/e2e_reload.rs +++ b/http/tests/e2e_reload.rs @@ -86,7 +86,7 @@ async fn global_middleware_added_via_config_set_blocks_without_restart() { }); iii.trigger(TriggerRequest { function_id: "configuration::set".to_string(), - payload: json!({ "id": configuration::CONFIG_ID, "value": new_value }), + payload: json!({ "id": configuration::config_id(), "value": new_value }), action: None, timeout_ms: Some(10_000), }) @@ -166,7 +166,7 @@ async fn cors_restricted_via_config_set_applies_without_restart() { }); iii.trigger(TriggerRequest { function_id: "configuration::set".to_string(), - payload: json!({ "id": configuration::CONFIG_ID, "value": new_value }), + payload: json!({ "id": configuration::config_id(), "value": new_value }), action: None, timeout_ms: Some(10_000), }) @@ -319,7 +319,7 @@ async fn host_port_change_rebinds_listener_without_restart() { let new_value = json!({ "host": "127.0.0.1", "port": p2 }); iii.trigger(TriggerRequest { function_id: "configuration::set".to_string(), - payload: json!({ "id": configuration::CONFIG_ID, "value": new_value }), + payload: json!({ "id": configuration::config_id(), "value": new_value }), action: None, timeout_ms: Some(10_000), }) diff --git a/iii-directory/src/configuration.rs b/iii-directory/src/configuration.rs index f09fc04b6..9d0f762f6 100644 --- a/iii-directory/src/configuration.rs +++ b/iii-directory/src/configuration.rs @@ -25,7 +25,25 @@ use crate::config::{SharedConfig, SkillsConfig, Topology}; use crate::functions::registry::RegistryCache; use crate::functions::skills::RegisteredWorkersCache; -pub const CONFIG_ID: &str = "iii-directory"; +pub const DEFAULT_CONFIG_ID: &str = "iii-directory"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "directory::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -71,7 +89,7 @@ impl SharedState { /// Otherwise, built-in defaults are seeded only when no stored value exists. pub async fn register_config(iii: &IIIClient, seed: Option<&SkillsConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "iii-directory", "description": "Skills/prompts folders, workers-registry URL, download timeouts, \ and skill-visibility filters for the iii-directory worker.", @@ -108,12 +126,12 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// Returns `Ok(None)` when the entry does not exist (`NOT_FOUND`). async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -169,7 +187,7 @@ pub fn register_config_trigger(iii: &IIIClient, state: SharedState) -> Result<() trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/memory-consolidate/src/configuration.rs b/memory-consolidate/src/configuration.rs index c328e97d4..9f1f2747b 100644 --- a/memory-consolidate/src/configuration.rs +++ b/memory-consolidate/src/configuration.rs @@ -13,7 +13,25 @@ use serde_json::{json, Value}; use crate::config::WorkerConfig; use crate::functions::ConfigCell; -pub const CONFIG_ID: &str = "memory-consolidate"; +pub const DEFAULT_CONFIG_ID: &str = "memory-consolidate"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "memory-consolidate::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -21,7 +39,7 @@ const CONFIG_RETRY_BACKOFF_MS: u64 = 250; pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Memory Consolidate", "description": "Scheduled memory hygiene: dedup interval, dry-run mode, bank allowlist, \ and the per-pass supersede cap.", @@ -56,14 +74,14 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// `Ok(None)` = the entry does not exist. A successful reply MUST carry /// `value` — a malformed response must not seed defaults over an intended /// configuration. async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => resp .get("value") .cloned() @@ -113,7 +131,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/memory/src/configuration.rs b/memory/src/configuration.rs index cae7e5983..2e45d8c13 100644 --- a/memory/src/configuration.rs +++ b/memory/src/configuration.rs @@ -23,7 +23,25 @@ pub type ConfigCell = Arc>>; /// Hot-swappable store handle (rebuilt on a `data_dir` change). pub type StoreCell = Arc>>; -pub const CONFIG_ID: &str = "memory"; +pub const DEFAULT_CONFIG_ID: &str = "memory"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "memory::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -35,7 +53,7 @@ const CONFIG_RETRY_BACKOFF_MS: u64 = 250; /// stored value exists yet. pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Memory", "description": "Cross-session agent memory: bank data directory, default bank, \ per-turn injection toggles and budgets, and the post-turn \ @@ -73,13 +91,13 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// Returns `Ok(None)` when the entry does not exist. The engine's /// missing-entry codes vary in case, so match case-insensitively. async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { // A successful reply MUST carry `value`; treating its absence as // "no entry" would let a malformed response seed defaults over an // intended configuration. @@ -147,7 +165,7 @@ pub fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/provider-xai/src/configuration.rs b/provider-xai/src/configuration.rs index 04f590ca9..b92142091 100644 --- a/provider-xai/src/configuration.rs +++ b/provider-xai/src/configuration.rs @@ -18,7 +18,25 @@ use crate::config::WorkerConfig; /// Hot-swappable config snapshot shared with the stream handler. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "provider-xai"; +pub const DEFAULT_CONFIG_ID: &str = "provider-xai"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "provider::xai::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -31,7 +49,7 @@ pub fn new_cell() -> ConfigCell { /// when no stored value exists yet. pub async fn register_config(iii: &IIIClient) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "xAI Provider", "description": "xAI provider behaviour: enable Agent Tools (live X / web search via the /v1/responses API) and pick which server-side tools to offer. Credentials and endpoints are managed by the llm-router configuration entry, not here.", "schema": WorkerConfig::json_schema(), @@ -59,7 +77,7 @@ async fn should_seed_default(iii: &IIIClient) -> Result { /// `Ok(None)` when the entry does not exist (`NOT_FOUND`). async fn try_get_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -97,7 +115,7 @@ pub fn register_config_trigger(iii: &IIIClient, cell: ConfigCell) -> Result<(), trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/pubsub/src/configuration.rs b/pubsub/src/configuration.rs index 70f09f1ae..38c2e74a5 100644 --- a/pubsub/src/configuration.rs +++ b/pubsub/src/configuration.rs @@ -24,7 +24,25 @@ use crate::boot::{ApplyLock, ConfigCell}; use crate::config::PubSubConfig; use crate::hub::Hub; -pub const CONFIG_ID: &str = "pubsub"; +pub const DEFAULT_CONFIG_ID: &str = "pubsub"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "pubsub::on-config-change"; const CONFIG_RETRIES: u32 = 3; const CONFIG_RETRY_BACKOFF_MS: u64 = 250; @@ -38,7 +56,7 @@ const CONFIG_BUS_TIMEOUT_MS: u64 = 10_000; /// included only when nothing is stored yet, so runtime edits survive restarts. pub async fn register_config(iii: &IIIClient, seed: Option<&PubSubConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "PubSub", "description": "PubSub worker settings — the pub/sub backend adapter (`local` in-process broadcast, or `redis` for cross-instance delivery). The adapter hot-swaps at runtime: a change rebuilds the backend and re-subscribes live subscriptions onto it.", "schema": PubSubConfig::json_schema(), @@ -64,7 +82,7 @@ pub async fn fetch_config(iii: &IIIClient) -> Result { match try_get_config_value(iii).await? { Some(value) if !value.is_null() => PubSubConfig::from_json(&value), _ => { - tracing::info!("no `{CONFIG_ID}` configuration value stored; using built-in default"); + tracing::info!("no `{config_entry}` configuration value stored; using built-in default", config_entry = config_id()); Ok(PubSubConfig::default()) } } @@ -81,7 +99,7 @@ async fn try_get_config_value(iii: &IIIClient) -> Result, String> match trigger_with_retry( iii, "configuration::get", - json!({ "id": CONFIG_ID }), + json!({ "id": config_id() }), CONFIG_BUS_TIMEOUT_MS, ) .await @@ -136,7 +154,7 @@ pub fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/queue/src/configuration.rs b/queue/src/configuration.rs index 500a823de..358456adc 100644 --- a/queue/src/configuration.rs +++ b/queue/src/configuration.rs @@ -15,7 +15,25 @@ use crate::trigger::QueueTriggerHandler; #[cfg(test)] use crate::{adapter::SwappableAdapter, boot, trigger::Invoker}; -pub const CONFIG_ID: &str = "queue"; +pub const DEFAULT_CONFIG_ID: &str = "queue"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} pub const CONFIG_FN_ID: &str = "queue::on-config-change"; const CONFIG_RETRIES: u32 = 3; const CONFIG_RETRY_BACKOFF_MS: u64 = 250; @@ -27,7 +45,7 @@ pub fn new_cell(config: QueueConfig) -> ConfigCell { pub async fn register_config(iii: &IIIClient, seed: Option<&QueueConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Queue", "description": "Durable queue worker settings: transport persistence and named function queues.", "schema": QueueConfig::json_schema(), @@ -54,7 +72,8 @@ pub async fn fetch_config(iii: &IIIClient) -> Result { Some(value) if !value.is_null() => QueueConfig::from_json(&value).map(|c| c.normalized()), _ => { tracing::info!( - "no `{CONFIG_ID}` configuration value stored; using durable packaged default" + "no `{config_entry}` configuration value stored; using durable packaged default", + config_entry = config_id() ); Ok(QueueConfig::packaged_default()) } @@ -69,7 +88,7 @@ pub async fn persist_config(iii: &IIIClient, config: &QueueConfig) -> Result<(), trigger_with_retry( iii, "configuration::set", - json!({ "id": CONFIG_ID, "value": config.to_json() }), + json!({ "id": config_id(), "value": config.to_json() }), CONFIG_BUS_TIMEOUT_MS, ) .await?; @@ -98,7 +117,7 @@ pub fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, @@ -156,7 +175,7 @@ async fn try_get_config_value(iii: &IIIClient) -> Result, String> match trigger_with_retry( iii, "configuration::get", - json!({ "id": CONFIG_ID }), + json!({ "id": config_id() }), CONFIG_BUS_TIMEOUT_MS, ) .await diff --git a/rbac-proxy/src/configuration.rs b/rbac-proxy/src/configuration.rs index dd12db53a..a102f52b2 100644 --- a/rbac-proxy/src/configuration.rs +++ b/rbac-proxy/src/configuration.rs @@ -33,7 +33,25 @@ use crate::server::ServerHandle; /// reload whole-snapshot replaces the inner `Arc` under the write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "rbac-proxy"; +pub const DEFAULT_CONFIG_ID: &str = "rbac-proxy"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "rbac-proxy::on-config-change"; const FUNCTIONS_AVAILABLE_FN_ID: &str = "rbac-proxy::on-functions-available"; const CONFIG_RETRIES: u32 = 3; @@ -50,7 +68,7 @@ pub async fn register_config( seed: Option<&WorkerConfig>, ) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "RBAC Proxy", "description": "Boundary-proxy settings: the public RBAC port, the trusted upstream engine URL, \ the RBAC contract (auth function, expose filters, registration hooks), middleware, \ @@ -101,13 +119,13 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// `Ok(None)` when the entry does not exist. Engine missing-entry codes vary in /// case, so match case-insensitively. async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.to_ascii_uppercase().contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -167,7 +185,7 @@ pub fn register_config_trigger( trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/session-manager/src/configuration.rs b/session-manager/src/configuration.rs index a51ba4bf0..06864550b 100644 --- a/session-manager/src/configuration.rs +++ b/session-manager/src/configuration.rs @@ -42,7 +42,25 @@ use crate::runtime::{build_runtime, SessionBuildContext, SessionRuntime}; /// replaces the inner `Arc` under the write lock. pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "session-manager"; +pub const DEFAULT_CONFIG_ID: &str = "session-manager"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "session::on-config-change"; const CONFIG_STATUS_FN_ID: &str = "session::config-status"; const CONFIG_TIMEOUT_MS: u64 = 5_000; @@ -138,7 +156,7 @@ impl ReloadStatus { /// this is safe to call every boot). pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Session Manager", "description": "Durable conversation store settings: the storage adapter (fs / bridge) \ and its config, plus the default and maximum page sizes for \ @@ -176,14 +194,14 @@ async fn should_seed_default_value(iii: &IIIClient) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } /// Returns `Ok(None)` when the entry does not exist. The engine's /// missing-entry codes vary in case (`function_not_found`, /// `STATEMENT_NOT_FOUND`, `NOT_FOUND`), so match case-insensitively. async fn try_get_config_value(iii: &IIIClient) -> Result, String> { - match trigger_with_retry(iii, "configuration::get", json!({ "id": CONFIG_ID })).await { + match trigger_with_retry(iii, "configuration::get", json!({ "id": config_id() })).await { Ok(resp) => Ok(resp.get("value").cloned()), Err(e) if e.to_ascii_uppercase().contains("NOT_FOUND") => Ok(None), Err(e) => Err(e), @@ -359,7 +377,7 @@ pub fn register_config_trigger(iii: &IIIClient, state: AppState) -> Result<(), E trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/shell/src/configuration.rs b/shell/src/configuration.rs index c25bb9251..11ed19a1c 100644 --- a/shell/src/configuration.rs +++ b/shell/src/configuration.rs @@ -17,7 +17,25 @@ use crate::config::ShellConfig; use crate::fs::host::{HostFsBackend, HostFsConfig, IiiChannelMaker}; use crate::fs::FsBackend; -pub const CONFIG_ID: &str = "shell"; +pub const DEFAULT_CONFIG_ID: &str = "shell"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "shell::on-config-change"; const CONFIG_TIMEOUT_MS: u64 = 5_000; const CONFIG_RETRIES: u32 = 3; @@ -180,7 +198,7 @@ pub fn build_runtime(cfg: &ShellConfig, iii: &IIIClient) -> Result) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Shell", "description": "Command denylist, timeout & output caps, and the fs jail.", "schema": ShellConfig::json_schema(), @@ -258,14 +276,14 @@ fn parse_fetched_value(value: Value) -> Result { async fn get_config_value(iii: &IIIClient) -> Result { try_get_config_value(iii, false) .await? - .ok_or_else(|| format!("configuration `{CONFIG_ID}` not found")) + .ok_or_else(|| format!("configuration `{config_entry}` not found", config_entry = config_id())) } async fn try_get_config_value(iii: &IIIClient, raw: bool) -> Result, String> { match trigger_with_retry( iii, "configuration::get", - json!({ "id": CONFIG_ID, "raw": raw }), + json!({ "id": config_id(), "raw": raw }), ) .await { @@ -360,7 +378,7 @@ pub fn register_config_trigger(iii: &IIIClient, state: AppState) -> Result<(), E trigger_type: "configuration".to_string(), function_id: CONFIG_FN_ID.to_string(), config: json!({ - "configuration_id": CONFIG_ID, + "configuration_id": config_id(), "event_types": ["configuration:updated"], }), metadata: None, diff --git a/slack/src/configuration.rs b/slack/src/configuration.rs index ec0326f8f..4d2d355d8 100644 --- a/slack/src/configuration.rs +++ b/slack/src/configuration.rs @@ -16,7 +16,25 @@ use crate::ingress; pub type ConfigCell = Arc>>; -pub const CONFIG_ID: &str = "slack"; +pub const DEFAULT_CONFIG_ID: &str = "slack"; + +/// The configuration entry this worker owns. +/// +/// `III_CONFIG_NAME` when a supervisor set it, else the built-in name. A worker +/// that hardcodes its id turns that id into a global scarce name: two instances +/// share one entry and take turns overwriting it, and each write wakes both. +/// Being told which entry is its own is what lets them differ. +pub fn config_id() -> &'static str { + static ID: std::sync::OnceLock = std::sync::OnceLock::new(); + ID.get_or_init(|| { + std::env::var("III_CONFIG_NAME") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()) + .unwrap_or_else(|| DEFAULT_CONFIG_ID.to_string()) + }) + .as_str() +} const CONFIG_FN_ID: &str = "slack::on-config-change"; const CONFIG_RETRIES: u32 = 3; const CONFIG_RETRY_BACKOFF_MS: u64 = 250; @@ -28,7 +46,7 @@ fn config_rpc_timeout_ms(seed: Option<&WorkerConfig>) -> u64 { pub async fn register_config(iii: &IIIClient, seed: Option<&WorkerConfig>) -> Result<(), String> { let mut payload = json!({ - "id": CONFIG_ID, + "id": config_id(), "name": "Slack", "description": "Slack worker: bot/user tokens, optional channel/team scoping, and RPC timeout. Configurable here or via env (${SLACK_BOT_TOKEN}).", "schema": WorkerConfig::json_schema(), @@ -76,7 +94,7 @@ async fn try_get_config_value(iii: &IIIClient, timeout_ms: u64) -> Result