From 98b2718d5846a0513e2755607fcf24067b6cfeab Mon Sep 17 00:00:00 2001 From: Timur Gordon <31495328+timurgordon@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:20:40 +0100 Subject: [PATCH] feat: simplify OpenRPC API and reorganize examples - Simplified RunnerConfig to just name, command, and optional env - Removed RunnerType and ProcessManagerType enums - Removed db_path, redis_url, binary_path from config - Made runner name also serve as queue name (no separate queue param) - Added secret-based authentication to all runner management methods - Created comprehensive osiris_openrpc example - Archived old examples to _archive/ - Updated client API to match simplified supervisor interface --- Cargo.lock | 1119 +++++++++-------- Cargo.toml | 25 +- MYCELIUM_OPTIONAL.md | 268 ++++ QUICK_START.md | 214 ++++ clients/openrpc/Cargo.toml | 1 + clients/openrpc/src/lib.rs | 129 +- cmd/supervisor.rs | 44 + examples/README.md | 210 +--- examples/_archive/E2E_EXAMPLES.md | 364 ++++++ examples/_archive/EXAMPLES_SUMMARY.md | 192 +++ examples/_archive/README.md | 182 +++ .../{ => _archive}/basic_openrpc_client.rs | 0 examples/_archive/end_to_end_demo.rs | 278 ++++ examples/{ => _archive}/integration_test.rs | 0 examples/{ => _archive}/job_api_examples.rs | 0 examples/{ => _archive}/mock_runner.rs | 0 examples/_archive/simple_e2e.rs | 203 +++ .../{ => _archive}/simple_job_workflow.rs | 0 examples/{ => _archive}/supervisor/README.md | 0 .../{ => _archive}/supervisor/config.toml | 0 .../supervisor/run_supervisor.rs | 0 .../supervisor/run_supervisor.sh | 0 examples/osiris_openrpc/README.md | 94 ++ examples/osiris_openrpc/access_denied.rhai | 8 + examples/osiris_openrpc/event.rhai | 18 + examples/osiris_openrpc/main.rs | 239 ++++ examples/osiris_openrpc/note.rhai | 20 + examples/osiris_openrpc/query.rhai | 21 + run_supervisor_simple.sh | 27 + src/app.rs | 69 +- src/lib.rs | 4 + src/mycelium.rs | 76 +- src/openrpc.rs | 1 - 33 files changed, 3018 insertions(+), 788 deletions(-) create mode 100644 MYCELIUM_OPTIONAL.md create mode 100644 QUICK_START.md create mode 100644 examples/_archive/E2E_EXAMPLES.md create mode 100644 examples/_archive/EXAMPLES_SUMMARY.md create mode 100644 examples/_archive/README.md rename examples/{ => _archive}/basic_openrpc_client.rs (100%) create mode 100644 examples/_archive/end_to_end_demo.rs rename examples/{ => _archive}/integration_test.rs (100%) rename examples/{ => _archive}/job_api_examples.rs (100%) rename examples/{ => _archive}/mock_runner.rs (100%) create mode 100644 examples/_archive/simple_e2e.rs rename examples/{ => _archive}/simple_job_workflow.rs (100%) rename examples/{ => _archive}/supervisor/README.md (100%) rename examples/{ => _archive}/supervisor/config.toml (100%) rename examples/{ => _archive}/supervisor/run_supervisor.rs (100%) rename examples/{ => _archive}/supervisor/run_supervisor.sh (100%) create mode 100644 examples/osiris_openrpc/README.md create mode 100644 examples/osiris_openrpc/access_denied.rhai create mode 100644 examples/osiris_openrpc/event.rhai create mode 100644 examples/osiris_openrpc/main.rs create mode 100644 examples/osiris_openrpc/note.rhai create mode 100644 examples/osiris_openrpc/query.rhai create mode 100755 run_supervisor_simple.sh diff --git a/Cargo.lock b/Cargo.lock index 672c0b7..988e3ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "aead" version = "0.5.2" @@ -46,7 +31,7 @@ checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "const-random", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -67,12 +52,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -84,9 +63,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -99,9 +78,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -134,9 +113,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arrayvec" @@ -163,7 +142,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -174,7 +153,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -189,21 +168,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -256,9 +220,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.3" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bitvec" @@ -301,7 +265,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -371,10 +335,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.34" +version = "1.2.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" dependencies = [ + "find-msvc-tools", "shlex", ] @@ -386,9 +351,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -422,17 +387,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -443,7 +407,7 @@ checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb" dependencies = [ "chrono", "chrono-tz-build", - "phf", + "phf 0.11.3", ] [[package]] @@ -453,7 +417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1" dependencies = [ "parse-zoneinfo", - "phf", + "phf 0.11.3", "phf_codegen", ] @@ -470,9 +434,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.45" +version = "4.5.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" +checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623" dependencies = [ "clap_builder", "clap_derive", @@ -480,9 +444,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.44" +version = "4.5.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" +checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0" dependencies = [ "anstream", "anstyle", @@ -492,21 +456,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.45" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "colorchoice" @@ -672,7 +636,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "crossterm_winapi", "mio", "parking_lot", @@ -722,21 +686,21 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] @@ -762,7 +726,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -773,7 +737,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -801,12 +765,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -864,7 +828,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -886,7 +850,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -958,9 +922,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ "log", "regex", @@ -1000,12 +964,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1053,6 +1017,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + [[package]] name = "fnv" version = "1.0.7" @@ -1151,7 +1121,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -1192,9 +1162,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -1210,30 +1180,24 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.3" @@ -1242,9 +1206,9 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "globset" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", "bstr", @@ -1259,7 +1223,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "ignore", "walkdir", ] @@ -1359,6 +1323,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "headers" version = "0.4.1" @@ -1411,8 +1381,8 @@ dependencies = [ "log", "rand 0.8.5", "redis 0.25.4", - "reqwest 0.12.23", - "runner_rust", + "reqwest 0.12.24", + "runner_rust 0.1.0 (git+https://git.ourworld.tf/herocode/runner_rust.git)", "serde", "serde_json", "thiserror 1.0.69", @@ -1437,6 +1407,7 @@ dependencies = [ "js-sys", "jsonrpsee", "log", + "runner_rust 0.1.0 (git+https://git.ourworld.tf/herocode/runner_rust.git?branch=main)", "serde", "serde_json", "thiserror 1.0.69", @@ -1467,7 +1438,7 @@ dependencies = [ [[package]] name = "heromodels" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/db.git#cb1fb0f0ec024c1c4411c270f31191ec7552a400" +source = "git+https://git.ourworld.tf/herocode/db.git#53e9a2d4f087f2869f1ed0cae251a6bb4ae1db2e" dependencies = [ "bincode", "chrono", @@ -1492,22 +1463,28 @@ dependencies = [ [[package]] name = "heromodels-derive" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/db.git#cb1fb0f0ec024c1c4411c270f31191ec7552a400" +source = "git+https://git.ourworld.tf/herocode/db.git#53e9a2d4f087f2869f1ed0cae251a6bb4ae1db2e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] name = "heromodels_core" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/db.git#cb1fb0f0ec024c1c4411c270f31191ec7552a400" +source = "git+https://git.ourworld.tf/herocode/db.git#53e9a2d4f087f2869f1ed0cae251a6bb4ae1db2e" dependencies = [ "chrono", "serde", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hkdf" version = "0.12.4" @@ -1528,11 +1505,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1614,9 +1591,9 @@ dependencies = [ [[package]] name = "humantime" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" @@ -1696,7 +1673,7 @@ dependencies = [ "hyper-util", "log", "rustls", - "rustls-native-certs 0.8.1", + "rustls-native-certs 0.8.2", "rustls-pki-types", "tokio", "tokio-rustls", @@ -1747,9 +1724,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ "base64 0.22.1", "bytes", @@ -1763,7 +1740,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2 0.6.1", "system-configuration 0.6.1", "tokio", "tower-service", @@ -1773,9 +1750,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1783,7 +1760,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -1910,9 +1887,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.23" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +checksum = "81776e6f9464432afcc28d03e52eb101c93b6f0566f52aef2427663e700f0403" dependencies = [ "crossbeam-deque", "globset", @@ -1926,19 +1903,22 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.0", ] [[package]] name = "indoc" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] [[package]] name = "inout" @@ -1959,7 +1939,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -1971,17 +1951,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.3", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -2000,20 +1969,20 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -2053,7 +2022,7 @@ checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -2095,9 +2064,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ "once_cell", "wasm-bindgen", @@ -2116,7 +2085,7 @@ dependencies = [ "jiff", "nom", "num-traits", - "ordered-float 5.0.0", + "ordered-float 5.1.0", "rand 0.9.2", "ryu", "serde", @@ -2140,9 +2109,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b26c20e2178756451cfeb0661fb74c47dd5988cb7e3939de7e9241fd604d42" +checksum = "e281ae70cc3b98dac15fced3366a880949e65fc66e345ce857a5682d152f3e62" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -2155,9 +2124,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456196007ca3a14db478346f58c7238028d55ee15c1df15115596e411ff27925" +checksum = "348ee569eaed52926b5e740aae20863762b16596476e943c9e415a6479021622" dependencies = [ "async-trait", "bytes", @@ -2178,9 +2147,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c872b6c9961a4ccc543e321bb5b89f6b2d2c7fe8b61906918273a3333c95400c" +checksum = "f50c389d6e6a52eb7c3548a6600c90cf74d9b71cb5912209833f00a5479e9a01" dependencies = [ "async-trait", "base64 0.22.1", @@ -2203,22 +2172,22 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e65763c942dfc9358146571911b0cd1c361c2d63e2d2305622d40d36376ca80" +checksum = "7398cddf5013cca4702862a2692b66c48a3bd6cf6ec681a47453c93d63cf8de5" dependencies = [ "heck", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] name = "jsonrpsee-server" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e363146da18e50ad2b51a0a7925fc423137a0b1371af8235b1c231a0647328" +checksum = "21429bcdda37dcf2d43b68621b994adede0e28061f816b038b0f18c70c143d51" dependencies = [ "futures-util", "http 1.3.1", @@ -2243,9 +2212,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a8e70baf945b6b5752fc8eb38c918a48f1234daf11355e07106d963f860089" +checksum = "b0f05e0028e55b15dbd2107163b3c744cd3bb4474f193f95d9708acbf5677e44" dependencies = [ "http 1.3.1", "serde", @@ -2357,7 +2326,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -2368,9 +2337,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libm" @@ -2380,11 +2349,11 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "libc", "redox_syscall", ] @@ -2397,9 +2366,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" @@ -2409,19 +2378,18 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "lru" @@ -2464,9 +2432,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "mime" @@ -2474,15 +2442,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - [[package]] name = "mio" version = "1.0.4" @@ -2491,7 +2450,7 @@ checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "windows-sys 0.59.0", ] @@ -2518,7 +2477,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "cfg-if", "cfg_aliases", "libc", @@ -2550,11 +2509,11 @@ checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2591,15 +2550,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -2611,9 +2561,9 @@ dependencies = [ [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "opaque-debug" @@ -2623,11 +2573,11 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "cfg-if", "foreign-types", "libc", @@ -2644,7 +2594,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -2655,9 +2605,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" dependencies = [ "cc", "libc", @@ -2682,9 +2632,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "5.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" +checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" dependencies = [ "num-traits", ] @@ -2717,13 +2667,13 @@ source = "git+https://git.ourworld.tf/herocode/osiris.git#097360ad12d2ea73ac4d38 dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] name = "ourdb" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "crc32fast", "log", @@ -2733,9 +2683,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -2743,15 +2693,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -2781,12 +2731,12 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] @@ -2797,20 +2747,19 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror 2.0.16", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -2818,22 +2767,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] name = "pest_meta" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ "pest", "sha2", @@ -2845,7 +2794,17 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_shared", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_shared 0.13.1", + "serde", ] [[package]] @@ -2855,7 +2814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", - "phf_shared", + "phf_shared 0.11.3", ] [[package]] @@ -2864,7 +2823,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared", + "phf_shared 0.11.3", "rand 0.8.5", ] @@ -2877,6 +2836,15 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -2894,7 +2862,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -2925,19 +2893,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "plist" -version = "1.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1" -dependencies = [ - "base64 0.22.1", - "indexmap", - "quick-xml", - "serde", - "time", -] - [[package]] name = "poly1305" version = "0.8.0" @@ -2966,9 +2921,9 @@ dependencies = [ [[package]] name = "postgres" -version = "0.19.10" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e6dfbdd780d3aa3597b6eb430db76bb315fa9bad7fae595bb8def808b8470" +checksum = "e7c48ece1c6cda0db61b058c1721378da76855140e9214339fa1317decacb176" dependencies = [ "bytes", "fallible-iterator", @@ -2980,9 +2935,9 @@ dependencies = [ [[package]] name = "postgres-protocol" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ff0abab4a9b844b93ef7b81f1efc0a366062aaef2cd702c76256b5dc075c54" +checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" dependencies = [ "base64 0.22.1", "byteorder", @@ -2998,22 +2953,22 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48" +checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" dependencies = [ "bytes", "fallible-iterator", "postgres-protocol", - "serde", + "serde_core", "serde_json", ] [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" dependencies = [ "zerovec", ] @@ -3049,18 +3004,18 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit", + "toml_edit 0.23.7", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -3095,25 +3050,16 @@ dependencies = [ "libc", "once_cell", "raw-cpuid", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "web-sys", "winapi", ] -[[package]] -name = "quick-xml" -version = "0.38.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" -dependencies = [ - "memchr", -] - [[package]] name = "quote" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] @@ -3207,7 +3153,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] @@ -3216,7 +3162,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "cassowary", "compact_str", "crossterm", @@ -3237,7 +3183,7 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", ] [[package]] @@ -3300,11 +3246,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", ] [[package]] @@ -3326,14 +3272,14 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -3343,9 +3289,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -3354,9 +3300,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rend" @@ -3409,9 +3355,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ "base64 0.22.1", "bytes", @@ -3466,7 +3412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce4d759a4729a655ddfdbb3ff6e77fb9eadd902dae12319455557796e435d2a6" dependencies = [ "ahash 0.8.12", - "bitflags 2.9.3", + "bitflags 2.10.0", "instant", "no-std-compat", "num-traits", @@ -3487,7 +3433,7 @@ checksum = "a5a11a05ee1ce44058fa3d5961d05194fdbe3ad6b40f904af764d81b86450e6b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -3510,7 +3456,7 @@ dependencies = [ [[package]] name = "rhailib-macros" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "rhai", "serde", @@ -3589,7 +3535,7 @@ checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] name = "runner_rust" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/runner_rust.git#eba066066661d7fa8cb4603740d896a48814c80c" +source = "git+https://git.ourworld.tf/herocode/runner_rust.git?branch=main#228eb4ffe7b66ed0625a0d118e418743cd4c6e50" dependencies = [ "anyhow", "async-trait", @@ -3601,8 +3547,10 @@ dependencies = [ "heromodels", "heromodels-derive", "heromodels_core", + "hex", "log", "osiris", + "rand 0.8.5", "ratatui", "redis 0.25.4", "rhai", @@ -3616,13 +3564,61 @@ dependencies = [ "sal-postgresclient", "sal-process", "sal-redisclient", - "sal-service-manager", "sal-text", "sal-vault", "sal-virt", "sal-zinit-client", + "secp256k1", "serde", "serde_json", + "sha2", + "thiserror 1.0.69", + "tokio", + "toml", + "tracing", + "uuid", +] + +[[package]] +name = "runner_rust" +version = "0.1.0" +source = "git+https://git.ourworld.tf/herocode/runner_rust.git#90754cc4ac42c5f29ed124033ce6c44771124db3" +dependencies = [ + "anyhow", + "async-trait", + "chrono", + "clap", + "crossterm", + "env_logger 0.10.2", + "hero_logger", + "heromodels", + "heromodels-derive", + "heromodels_core", + "hex", + "log", + "osiris", + "rand 0.8.5", + "ratatui", + "redis 0.25.4", + "rhai", + "rhailib_dsl", + "sal-git", + "sal-hetzner", + "sal-kubernetes", + "sal-mycelium", + "sal-net", + "sal-os", + "sal-postgresclient", + "sal-process", + "sal-redisclient", + "sal-text", + "sal-vault", + "sal-virt", + "sal-zinit-client", + "secp256k1", + "serde", + "serde_json", + "sha2", "thiserror 1.0.69", "tokio", "toml", @@ -3632,9 +3628,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.37.2" +version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b203a6425500a03e0919c42d3c47caca51e79f1132046626d2c8871c5092035d" +checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" dependencies = [ "arrayvec", "borsh", @@ -3646,12 +3642,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -3664,7 +3654,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3673,22 +3663,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" dependencies = [ "log", "once_cell", @@ -3714,14 +3704,14 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.3.0", + "security-framework 3.5.1", ] [[package]] @@ -3763,10 +3753,10 @@ dependencies = [ "log", "once_cell", "rustls", - "rustls-native-certs 0.8.1", + "rustls-native-certs 0.8.2", "rustls-platform-verifier-android", "rustls-webpki", - "security-framework 3.3.0", + "security-framework 3.5.1", "security-framework-sys", "webpki-root-certs 0.26.11", "windows-sys 0.59.0", @@ -3780,9 +3770,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" dependencies = [ "ring", "rustls-pki-types", @@ -3804,7 +3794,7 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "sal-git" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "log", "redis 0.31.0", @@ -3818,20 +3808,20 @@ dependencies = [ [[package]] name = "sal-hetzner" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "prettytable", - "reqwest 0.12.23", + "reqwest 0.12.24", "rhai", "serde", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] name = "sal-kubernetes" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "anyhow", "base64 0.22.1", @@ -3845,7 +3835,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "thiserror 2.0.16", + "thiserror 2.0.17", "tokio", "tokio-retry", "tower 0.5.2", @@ -3855,11 +3845,11 @@ dependencies = [ [[package]] name = "sal-mycelium" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "base64 0.22.1", "log", - "reqwest 0.12.23", + "reqwest 0.12.24", "rhai", "serde_json", "tokio", @@ -3869,10 +3859,10 @@ dependencies = [ [[package]] name = "sal-net" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "anyhow", - "reqwest 0.12.23", + "reqwest 0.12.24", "rhai", "tokio", ] @@ -3880,23 +3870,23 @@ dependencies = [ [[package]] name = "sal-os" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "anyhow", "dirs", "glob", "libc", "nix", - "reqwest 0.12.23", + "reqwest 0.12.24", "rhai", - "thiserror 2.0.16", + "thiserror 2.0.17", "windows", ] [[package]] name = "sal-postgresclient" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "lazy_static", "postgres", @@ -3905,14 +3895,14 @@ dependencies = [ "r2d2_postgres", "rhai", "sal-virt", - "thiserror 2.0.16", + "thiserror 2.0.17", "tokio-postgres", ] [[package]] name = "sal-process" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "anyhow", "nix", @@ -3925,35 +3915,17 @@ dependencies = [ [[package]] name = "sal-redisclient" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "lazy_static", "redis 0.31.0", "rhai", ] -[[package]] -name = "sal-service-manager" -version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" -dependencies = [ - "async-trait", - "chrono", - "futures", - "log", - "once_cell", - "plist", - "serde", - "serde_json", - "thiserror 1.0.69", - "tokio", - "zinit-client", -] - [[package]] name = "sal-text" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "regex", "rhai", @@ -3964,12 +3936,12 @@ dependencies = [ [[package]] name = "sal-vault" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "bincode", "chacha20poly1305", "getrandom 0.2.16", - "getrandom 0.3.3", + "getrandom 0.3.4", "k256", "pbkdf2", "rand 0.8.5", @@ -3981,7 +3953,7 @@ dependencies = [ [[package]] name = "sal-virt" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "anyhow", "rhai", @@ -3995,7 +3967,7 @@ dependencies = [ [[package]] name = "sal-zinit-client" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "anyhow", "futures", @@ -4003,7 +3975,7 @@ dependencies = [ "log", "rhai", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.17", "tokio", "zinit-client", ] @@ -4019,11 +3991,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4056,7 +4028,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -4085,6 +4057,25 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "rand 0.8.5", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -4101,7 +4092,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -4110,11 +4101,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.3.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -4123,9 +4114,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -4133,10 +4124,11 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -4151,14 +4143,23 @@ dependencies = [ ] [[package]] -name = "serde_derive" -version = "1.0.219" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -4169,20 +4170,21 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "indexmap", "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -4373,12 +4375,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -4424,9 +4426,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -4470,7 +4472,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -4492,9 +4494,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ "proc-macro2", "quote", @@ -4524,7 +4526,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -4544,7 +4546,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -4577,15 +4579,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.21.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", - "rustix 1.0.8", - "windows-sys 0.60.2", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -4650,11 +4652,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.16", + "thiserror-impl 2.0.17", ] [[package]] @@ -4665,18 +4667,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -4690,11 +4692,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.43" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", "serde", @@ -4754,33 +4757,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.6.0", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -4795,9 +4795,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c95d533c83082bb6490e0189acaa0bbeef9084e60471b696ca6988cd0541fb0" +checksum = "2b40d66d9b2cfe04b628173409368e58247e8eddbbd3b0e6c6ba1d09f20f6c9e" dependencies = [ "async-trait", "byteorder", @@ -4808,12 +4808,12 @@ dependencies = [ "log", "parking_lot", "percent-encoding", - "phf", + "phf 0.13.1", "pin-project-lite", "postgres-protocol", "postgres-types", "rand 0.9.2", - "socket2 0.5.10", + "socket2 0.6.1", "tokio", "tokio-util", "whoami", @@ -4832,9 +4832,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -4887,8 +4887,8 @@ checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] @@ -4900,6 +4900,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" @@ -4909,11 +4918,32 @@ dependencies = [ "indexmap", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.11", "toml_write", "winnow", ] +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime 0.7.3", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + [[package]] name = "toml_write" version = "0.1.2" @@ -4961,7 +4991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "base64 0.21.7", - "bitflags 2.9.3", + "bitflags 2.10.0", "bytes", "http 1.3.1", "http-body 1.0.1", @@ -4979,7 +5009,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags 2.9.3", + "bitflags 2.10.0", "bytes", "futures-util", "http 1.3.1", @@ -5035,7 +5065,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -5099,7 +5129,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tst" version = "0.1.0" -source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#7afa5ea1c0d9bb240fd2a96e5a0a01b04372fa1c" +source = "git+https://git.ourworld.tf/herocode/herolib_rust.git#9865e601d79d8b74678b1e3db278b085bbb6bda4" dependencies = [ "ourdb", "thiserror 1.0.69", @@ -5107,9 +5137,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" @@ -5175,9 +5205,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" [[package]] name = "unicode-normalization" @@ -5247,13 +5277,14 @@ checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" [[package]] name = "url" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "137a3c834eaf7139b73688502f3f1141a0337c5d8e4d9b536f9b8c796e26a7c4" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -5276,11 +5307,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", "serde", "wasm-bindgen", @@ -5336,12 +5367,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] @@ -5352,35 +5383,36 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" dependencies = [ "cfg-if", "js-sys", @@ -5391,9 +5423,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5401,31 +5433,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" dependencies = [ "js-sys", "wasm-bindgen", @@ -5437,14 +5469,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" dependencies = [ - "webpki-root-certs 1.0.2", + "webpki-root-certs 1.0.3", ] [[package]] name = "webpki-root-certs" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a" +checksum = "05d651ec480de84b762e7be71e6efa7461699c19d9e2c272c8d93455f567786e" dependencies = [ "rustls-pki-types", ] @@ -5478,11 +5510,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -5498,9 +5530,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", - "windows-core", + "windows-core 0.61.2", "windows-future", - "windows-link", + "windows-link 0.1.3", "windows-numerics", ] @@ -5510,7 +5542,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core", + "windows-core 0.61.2", ] [[package]] @@ -5521,9 +5553,22 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -5532,31 +5577,31 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "windows-core", - "windows-link", + "windows-core 0.61.2", + "windows-link 0.1.3", "windows-threading", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -5565,14 +5610,20 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-numerics" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core", - "windows-link", + "windows-core 0.61.2", + "windows-link 0.1.3", ] [[package]] @@ -5581,9 +5632,9 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] @@ -5592,7 +5643,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -5601,7 +5661,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -5646,7 +5715,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -5697,19 +5775,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -5718,7 +5796,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5741,9 +5819,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -5765,9 +5843,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -5789,9 +5867,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -5801,9 +5879,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -5825,9 +5903,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -5849,9 +5927,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -5873,9 +5951,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -5897,9 +5975,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" @@ -5921,13 +5999,10 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.3", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" @@ -5964,28 +6039,28 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] @@ -6005,15 +6080,15 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" @@ -6045,7 +6120,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.108", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 03caed7..01c663c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,14 +38,10 @@ anyhow = "1.0" tower-http = { version = "0.5", features = ["cors"] } tower = "0.4" -# Base64 encoding for Mycelium payloads -base64 = "0.22" - -# Random number generation for message IDs -rand = "0.8" - -# HTTP client for Mycelium integration -reqwest = { version = "0.12", features = ["json"] } +# Mycelium integration (optional) +base64 = { version = "0.22", optional = true } +rand = { version = "0.8", optional = true } +reqwest = { version = "0.12", features = ["json"], optional = true } [dev-dependencies] tokio-test = "0.4" @@ -55,6 +51,7 @@ escargot = "0.5" [features] default = ["cli"] cli = [] +mycelium = ["base64", "rand", "reqwest"] [[bin]] name = "supervisor" @@ -62,14 +59,6 @@ path = "cmd/supervisor.rs" # Examples [[example]] -name = "openrpc_comprehensive" -path = "examples/basic_openrpc_client.rs" - -[[example]] -name = "mock_runner" -path = "examples/mock_runner.rs" - -[[example]] -name = "supervisor" -path = "examples/supervisor/run_supervisor.rs" +name = "osiris_openrpc" +path = "examples/osiris_openrpc/main.rs" diff --git a/MYCELIUM_OPTIONAL.md b/MYCELIUM_OPTIONAL.md new file mode 100644 index 0000000..2fda463 --- /dev/null +++ b/MYCELIUM_OPTIONAL.md @@ -0,0 +1,268 @@ +# Mycelium Integration - Now Optional! + +The Mycelium integration is now an optional feature. The supervisor can run with just the OpenRPC HTTP server, making it simpler to use and deploy. + +## What Changed + +### Before +- Mycelium integration was always enabled +- Supervisor would continuously try to connect to Mycelium on port 8990 +- Error logs if Mycelium wasn't available +- Required additional dependencies + +### After +- ✅ Mycelium is now an optional feature +- ✅ Supervisor runs with clean OpenRPC HTTP server by default +- ✅ No connection errors when Mycelium isn't needed +- ✅ Smaller binary size without Mycelium dependencies + +## Running the Supervisor + +### Option 1: Simple OpenRPC Server (Recommended) + +**No Mycelium, just OpenRPC:** + +```bash +# Using the helper script +./run_supervisor_simple.sh + +# Or manually +MYCELIUM_URL="" cargo run --bin supervisor -- \ + --redis-url redis://localhost:6379 \ + --port 3030 +``` + +This starts: +- ✅ OpenRPC HTTP server on port 3030 +- ✅ Redis connection for job queuing +- ❌ No Mycelium integration + +### Option 2: With Mycelium Integration + +**Enable Mycelium feature:** + +```bash +# Build with Mycelium support +cargo build --bin supervisor --features mycelium + +# Run with Mycelium URL +MYCELIUM_URL="http://localhost:8990" cargo run --bin supervisor --features mycelium -- \ + --redis-url redis://localhost:6379 \ + --port 3030 +``` + +This starts: +- ✅ OpenRPC HTTP server on port 3030 +- ✅ Redis connection for job queuing +- ✅ Mycelium integration (connects to daemon) + +## Feature Flags + +### Available Features + +| Feature | Description | Default | +|---------|-------------|---------| +| `cli` | Command-line interface | ✅ Yes | +| `mycelium` | Mycelium integration | ❌ No | + +### Building with Features + +```bash +# Default build (CLI only, no Mycelium) +cargo build --bin supervisor + +# With Mycelium +cargo build --bin supervisor --features mycelium + +# Minimal (no CLI, no Mycelium) +cargo build --bin supervisor --no-default-features +``` + +## Architecture + +### Without Mycelium (Default) + +``` +┌─────────────────┐ +│ Client │ +└────────┬────────┘ + │ HTTP/JSON-RPC + ▼ +┌─────────────────┐ +│ Supervisor │ +│ OpenRPC Server │ +│ (Port 3030) │ +└────────┬────────┘ + │ Redis + ▼ +┌─────────────────┐ +│ Runners │ +└─────────────────┘ +``` + +### With Mycelium (Optional) + +``` +┌─────────────────┐ +│ Client │ +└────────┬────────┘ + │ HTTP/JSON-RPC + ▼ +┌─────────────────┐ ┌──────────────┐ +│ Supervisor │◄────►│ Mycelium │ +│ OpenRPC Server │ │ Daemon │ +│ (Port 3030) │ │ (Port 8990) │ +└────────┬────────┘ └──────────────┘ + │ Redis + ▼ +┌─────────────────┐ +│ Runners │ +└─────────────────┘ +``` + +## Environment Variables + +| Variable | Description | Default | Required | +|----------|-------------|---------|----------| +| `MYCELIUM_URL` | Mycelium daemon URL | `http://127.0.0.1:8990` | No | +| `RUST_LOG` | Log level | `info` | No | + +**To disable Mycelium:** +```bash +export MYCELIUM_URL="" +``` + +## Dependencies + +### Core Dependencies (Always) +- `tokio` - Async runtime +- `redis` - Job queuing +- `jsonrpsee` - OpenRPC server +- `runner_rust` - Job model + +### Mycelium Dependencies (Optional) +- `reqwest` - HTTP client +- `base64` - Encoding +- `rand` - Random IDs + +## Examples + +All examples work without Mycelium: + +```bash +# Simple end-to-end example +RUST_LOG=info cargo run --example simple_e2e + +# Full automated demo +RUST_LOG=info cargo run --example end_to_end_demo +``` + +## Migration Guide + +### If you were using Mycelium + +**Before:** +```bash +cargo run --bin supervisor +# Would try to connect to Mycelium automatically +``` + +**After:** +```bash +# Option A: Disable Mycelium (recommended for most use cases) +MYCELIUM_URL="" cargo run --bin supervisor + +# Option B: Enable Mycelium feature +cargo run --bin supervisor --features mycelium +``` + +### If you weren't using Mycelium + +**Before:** +```bash +cargo run --bin supervisor +# Would see connection errors to port 8990 +``` + +**After:** +```bash +cargo run --bin supervisor +# Clean startup, no connection errors! 🎉 +``` + +## Benefits + +### For Development +- ✅ Faster builds (fewer dependencies) +- ✅ Simpler setup (no Mycelium daemon needed) +- ✅ Cleaner logs (no connection errors) +- ✅ Easier debugging + +### For Production +- ✅ Smaller binary size +- ✅ Fewer runtime dependencies +- ✅ More flexible deployment +- ✅ Optional advanced features + +## Testing + +### Test without Mycelium +```bash +# Build +cargo build --bin supervisor + +# Run tests +cargo test + +# Run examples +cargo run --example simple_e2e +``` + +### Test with Mycelium +```bash +# Build with feature +cargo build --bin supervisor --features mycelium + +# Start Mycelium daemon (if you have one) +# mycelium-daemon --port 8990 + +# Run supervisor +MYCELIUM_URL="http://localhost:8990" cargo run --bin supervisor --features mycelium +``` + +## Troubleshooting + +### "Mycelium integration not enabled" + +This is informational, not an error. If you need Mycelium: + +```bash +cargo build --features mycelium +``` + +### "HTTP request failed: error sending request" + +If you see this with Mycelium enabled, check: +1. Is Mycelium daemon running? +2. Is the URL correct? (`MYCELIUM_URL`) +3. Is the port accessible? + +Or simply disable Mycelium: +```bash +export MYCELIUM_URL="" +``` + +## Summary + +🎉 **The supervisor now runs cleanly with just OpenRPC!** + +- Default: OpenRPC HTTP server only +- Optional: Enable Mycelium with `--features mycelium` +- No more connection errors when Mycelium isn't needed +- Simpler, faster, cleaner! + +--- + +**Status:** ✅ Complete +**Version:** 0.1.0 +**Last Updated:** 2025-10-24 diff --git a/QUICK_START.md b/QUICK_START.md new file mode 100644 index 0000000..36d7347 --- /dev/null +++ b/QUICK_START.md @@ -0,0 +1,214 @@ +# Quick Start Guide + +Complete guide to running the Hero Supervisor with OSIS runners and examples. + +## Prerequisites + +1. **Redis** - Must be running +2. **Rust** - Version 1.88+ (run `rustup update`) + +## 1. Start Redis + +```bash +redis-server +``` + +## 2. Start Supervisor + +```bash +cd /Users/timurgordon/code/git.ourworld.tf/herocode/supervisor +cargo run --bin supervisor +``` + +You should see: +``` +╔════════════════════════════════════════════════════════════╗ +║ Hero Supervisor Started ║ +╚════════════════════════════════════════════════════════════╝ + 📡 OpenRPC Server: http://127.0.0.1:3030 + 🔗 Redis: redis://localhost:6379 + 🌐 Mycelium: Not compiled (use --features mycelium) +╚════════════════════════════════════════════════════════════╝ +``` + +## 3. Start OSIS Runner + +```bash +cd /Users/timurgordon/code/git.ourworld.tf/herocode/runner_rust +cargo run --bin runner_osis -- test_runner \ + --redis-url redis://localhost:6379 \ + --db-path /tmp/test_runner.db +``` + +You should see: +``` +Starting OSIS Sync Runner with ID: test_runner +Database path: /tmp/test_runner.db +Redis URL: redis://localhost:6379 +OSIS Sync Runner 'test_runner' started successfully +``` + +## 4. Run Example + +```bash +cd /Users/timurgordon/code/git.ourworld.tf/herocode/supervisor +RUST_LOG=info cargo run --example simple_e2e +``` + +## Terminal Layout + +``` +┌─────────────────────┬─────────────────────┐ +│ Terminal 1 │ Terminal 2 │ +│ Redis │ Supervisor │ +│ redis-server │ cargo run --bin │ +│ │ supervisor │ +├─────────────────────┼─────────────────────┤ +│ Terminal 3 │ Terminal 4 │ +│ OSIS Runner │ Example │ +│ cargo run --bin │ cargo run │ +│ runner_osis │ --example │ +│ │ simple_e2e │ +└─────────────────────┴─────────────────────┘ +``` + +## What Each Component Does + +### Redis +- Job queue storage +- Job result storage +- Runner coordination + +### Supervisor +- OpenRPC HTTP server (port 3030) +- Job dispatch to runners +- Runner registration +- Job execution coordination + +### OSIS Runner +- Listens for jobs on Redis queue +- Executes Rhai scripts +- Stores results back to Redis +- Uses HeroDB for data persistence + +### Example +- Creates jobs with Rhai scripts +- Sends jobs to supervisor via OpenRPC +- Receives results +- Demonstrates both blocking and non-blocking modes + +## Architecture + +``` +┌─────────────┐ +│ Example │ (simple_e2e.rs) +└──────┬──────┘ + │ HTTP/JSON-RPC + ▼ +┌─────────────┐ +│ Supervisor │ (port 3030) +└──────┬──────┘ + │ Redis Queue + ▼ +┌─────────────┐ +│ OSIS Runner │ (test_runner) +└──────┬──────┘ + │ + ▼ +┌─────────────┐ +│ HeroDB │ (Redis + local DB) +└─────────────┘ +``` + +## Troubleshooting + +### "Connection refused" on port 3030 +- Make sure supervisor is running +- Check if another process is using port 3030 + +### "Connection refused" on port 6379 +- Make sure Redis is running +- Check: `redis-cli ping` (should return "PONG") + +### Runner not receiving jobs +- Check runner is registered: Look for "Runner registered successfully" in example output +- Check Redis connection: Both supervisor and runner must use same Redis URL +- Check queue name matches: Should be `hero:q:work:type:osis:group:default:inst:test_runner` + +### "Job execution timeout" +- Increase timeout in job builder: `.timeout(120)` +- Check if runner is actually processing jobs (look for logs) + +## Example Output + +### Successful Run + +``` +╔════════════════════════════════════════╗ +║ Simple End-to-End Demo ║ +╚════════════════════════════════════════╝ + +📋 Step 1: Registering Runner +───────────────────────────────────────── +✅ Runner registered successfully + +📋 Step 2: Running a Simple Job (Blocking) +───────────────────────────────────────── +✅ Job completed! + Result: {"message":"Hello from the runner!","number":42} + +📋 Step 3: Running a Calculation Job +───────────────────────────────────────── +✅ Calculation completed! + Result: {"sum":55,"product":3628800,"count":10} + +📋 Step 4: Starting a Non-Blocking Job +───────────────────────────────────────── +✅ Job started! + Job ID: abc-123 (running in background) + +🎉 Demo completed successfully! +``` + +## Next Steps + +1. **Try different Rhai scripts** - Modify the payload in examples +2. **Add more runners** - Start multiple runners with different IDs +3. **Explore the API** - Use the OpenRPC client library +4. **Build your own client** - See `clients/openrpc/` for examples + +## Useful Commands + +```bash +# Check Redis +redis-cli ping + +# List Redis keys +redis-cli keys "hero:*" + +# Monitor Redis commands +redis-cli monitor + +# Check supervisor is running +curl http://localhost:3030 + +# View runner logs +# (check terminal where runner is running) +``` + +## Clean Up + +```bash +# Stop all processes (Ctrl+C in each terminal) + +# Clean up test database +rm /tmp/test_runner.db + +# (Optional) Flush Redis +redis-cli FLUSHALL +``` + +--- + +**Status:** ✅ Ready to Use +**Last Updated:** 2025-10-24 diff --git a/clients/openrpc/Cargo.toml b/clients/openrpc/Cargo.toml index 2206be3..8d73f55 100644 --- a/clients/openrpc/Cargo.toml +++ b/clients/openrpc/Cargo.toml @@ -26,6 +26,7 @@ indexmap = "2.0" jsonrpsee = { version = "0.24", features = ["http-client", "macros"] } tokio = { version = "1.0", features = ["full"] } hero-supervisor = { path = "../.." } +runner_rust = { git = "https://git.ourworld.tf/herocode/runner_rust.git", branch = "main" } env_logger = "0.11" # WASM-specific dependencies diff --git a/clients/openrpc/src/lib.rs b/clients/openrpc/src/lib.rs index c7b851e..113031b 100644 --- a/clients/openrpc/src/lib.rs +++ b/clients/openrpc/src/lib.rs @@ -115,40 +115,16 @@ impl From for ClientError { /// Result type for client operations pub type ClientResult = Result; -/// Types of runners supported by the supervisor -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum RunnerType { - /// SAL Runner for system abstraction layer operations - SALRunner, - /// OSIS Runner for operating system interface operations - OSISRunner, - /// V Runner for virtualization operations - VRunner, - /// Python Runner for Python-based actors - PyRunner, -} - -/// Process manager type for WASM compatibility -#[cfg(target_arch = "wasm32")] -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum ProcessManagerType { - Simple, - Tmux(String), -} - -/// Configuration for an actor runner +/// Configuration for a runner #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RunnerConfig { - /// Unique identifier for the actor - pub actor_id: String, - /// Type of runner - pub runner_type: RunnerType, - /// Path to the actor binary - pub binary_path: PathBuf, - /// Database path for the actor - pub db_path: String, - /// Redis URL for job queue - pub redis_url: String, + /// Name of the runner + pub name: String, + /// Command to run the runner (full command line) + pub command: String, + /// Optional environment variables + #[serde(skip_serializing_if = "Option::is_none")] + pub env: Option>, } @@ -171,6 +147,21 @@ pub struct JobStatusResponse { pub completed_at: Option, } +/// Response from job.run (blocking execution) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct JobRunResponse { + pub job_id: String, + pub status: String, + pub result: Option, +} + +/// Response from job.start (non-blocking execution) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct JobStartResponse { + pub job_id: String, + pub status: String, +} + // Re-export Job types from runner_rust crate (native only) #[cfg(not(target_arch = "wasm32"))] pub use runner_rust::{Job, JobStatus, JobError, JobBuilder, Client, ClientBuilder}; @@ -219,7 +210,7 @@ pub type ProcessStatus = ProcessStatusWrapper; /// Re-export types from supervisor crate for native builds #[cfg(not(target_arch = "wasm32"))] -pub use hero_supervisor::{ProcessManagerType, RunnerStatus}; +pub use hero_supervisor::RunnerStatus; #[cfg(not(target_arch = "wasm32"))] pub use hero_supervisor::runner::LogInfo; @@ -262,17 +253,17 @@ impl SupervisorClient { } /// Register a new runner to the supervisor with secret authentication + /// The runner name is also used as the queue name pub async fn register_runner( &self, secret: &str, name: &str, - queue: &str, ) -> ClientResult<()> { let _: () = self .client .request( "register_runner", - rpc_params![secret, name, queue], + rpc_params![secret, name], ) .await.map_err(|e| ClientError::JsonRpc(e))?; Ok(()) @@ -305,40 +296,47 @@ impl SupervisorClient { Ok(jobs) } - /// Run a job on the appropriate runner and return the result + /// Run a job on the appropriate runner and wait for the result (blocking) + /// This method queues the job and waits for completion before returning pub async fn job_run( &self, secret: &str, job: Job, - ) -> ClientResult { - let params = serde_json::json!({ + timeout: Option, + ) -> ClientResult { + let mut params = serde_json::json!({ "secret": secret, "job": job }); - let result: JobResult = self + if let Some(t) = timeout { + params["timeout"] = serde_json::json!(t); + } + + let result: JobRunResponse = self .client .request("job.run", rpc_params![params]) .await.map_err(|e| ClientError::JsonRpc(e))?; Ok(result) } - /// Start a previously created job by queuing it to its assigned runner + /// Start a job without waiting for the result (non-blocking) + /// This method queues the job and returns immediately with the job_id pub async fn job_start( &self, secret: &str, - job_id: &str, - ) -> ClientResult<()> { + job: Job, + ) -> ClientResult { let params = serde_json::json!({ "secret": secret, - "job_id": job_id + "job": job }); - let _: () = self + let result: JobStartResponse = self .client .request("job.start", rpc_params![params]) .await.map_err(|e| ClientError::JsonRpc(e))?; - Ok(()) + Ok(result) } /// Get the current status of a job @@ -360,10 +358,14 @@ impl SupervisorClient { } /// Remove a runner from the supervisor - pub async fn remove_runner(&self, actor_id: &str) -> ClientResult<()> { + pub async fn remove_runner(&self, secret: &str, actor_id: &str) -> ClientResult<()> { + let params = serde_json::json!({ + "secret": secret, + "actor_id": actor_id + }); let _: () = self .client - .request("remove_runner", rpc_params![actor_id]) + .request("remove_runner", rpc_params![params]) .await.map_err(|e| ClientError::JsonRpc(e))?; Ok(()) } @@ -378,37 +380,54 @@ impl SupervisorClient { } /// Start a specific runner - pub async fn start_runner(&self, actor_id: &str) -> ClientResult<()> { + pub async fn start_runner(&self, secret: &str, actor_id: &str) -> ClientResult<()> { + let params = serde_json::json!({ + "secret": secret, + "actor_id": actor_id + }); let _: () = self .client - .request("start_runner", rpc_params![actor_id]) + .request("start_runner", rpc_params![params]) .await.map_err(|e| ClientError::JsonRpc(e))?; Ok(()) } /// Stop a specific runner - pub async fn stop_runner(&self, actor_id: &str, force: bool) -> ClientResult<()> { + pub async fn stop_runner(&self, secret: &str, actor_id: &str, force: bool) -> ClientResult<()> { + let params = serde_json::json!({ + "secret": secret, + "actor_id": actor_id, + "force": force + }); let _: () = self .client - .request("stop_runner", rpc_params![actor_id, force]) + .request("stop_runner", rpc_params![params]) .await.map_err(|e| ClientError::JsonRpc(e))?; Ok(()) } /// Add a runner to the supervisor - pub async fn add_runner(&self, config: RunnerConfig, process_manager: ProcessManagerType) -> ClientResult<()> { + pub async fn add_runner(&self, secret: &str, config: RunnerConfig) -> ClientResult<()> { + let params = serde_json::json!({ + "secret": secret, + "config": config + }); let _: () = self .client - .request("add_runner", rpc_params![config, process_manager]) + .request("add_runner", rpc_params![params]) .await.map_err(|e| ClientError::JsonRpc(e))?; Ok(()) } /// Get status of a specific runner - pub async fn get_runner_status(&self, actor_id: &str) -> ClientResult { + pub async fn get_runner_status(&self, secret: &str, actor_id: &str) -> ClientResult { + let params = serde_json::json!({ + "secret": secret, + "actor_id": actor_id + }); let status: RunnerStatus = self .client - .request("get_runner_status", rpc_params![actor_id]) + .request("get_runner_status", rpc_params![params]) .await.map_err(|e| ClientError::JsonRpc(e))?; Ok(status) } diff --git a/cmd/supervisor.rs b/cmd/supervisor.rs index cc2e438..327b943 100644 --- a/cmd/supervisor.rs +++ b/cmd/supervisor.rs @@ -50,6 +50,14 @@ struct Args { /// Mycelium topic for supervisor RPC messages #[arg(long, default_value = "supervisor.rpc")] topic: String, + + /// Port for OpenRPC HTTP server + #[arg(long, default_value = "3030")] + port: u16, + + /// Bind address for OpenRPC HTTP server + #[arg(long, default_value = "127.0.0.1")] + bind_address: String, } #[tokio::main] @@ -97,6 +105,42 @@ async fn main() -> Result<(), Box> { } }; + // Print startup information + let server_url = format!("http://{}:{}", args.bind_address, args.port); + println!("\n╔════════════════════════════════════════════════════════════╗"); + println!("║ Hero Supervisor Started ║"); + println!("╚════════════════════════════════════════════════════════════╝"); + println!(" 📡 OpenRPC Server: {}", server_url); + println!(" 🔗 Redis: {}", args.redis_url); + #[cfg(feature = "mycelium")] + if !args.mycelium_url.is_empty() { + println!(" 🌐 Mycelium: {}", args.mycelium_url); + } else { + println!(" 🌐 Mycelium: Disabled"); + } + #[cfg(not(feature = "mycelium"))] + println!(" 🌐 Mycelium: Not compiled (use --features mycelium)"); + println!("╚════════════════════════════════════════════════════════════╝\n"); + + // Start OpenRPC server in background + use std::sync::Arc; + use tokio::sync::Mutex; + use hero_supervisor::openrpc::start_http_openrpc_server; + + let supervisor_arc = Arc::new(Mutex::new(supervisor.clone())); + let bind_addr = args.bind_address.clone(); + let port = args.port; + + tokio::spawn(async move { + info!("Starting OpenRPC server on {}:{}", bind_addr, port); + if let Err(e) = start_http_openrpc_server(supervisor_arc, &bind_addr, port).await { + error!("OpenRPC server error: {}", e); + } + }); + + // Give the server a moment to start + tokio::time::sleep(tokio::time::Duration::from_millis(500)).await; + let mut app = SupervisorApp::new(supervisor, args.mycelium_url, args.topic); // Start the complete supervisor application diff --git a/examples/README.md b/examples/README.md index bd21499..76131a1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,182 +1,74 @@ # Hero Supervisor Examples -This directory contains examples demonstrating the new job API functionality and workflows. +This directory contains examples demonstrating Hero Supervisor functionality. -## Examples Overview +## Available Examples -### 1. `job_api_examples.rs` - Comprehensive API Demo -Complete demonstration of all new job API methods: -- **Fire-and-forget execution** using `job.run` -- **Asynchronous processing** with `jobs.create`, `job.start`, `job.status`, `job.result` -- **Batch job processing** for multiple jobs -- **Job listing** with `jobs.list` +### osiris_openrpc -**Run with:** +Comprehensive example showing the complete workflow of using Hero Supervisor with OSIRIS runners via OpenRPC. + +**Features:** +- Automatic supervisor and runner startup +- OpenRPC client communication +- Runner registration and management +- Job dispatching with multiple scripts +- Context-based access control +- Graceful shutdown + +**Run:** ```bash -cargo run --example job_api_examples +cargo run --example osiris_openrpc ``` -### 2. `simple_job_workflow.rs` - Basic Workflow -Simple example showing the basic job lifecycle: -1. Create job with `jobs.create` -2. Start job with `job.start` -3. Monitor with `job.status` -4. Get result with `job.result` - -**Run with:** -```bash -cargo run --example simple_job_workflow -``` - -### 3. `integration_test.rs` - Integration Tests -Comprehensive integration tests validating: -- Complete job lifecycle -- Immediate job execution -- Job listing functionality -- Authentication error handling -- Nonexistent job operations - -**Run with:** -```bash -cargo test --test integration_test -``` +See [osiris_openrpc/README.md](osiris_openrpc/README.md) for details. ## Prerequisites -Before running the examples, ensure: +All examples require: +- Redis server running on `localhost:6379` +- Rust toolchain installed -1. **Redis is running:** - ```bash - docker run -d -p 6379:6379 redis:alpine - ``` +## Example Structure -2. **Supervisor is running:** - ```bash - ./target/debug/supervisor --config examples/supervisor/config.toml - ``` - -3. **Runners are configured** in your config.toml: - ```toml - [[actors]] - id = "osis_runner_1" - name = "osis_runner_1" - binary_path = "/path/to/osis_runner" - db_path = "/tmp/osis_db" - redis_url = "redis://localhost:6379" - process_manager = "simple" - ``` - -## API Convention Summary - -The examples demonstrate the new job API convention: - -### General Operations (`jobs.`) -- `jobs.create` - Create a job without queuing it -- `jobs.list` - List all job IDs in the system - -### Specific Operations (`job.`) -- `job.run` - Run a job immediately and return result -- `job.start` - Start a previously created job -- `job.status` - Get current job status (non-blocking) -- `job.result` - Get job result (blocking until complete) - -## Workflow Patterns - -### Pattern 1: Fire-and-Forget -```rust -let result = client.job_run(secret, job).await?; -match result { - JobResult::Success { success } => println!("Output: {}", success), - JobResult::Error { error } => println!("Error: {}", error), -} +``` +examples/ +├── README.md # This file +├── osiris_openrpc/ # OSIRIS + OpenRPC example +│ ├── main.rs # Main example code +│ ├── README.md # Detailed documentation +│ ├── note.rhai # Note creation script +│ ├── event.rhai # Event creation script +│ ├── query.rhai # Query script +│ └── access_denied.rhai # Access control test script +└── _archive/ # Archived old examples ``` -### Pattern 2: Asynchronous Processing -```rust -// Create and start -let job_id = client.jobs_create(secret, job).await?; -client.job_start(secret, &job_id).await?; +## Architecture Overview -// Monitor (non-blocking) -loop { - let status = client.job_status(&job_id).await?; - if status.status == "completed" { break; } - sleep(Duration::from_secs(1)).await; -} +The examples demonstrate the Hero Supervisor architecture: -// Get result -let result = client.job_result(&job_id).await?; +``` +Client (OpenRPC) + ↓ +Supervisor (OpenRPC Server) + ↓ +Redis Queue + ↓ +Runners (OSIRIS, SAL, etc.) ``` -### Pattern 3: Batch Processing -```rust -// Create all jobs -let mut job_ids = Vec::new(); -for job_spec in job_specs { - let job_id = client.jobs_create(secret, job_spec).await?; - job_ids.push(job_id); -} +## Development -// Start all jobs -for job_id in &job_ids { - client.job_start(secret, job_id).await?; -} +To add a new example: -// Collect results -for job_id in &job_ids { - let result = client.job_result(job_id).await?; - // Process result... -} -``` +1. Create a new directory under `examples/` +2. Add `main.rs` with your example code +3. Add any required script files (`.rhai`) +4. Add a `README.md` documenting the example +5. Update `Cargo.toml` to register the example +6. Update this README with a link -## Error Handling +## Archived Examples -The examples demonstrate proper error handling for: -- **Authentication errors** - Invalid secrets -- **Job not found errors** - Nonexistent job IDs -- **Connection errors** - Supervisor not available -- **Execution errors** - Job failures - -## Authentication - -Examples use different secret types: -- **Admin secrets**: Full system access -- **User secrets**: Job operations only (used in examples) -- **Register secrets**: Runner registration only - -Configure secrets in your supervisor config: -```toml -admin_secrets = ["admin-secret-123"] -user_secrets = ["user-secret-456"] -register_secrets = ["register-secret-789"] -``` - -## Troubleshooting - -### Common Issues - -1. **Connection refused** - - Ensure supervisor is running on localhost:3030 - - Check supervisor logs for errors - -2. **Authentication failed** - - Verify secret is configured in supervisor - - Check secret type matches operation requirements - -3. **Job execution failed** - - Ensure runners are properly configured and running - - Check runner logs for execution errors - - Verify job payload is valid for the target runner - -4. **Redis connection failed** - - Ensure Redis is running on localhost:6379 - - Check Redis connectivity from supervisor - -### Debug Mode - -Run examples with debug logging: -```bash -RUST_LOG=debug cargo run --example job_api_examples -``` - -This will show detailed API calls and responses for troubleshooting. +Previous examples have been moved to `_archive/` for reference. These may be outdated but can provide useful patterns for specific use cases. diff --git a/examples/_archive/E2E_EXAMPLES.md b/examples/_archive/E2E_EXAMPLES.md new file mode 100644 index 0000000..f763f02 --- /dev/null +++ b/examples/_archive/E2E_EXAMPLES.md @@ -0,0 +1,364 @@ +# End-to-End Examples + +Complete examples demonstrating the full Supervisor + Runner + Client workflow. + +## Overview + +These examples show how to: +1. Start a Hero Supervisor +2. Start an OSIS Runner +3. Register the runner with the supervisor +4. Execute jobs using both blocking (`job.run`) and non-blocking (`job.start`) modes + +## Prerequisites + +### Required Services + +1. **Redis** - Must be running on `localhost:6379` + ```bash + redis-server + ``` + +2. **Supervisor** - Hero Supervisor with Mycelium integration + ```bash + cargo run --bin hero-supervisor -- --redis-url redis://localhost:6379 + ``` + +3. **Runner** - OSIS Runner to execute jobs + ```bash + cargo run --bin runner_osis -- test_runner --redis-url redis://localhost:6379 + ``` + +## Examples + +### 1. Simple End-to-End (`simple_e2e.rs`) + +**Recommended for beginners** - A minimal example with clear step-by-step execution. + +#### What it does: +- Registers a runner with the supervisor +- Runs 2 blocking jobs (with immediate results) +- Starts 1 non-blocking job (fire and forget) +- Shows clear output at each step + +#### How to run: + +**Terminal 1 - Redis:** +```bash +redis-server +``` + +**Terminal 2 - Supervisor:** +```bash +cd /Users/timurgordon/code/git.ourworld.tf/herocode/supervisor +RUST_LOG=info cargo run --bin hero-supervisor -- --redis-url redis://localhost:6379 +``` + +**Terminal 3 - Runner:** +```bash +cd /Users/timurgordon/code/git.ourworld.tf/herocode/runner_rust +RUST_LOG=info cargo run --bin runner_osis -- test_runner \ + --redis-url redis://localhost:6379 \ + --db-path /tmp/test_runner.db +``` + +**Terminal 4 - Demo:** +```bash +cd /Users/timurgordon/code/git.ourworld.tf/herocode/supervisor +RUST_LOG=info cargo run --example simple_e2e +``` + +#### Expected Output: + +``` +╔════════════════════════════════════════╗ +║ Simple End-to-End Demo ║ +╚════════════════════════════════════════╝ + +📋 Step 1: Registering Runner +───────────────────────────────────────── +✅ Runner registered successfully + +📋 Step 2: Running a Simple Job (Blocking) +───────────────────────────────────────── +✅ Job completed! + Result: {"message":"Hello from the runner!","number":42,"timestamp":1234567890} + +📋 Step 3: Running a Calculation Job +───────────────────────────────────────── +✅ Calculation completed! + Result: {"sum":55,"product":3628800,"count":10,"average":5} + +📋 Step 4: Starting a Non-Blocking Job +───────────────────────────────────────── +✅ Job started! + Job ID: abc-123 (running in background) + +🎉 Demo completed successfully! +``` + +### 2. Full End-to-End (`end_to_end_demo.rs`) + +**Advanced** - Automatically spawns supervisor and runner processes. + +#### What it does: +- Automatically starts supervisor and runner +- Runs multiple test jobs +- Demonstrates both execution modes +- Handles cleanup automatically + +#### How to run: + +**Terminal 1 - Redis:** +```bash +redis-server +``` + +**Terminal 2 - Demo:** +```bash +cd /Users/timurgordon/code/git.ourworld.tf/herocode/supervisor +RUST_LOG=info cargo run --example end_to_end_demo +``` + +#### Features: +- ✅ Automatic process management +- ✅ Multiple job examples +- ✅ Graceful shutdown +- ✅ Comprehensive logging + +## Job Execution Modes + +### job.run (Blocking) + +Executes a job and waits for the result. + +**Request:** +```json +{ + "jsonrpc": "2.0", + "method": "job.run", + "params": [{ + "secret": "admin_secret", + "job": { /* job object */ }, + "timeout": 30 + }], + "id": 1 +} +``` + +**Response:** +```json +{ + "jsonrpc": "2.0", + "result": { + "job_id": "uuid", + "status": "completed", + "result": "{ /* actual result */ }" + }, + "id": 1 +} +``` + +**Use when:** +- You need immediate results +- Job completes quickly (< 60 seconds) +- Synchronous workflow + +### job.start (Non-Blocking) + +Starts a job and returns immediately. + +**Request:** +```json +{ + "jsonrpc": "2.0", + "method": "job.start", + "params": [{ + "secret": "admin_secret", + "job": { /* job object */ } + }], + "id": 1 +} +``` + +**Response:** +```json +{ + "jsonrpc": "2.0", + "result": { + "job_id": "uuid", + "status": "queued" + }, + "id": 1 +} +``` + +**Use when:** +- Long-running operations +- Background processing +- Async workflows +- Don't need immediate results + +## Job Structure + +Jobs are created using the `JobBuilder`: + +```rust +use runner_rust::job::JobBuilder; + +let job = JobBuilder::new() + .caller_id("my_client") + .context_id("my_context") + .payload(r#" + // Rhai script to execute + let result = 2 + 2; + to_json(result) + "#) + .runner("runner_name") + .executor("rhai") + .timeout(30) + .build()?; +``` + +### Job Fields + +- **caller_id**: Identifier for the client making the request +- **context_id**: Context for the job execution +- **payload**: Rhai script to execute +- **runner**: Name of the runner to execute on +- **executor**: Type of executor (always "rhai" for OSIS) +- **timeout**: Maximum execution time in seconds + +## Rhai Script Examples + +### Simple Calculation +```rhai +let result = 2 + 2; +to_json(result) +``` + +### String Manipulation +```rhai +let message = "Hello, World!"; +let upper = message.to_upper(); +to_json(upper) +``` + +### Array Operations +```rhai +let numbers = [1, 2, 3, 4, 5]; +let sum = 0; +for n in numbers { + sum += n; +} +to_json(#{sum: sum, count: numbers.len()}) +``` + +### Object Creation +```rhai +let person = #{ + name: "Alice", + age: 30, + email: "alice@example.com" +}; +to_json(person) +``` + +## Troubleshooting + +### "Failed to connect to supervisor" + +**Problem:** Supervisor is not running or wrong port. + +**Solution:** +```bash +# Check if supervisor is running +curl http://localhost:3030 + +# Start supervisor +cargo run --bin hero-supervisor -- --redis-url redis://localhost:6379 +``` + +### "Runner not found" + +**Problem:** Runner is not registered or not running. + +**Solution:** +```bash +# Start the runner +cargo run --bin runner_osis -- test_runner --redis-url redis://localhost:6379 + +# Check runner logs for connection issues +``` + +### "Job execution timeout" + +**Problem:** Job took longer than timeout value. + +**Solution:** +- Increase timeout in job builder: `.timeout(60)` +- Or in job.run request: `"timeout": 60` + +### "Redis connection failed" + +**Problem:** Redis is not running. + +**Solution:** +```bash +# Start Redis +redis-server + +# Or specify custom Redis URL +cargo run --bin hero-supervisor -- --redis-url redis://localhost:6379 +``` + +## Architecture + +``` +┌─────────────┐ +│ Client │ +│ (Example) │ +└──────┬──────┘ + │ HTTP/JSON-RPC + ▼ +┌─────────────┐ +│ Supervisor │ +│ (Mycelium) │ +└──────┬──────┘ + │ Redis Queue + ▼ +┌─────────────┐ +│ Runner │ +│ (OSIS) │ +└─────────────┘ +``` + +### Flow + +1. **Client** creates a job with Rhai script +2. **Client** sends job to supervisor via JSON-RPC +3. **Supervisor** verifies signatures (if present) +4. **Supervisor** queues job to runner's Redis queue +5. **Runner** picks up job from queue +6. **Runner** executes Rhai script +7. **Runner** stores result in Redis +8. **Supervisor** retrieves result (for job.run) +9. **Client** receives result + +## Next Steps + +- Add signature verification to jobs (see `JOB_SIGNATURES.md`) +- Implement job status polling for non-blocking jobs +- Create custom Rhai functions for your use case +- Scale with multiple runners + +## Related Documentation + +- `JOB_EXECUTION.md` - Detailed job execution modes +- `JOB_SIGNATURES.md` - Cryptographic job signing +- `README.md` - Supervisor overview + +--- + +**Status:** ✅ Production Ready +**Last Updated:** 2025-10-24 diff --git a/examples/_archive/EXAMPLES_SUMMARY.md b/examples/_archive/EXAMPLES_SUMMARY.md new file mode 100644 index 0000000..819468c --- /dev/null +++ b/examples/_archive/EXAMPLES_SUMMARY.md @@ -0,0 +1,192 @@ +# Supervisor Examples - Summary + +## ✅ **Complete End-to-End Examples with OpenRPC Client** + +All examples now use the official `hero-supervisor-openrpc-client` library for type-safe, async communication with the supervisor. + +### **What Was Updated:** + +1. **OpenRPC Client Library** (`clients/openrpc/src/lib.rs`) + - Added `JobRunResponse` - Response from blocking `job.run` + - Added `JobStartResponse` - Response from non-blocking `job.start` + - Updated `job_run()` method - Now accepts timeout parameter + - Updated `job_start()` method - Now accepts Job instead of job_id + - Re-exports `Job` and `JobBuilder` from `runner_rust` + +2. **Simple E2E Example** (`examples/simple_e2e.rs`) + - Uses `SupervisorClient` from OpenRPC library + - Clean, type-safe API calls + - No manual JSON-RPC construction + - Perfect for learning and testing + +3. **Full E2E Demo** (`examples/end_to_end_demo.rs`) + - Automated supervisor and runner spawning + - Uses OpenRPC client throughout + - Helper functions for common operations + - Comprehensive test scenarios + +### **Key Changes:** + +**Before (Manual JSON-RPC):** +```rust +let request = json!({ + "jsonrpc": "2.0", + "method": "job.run", + "params": [{ + "secret": secret, + "job": job, + "timeout": 30 + }], + "id": 1 +}); +let response = http_client.post(url).json(&request).send().await?; +``` + +**After (OpenRPC Client):** +```rust +let response = client.job_run(secret, job, Some(30)).await?; +println!("Result: {:?}", response.result); +``` + +### **Client API:** + +#### **Job Execution** + +```rust +use hero_supervisor_openrpc_client::{SupervisorClient, JobBuilder}; + +// Create client +let client = SupervisorClient::new("http://localhost:3030")?; + +// Register runner +client.register_runner("admin_secret", "runner_name", "queue_name").await?; + +// Run job (blocking - waits for result) +let response = client.job_run("admin_secret", job, Some(60)).await?; +// response.result contains the actual result + +// Start job (non-blocking - returns immediately) +let response = client.job_start("admin_secret", job).await?; +// response.job_id for later polling +``` + +#### **Response Types** + +```rust +// JobRunResponse (from job.run) +pub struct JobRunResponse { + pub job_id: String, + pub status: String, // "completed" + pub result: Option, // Actual result from runner +} + +// JobStartResponse (from job.start) +pub struct JobStartResponse { + pub job_id: String, + pub status: String, // "queued" +} +``` + +### **Examples Overview:** + +| Example | Description | Use Case | +|---------|-------------|----------| +| `simple_e2e.rs` | Manual setup, step-by-step | Learning, testing | +| `end_to_end_demo.rs` | Automated, comprehensive | CI/CD, integration tests | + +### **Running the Examples:** + +**Prerequisites:** +```bash +# Terminal 1: Redis +redis-server + +# Terminal 2: Supervisor +cargo run --bin hero-supervisor -- --redis-url redis://localhost:6379 + +# Terminal 3: Runner +cargo run --bin runner_osis -- test_runner --redis-url redis://localhost:6379 +``` + +**Run Simple Example:** +```bash +# Terminal 4 +RUST_LOG=info cargo run --example simple_e2e +``` + +**Run Full Demo:** +```bash +# Only needs Redis running (spawns supervisor and runner automatically) +RUST_LOG=info cargo run --example end_to_end_demo +``` + +### **Benefits of OpenRPC Client:** + +✅ **Type Safety** - Compile-time checking of requests/responses +✅ **Async/Await** - Native Rust async support +✅ **Error Handling** - Proper Result types with detailed errors +✅ **Auto Serialization** - No manual JSON construction +✅ **Documentation** - IntelliSense and type hints +✅ **Maintainability** - Single source of truth for API + +### **Architecture:** + +``` +┌─────────────────┐ +│ Example Code │ +│ (simple_e2e) │ +└────────┬────────┘ + │ + ▼ +┌─────────────────┐ +│ OpenRPC Client │ +│ (typed API) │ +└────────┬────────┘ + │ JSON-RPC over HTTP + ▼ +┌─────────────────┐ +│ Supervisor │ +│ (Mycelium) │ +└────────┬────────┘ + │ Redis Queue + ▼ +┌─────────────────┐ +│ OSIS Runner │ +│ (Rhai Engine) │ +└─────────────────┘ +``` + +### **Job Execution Modes:** + +**Blocking (`job.run`):** +- Client waits for result +- Uses `queue_and_wait` internally +- Returns actual result +- Best for: CRUD, queries, short jobs + +**Non-Blocking (`job.start`):** +- Client returns immediately +- Job runs in background +- Returns job_id for polling +- Best for: Long jobs, batch processing + +### **Files Modified:** + +- ✅ `clients/openrpc/src/lib.rs` - Updated client methods and response types +- ✅ `examples/simple_e2e.rs` - Refactored to use OpenRPC client +- ✅ `examples/end_to_end_demo.rs` - Refactored to use OpenRPC client +- ✅ `examples/E2E_EXAMPLES.md` - Updated documentation +- ✅ `examples/EXAMPLES_SUMMARY.md` - This file + +### **Next Steps:** + +1. **Add more examples** - Specific use cases (batch jobs, error handling) +2. **Job polling** - Implement `wait_for_job()` helper +3. **WASM support** - Browser-based examples +4. **Signature examples** - Jobs with cryptographic signatures + +--- + +**Status:** ✅ Complete and Production Ready +**Last Updated:** 2025-10-24 +**Client Version:** hero-supervisor-openrpc-client 0.1.0 diff --git a/examples/_archive/README.md b/examples/_archive/README.md new file mode 100644 index 0000000..bd21499 --- /dev/null +++ b/examples/_archive/README.md @@ -0,0 +1,182 @@ +# Hero Supervisor Examples + +This directory contains examples demonstrating the new job API functionality and workflows. + +## Examples Overview + +### 1. `job_api_examples.rs` - Comprehensive API Demo +Complete demonstration of all new job API methods: +- **Fire-and-forget execution** using `job.run` +- **Asynchronous processing** with `jobs.create`, `job.start`, `job.status`, `job.result` +- **Batch job processing** for multiple jobs +- **Job listing** with `jobs.list` + +**Run with:** +```bash +cargo run --example job_api_examples +``` + +### 2. `simple_job_workflow.rs` - Basic Workflow +Simple example showing the basic job lifecycle: +1. Create job with `jobs.create` +2. Start job with `job.start` +3. Monitor with `job.status` +4. Get result with `job.result` + +**Run with:** +```bash +cargo run --example simple_job_workflow +``` + +### 3. `integration_test.rs` - Integration Tests +Comprehensive integration tests validating: +- Complete job lifecycle +- Immediate job execution +- Job listing functionality +- Authentication error handling +- Nonexistent job operations + +**Run with:** +```bash +cargo test --test integration_test +``` + +## Prerequisites + +Before running the examples, ensure: + +1. **Redis is running:** + ```bash + docker run -d -p 6379:6379 redis:alpine + ``` + +2. **Supervisor is running:** + ```bash + ./target/debug/supervisor --config examples/supervisor/config.toml + ``` + +3. **Runners are configured** in your config.toml: + ```toml + [[actors]] + id = "osis_runner_1" + name = "osis_runner_1" + binary_path = "/path/to/osis_runner" + db_path = "/tmp/osis_db" + redis_url = "redis://localhost:6379" + process_manager = "simple" + ``` + +## API Convention Summary + +The examples demonstrate the new job API convention: + +### General Operations (`jobs.`) +- `jobs.create` - Create a job without queuing it +- `jobs.list` - List all job IDs in the system + +### Specific Operations (`job.`) +- `job.run` - Run a job immediately and return result +- `job.start` - Start a previously created job +- `job.status` - Get current job status (non-blocking) +- `job.result` - Get job result (blocking until complete) + +## Workflow Patterns + +### Pattern 1: Fire-and-Forget +```rust +let result = client.job_run(secret, job).await?; +match result { + JobResult::Success { success } => println!("Output: {}", success), + JobResult::Error { error } => println!("Error: {}", error), +} +``` + +### Pattern 2: Asynchronous Processing +```rust +// Create and start +let job_id = client.jobs_create(secret, job).await?; +client.job_start(secret, &job_id).await?; + +// Monitor (non-blocking) +loop { + let status = client.job_status(&job_id).await?; + if status.status == "completed" { break; } + sleep(Duration::from_secs(1)).await; +} + +// Get result +let result = client.job_result(&job_id).await?; +``` + +### Pattern 3: Batch Processing +```rust +// Create all jobs +let mut job_ids = Vec::new(); +for job_spec in job_specs { + let job_id = client.jobs_create(secret, job_spec).await?; + job_ids.push(job_id); +} + +// Start all jobs +for job_id in &job_ids { + client.job_start(secret, job_id).await?; +} + +// Collect results +for job_id in &job_ids { + let result = client.job_result(job_id).await?; + // Process result... +} +``` + +## Error Handling + +The examples demonstrate proper error handling for: +- **Authentication errors** - Invalid secrets +- **Job not found errors** - Nonexistent job IDs +- **Connection errors** - Supervisor not available +- **Execution errors** - Job failures + +## Authentication + +Examples use different secret types: +- **Admin secrets**: Full system access +- **User secrets**: Job operations only (used in examples) +- **Register secrets**: Runner registration only + +Configure secrets in your supervisor config: +```toml +admin_secrets = ["admin-secret-123"] +user_secrets = ["user-secret-456"] +register_secrets = ["register-secret-789"] +``` + +## Troubleshooting + +### Common Issues + +1. **Connection refused** + - Ensure supervisor is running on localhost:3030 + - Check supervisor logs for errors + +2. **Authentication failed** + - Verify secret is configured in supervisor + - Check secret type matches operation requirements + +3. **Job execution failed** + - Ensure runners are properly configured and running + - Check runner logs for execution errors + - Verify job payload is valid for the target runner + +4. **Redis connection failed** + - Ensure Redis is running on localhost:6379 + - Check Redis connectivity from supervisor + +### Debug Mode + +Run examples with debug logging: +```bash +RUST_LOG=debug cargo run --example job_api_examples +``` + +This will show detailed API calls and responses for troubleshooting. diff --git a/examples/basic_openrpc_client.rs b/examples/_archive/basic_openrpc_client.rs similarity index 100% rename from examples/basic_openrpc_client.rs rename to examples/_archive/basic_openrpc_client.rs diff --git a/examples/_archive/end_to_end_demo.rs b/examples/_archive/end_to_end_demo.rs new file mode 100644 index 0000000..11c3f19 --- /dev/null +++ b/examples/_archive/end_to_end_demo.rs @@ -0,0 +1,278 @@ +//! End-to-End Demo: Supervisor + Runner + Client +//! +//! This example demonstrates the complete workflow: +//! 1. Starts a supervisor with Mycelium integration +//! 2. Starts an OSIS runner +//! 3. Uses the supervisor client to run jobs +//! 4. Shows both job.run (blocking) and job.start (non-blocking) modes +//! +//! Prerequisites: +//! - Redis running on localhost:6379 +//! +//! Usage: +//! ```bash +//! RUST_LOG=info cargo run --example end_to_end_demo +//! ``` + +use anyhow::{Result, Context}; +use log::{info, error}; +use std::process::{Command, Child, Stdio}; +use std::time::Duration; +use tokio::time::sleep; +use hero_supervisor_openrpc_client::{SupervisorClient, JobBuilder}; + +/// Configuration for the demo +struct DemoConfig { + redis_url: String, + supervisor_port: u16, + runner_id: String, + db_path: String, +} + +impl Default for DemoConfig { + fn default() -> Self { + Self { + redis_url: "redis://localhost:6379".to_string(), + supervisor_port: 3030, + runner_id: "example_runner".to_string(), + db_path: "/tmp/example_runner.db".to_string(), + } + } +} + +/// Supervisor process wrapper +struct SupervisorProcess { + child: Child, +} + +impl SupervisorProcess { + fn start(config: &DemoConfig) -> Result { + info!("🚀 Starting supervisor on port {}...", config.supervisor_port); + + let child = Command::new("cargo") + .args(&[ + "run", + "--bin", + "hero-supervisor", + "--", + "--redis-url", + &config.redis_url, + "--port", + &config.supervisor_port.to_string(), + ]) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .context("Failed to start supervisor")?; + + Ok(Self { child }) + } +} + +impl Drop for SupervisorProcess { + fn drop(&mut self) { + info!("🛑 Stopping supervisor..."); + let _ = self.child.kill(); + let _ = self.child.wait(); + } +} + +/// Runner process wrapper +struct RunnerProcess { + child: Child, +} + +impl RunnerProcess { + fn start(config: &DemoConfig) -> Result { + info!("🤖 Starting OSIS runner '{}'...", config.runner_id); + + let child = Command::new("cargo") + .args(&[ + "run", + "--bin", + "runner_osis", + "--", + &config.runner_id, + "--db-path", + &config.db_path, + "--redis-url", + &config.redis_url, + ]) + .env("RUST_LOG", "info") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .context("Failed to start runner")?; + + Ok(Self { child }) + } +} + +impl Drop for RunnerProcess { + fn drop(&mut self) { + info!("🛑 Stopping runner..."); + let _ = self.child.kill(); + let _ = self.child.wait(); + } +} + +/// Helper functions for the demo +async fn register_runner_helper(client: &SupervisorClient, runner_id: &str, secret: &str) -> Result<()> { + info!("📝 Registering runner '{}'...", runner_id); + + let queue = format!("hero:q:work:type:osis:group:default:inst:{}", runner_id); + client.register_runner(secret, runner_id, &queue).await?; + + info!("✅ Runner registered successfully"); + Ok(()) +} + +async fn run_job_helper(client: &SupervisorClient, job: runner_rust::job::Job, secret: &str, timeout: u64) -> Result { + info!("🚀 Running job {} (blocking)...", job.id); + + let response = client.job_run(secret, job, Some(timeout)).await?; + + let result = response.result + .ok_or_else(|| anyhow::anyhow!("No result in response"))?; + + info!("✅ Job completed with result: {}", result); + Ok(result) +} + +async fn start_job_helper(client: &SupervisorClient, job: runner_rust::job::Job, secret: &str) -> Result { + info!("🚀 Starting job {} (non-blocking)...", job.id); + + let response = client.job_start(secret, job).await?; + + info!("✅ Job queued with ID: {}", response.job_id); + Ok(response.job_id) +} + +#[tokio::main] +async fn main() -> Result<()> { + // Initialize logging + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + println!("\n╔════════════════════════════════════════════════════════════╗"); + println!("║ End-to-End Demo: Supervisor + Runner + Client ║"); + println!("╚════════════════════════════════════════════════════════════╝\n"); + + let config = DemoConfig::default(); + + // Step 1: Start supervisor + println!("📋 Step 1: Starting Supervisor"); + println!("─────────────────────────────────────────────────────────────"); + let _supervisor = SupervisorProcess::start(&config)?; + sleep(Duration::from_secs(3)).await; + println!("✅ Supervisor started on port {}\n", config.supervisor_port); + + // Step 2: Start runner + println!("📋 Step 2: Starting OSIS Runner"); + println!("─────────────────────────────────────────────────────────────"); + let _runner = RunnerProcess::start(&config)?; + sleep(Duration::from_secs(3)).await; + println!("✅ Runner '{}' started\n", config.runner_id); + + // Step 3: Create client and register runner + println!("📋 Step 3: Registering Runner with Supervisor"); + println!("─────────────────────────────────────────────────────────────"); + let client = SupervisorClient::new(&format!("http://localhost:{}", config.supervisor_port))?; + register_runner_helper(&client, &config.runner_id, "admin_secret").await?; + println!("✅ Runner registered\n"); + + sleep(Duration::from_secs(2)).await; + + // Step 4: Run blocking jobs (job.run) + println!("📋 Step 4: Running Blocking Jobs (job.run)"); + println!("─────────────────────────────────────────────────────────────"); + + // Job 1: Simple calculation + println!("\n🔹 Job 1: Simple Calculation"); + let job1 = JobBuilder::new() + .caller_id("demo_client") + .context_id("demo_context") + .payload("let result = 2 + 2; to_json(result)") + .runner(&config.runner_id) + .executor("rhai") + .timeout(30) + .build()?; + + let result1 = run_job_helper(&client, job1, "admin_secret", 30).await?; + println!(" Result: {}", result1); + + // Job 2: String manipulation + println!("\n🔹 Job 2: String Manipulation"); + let job2 = JobBuilder::new() + .caller_id("demo_client") + .context_id("demo_context") + .payload(r#"let msg = "Hello from OSIS Runner!"; to_json(msg)"#) + .runner(&config.runner_id) + .executor("rhai") + .timeout(30) + .build()?; + + let result2 = run_job_helper(&client, job2, "admin_secret", 30).await?; + println!(" Result: {}", result2); + + // Job 3: Array operations + println!("\n🔹 Job 3: Array Operations"); + let job3 = JobBuilder::new() + .caller_id("demo_client") + .context_id("demo_context") + .payload(r#" + let numbers = [1, 2, 3, 4, 5]; + let sum = 0; + for n in numbers { + sum += n; + } + to_json(#{sum: sum, count: numbers.len()}) + "#) + .runner(&config.runner_id) + .executor("rhai") + .timeout(30) + .build()?; + + let result3 = run_job_helper(&client, job3, "admin_secret", 30).await?; + println!(" Result: {}", result3); + + println!("\n✅ All blocking jobs completed successfully\n"); + + // Step 5: Start non-blocking jobs (job.start) + println!("📋 Step 5: Starting Non-Blocking Jobs (job.start)"); + println!("─────────────────────────────────────────────────────────────"); + + println!("\n🔹 Job 4: Background Task"); + let job4 = JobBuilder::new() + .caller_id("demo_client") + .context_id("demo_context") + .payload(r#" + let result = "Background task completed"; + to_json(result) + "#) + .runner(&config.runner_id) + .executor("rhai") + .timeout(30) + .build()?; + + let job4_id = start_job_helper(&client, job4, "admin_secret").await?; + println!(" Job ID: {} (running in background)", job4_id); + + println!("\n✅ Non-blocking job started\n"); + + // Step 6: Summary + println!("📋 Step 6: Demo Summary"); + println!("─────────────────────────────────────────────────────────────"); + println!("✅ Supervisor: Running on port {}", config.supervisor_port); + println!("✅ Runner: '{}' registered and processing jobs", config.runner_id); + println!("✅ Blocking jobs: 3 completed successfully"); + println!("✅ Non-blocking jobs: 1 started"); + println!("\n🎉 Demo completed successfully!"); + + // Keep processes running for a bit to see logs + println!("\n⏳ Keeping processes running for 5 seconds..."); + sleep(Duration::from_secs(5)).await; + + println!("\n🛑 Shutting down..."); + + Ok(()) +} diff --git a/examples/integration_test.rs b/examples/_archive/integration_test.rs similarity index 100% rename from examples/integration_test.rs rename to examples/_archive/integration_test.rs diff --git a/examples/job_api_examples.rs b/examples/_archive/job_api_examples.rs similarity index 100% rename from examples/job_api_examples.rs rename to examples/_archive/job_api_examples.rs diff --git a/examples/mock_runner.rs b/examples/_archive/mock_runner.rs similarity index 100% rename from examples/mock_runner.rs rename to examples/_archive/mock_runner.rs diff --git a/examples/_archive/simple_e2e.rs b/examples/_archive/simple_e2e.rs new file mode 100644 index 0000000..5776b9f --- /dev/null +++ b/examples/_archive/simple_e2e.rs @@ -0,0 +1,203 @@ +//! Simple End-to-End Example +//! +//! A minimal example showing supervisor + runner + client workflow. +//! +//! Prerequisites: +//! - Redis running on localhost:6379 +//! +//! Usage: +//! ```bash +//! # Terminal 1: Start Redis +//! redis-server +//! +//! # Terminal 2: Run this example +//! RUST_LOG=info cargo run --example simple_e2e +//! ``` + +use anyhow::Result; +use log::info; +use std::time::Duration; +use tokio::time::sleep; +use hero_supervisor_openrpc_client::{SupervisorClient, JobBuilder}; + +#[tokio::main] +async fn main() -> Result<()> { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + + println!("\n╔════════════════════════════════════════╗"); + println!("║ Simple End-to-End Demo ║"); + println!("╚════════════════════════════════════════╝\n"); + + let supervisor_url = "http://localhost:3030"; + let runner_id = "test_runner"; + let secret = "admin_secret"; + + // Create supervisor client + let client = SupervisorClient::new(supervisor_url)?; + + println!("📝 Prerequisites:"); + println!(" 1. Redis running on localhost:6379"); + println!(" 2. Supervisor running on {}", supervisor_url); + println!(" 3. Runner '{}' registered and running\n", runner_id); + + println!("💡 To start the supervisor:"); + println!(" cargo run --bin hero-supervisor -- --redis-url redis://localhost:6379\n"); + + println!("💡 To start a runner:"); + println!(" cd /Users/timurgordon/code/git.ourworld.tf/herocode/runner_rust"); + println!(" cargo run --bin runner_osis -- {} --redis-url redis://localhost:6379\n", runner_id); + + println!("⏳ Waiting 3 seconds for you to start the prerequisites...\n"); + sleep(Duration::from_secs(3)).await; + + // Register runner + println!("📋 Step 1: Registering Runner"); + println!("─────────────────────────────────────────"); + + let queue = format!("hero:q:work:type:osis:group:default:inst:{}", runner_id); + match client.register_runner(secret, runner_id, &queue).await { + Ok(_) => { + println!("✅ Runner registered successfully"); + } + Err(e) => { + println!("⚠️ Registration error: {} (runner might already be registered)", e); + } + } + + sleep(Duration::from_secs(1)).await; + + // Run a simple job + println!("\n📋 Step 2: Running a Simple Job (Blocking)"); + println!("─────────────────────────────────────────"); + + let job = JobBuilder::new() + .caller_id("simple_demo") + .context_id("demo_context") + .payload(r#" + let message = "Hello from the runner!"; + let number = 42; + to_json(#{ + message: message, + number: number, + timestamp: timestamp() + }) + "#) + .runner(runner_id) + .executor("rhai") + .timeout(30) + .build()?; + + let job_id = job.id.clone(); + info!("Sending job with ID: {}", job_id); + + match client.job_run(secret, job, Some(30)).await { + Ok(response) => { + println!("✅ Job completed!"); + if let Some(result) = response.result { + println!(" Result: {}", result); + } + } + Err(e) => { + println!("❌ Job failed: {}", e); + return Ok(()); + } + } + + // Run another job (calculation) + println!("\n📋 Step 3: Running a Calculation Job"); + println!("─────────────────────────────────────────"); + + let calc_job = JobBuilder::new() + .caller_id("simple_demo") + .context_id("demo_context") + .payload(r#" + let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let sum = 0; + let product = 1; + + for n in numbers { + sum += n; + product *= n; + } + + to_json(#{ + sum: sum, + product: product, + count: numbers.len(), + average: sum / numbers.len() + }) + "#) + .runner(runner_id) + .executor("rhai") + .timeout(30) + .build()?; + + let calc_job_id = calc_job.id.clone(); + info!("Sending calculation job with ID: {}", calc_job_id); + + match client.job_run(secret, calc_job, Some(30)).await { + Ok(response) => { + println!("✅ Calculation completed!"); + if let Some(result) = response.result { + println!(" Result: {}", result); + } + } + Err(e) => { + println!("❌ Calculation failed: {}", e); + } + } + + // Start a non-blocking job + println!("\n📋 Step 4: Starting a Non-Blocking Job"); + println!("─────────────────────────────────────────"); + + let async_job = JobBuilder::new() + .caller_id("simple_demo") + .context_id("demo_context") + .payload(r#" + let result = "This job was started asynchronously"; + to_json(result) + "#) + .runner(runner_id) + .executor("rhai") + .timeout(30) + .build()?; + + let async_job_id = async_job.id.clone(); + info!("Starting async job with ID: {}", async_job_id); + + match client.job_start(secret, async_job).await { + Ok(response) => { + println!("✅ Job started!"); + println!(" Job ID: {} (running in background)", response.job_id); + println!(" Status: {}", response.status); + } + Err(e) => { + println!("❌ Failed to start job: {}", e); + } + } + + // Summary + println!("\n╔════════════════════════════════════════╗"); + println!("║ Demo Summary ║"); + println!("╚════════════════════════════════════════╝"); + println!("✅ Runner registered: {}", runner_id); + println!("✅ Blocking jobs completed: 2"); + println!("✅ Non-blocking jobs started: 1"); + println!("\n🎉 Demo completed successfully!\n"); + + println!("📚 What happened:"); + println!(" 1. Registered a runner with the supervisor"); + println!(" 2. Sent jobs with Rhai scripts to execute"); + println!(" 3. Supervisor queued jobs to the runner"); + println!(" 4. Runner executed the scripts and returned results"); + println!(" 5. Client received results (for blocking jobs)\n"); + + println!("🔍 Key Concepts:"); + println!(" • job.run = Execute and wait for result (blocking)"); + println!(" • job.start = Start and return immediately (non-blocking)"); + println!(" • Jobs contain Rhai scripts that run on the runner"); + println!(" • Supervisor coordinates job distribution via Redis\n"); + + Ok(()) +} diff --git a/examples/simple_job_workflow.rs b/examples/_archive/simple_job_workflow.rs similarity index 100% rename from examples/simple_job_workflow.rs rename to examples/_archive/simple_job_workflow.rs diff --git a/examples/supervisor/README.md b/examples/_archive/supervisor/README.md similarity index 100% rename from examples/supervisor/README.md rename to examples/_archive/supervisor/README.md diff --git a/examples/supervisor/config.toml b/examples/_archive/supervisor/config.toml similarity index 100% rename from examples/supervisor/config.toml rename to examples/_archive/supervisor/config.toml diff --git a/examples/supervisor/run_supervisor.rs b/examples/_archive/supervisor/run_supervisor.rs similarity index 100% rename from examples/supervisor/run_supervisor.rs rename to examples/_archive/supervisor/run_supervisor.rs diff --git a/examples/supervisor/run_supervisor.sh b/examples/_archive/supervisor/run_supervisor.sh similarity index 100% rename from examples/supervisor/run_supervisor.sh rename to examples/_archive/supervisor/run_supervisor.sh diff --git a/examples/osiris_openrpc/README.md b/examples/osiris_openrpc/README.md new file mode 100644 index 0000000..9bad09f --- /dev/null +++ b/examples/osiris_openrpc/README.md @@ -0,0 +1,94 @@ +# OSIRIS + OpenRPC Comprehensive Example + +This example demonstrates the complete workflow of using Hero Supervisor with OSIRIS runners via OpenRPC. + +## What This Example Does + +1. **Builds and starts** Hero Supervisor with OpenRPC server enabled +2. **Builds** the OSIRIS runner binary +3. **Connects** an OpenRPC client to the supervisor +4. **Registers and starts** an OSIRIS runner +5. **Dispatches multiple jobs** via OpenRPC: + - Create a Note + - Create an Event + - Query stored data + - Test access control (expected to fail) +6. **Monitors** job execution and results +7. **Gracefully shuts down** all components + +## Prerequisites + +- Redis server running on `localhost:6379` +- Rust toolchain installed +- Both `supervisor` and `runner_rust` crates available + +## Running the Example + +```bash +cargo run --example osiris_openrpc +``` + +## Job Scripts + +The example uses separate Rhai script files for each job: + +- `note.rhai` - Creates and stores a Note object +- `event.rhai` - Creates and stores an Event object +- `query.rhai` - Queries and retrieves stored objects +- `access_denied.rhai` - Tests access control (should fail) + +## Architecture + +``` +┌─────────────────┐ +│ This Example │ +│ (OpenRPC │ +│ Client) │ +└────────┬────────┘ + │ JSON-RPC + ↓ +┌─────────────────┐ +│ Supervisor │ +│ (OpenRPC │ +│ Server) │ +└────────┬────────┘ + │ Redis Queue + ↓ +┌─────────────────┐ +│ OSIRIS Runner │ +│ (Rhai Engine │ +│ + HeroDB) │ +└─────────────────┘ +``` + +## Key Features Demonstrated + +- **Automatic binary building** using escargot +- **OpenRPC communication** between client and supervisor +- **Runner registration** with configuration +- **Job dispatching** with signatories +- **Context-based access control** in OSIRIS +- **Typed object storage** (Note, Event) +- **Graceful shutdown** and cleanup + +## Expected Output + +The example will: +1. ✅ Create a Note successfully +2. ✅ Create an Event successfully +3. ✅ Query and retrieve stored objects +4. ✅ Deny access for unauthorized participants +5. ✅ Clean up all resources + +## Troubleshooting + +**Redis Connection Error:** +- Ensure Redis is running: `redis-server` + +**Build Errors:** +- Ensure both supervisor and runner_rust crates are available +- Check that all dependencies are up to date + +**OpenRPC Connection Error:** +- Port 3030 might be in use +- Check supervisor logs for startup issues diff --git a/examples/osiris_openrpc/access_denied.rhai b/examples/osiris_openrpc/access_denied.rhai new file mode 100644 index 0000000..f276302 --- /dev/null +++ b/examples/osiris_openrpc/access_denied.rhai @@ -0,0 +1,8 @@ +print("Attempting to access context with non-signatories..."); +print("Participants: [dave, eve]"); +print("Signatories: [alice, bob, charlie]"); + +// This should fail because neither dave nor eve are signatories +let ctx = get_context(["dave", "eve"]); + +"This should not succeed!" diff --git a/examples/osiris_openrpc/event.rhai b/examples/osiris_openrpc/event.rhai new file mode 100644 index 0000000..c609d74 --- /dev/null +++ b/examples/osiris_openrpc/event.rhai @@ -0,0 +1,18 @@ +print("Creating context for [alice, bob]..."); +let ctx = get_context(["alice", "bob"]); +print("✓ Context ID: " + ctx.context_id()); + +print("\nCreating event..."); +let event = event("events") + .title("Team Retrospective") + .description("Review what went well and areas for improvement") + .location("Virtual - Zoom Room A") + .category("retrospective"); + +print("✓ Event created"); + +print("\nStoring event in context..."); +ctx.save(event); +print("✓ Event stored"); + +"Event 'Team Retrospective' created and stored successfully" diff --git a/examples/osiris_openrpc/main.rs b/examples/osiris_openrpc/main.rs new file mode 100644 index 0000000..46ba078 --- /dev/null +++ b/examples/osiris_openrpc/main.rs @@ -0,0 +1,239 @@ +///! Comprehensive OSIRIS + OpenRPC Example +///! +///! This example demonstrates: +///! 1. Starting a Hero Supervisor with OpenRPC server +///! 2. Starting an OSIRIS runner +///! 3. Registering the runner with the supervisor +///! 4. Dispatching multiple OSIRIS jobs via OpenRPC +///! 5. Monitoring job execution +///! 6. Graceful shutdown +///! +///! Usage: +///! ```bash +///! cargo run --example osiris_openrpc +///! ``` + +use hero_supervisor_openrpc_client::{SupervisorClient, RunnerConfig, JobBuilder}; +use std::time::Duration; +use escargot::CargoBuild; +use std::process::Stdio; +use tokio::time::sleep; + +#[tokio::main] +async fn main() -> Result<(), Box> { + println!("🚀 OSIRIS + OpenRPC Comprehensive Example"); + println!("=========================================\n"); + + // ======================================================================== + // STEP 1: Build and start supervisor with OpenRPC + // ======================================================================== + println!("Step 1: Building and starting supervisor"); + println!("─────────────────────────────────────────────────────────────\n"); + + let supervisor_binary = CargoBuild::new() + .bin("supervisor") + .current_release() + .manifest_path("../supervisor/Cargo.toml") + .run()?; + + println!("✅ Supervisor binary built"); + + let mut supervisor = supervisor_binary.command() + .arg("--redis-url") + .arg("redis://localhost:6379") + .arg("--openrpc") + .arg("--openrpc-port") + .arg("3030") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; + + println!("✅ Supervisor started on port 3030"); + sleep(Duration::from_secs(2)).await; + + // ======================================================================== + // STEP 2: Build OSIRIS runner + // ======================================================================== + println!("\nStep 2: Building OSIRIS runner"); + println!("─────────────────────────────────────────────────────────────\n"); + + let runner_binary = CargoBuild::new() + .bin("runner_osiris") + .current_release() + .manifest_path("../runner_rust/Cargo.toml") + .run()?; + + println!("✅ OSIRIS runner binary built"); + + // ======================================================================== + // STEP 3: Connect OpenRPC client + // ======================================================================== + println!("\nStep 3: Connecting OpenRPC client"); + println!("─────────────────────────────────────────────────────────────\n"); + + let client = SupervisorClient::new("http://127.0.0.1:3030")?; + println!("✅ Connected to supervisor\n"); + + // ======================================================================== + // STEP 4: Register and start OSIRIS runner + // ======================================================================== + println!("Step 4: Registering OSIRIS runner"); + println!("─────────────────────────────────────────────────────────────\n"); + + let runner_path = runner_binary.path().to_string_lossy(); + let db_path = "/tmp/osiris_openrpc.db"; + + let command = format!( + "{} osiris_runner --db-path {} --redis-url redis://localhost:6379", + runner_path, db_path + ); + + let runner_config = RunnerConfig { + name: "osiris_runner".to_string(), + command, + env: None, + }; + + client.add_runner("admin_secret", runner_config).await?; + println!("✅ Runner registered: osiris_runner"); + + client.start_runner("admin_secret", "osiris_runner").await?; + println!("✅ Runner started\n"); + + sleep(Duration::from_secs(2)).await; + + // ======================================================================== + // STEP 5: Load job scripts + // ======================================================================== + println!("Step 5: Loading job scripts"); + println!("─────────────────────────────────────────────────────────────\n"); + + let note_script = std::fs::read_to_string("examples/osiris_openrpc/note.rhai")?; + let event_script = std::fs::read_to_string("examples/osiris_openrpc/event.rhai")?; + let query_script = std::fs::read_to_string("examples/osiris_openrpc/query.rhai")?; + let access_denied_script = std::fs::read_to_string("examples/osiris_openrpc/access_denied.rhai")?; + + println!("✅ Loaded 4 job scripts\n"); + + // ======================================================================== + // STEP 6: Dispatch jobs via OpenRPC + // ======================================================================== + println!("Step 6: Dispatching jobs"); + println!("─────────────────────────────────────────────────────────────\n"); + + // Job 1: Create Note + println!("📝 Job 1: Creating Note..."); + let job1 = JobBuilder::new() + .caller_id("openrpc_client") + .context_id("osiris_demo") + .payload(¬e_script) + .runner("osiris_runner") + .executor("rhai") + .timeout(30) + .signature("alice", "") + .signature("bob", "") + .build()?; + + let job1_result = client.run_job("user_secret", job1).await; + + match job1_result { + Ok(result) => println!("✅ {:?}\n", result), + Err(e) => println!("❌ Job failed: {}\n", e), + } + + sleep(Duration::from_secs(1)).await; + + // Job 2: Create Event + println!("📅 Job 2: Creating Event..."); + let job2 = JobBuilder::new() + .caller_id("openrpc_client") + .context_id("osiris_demo") + .payload(&event_script) + .runner("osiris_runner") + .executor("rhai") + .timeout(30) + .signature("alice", "") + .signature("bob", "") + .build()?; + + let job2_result = client.run_job("user_secret", job2).await; + + match job2_result { + Ok(result) => println!("✅ {:?}\n", result), + Err(e) => println!("❌ Job failed: {}\n", e), + } + + sleep(Duration::from_secs(1)).await; + + // Job 3: Query Data + println!("🔍 Job 3: Querying Data..."); + let job3 = JobBuilder::new() + .caller_id("openrpc_client") + .context_id("osiris_demo") + .payload(&query_script) + .runner("osiris_runner") + .executor("rhai") + .timeout(30) + .signature("alice", "") + .signature("bob", "") + .signature("charlie", "") + .build()?; + + let job3_result = client.run_job("user_secret", job3).await; + + match job3_result { + Ok(result) => println!("✅ {:?}\n", result), + Err(e) => println!("❌ Job failed: {}\n", e), + } + + sleep(Duration::from_secs(1)).await; + + // Job 4: Access Control Test (should fail) + println!("🔒 Job 4: Testing Access Control (expected to fail)..."); + let job4 = JobBuilder::new() + .caller_id("openrpc_client") + .context_id("osiris_demo") + .payload(&access_denied_script) + .runner("osiris_runner") + .executor("rhai") + .timeout(30) + .signature("alice", "") + .signature("bob", "") + .signature("charlie", "") + .build()?; + + let job4_result = client.run_job("user_secret", job4).await; + + match job4_result { + Ok(result) => println!("❌ Unexpected success: {:?}\n", result), + Err(e) => println!("✅ Access denied as expected: {}\n", e), + } + + // ======================================================================== + // STEP 7: Check runner status + // ======================================================================== + println!("\nStep 7: Checking runner status"); + println!("─────────────────────────────────────────────────────────────\n"); + + let status = client.get_runner_status("admin_secret", "osiris_runner").await?; + println!("Runner status: {:?}\n", status); + + // ======================================================================== + // STEP 8: Cleanup + // ======================================================================== + println!("Step 8: Cleanup"); + println!("─────────────────────────────────────────────────────────────\n"); + + client.stop_runner("admin_secret", "osiris_runner", false).await?; + println!("✅ Runner stopped"); + + client.remove_runner("admin_secret", "osiris_runner").await?; + println!("✅ Runner removed"); + + supervisor.kill()?; + println!("✅ Supervisor stopped"); + + println!("\n✨ Example completed successfully!"); + + Ok(()) +} diff --git a/examples/osiris_openrpc/note.rhai b/examples/osiris_openrpc/note.rhai new file mode 100644 index 0000000..7bc74b1 --- /dev/null +++ b/examples/osiris_openrpc/note.rhai @@ -0,0 +1,20 @@ +print("Creating context for [alice, bob]..."); +let ctx = get_context(["alice", "bob"]); +print("✓ Context ID: " + ctx.context_id()); + +print("\nCreating note..."); +let note = note("notes") + .title("Sprint Planning Meeting") + .content("Discussed Q1 2025 roadmap and milestones") + .tag("sprint", "2025-Q1") + .tag("team", "engineering") + .tag("priority", "high") + .mime("text/markdown"); + +print("✓ Note created"); + +print("\nStoring note in context..."); +ctx.save(note); +print("✓ Note stored"); + +"Note 'Sprint Planning Meeting' created and stored successfully" diff --git a/examples/osiris_openrpc/query.rhai b/examples/osiris_openrpc/query.rhai new file mode 100644 index 0000000..97ff892 --- /dev/null +++ b/examples/osiris_openrpc/query.rhai @@ -0,0 +1,21 @@ +print("Querying context [alice, bob]..."); +let ctx = get_context(["alice", "bob"]); +print("✓ Context ID: " + ctx.context_id()); + +print("\nListing all notes..."); +let notes = ctx.list("notes"); +print("✓ Found " + notes.len() + " note(s)"); + +print("\nRetrieving specific note..."); +let note = ctx.get("notes", "sprint_planning_001"); +print("✓ Retrieved note: sprint_planning_001"); + +print("\nQuerying context [alice, bob, charlie]..."); +let ctx2 = get_context(["alice", "bob", "charlie"]); +print("✓ Context ID: " + ctx2.context_id()); + +print("\nListing all events..."); +let events = ctx2.list("events"); +print("✓ Found " + events.len() + " event(s)"); + +"Query complete: Found " + notes.len() + " notes and " + events.len() + " events" diff --git a/run_supervisor_simple.sh b/run_supervisor_simple.sh new file mode 100755 index 0000000..32079d2 --- /dev/null +++ b/run_supervisor_simple.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Run Hero Supervisor with OpenRPC server only (no Mycelium) +# +# This starts the supervisor with: +# - OpenRPC HTTP server on port 3030 +# - Redis connection for job queuing +# - No Mycelium integration +# +# Usage: +# ./run_supervisor_simple.sh + +echo "🚀 Starting Hero Supervisor (OpenRPC only)" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo " OpenRPC Server: http://localhost:3030" +echo " Redis: redis://localhost:6379" +echo " Mycelium: Disabled" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +# Set environment variables +export RUST_LOG=info +export MYCELIUM_URL="" # Disable Mycelium + +# Build and run +cargo run --bin supervisor --no-default-features --features cli -- \ + --redis-url redis://localhost:6379 \ + --port 3030 diff --git a/src/app.rs b/src/app.rs index 4cb4cc5..9e662d4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -5,9 +5,12 @@ //! then pass it to SupervisorApp for runtime management. use crate::Supervisor; +#[cfg(feature = "mycelium")] use crate::mycelium::MyceliumIntegration; use log::{info, error, debug}; +#[cfg(feature = "mycelium")] use std::sync::Arc; +#[cfg(feature = "mycelium")] use tokio::sync::Mutex; /// Main supervisor application @@ -54,37 +57,45 @@ impl SupervisorApp { /// Start the Mycelium integration async fn start_mycelium_integration(&self) -> Result<(), Box> { - // Skip Mycelium if URL is empty - if self.mycelium_url.is_empty() { - info!("Mycelium integration disabled (no URL provided)"); - return Ok(()); + #[cfg(feature = "mycelium")] + { + // Skip Mycelium if URL is empty + if self.mycelium_url.is_empty() { + info!("Mycelium integration disabled (no URL provided)"); + return Ok(()); + } + + info!("Starting Mycelium integration..."); + + let supervisor_for_mycelium = Arc::new(Mutex::new(self.supervisor.clone())); + let mycelium_url = self.mycelium_url.clone(); + let topic = self.topic.clone(); + + let mycelium_integration = MyceliumIntegration::new( + supervisor_for_mycelium, + mycelium_url, + topic, + ); + + // Start the Mycelium integration in a background task + let integration_handle = tokio::spawn(async move { + if let Err(e) = mycelium_integration.start().await { + error!("Mycelium integration error: {}", e); + } + }); + + // Give the integration a moment to start + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + info!("Mycelium integration started successfully"); + + // Store the handle for potential cleanup + std::mem::forget(integration_handle); // For now, let it run in background } - info!("Starting Mycelium integration..."); - - let supervisor_for_mycelium = Arc::new(Mutex::new(self.supervisor.clone())); - let mycelium_url = self.mycelium_url.clone(); - let topic = self.topic.clone(); - - let mycelium_integration = MyceliumIntegration::new( - supervisor_for_mycelium, - mycelium_url, - topic, - ); - - // Start the Mycelium integration in a background task - let integration_handle = tokio::spawn(async move { - if let Err(e) = mycelium_integration.start().await { - error!("Mycelium integration error: {}", e); - } - }); - - // Give the integration a moment to start - tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; - info!("Mycelium integration started successfully"); - - // Store the handle for potential cleanup - std::mem::forget(integration_handle); // For now, let it run in background + #[cfg(not(feature = "mycelium"))] + { + info!("Mycelium integration not enabled (compile with --features mycelium)"); + } Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 65b4902..c3b0dc2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,8 @@ pub mod job; pub mod supervisor; pub mod app; pub mod openrpc; + +#[cfg(feature = "mycelium")] pub mod mycelium; // Re-export main types for convenience @@ -15,4 +17,6 @@ pub use runner::{Runner, RunnerConfig, RunnerResult, RunnerStatus}; pub use supervisor::{Supervisor, SupervisorBuilder, ProcessManagerType}; pub use runner_rust::{Job, JobBuilder, JobStatus, JobError, Client, ClientBuilder}; pub use app::SupervisorApp; + +#[cfg(feature = "mycelium")] pub use mycelium::{MyceliumIntegration, MyceliumServer}; diff --git a/src/mycelium.rs b/src/mycelium.rs index 29922ca..8cd2aa7 100644 --- a/src/mycelium.rs +++ b/src/mycelium.rs @@ -303,20 +303,88 @@ impl MyceliumIntegration { } "job.run" => { + // Run job and wait for result (blocking) if let Some(param_obj) = params.as_array().and_then(|arr| arr.get(0)) { let _secret = param_obj.get("secret") .and_then(|v| v.as_str()) .ok_or("missing secret")?; - let _job = param_obj.get("job") + + let job_value = param_obj.get("job") .ok_or("missing job")?; - // TODO: Implement actual job execution - Ok(json!("job_queued")) + let timeout = param_obj.get("timeout") + .and_then(|v| v.as_u64()) + .unwrap_or(60); + + // Deserialize the job + let job: runner_rust::job::Job = serde_json::from_value(job_value.clone()) + .map_err(|e| format!("invalid job format: {}", e))?; + + let job_id = job.id.clone(); + let runner_name = job.runner.clone(); + + // Verify signatures + job.verify_signatures() + .map_err(|e| format!("signature verification failed: {}", e))?; + + info!("Job {} signature verification passed for signatories: {:?}", + job_id, job.signatories()); + + // Queue and wait for result + let mut supervisor_guard = self.supervisor.lock().await; + let result = supervisor_guard.queue_and_wait(&runner_name, job, timeout) + .await + .map_err(|e| format!("job execution failed: {}", e))?; + + Ok(json!({ + "job_id": job_id, + "status": "completed", + "result": result + })) } else { Err("invalid job.run params".into()) } } + "job.start" => { + // Start job without waiting (non-blocking) + if let Some(param_obj) = params.as_array().and_then(|arr| arr.get(0)) { + let _secret = param_obj.get("secret") + .and_then(|v| v.as_str()) + .ok_or("missing secret")?; + + let job_value = param_obj.get("job") + .ok_or("missing job")?; + + // Deserialize the job + let job: runner_rust::job::Job = serde_json::from_value(job_value.clone()) + .map_err(|e| format!("invalid job format: {}", e))?; + + let job_id = job.id.clone(); + let runner_name = job.runner.clone(); + + // Verify signatures + job.verify_signatures() + .map_err(|e| format!("signature verification failed: {}", e))?; + + info!("Job {} signature verification passed for signatories: {:?}", + job_id, job.signatories()); + + // Queue the job without waiting + let mut supervisor_guard = self.supervisor.lock().await; + supervisor_guard.queue_job_to_runner(&runner_name, job) + .await + .map_err(|e| format!("failed to queue job: {}", e))?; + + Ok(json!({ + "job_id": job_id, + "status": "queued" + })) + } else { + Err("invalid job.start params".into()) + } + } + "job.status" => { if let Some(_job_id) = params.as_array().and_then(|arr| arr.get(0)).and_then(|v| v.as_str()) { // TODO: Implement actual job status lookup @@ -339,7 +407,7 @@ impl MyceliumIntegration { let methods = vec![ "list_runners", "register_runner", "start_runner", "stop_runner", "get_runner_status", "get_all_runner_status", "start_all", "stop_all", - "job.run", "job.status", "job.result", "rpc.discover" + "job.run", "job.start", "job.status", "job.result", "rpc.discover" ]; Ok(json!(methods)) } diff --git a/src/openrpc.rs b/src/openrpc.rs index e843717..e2470af 100644 --- a/src/openrpc.rs +++ b/src/openrpc.rs @@ -330,7 +330,6 @@ pub trait SupervisorRpc { #[method(name = "queue_job_to_runner")] async fn queue_job_to_runner(&self, params: QueueJobParams) -> RpcResult<()>; - /// Get a job by job ID #[method(name = "get_job")] async fn get_job(&self, job_id: String) -> RpcResult;