diff --git a/.github/workflows/_ci-desktop.yml b/.github/workflows/_ci-desktop.yml index 667b484141..108e18a215 100644 --- a/.github/workflows/_ci-desktop.yml +++ b/.github/workflows/_ci-desktop.yml @@ -92,6 +92,10 @@ jobs: run: just desktop-tauri-test env: CMAKE_POLICY_VERSION_MINIMUM: "3.5" + - name: Desktop Mesh feature tests + run: cargo test --manifest-path desktop/src-tauri/Cargo.toml --features mesh-llm --lib + env: + CMAKE_POLICY_VERSION_MINIMUM: "3.5" - name: Desktop Tauri compiled-flag verification run: just desktop-tauri-test-compiled-flags env: diff --git a/.release/desktop-candidate.json b/.release/desktop-candidate.json index 3832108ef6..9b5c9e020c 100644 --- a/.release/desktop-candidate.json +++ b/.release/desktop-candidate.json @@ -1,10 +1,10 @@ { "schema": 2, - "version": "0.5.22", - "base_sha": "75f101d8b4f5b4b26f9891b73b87c67fedac25a0", - "previous_tag": "desktop-v0.5.20", - "previous_base_sha": "8471049c430073474939336dfc6aa98272bc8762", - "previous_merge_sha": "52621c09bea503f4d5860030dfabfaf9ade71bfa", - "tag": "desktop-v0.5.22", - "commit_count": 114 + "version": "0.5.23", + "base_sha": "dad5a33865fc81a2e55b3b60746632f615ec1e3a", + "previous_tag": "desktop-v0.5.22", + "previous_base_sha": "75f101d8b4f5b4b26f9891b73b87c67fedac25a0", + "previous_merge_sha": "01bacb8df3d2f5718e0a468828e07ae874a38eae", + "tag": "desktop-v0.5.23", + "commit_count": 16 } diff --git a/CHANGELOG.md b/CHANGELOG.md index 50c056f46c..092d0f9452 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## v0.5.23 + +### Desktop and shared changes + +- fix(desktop): keep packaged frontendDist relative so Windows embeds assets ([#7177](https://github.com/block/buzz/pull/7177)) ([`dad5a33865fc81a2e55b3b60746632f615ec1e3a`](https://github.com/block/buzz/commit/dad5a33865fc81a2e55b3b60746632f615ec1e3a)) +- fix(sidebar): simplify unread indicators and emphasize priority activity ([#7134](https://github.com/block/buzz/pull/7134)) ([`f038cbbb0d4092a72ffd93f17916f84d2b39bb43`](https://github.com/block/buzz/commit/f038cbbb0d4092a72ffd93f17916f84d2b39bb43)) +- feat(buzz-acp): update base prompt; add buzz context and skills to Pi agents ([#7335](https://github.com/block/buzz/pull/7335)) ([`4beffef6979347f7ebdc760705865bdd04d23508`](https://github.com/block/buzz/commit/4beffef6979347f7ebdc760705865bdd04d23508)) +- fix(desktop): restore mention chip identity icons ([#7338](https://github.com/block/buzz/pull/7338)) ([`4afef8649ab11d60b423893e9e4f8cd36868d35a`](https://github.com/block/buzz/commit/4afef8649ab11d60b423893e9e4f8cd36868d35a)) +- Persist video playback speed preference ([#7336](https://github.com/block/buzz/pull/7336)) ([`5d107836c6bd6a57e2da28560ec0acc0d016b8d9`](https://github.com/block/buzz/commit/5d107836c6bd6a57e2da28560ec0acc0d016b8d9)) +- feat(desktop): invite owned agents from standalone forums ([#7125](https://github.com/block/buzz/pull/7125)) ([`e7e29937a145aca7a3c7f5436b07e32c6c20087f`](https://github.com/block/buzz/commit/e7e29937a145aca7a3c7f5436b07e32c6c20087f)) +- fix(desktop): authorize remote mentions at publication ([#7124](https://github.com/block/buzz/pull/7124)) ([`d595806fc3b9c9758992e39b9b51cbb5f55791b0`](https://github.com/block/buzz/commit/d595806fc3b9c9758992e39b9b51cbb5f55791b0)) +- fix(acp): rename system tag to agent-instructions ([#7332](https://github.com/block/buzz/pull/7332)) ([`ce9decb235f628c484631ac923db96466460fc3f`](https://github.com/block/buzz/commit/ce9decb235f628c484631ac923db96466460fc3f)) +- fix(desktop): bind duplicate mention selections to exact recipients ([#7133](https://github.com/block/buzz/pull/7133)) ([`ee883d73fb84752d26f52c6606ad3cadc9f12cc7`](https://github.com/block/buzz/commit/ee883d73fb84752d26f52c6606ad3cadc9f12cc7)) +- feat(desktop): preserve mentions across copy and paste ([#7228](https://github.com/block/buzz/pull/7228)) ([`b1f6b7ef770dddbb7f33c9f5861c379a47bca1d6`](https://github.com/block/buzz/commit/b1f6b7ef770dddbb7f33c9f5861c379a47bca1d6)) +- test(desktop): await Bestie drag and profile hover endpoints ([#7294](https://github.com/block/buzz/pull/7294)) ([`4b0744d7f3161d9f045dd67a73e014e4440c2b47`](https://github.com/block/buzz/commit/4b0744d7f3161d9f045dd67a73e014e4440c2b47)) +- Collapse contiguous join messages ([#7262](https://github.com/block/buzz/pull/7262)) ([`2ac0aa1dd18c0b9d4fa722658c4692b0c79a496f`](https://github.com/block/buzz/commit/2ac0aa1dd18c0b9d4fa722658c4692b0c79a496f)) + +### Other repository changes + +- Add generic information-flow control core ([#7293](https://github.com/block/buzz/pull/7293)) ([`4d447b9c20a23fb33c94778e6cf309424abea6c8`](https://github.com/block/buzz/commit/4d447b9c20a23fb33c94778e6cf309424abea6c8)) +- Verify ACP relay events before prompt routing ([#7010](https://github.com/block/buzz/pull/7010)) ([`e09f715c9d0ee2cb7bf8a39061e601f3a502f588`](https://github.com/block/buzz/commit/e09f715c9d0ee2cb7bf8a39061e601f3a502f588)) +- fix(buzz-acp): bound busy-owner hold to prevent cross-channel starvation ([#7337](https://github.com/block/buzz/pull/7337)) ([`b17c0776b7438d59904e8c38926148bf692fa5f5`](https://github.com/block/buzz/commit/b17c0776b7438d59904e8c38926148bf692fa5f5)) +- refactor(relay): extract NIP-29 membership authorization ([#7285](https://github.com/block/buzz/pull/7285)) ([`cd02b693aae86444b0b5636474a3d202c6fc8f26`](https://github.com/block/buzz/commit/cd02b693aae86444b0b5636474a3d202c6fc8f26)) + +[Compare desktop-v0.5.22...desktop-v0.5.23](https://github.com/block/buzz/compare/desktop-v0.5.22...desktop-v0.5.23) + ## v0.5.22 ### Desktop and shared changes diff --git a/Cargo.lock b/Cargo.lock index ffe9b7a618..72d9a1930a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,7 +58,7 @@ dependencies = [ "futures-concurrency", "rustc-hash", "rustix 1.1.4", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", "shell-words", @@ -69,12 +69,12 @@ dependencies = [ [[package]] name = "agent-client-protocol-derive" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3abd4080f51e4f24f5042beb7fb7a66ede29a2dc1c2582c329532e1c27264ddc" +checksum = "7e8d5f32208cdc11238004bec4e4229d68fb937598f900e153468ca084865fa5" dependencies = [ "quote", - "syn 3.0.4", + "syn 3.0.3", ] [[package]] @@ -85,7 +85,7 @@ checksum = "d5c231915b4ab578c722eca2d1bd7df4d300bfd6cac3b8e9f0d1e3ddc95b187c" dependencies = [ "anyhow", "derive_more", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", "serde_with", @@ -109,9 +109,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.5" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -124,9 +124,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android_system_properties" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] @@ -248,10 +248,16 @@ dependencies = [ ] [[package]] -name = "arrayvec" -version = "0.7.8" +name = "arrayref" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-broadcast" @@ -344,7 +350,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -384,7 +390,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -401,14 +407,14 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.3", ] [[package]] name = "async-utility" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "188f83b9a198af8c336e505611edb00d6d2ac5c694241c5a4f9a12316938cfe9" +checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151" dependencies = [ "futures-util", "gloo-timers", @@ -473,12 +479,12 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atomic-write-file" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae67d5c03ee972c101a1d8db3ddbf8a9c819ad1ea9d6fd9cd385605547b60edb" +checksum = "84790c55b5704b0d35130bf16a4ce22a8e70eb0ea773522557524d9a4852663d" dependencies = [ - "nix 0.31.3", - "rand 0.10.2", + "nix 0.30.1", + "rand 0.9.4", ] [[package]] @@ -494,14 +500,14 @@ dependencies = [ "serde", "serde_json", "url", - "webpki-roots 1.0.9", + "webpki-roots 1.0.7", ] [[package]] name = "autocfg" -version = "1.5.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-creds" @@ -514,16 +520,16 @@ dependencies = [ "quick-xml 0.38.4", "rust-ini", "serde", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "url", ] [[package]] name = "aws-lc-rs" -version = "1.18.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" dependencies = [ "aws-lc-sys", "untrusted 0.7.1", @@ -532,15 +538,14 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.45.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" dependencies = [ "cc", "cmake", "dunce", "fs_extra", - "pkg-config", ] [[package]] @@ -549,7 +554,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "838b36c8dc927b6db1b6c6b8f5d05865f2213550b9e83bf92fa99ed6525472c0" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -579,7 +584,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sha1 0.10.7", + "sha1 0.10.6", "sync_wrapper", "tokio", "tokio-tungstenite 0.29.0", @@ -616,7 +621,7 @@ checksum = "7aa268c23bfbbd2c4363b9cd302a4f504fb2a9dfe7e3451d66f35dd392e20aca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -684,7 +689,7 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc" dependencies = [ - "bitcoin_hashes 0.14.101", + "bitcoin_hashes 0.14.1", "serde", "unicode-normalization", ] @@ -721,13 +726,11 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitcoin-consensus-encoding" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6712f9c6fd6785b3b270884e57c441c403dc5d7e19ca45368c97c7a1de3000ec" +checksum = "207311705279250ba465076a1bac4b1ac982855fff73fc5f67e22158ac58cdc9" dependencies = [ "bitcoin-internals", - "hex-conservative 1.2.0", - "serde", ] [[package]] @@ -738,21 +741,18 @@ checksum = "d573f4cf32996a8dce612e4348cece65a241f1882ed594047c9ba348e8869fa5" [[package]] name = "bitcoin-io" -version = "0.1.101" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb5de036369d1ac59d3c1819ebc4d850f89466f5401c571a285b6ed564a4cb78" -dependencies = [ - "bitcoin-consensus-encoding", -] +checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" [[package]] name = "bitcoin_hashes" -version = "0.14.101" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" dependencies = [ "bitcoin-io", - "hex-conservative 0.2.3", + "hex-conservative 0.2.2", "serde", ] @@ -776,9 +776,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "serde_core", ] @@ -794,15 +794,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.7" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ + "arrayref", "arrayvec", "cc", "cfg-if 1.0.4", - "constant_time_eq 0.4.2", - "cpufeatures 0.3.1", + "constant_time_eq", + "cpufeatures 0.3.0", ] [[package]] @@ -816,9 +817,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.12.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ "hybrid-array", ] @@ -843,9 +844,9 @@ dependencies = [ [[package]] name = "blocking" -version = "1.7.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ "async-channel", "async-task", @@ -862,25 +863,27 @@ checksum = "e79769241dcd44edf79a732545e8b5cec84c247ac060f5252cd51885d093a8fc" [[package]] name = "bon" -version = "3.10.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3fac94a66da67200398458a25412bcc3f9b6443b5119a6cad9cf3ccfcd8cc6" +checksum = "f47dbe92550676ee653353c310dfb9cf6ba17ee70396e1f7cf0a2020ad49b2fe" dependencies = [ "bon-macros", + "rustversion", ] [[package]] name = "bon-macros" -version = "3.10.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4654961ad0494e4774c5c60b4cb4cd0ae9b9d92d039d901638b1dba97ebebf5" +checksum = "519bd3116aeeb42d5372c29d982d16d0170d3d4a5ed85fc7dd91642ffff3c67c" dependencies = [ - "darling 0.24.1", + "darling 0.23.0", "ident_case", - "prettyplease 0.3.0", + "prettyplease", "proc-macro2", "quote", - "syn 3.0.4", + "rustversion", + "syn 2.0.117", ] [[package]] @@ -894,20 +897,20 @@ dependencies = [ [[package]] name = "bstr" -version = "1.13.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "regex-automata", - "serde_core", + "serde", ] [[package]] name = "bumpalo" -version = "3.20.3" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "buzz-acp" @@ -925,17 +928,17 @@ dependencies = [ "hex", "httparse", "nix 0.31.3", - "nostr 0.44.8", + "nostr 0.44.7", "reqwest 0.13.4", "rustls", "serde", "serde_json", "sha2 0.11.0", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-tungstenite 0.29.0", "tokio-util", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", "tracing", "tracing-subscriber", "url", @@ -959,7 +962,7 @@ dependencies = [ "clap", "deadpool-redis", "hex", - "nostr 0.44.8", + "nostr 0.44.7", "rustls", "serde_json", "sqlx", @@ -1021,7 +1024,7 @@ dependencies = [ "serde_json", "sha2 0.11.0", "sqlx", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "uuid", @@ -1037,13 +1040,13 @@ dependencies = [ "futures-util", "hex", "jsonwebtoken", - "nostr 0.44.8", - "rand 0.10.2", + "nostr 0.44.7", + "rand 0.10.1", "reqwest 0.13.4", "serde", "serde_json", "sha2 0.11.0", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "url", @@ -1060,8 +1063,8 @@ dependencies = [ "http-body-util", "k8s-openapi", "kube", - "nostr 0.44.8", - "rand 0.10.2", + "nostr 0.44.7", + "rand 0.10.1", "rustls", "serde", "serde_json", @@ -1087,15 +1090,15 @@ dependencies = [ "dirs", "hex", "infer", - "nostr 0.44.8", - "rand 0.10.2", + "nostr 0.44.7", + "rand 0.10.1", "reqwest 0.13.4", "rustls", "serde", "serde_json", "sha2 0.11.0", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "url", "uuid", @@ -1108,7 +1111,7 @@ dependencies = [ "proptest", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "uuid", ] @@ -1120,14 +1123,14 @@ dependencies = [ "chrono", "hex", "hmac 0.13.0", - "nostr 0.44.8", + "nostr 0.44.7", "percent-encoding", - "rand 0.10.2", + "rand 0.10.1", "serde", "serde_json", "sha2 0.11.0", "subtle", - "thiserror 2.0.20", + "thiserror 2.0.18", "url", "uuid", "zeroize", @@ -1139,11 +1142,11 @@ version = "0.1.0" dependencies = [ "metrics", "metrics-util", - "opentelemetry 0.32.0", - "opentelemetry_sdk 0.32.1", + "opentelemetry", + "opentelemetry_sdk", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", "tokio", "tracing", "tracing-opentelemetry", @@ -1160,13 +1163,13 @@ dependencies = [ "hex", "metrics", "metrics-util", - "nostr 0.44.8", - "rand 0.10.2", + "nostr 0.44.7", + "rand 0.10.1", "serde", "serde_json", "sha2 0.11.0", "sqlx", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "uuid", @@ -1188,7 +1191,7 @@ dependencies = [ "serde", "serde_json", "sqlx", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "uuid", @@ -1206,11 +1209,11 @@ dependencies = [ "ignore", "image", "nix 0.31.3", - "nostr 0.44.8", + "nostr 0.44.7", "reqwest 0.13.4", "rmcp 1.8.0", "rustls", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", "similar", @@ -1239,14 +1242,14 @@ dependencies = [ "imagesize", "infer", "mp4", - "nostr 0.44.8", + "nostr 0.44.7", "quick-xml 0.38.4", "rust-s3", "serde", "serde_json", "sha2 0.11.0", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tracing", @@ -1302,9 +1305,9 @@ dependencies = [ "clap", "futures-util", "hex", - "nostr 0.44.8", + "nostr 0.44.7", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-tungstenite 0.29.0", "url", @@ -1319,7 +1322,7 @@ dependencies = [ "serde_json", "serde_yaml", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -1331,11 +1334,11 @@ dependencies = [ "chrono", "deadpool-redis", "futures-util", - "nostr 0.44.8", + "nostr 0.44.7", "redis", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "uuid", @@ -1357,15 +1360,15 @@ dependencies = [ "metrics", "metrics-exporter-prometheus", "minicbor", - "nostr 0.44.8", + "nostr 0.44.7", "proptest", - "rand 0.10.2", + "rand 0.10.1", "reqwest 0.13.4", "serde", "serde_json", "sha2 0.11.0", "sqlx", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tower", "tower-http", @@ -1415,13 +1418,13 @@ dependencies = [ "metrics-exporter-prometheus", "metrics-util", "moka", - "nostr 0.44.8", - "opentelemetry 0.32.0", - "opentelemetry-otlp 0.32.0", - "opentelemetry_sdk 0.32.1", + "nostr 0.44.7", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", "postcard", "pulldown-cmark", - "rand 0.10.2", + "rand 0.10.1", "redis", "reqwest 0.13.4", "rust-s3", @@ -1433,7 +1436,7 @@ dependencies = [ "sqlx", "subtle", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-tungstenite 0.29.0", "tokio-util", @@ -1456,14 +1459,14 @@ dependencies = [ "hex", "hmac 0.13.0", "iroh", - "nostr 0.44.8", + "nostr 0.44.7", "postcard", "proptest", "redis", "serde", "serde_json", "sha2 0.11.0", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "uuid", @@ -1474,10 +1477,10 @@ name = "buzz-sdk" version = "0.1.0" dependencies = [ "buzz-core", - "nostr 0.44.8", + "nostr 0.44.7", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "uuid", ] @@ -1489,7 +1492,7 @@ dependencies = [ "buzz-datastore-tracing", "metrics", "sqlx", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "uuid", @@ -1508,8 +1511,8 @@ dependencies = [ "chrono", "futures-util", "hex", - "nostr 0.44.8", - "rand 0.10.2", + "nostr 0.44.7", + "rand 0.10.1", "reqwest 0.13.4", "rust-s3", "rustls", @@ -1517,7 +1520,7 @@ dependencies = [ "serde_json", "sha2 0.11.0", "sqlx", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-tungstenite 0.29.0", "tracing", @@ -1534,7 +1537,7 @@ dependencies = [ "hex", "ort", "ort-sys", - "rand 0.10.2", + "rand 0.10.1", "sentencepiece-model", "serde", "serde_json", @@ -1558,12 +1561,12 @@ dependencies = [ "evalexpr", "hex", "moka", - "nostr 0.44.8", + "nostr 0.44.7", "reqwest 0.13.4", "serde", "serde_json", "serde_yaml", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "uuid", @@ -1574,9 +1577,9 @@ name = "buzz-ws-client" version = "0.1.0" dependencies = [ "futures-util", - "nostr 0.44.8", + "nostr 0.44.7", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-tungstenite 0.29.0", "tracing", @@ -1591,9 +1594,9 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" -version = "1.25.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -1609,9 +1612,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.12.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "bzip2" @@ -1623,15 +1626,6 @@ dependencies = [ "libc", ] -[[package]] -name = "bzip2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" -dependencies = [ - "bzip2-sys", -] - [[package]] name = "bzip2-sys" version = "0.1.13+1.0.8" @@ -1662,9 +1656,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.4.4" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "jobserver", @@ -1720,12 +1714,12 @@ dependencies = [ [[package]] name = "chacha20" -version = "0.10.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "rand_core 0.10.1", ] @@ -1798,7 +1792,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.3", ] [[package]] @@ -1818,9 +1812,9 @@ dependencies = [ [[package]] name = "cmov" -version = "0.5.4" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" [[package]] name = "cobs" @@ -1828,7 +1822,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -1854,9 +1848,9 @@ dependencies = [ [[package]] name = "combine" -version = "4.6.8" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "futures-core", @@ -1966,19 +1960,13 @@ checksum = "18f12cc9948ed9604230cdddc7c86e270f9401ccbe3c2e98a4378c5e7632212f" [[package]] name = "const_panic" -version = "0.2.17" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9603f79528ece8163c496f8932121cb36cfe46259e9c907bb3d8205139d7caa3" +checksum = "e262cdaac42494e3ae34c43969f9cdeb7da178bdb4b66fa6a1ea2edb4c8ae652" dependencies = [ "typewit", ] -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - [[package]] name = "constant_time_eq" version = "0.4.2" @@ -1996,9 +1984,9 @@ dependencies = [ [[package]] name = "cordyceps" -version = "0.3.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9ab7e0ca1d179628fa0172b2b97203c7fa0cd81be2448bd446fb9559ca9261" +checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" dependencies = [ "loom", "tracing", @@ -2037,7 +2025,7 @@ dependencies = [ "anyhow", "buzz-sdk", "futures-util", - "nostr 0.44.8", + "nostr 0.44.7", "serde_json", "tokio", "tokio-tungstenite 0.29.0", @@ -2064,9 +2052,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -2088,9 +2076,9 @@ checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crc32fast" -version = "1.5.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if 1.0.4", ] @@ -2115,18 +2103,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.16" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.7" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -2143,18 +2131,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.13" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crossterm" @@ -2162,7 +2150,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "crossterm_winapi", "mio", "parking_lot", @@ -2178,7 +2166,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "crossterm_winapi", "derive_more", "document-features", @@ -2223,7 +2211,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array", - "rand_core 0.10.1", ] [[package]] @@ -2267,9 +2254,9 @@ dependencies = [ [[package]] name = "ctor" -version = "1.0.13" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914a755b7c2d4af2bdcff7ce1739e2db9a1b81a9b07123d8015786ae03c0980d" +checksum = "2d83cb7e7a873830708d6b02a78cd36a592c6fa14bf267b68725103b85c0d77f" dependencies = [ "link-section", "linktime-proc-macro", @@ -2310,12 +2297,12 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "5.0.0" +version = "5.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23" +checksum = "4f359e08ca85e7bd759e1fd933ff2bccd81864c60a8fba0e259c7f822b0924bf" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "curve25519-dalek-derive", "digest 0.11.3", "fiat-crypto 0.3.0", @@ -2334,7 +2321,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2378,7 +2365,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2391,7 +2378,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2404,7 +2391,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 3.0.4", + "syn 3.0.3", ] [[package]] @@ -2415,7 +2402,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2426,7 +2413,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2437,7 +2424,7 @@ checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core 0.24.1", "quote", - "syn 3.0.4", + "syn 3.0.3", ] [[package]] @@ -2465,15 +2452,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.11.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "data-encoding-macro" -version = "0.1.21" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6a127ecbb3c4632e1525380e04c0c3fcf8dcb44d32a79ea290d8a36906edcd8" +checksum = "3259c913752a86488b501ed8680446a5ed2d5aeac6e596cb23ba3800768ea32c" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -2481,19 +2468,19 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.19" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54e03a951783e8b327515db3f2a2fd0e3bed362a96b066f341ce66ed49b4ead" +checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" dependencies = [ "data-encoding", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] name = "dbus" -version = "0.9.12" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab69f03cc8c4340c9c8e315114e1658e6775a9b16a04357973aa21cec22b32e" +checksum = "b942602992bb7acfd1f51c49811c58a610ef9181b6e66f3e519d79b540a3bf73" dependencies = [ "libc", "libdbus-sys", @@ -2521,19 +2508,20 @@ dependencies = [ [[package]] name = "deadpool" -version = "0.13.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e98a7e119cd347f4201e1159b19831029e203e2d8b790547708e8157b4acf1e" +checksum = "883466cb8db62725aee5f4a6011e8a5d42912b42632df32aad57fc91127c6e04" dependencies = [ "deadpool-runtime", + "num_cpus", "tokio", ] [[package]] name = "deadpool-redis" -version = "0.23.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243852fff546d8c5aac6ceaac7587f7137915b102c3fbec6256a64ce52452bd2" +checksum = "bafa30c49dafe086d10116074e422ad7fc1c3cf554697e744a3ab112599ebd09" dependencies = [ "deadpool", "redis", @@ -2548,12 +2536,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "deflate64" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2" - [[package]] name = "defmt" version = "1.1.1" @@ -2573,7 +2555,7 @@ dependencies = [ "defmt-parser", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2582,7 +2564,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -2593,9 +2575,9 @@ checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" [[package]] name = "der" -version = "0.8.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d" +checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" dependencies = [ "const-oid", "pem-rfc7468", @@ -2608,6 +2590,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ + "powerfmt", "serde_core", ] @@ -2619,7 +2602,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2640,7 +2623,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2650,7 +2633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2672,7 +2655,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.119", + "syn 2.0.117", "unicode-xid", ] @@ -2684,9 +2667,9 @@ checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" [[package]] name = "diffy" -version = "0.5.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e3dc2f773b6aaa63b1a7684b8589f670a8a0146a510b74d23a401c882364b49" +checksum = "10aec8f7f9393bd6a4f2762be0ceb012d3cbe2478987258cc9960de148561914" dependencies = [ "hashbrown 0.17.1", ] @@ -2708,7 +2691,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "block-buffer 0.12.1", + "block-buffer 0.12.0", "const-oid", "crypto-common 0.2.2", "ctutils", @@ -2741,7 +2724,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -2749,13 +2732,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.7" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -2822,7 +2805,7 @@ version = "3.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60" dependencies = [ - "curve25519-dalek 5.0.0", + "curve25519-dalek 5.0.0-rc.0", "ed25519", "rand_core 0.10.1", "serde", @@ -2834,9 +2817,9 @@ dependencies = [ [[package]] name = "either" -version = "1.18.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" dependencies = [ "serde", ] @@ -2876,13 +2859,13 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "enum-assoc" -version = "1.4.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0590c4a94da3372e83493b956755a6e2266830b6e4e3b101afe66e3f39477b91" +checksum = "3ed8956bd5c1f0415200516e78ff07ec9e16415ade83c056c230d7b7ea0d55b7" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -2903,7 +2886,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -2955,10 +2938,11 @@ checksum = "b6aff27af350e7b53e82aac3e5ab6389abd8f280640ac034508dff0608c4c7e5" [[package]] name = "event-listener" -version = "5.4.2" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ + "concurrent-queue", "parking", "pin-project-lite", ] @@ -2990,6 +2974,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fancy-regex" version = "0.11.0" @@ -3011,6 +3007,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "faster-hex" version = "0.10.0" @@ -3023,9 +3025,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fdeflate" @@ -3071,9 +3073,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "finl_unicode" @@ -3095,13 +3097,12 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.10" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", - "miniz_oxide 0.9.1", - "zlib-rs", + "miniz_oxide", ] [[package]] @@ -3112,7 +3113,7 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.9", + "spin 0.9.8", ] [[package]] @@ -3123,7 +3124,7 @@ checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.9", + "spin 0.9.8", ] [[package]] @@ -3209,7 +3210,7 @@ dependencies = [ "diatomic-waker", "futures-core", "pin-project-lite", - "spin 0.10.1", + "spin 0.10.0", ] [[package]] @@ -3290,7 +3291,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.3", ] [[package]] @@ -3333,9 +3334,9 @@ dependencies = [ [[package]] name = "generator" -version = "0.8.9" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b854b0e584ead1a33f18b2fcad7cf7be18b3875c78816b753639aa501513ae" +checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9" dependencies = [ "cc", "cfg-if 1.0.4", @@ -3377,11 +3378,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if 1.0.4", - "js-sys", "libc", "r-efi 5.3.0", "wasip2", - "wasm-bindgen", ] [[package]] @@ -3423,7 +3422,7 @@ name = "git-credential-nostr" version = "0.1.0" dependencies = [ "base64 0.22.1", - "nostr 0.44.8", + "nostr 0.44.7", "serde_json", "zeroize", ] @@ -3436,7 +3435,7 @@ dependencies = [ "chrono", "hex", "libc", - "nostr 0.44.8", + "nostr 0.44.7", "serde_json", "zeroize", ] @@ -3458,14 +3457,14 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "globset" -version = "0.4.20" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", "bstr", @@ -3489,7 +3488,7 @@ dependencies = [ [[package]] name = "goose-agent" version = "0.1.0-alpha.6" -source = "git+https://github.com/aaif-goose/goose?rev=5a9a13b72aaf8f9aa17ce064bd4d4d761d656982#5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" +source = "git+https://github.com/aaif-goose/goose?rev=2f2c92c24c1438cef142476ee6507df82e6c3fba#2f2c92c24c1438cef142476ee6507df82e6c3fba" dependencies = [ "anyhow", "async-trait", @@ -3497,7 +3496,7 @@ dependencies = [ "goose-provider-types", "goose-sdk-types", "ignore", - "indexmap 2.14.1", + "indexmap 2.14.0", "libc", "minijinja", "once_cell", @@ -3518,7 +3517,7 @@ dependencies = [ [[package]] name = "goose-context-management" version = "0.1.0-alpha.6" -source = "git+https://github.com/aaif-goose/goose?rev=5a9a13b72aaf8f9aa17ce064bd4d4d761d656982#5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" +source = "git+https://github.com/aaif-goose/goose?rev=2f2c92c24c1438cef142476ee6507df82e6c3fba#2f2c92c24c1438cef142476ee6507df82e6c3fba" dependencies = [ "anyhow", "async-trait", @@ -3534,7 +3533,7 @@ dependencies = [ [[package]] name = "goose-provider-types" version = "0.1.0-alpha.6" -source = "git+https://github.com/aaif-goose/goose?rev=5a9a13b72aaf8f9aa17ce064bd4d4d761d656982#5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" +source = "git+https://github.com/aaif-goose/goose?rev=2f2c92c24c1438cef142476ee6507df82e6c3fba#2f2c92c24c1438cef142476ee6507df82e6c3fba" dependencies = [ "anyhow", "async-stream", @@ -3543,14 +3542,14 @@ dependencies = [ "chrono", "futures", "once_cell", - "rand 0.10.2", + "rand 0.10.1", "regex", "reqwest 0.13.4", "rmcp 3.2.0", "serde", "serde_json", "strum", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "unicode-normalization", @@ -3560,7 +3559,7 @@ dependencies = [ [[package]] name = "goose-providers" version = "0.1.0-alpha.6" -source = "git+https://github.com/aaif-goose/goose?rev=5a9a13b72aaf8f9aa17ce064bd4d4d761d656982#5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" +source = "git+https://github.com/aaif-goose/goose?rev=2f2c92c24c1438cef142476ee6507df82e6c3fba#2f2c92c24c1438cef142476ee6507df82e6c3fba" dependencies = [ "anyhow", "async-stream", @@ -3584,20 +3583,20 @@ dependencies = [ [[package]] name = "goose-sdk-types" version = "0.1.0-alpha.6" -source = "git+https://github.com/aaif-goose/goose?rev=5a9a13b72aaf8f9aa17ce064bd4d4d761d656982#5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" +source = "git+https://github.com/aaif-goose/goose?rev=2f2c92c24c1438cef142476ee6507df82e6c3fba#2f2c92c24c1438cef142476ee6507df82e6c3fba" dependencies = [ "agent-client-protocol", "agent-client-protocol-schema", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", ] [[package]] name = "h2" -version = "0.4.19" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +checksum = "a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27" dependencies = [ "atomic-waker", "bytes", @@ -3605,7 +3604,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.14.1", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -3672,9 +3671,18 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.11.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "hashlink" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ "hashbrown 0.16.1", ] @@ -3703,9 +3711,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -3715,9 +3723,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-conservative" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3fef046dca3ca91ee1408a8c1b80ab777e80a4d308d1bf4e7adb3fcb047e08" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" dependencies = [ "arrayvec", ] @@ -3744,7 +3752,7 @@ dependencies = [ "more-asserts", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tokio_with_wasm", @@ -3775,9 +3783,9 @@ dependencies = [ "idna", "ipnet", "jni 0.22.4", - "rand 0.10.2", + "rand 0.10.1", "rustls", - "thiserror 2.0.20", + "thiserror 2.0.18", "tinyvec", "tokio", "tokio-rustls", @@ -3797,9 +3805,9 @@ dependencies = [ "jni 0.22.4", "once_cell", "prefix-trie", - "rand 0.10.2", + "rand 0.10.1", "ring", - "thiserror 2.0.20", + "thiserror 2.0.18", "tinyvec", "tracing", "url", @@ -3822,12 +3830,12 @@ dependencies = [ "ndk-context", "once_cell", "parking_lot", - "rand 0.10.2", + "rand 0.10.1", "resolv-conf", "rustls", "smallvec", "system-configuration", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-rustls", "tracing", @@ -3880,9 +3888,9 @@ dependencies = [ [[package]] name = "http" -version = "1.5.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -3890,9 +3898,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.1.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", @@ -3931,24 +3939,24 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.4.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hybrid-array" -version = "0.4.14" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "typenum", ] [[package]] name = "hyper" -version = "1.11.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -3981,7 +3989,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.9", + "webpki-roots 1.0.7", ] [[package]] @@ -4064,9 +4072,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", @@ -4078,9 +4086,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -4091,9 +4099,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -4105,17 +4113,16 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", @@ -4126,15 +4133,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.3.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -4197,9 +4204,9 @@ dependencies = [ [[package]] name = "igd-next" -version = "0.17.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de7238d487a9aff61f81b5ab41c0a841532a115a398b5fa92a2fadd0885e2581" +checksum = "bac9a3c8278f43b4cd8463380f4a25653ac843e5b177e1d3eaf849cc9ba10d4d" dependencies = [ "attohttpc", "bytes", @@ -4209,7 +4216,7 @@ dependencies = [ "hyper", "hyper-util", "log", - "rand 0.10.2", + "rand 0.10.1", "tokio", "url", "xmltree", @@ -4217,9 +4224,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.33" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b69833ed729dc5aa7d19541d96d6cf8e9137194207a04916d658e43168402f" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" dependencies = [ "crossbeam-deque", "globset", @@ -4297,9 +4304,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.1", @@ -4337,15 +4344,15 @@ dependencies = [ [[package]] name = "instability" -version = "0.3.13" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf84e73fa6f27f299dec58e13223cf70db80da872eb921d4f6138342a0eabc8" +checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" dependencies = [ - "darling 0.24.1", + "darling 0.23.0", "indoc", "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -4375,18 +4382,18 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.12.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" dependencies = [ "serde", ] [[package]] name = "iroh" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329552fad4e46b5ccb4439d5635216f6289eec2c46f3fde4bc732d762694b9e5" +checksum = "460de6bc52163b41b1646931f2897e5ab986f0966ade444467fec25024751a72" dependencies = [ "backon", "blake3", @@ -4416,7 +4423,7 @@ dependencies = [ "pin-project", "portable-atomic", "portmapper", - "rand 0.10.2", + "rand 0.10.1", "reqwest 0.13.4", "rustc-hash", "rustls", @@ -4435,18 +4442,18 @@ dependencies = [ [[package]] name = "iroh-base" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ccf4cde68a02ef03c0095ab2c031c6adfe508f3bc8e7c258558a027ebe64a8e" +checksum = "6be73e16ee21c923aca9b3121aaa0db936f7c7ecc156ff47b8dac944c68d59a8" dependencies = [ - "curve25519-dalek 5.0.0", + "curve25519-dalek 5.0.0-rc.0", "data-encoding", "data-encoding-macro", "derive_more", "ed25519-dalek", "getrandom 0.4.3", "n0-error", - "rand 0.10.2", + "rand 0.10.1", "serde", "url", "zeroize", @@ -4454,9 +4461,9 @@ dependencies = [ [[package]] name = "iroh-dns" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a41224eb0140a5c519935d4073fc6b236d174080be401f9bf7da126b2ee3aa4" +checksum = "46f6a9b39d18e6345f5c151afd299f2488e2cb5c520fe41b107b6bd3dc4c3349" dependencies = [ "arc-swap", "cfg_aliases", @@ -4467,7 +4474,7 @@ dependencies = [ "n0-future", "ndk-context", "portable-atomic", - "rand 0.10.2", + "rand 0.10.1", "rustls", "simple-dns", "strum", @@ -4500,14 +4507,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "iroh-relay" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5f6f07e2c9b0c4bc82e2864be09f4aea4320165d5316e668616dbc822f428a" +checksum = "24bd586cf927f7b700f56ec3639b53cb5fa901ce284784051ff71092bfbf8193" dependencies = [ "blake3", "bytes", @@ -4531,7 +4538,7 @@ dependencies = [ "num_enum", "pin-project", "postcard", - "rand 0.10.2", + "rand 0.10.1", "reqwest 0.13.4", "rustls", "rustls-pki-types", @@ -4544,7 +4551,7 @@ dependencies = [ "tokio-websockets", "tracing", "url", - "webpki-roots 1.0.9", + "webpki-roots 1.0.7", "ws_stream_wasm", ] @@ -4604,7 +4611,7 @@ dependencies = [ "jiff-core", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -4650,7 +4657,7 @@ dependencies = [ "jni-sys 0.4.1", "log", "simd_cesu8", - "thiserror 2.0.20", + "thiserror 2.0.18", "walkdir", "windows-link 0.2.1", ] @@ -4665,7 +4672,7 @@ dependencies = [ "quote", "rustc_version", "simd_cesu8", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -4693,40 +4700,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "jobserver" -version = "0.1.35" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.4.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ "cfg-if 1.0.4", "futures-util", + "once_cell", "wasm-bindgen", ] -[[package]] -name = "json5" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733a844dbd6fef128e98cb4487b887cb55454d92cd9994b1bafe004fabbe670c" -dependencies = [ - "serde", - "ucd-trie", -] - [[package]] name = "jsonpath-rust" version = "0.7.5" @@ -4737,7 +4735,7 @@ dependencies = [ "pest_derive", "regex", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -4778,7 +4776,7 @@ checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" dependencies = [ "hashbrown 0.16.1", "portable-atomic", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -4854,7 +4852,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tower", @@ -4876,7 +4874,7 @@ dependencies = [ "serde", "serde-value", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -4893,9 +4891,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "left-right" -version = "0.11.8" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bc015ded5d9b3054dbbdb63332cdd6ee42352ccef19e911e25117490e2f48ee" +checksum = "0f0c21e4c8ff95f487fb34e6f9182875f42c84cef966d29216bf115d9bba835a" dependencies = [ "crossbeam-utils", "loom", @@ -4936,43 +4934,44 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.23" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d8f1ea3f21fd3405dcaf6c9b5c1630af9afc422d9073ea39c5f6d6c772e08ed" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ "libc", ] [[package]] name = "libsqlite3-sys" -version = "0.37.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" +checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" dependencies = [ + "cc", "pkg-config", "vcpkg", ] [[package]] name = "line-clipping" -version = "0.3.8" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e752191d037c44ad111a8caa762921926658402f01cc1253f7bef2020ece4f5e" +checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", ] [[package]] name = "link-section" -version = "0.19.3" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c29a617ce3df32c08497bdc1ab6e2376e0b17948ac166a2fbe5977c5954cd9" +checksum = "5ee1a0d6e252afe82e7bc2db42fba60e02ddf3b1accaf8cb21d96e34ba61f3d4" [[package]] name = "linktime-proc-macro" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e57c38c1e860fd37c604281cdfb1dd2216977fd76a50f85ba2f388ef3219616" +checksum = "348d0075b1fc163b26d72a7f75fc5141daf2fd1bdf128d873cbaf6785d495bdf" [[package]] name = "linux-raw-sys" @@ -4988,9 +4987,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "litrs" @@ -5009,9 +5008,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.34" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "logos" @@ -5034,7 +5033,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -5061,9 +5060,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.18.3" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d317b4b9eb398e6acce275758ec6125535505e7a146fb1a9b8bda2451b0ff4c" +checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9" dependencies = [ "hashbrown 0.17.1", ] @@ -5083,27 +5082,6 @@ dependencies = [ "twox-hash", ] -[[package]] -name = "lzma-rs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" -dependencies = [ - "byteorder", - "crc", -] - -[[package]] -name = "lzma-sys" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "mac-addr" version = "0.3.0" @@ -5169,7 +5147,7 @@ checksum = "746873a384ad60adc5db74471dfaba74bd278afbdcfd81db93fafcdfc8b5ca0c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -5184,9 +5162,9 @@ dependencies = [ [[package]] name = "md5" -version = "0.8.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebb8d8732c6a6df3d8f032a82911cfc747e00efb95cc46e8d0acd5b5b88570c" +checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" [[package]] name = "mdns-sd" @@ -5205,9 +5183,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.3" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmem" @@ -5217,9 +5195,9 @@ checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" [[package]] name = "memo-map" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b" +checksum = "5449c8c750f1a07ea702bbd212bd999fceece9b3d1508b17023b3e174583124b" [[package]] name = "memoffset" @@ -5232,18 +5210,18 @@ dependencies = [ [[package]] name = "mesh-llm-api-client" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "hex", "mesh-llm-client", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "mesh-llm-api-server" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "mesh-llm-api-client", @@ -5253,21 +5231,18 @@ dependencies = [ [[package]] name = "mesh-llm-build-info" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" [[package]] name = "mesh-llm-client" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "async-trait", "base64 0.22.1", "bytes", - "crypto_box", - "ed25519-dalek", - "hex", "httparse", "iroh", "mesh-llm-identity", @@ -5276,13 +5251,11 @@ dependencies = [ "mesh-llm-types", "model-artifact", "nostr-sdk", - "prost 0.14.4", - "rand 0.10.2", + "prost 0.14.3", "rustls", "serde", "serde_json", - "sha2 0.10.9", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "uuid", @@ -5290,8 +5263,8 @@ dependencies = [ [[package]] name = "mesh-llm-config" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "dirs", @@ -5306,8 +5279,8 @@ dependencies = [ [[package]] name = "mesh-llm-embedded-runtime" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "mesh-llm-host-runtime", @@ -5316,20 +5289,25 @@ dependencies = [ [[package]] name = "mesh-llm-events" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", + "chrono", "clap", "crossterm 0.28.1", + "libc", "ratatui", + "serde", "serde_json", + "tracing", + "uuid", ] [[package]] name = "mesh-llm-gpu-bench" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", "serde_json", @@ -5338,8 +5316,8 @@ dependencies = [ [[package]] name = "mesh-llm-guardrails" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", "serde_json", @@ -5347,8 +5325,8 @@ dependencies = [ [[package]] name = "mesh-llm-hardware-profile" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "mesh-llm-native-runtime", ] @@ -5373,7 +5351,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.11.0", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-retry", "tokio-util", @@ -5384,8 +5362,8 @@ dependencies = [ [[package]] name = "mesh-llm-host-runtime" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "argon2", @@ -5407,7 +5385,6 @@ dependencies = [ "http-body-util", "httparse", "iroh", - "json5", "keyring", "libc", "mdns-sd", @@ -5419,6 +5396,7 @@ dependencies = [ "mesh-llm-guardrails", "mesh-llm-hf-hub", "mesh-llm-identity", + "mesh-llm-log-store", "mesh-llm-native-runtime", "mesh-llm-node", "mesh-llm-plugin", @@ -5438,21 +5416,20 @@ dependencies = [ "model-resolver", "nostr-sdk", "openai-frontend", - "opentelemetry 0.31.0", - "opentelemetry-otlp 0.31.1", - "opentelemetry_sdk 0.31.0", - "prost 0.14.4", - "rand 0.10.2", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", + "prost 0.14.3", + "rand 0.10.1", "regex-lite", "reqwest 0.12.28", "rmcp 1.8.0", "rpassword", "rustls", - "schemars 1.2.2", + "schemars 1.2.1", "semver", "serde", "serde_json", - "serde_yaml", "sha2 0.10.9", "skippy-coordinator", "skippy-ffi", @@ -5464,7 +5441,7 @@ dependencies = [ "tabwriter", "tar", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-stream", "toml 0.9.12+spec-1.1.0", @@ -5472,14 +5449,16 @@ dependencies = [ "tracing-subscriber", "url", "urlencoding", + "uuid", + "windows-sys 0.61.2", "zeroize", "zip", ] [[package]] name = "mesh-llm-identity" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "argon2", "base64 0.22.1", @@ -5490,18 +5469,36 @@ dependencies = [ "ed25519-dalek", "hex", "keyring", - "rand 0.10.2", + "rand 0.10.1", "serde", "serde_json", "sha2 0.10.9", - "thiserror 2.0.20", + "thiserror 2.0.18", "zeroize", ] +[[package]] +name = "mesh-llm-log-store" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" +dependencies = [ + "chrono", + "data-encoding", + "hex", + "mesh-llm-events", + "rusqlite", + "serde", + "serde_json", + "sha2 0.10.9", + "thiserror 2.0.18", + "uuid", + "windows-sys 0.61.2", +] + [[package]] name = "mesh-llm-native-runtime" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "serde", @@ -5511,8 +5508,8 @@ dependencies = [ [[package]] name = "mesh-llm-node" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "mesh-llm-types", @@ -5525,16 +5522,16 @@ dependencies = [ [[package]] name = "mesh-llm-plugin" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "async-trait", - "prost 0.14.4", - "prost-build 0.14.4", + "prost 0.14.3", + "prost-build 0.14.3", "protoc-bin-vendored", "rmcp 1.8.0", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", "tokio", @@ -5542,8 +5539,8 @@ dependencies = [ [[package]] name = "mesh-llm-plugin-manager" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "dirs", @@ -5561,21 +5558,21 @@ dependencies = [ [[package]] name = "mesh-llm-protocol" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "hex", "iroh", - "prost 0.14.4", + "prost 0.14.3", "serde_json", "sha2 0.10.9", ] [[package]] name = "mesh-llm-release-footer" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "hex", "sha2 0.10.9", @@ -5583,16 +5580,19 @@ dependencies = [ [[package]] name = "mesh-llm-routing" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ + "blake3", "iroh", + "serde", + "serde_json", ] [[package]] name = "mesh-llm-runtime-install" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "dirs", @@ -5614,8 +5614,8 @@ dependencies = [ [[package]] name = "mesh-llm-sdk" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "mesh-llm-api-client", @@ -5629,8 +5629,8 @@ dependencies = [ [[package]] name = "mesh-llm-skills" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "dirs", @@ -5640,8 +5640,8 @@ dependencies = [ [[package]] name = "mesh-llm-system" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "chrono", @@ -5667,8 +5667,8 @@ dependencies = [ [[package]] name = "mesh-llm-types" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "hex", "serde", @@ -5678,13 +5678,13 @@ dependencies = [ [[package]] name = "mesh-llm-ui" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" [[package]] name = "mesh-mixture-of-agents" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "async-trait", "mesh-llm-guardrails", @@ -5697,18 +5697,19 @@ dependencies = [ [[package]] name = "mesh-native-serving-plugin-api" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" [[package]] name = "mesh-native-serving-plugin-host" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "libloading", "mesh-native-serving-plugin-api", "skippy-server", + "skippy-tokenizer", ] [[package]] @@ -5733,13 +5734,13 @@ dependencies = [ "hyper", "hyper-rustls", "hyper-util", - "indexmap 2.14.1", + "indexmap 2.14.0", "ipnet", "metrics", "metrics-util", "quanta", "rustls", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -5754,12 +5755,12 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "hashbrown 0.16.1", - "indexmap 2.14.1", + "indexmap 2.14.0", "metrics", - "ordered-float 5.5.0", + "ordered-float 5.3.0", "quanta", "radix_trie", - "rand 0.9.5", + "rand 0.9.4", "rand_xoshiro", "rapidhash", "sketches-ddsketch", @@ -5784,7 +5785,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -5844,21 +5845,11 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "miniz_oxide" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" -dependencies = [ - "adler2", - "simd-adler32", -] - [[package]] name = "mio" -version = "1.2.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "log", @@ -5868,8 +5859,8 @@ dependencies = [ [[package]] name = "model-artifact" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "async-trait", @@ -5879,26 +5870,29 @@ dependencies = [ [[package]] name = "model-hf" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "async-trait", "chrono", "dirs", + "libc", "mesh-llm-hf-hub", "model-artifact", "model-ref", + "rustls", "serde", "serde_json", "sha2 0.10.9", "tokio", + "tracing", ] [[package]] name = "model-package" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "bytes", @@ -5917,16 +5911,16 @@ dependencies = [ [[package]] name = "model-ref" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", ] [[package]] name = "model-resolver" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "model-artifact", @@ -5937,9 +5931,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.16" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4293f18e7567a1caf3c584855554377025c65e0aa445344d04171f5ad63d19b9" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -5971,7 +5965,7 @@ checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -6012,9 +6006,9 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "n0-error" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c59ea174675ce6bc196878851e5049e11b8b1f9af3ba87e4d6df8d828bb001" +checksum = "c37e81176a83a77d2514528b91bdafc70ef88aab428f0e1b91aebb8d99888895" dependencies = [ "n0-error-macros", "spez", @@ -6028,7 +6022,7 @@ checksum = "e2acd8b070213b0299282f884b4beba4e7b52d624fdcd504a3ad3665390c11e1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -6103,9 +6097,9 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "negentropy" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81c353b400a5503efdcf398f11a83fb7aa84f59f5d76fc4bf5bbc1e4f5366caa" +checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d" [[package]] name = "netdev" @@ -6121,9 +6115,9 @@ dependencies = [ "libc", "mac-addr", "ndk-context", - "netlink-packet-core 0.8.2", - "netlink-packet-route 0.31.0", - "netlink-sys 0.8.8", + "netlink-packet-core", + "netlink-packet-route", + "netlink-sys", "objc2", "objc2-core-foundation", "objc2-core-wlan", @@ -6134,83 +6128,39 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "netdev" -version = "0.46.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4db4135b187ddae3b6813c4f9d9ac9d5181859fa6a08b4e006c63a130974ed62" -dependencies = [ - "block2", - "dispatch2", - "dlopen2", - "ipnet", - "jni 0.21.1", - "libc", - "mac-addr", - "ndk-context", - "netlink-packet-core 0.9.0", - "netlink-packet-route 0.33.0", - "netlink-sys 0.9.0", - "objc2-core-foundation", - "objc2-system-configuration", - "once_cell", - "plist", - "windows-sys 0.61.2", -] - [[package]] name = "netlink-packet-core" -version = "0.8.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b897d7bd4f0af82e68d40d0344cf37e97f9c97ddf74a098de3e4da05e96ca395" +checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" dependencies = [ "paste", ] -[[package]] -name = "netlink-packet-core" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6e2daf9a8c2e21302714706860a0e6be02e03d17294ecc66b354ea7d4059dd" - [[package]] name = "netlink-packet-route" version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2288fcb784eb3defd5fb16f4c4160d5f477de192eac730f43e1d11c24d9a007" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "libc", "log", - "netlink-packet-core 0.8.2", -] - -[[package]] -name = "netlink-packet-route" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d48ffc8b73a506e1ff0878528c72668f2bfbc3d875b6be890a96be5d0d5576" -dependencies = [ - "bitflags 2.13.1", - "libc", - "log", - "netlink-packet-core 0.9.0", - "zerocopy", + "netlink-packet-core", ] [[package]] name = "netlink-proto" -version = "0.12.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93af8261786086024cd5e96e0a991dd65ced07bbf7c233a487bbc96b971d5539" +checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128" dependencies = [ "bytes", - "futures-channel", - "futures-util", + "futures", "log", - "netlink-packet-core 0.8.2", - "netlink-sys 0.8.8", - "thiserror 2.0.20", + "netlink-packet-core", + "netlink-sys", + "thiserror 2.0.18", ] [[package]] @@ -6226,22 +6176,11 @@ dependencies = [ "tokio", ] -[[package]] -name = "netlink-sys" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c99d38e00b420df49e940fe0826e667c3dad82ac68eb4c2bbf754c1c14a83a10" -dependencies = [ - "bytes", - "libc", - "log", -] - [[package]] name = "netwatch" -version = "0.19.3" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39da9cad5f23aa43401f09497d3b280e51b5feba115d9ffbf38ca35d6ff95e96" +checksum = "4d9cbe01741347ef750d743d6690603f5eed8341e679fb51c8e629337aa11976" dependencies = [ "atomic-waker", "bytes", @@ -6253,12 +6192,11 @@ dependencies = [ "n0-error", "n0-future", "n0-watcher", - "netdev 0.45.0", - "netdev 0.46.2", - "netlink-packet-core 0.8.2", - "netlink-packet-route 0.31.0", + "netdev", + "netlink-packet-core", + "netlink-packet-route", "netlink-proto", - "netlink-sys 0.8.8", + "netlink-sys", "noq-udp", "objc2-core-foundation", "objc2-system-configuration", @@ -6290,20 +6228,32 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases", "libc", "memoffset", ] +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.13.0", + "cfg-if 1.0.4", + "cfg_aliases", + "libc", +] + [[package]] name = "nix" version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases", "libc", @@ -6321,9 +6271,9 @@ dependencies = [ [[package]] name = "noq" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e6c57353d26be91a242f0ec96073066c4481a03f6be874daafb18902394515" +checksum = "09e4bb6601fa543c110d8957813267d5a8d775a0f8fbaccf1f615d06ba9b10da" dependencies = [ "bytes", "cfg_aliases", @@ -6334,7 +6284,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -6343,9 +6293,9 @@ dependencies = [ [[package]] name = "noq-proto" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a46813e306c29c4f86357b6ffa39a8e1c97bb274b9a296a19a56d62e4111225" +checksum = "baa7b5ccd819a9c68a0d955e67a881032d09b1a17219b1f90b0997a0888e1a15" dependencies = [ "aes-gcm", "aws-lc-rs", @@ -6355,7 +6305,7 @@ dependencies = [ "getrandom 0.4.3", "identity-hash", "lru-slab", - "rand 0.10.2", + "rand 0.10.1", "rand_pcg", "ring", "rustc-hash", @@ -6363,7 +6313,7 @@ dependencies = [ "rustls-pki-types", "slab", "sorted-index-buffer", - "thiserror 2.0.20", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -6371,9 +6321,9 @@ dependencies = [ [[package]] name = "noq-udp" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b56d621ed2c1773b5356ab39cc68c819f8d0103f7493d8661c4a5f5f8ea55f40" +checksum = "02bba20e097a5a16cd0ad14ec882fae1e80a092a124e9422fc4dddd92e96a647" dependencies = [ "cfg_aliases", "libc", @@ -6384,14 +6334,14 @@ dependencies = [ [[package]] name = "nostr" -version = "0.44.8" +version = "0.44.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ff7b77ef428b40aa2834a6acbae38a0e104c98b306208ca4b87a420d579a4b" +checksum = "c7d3d987ea7078dc36947cde532637c472a229426702e4331dd7667325378bd9" dependencies = [ "base64 0.22.1", "bech32 0.11.1", "bip39", - "bitcoin_hashes 0.14.101", + "bitcoin_hashes 0.14.1", "cbc", "chacha20 0.9.1", "chacha20poly1305", @@ -6408,9 +6358,9 @@ dependencies = [ [[package]] name = "nostr" -version = "0.45.4" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67bacf4195a119bc55d576ec6b54cc103723cb46fff5f907b8bdac8fd29ac4a0" +checksum = "5dde8c76076d334409d86c2e1db3e97abe5deb8cb92744f939cbc1fa45bd69e7" dependencies = [ "base64 0.22.1", "bech32 0.12.0", @@ -6421,7 +6371,7 @@ dependencies = [ "chacha20poly1305", "faster-hex", "opaquerr", - "rand 0.10.2", + "rand 0.10.1", "secp256k1 0.30.0", "serde", "serde_json", @@ -6437,7 +6387,7 @@ version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b1fdb9fcba732e32719662afad1b267e50322dbe89e506017ec13f24361bddf" dependencies = [ - "nostr 0.45.4", + "nostr 0.45.1", "opaquerr", ] @@ -6447,15 +6397,15 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa07539e52a71cb91fe0d693facaa298f03fcf9edcd66a521094e18e286e2336" dependencies = [ - "nostr 0.45.4", + "nostr 0.45.1", "opaquerr", ] [[package]] name = "nostr-sdk" -version = "0.45.2" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245f8642b10feecb0a40739a886ca1850e3be4e35dc6592b806ec437403ab9c9" +checksum = "26c86342f367bd9b173ec4a697e936e3a82d6dad5b4aa06c0d35d9b4f88a8e72" dependencies = [ "async-utility", "async-wsocket", @@ -6463,11 +6413,11 @@ dependencies = [ "futures", "lru", "negentropy", - "nostr 0.45.4", + "nostr 0.45.1", "nostr-database", "nostr-gossip", "opaquerr", - "rand 0.10.2", + "rand 0.10.1", "tokio", "tokio-stream", "tracing", @@ -6498,7 +6448,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint 0.4.8", + "num-bigint", "num-complex", "num-integer", "num-iter", @@ -6508,19 +6458,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.8" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e7820bc0a80a0238e650327316f929ba18d5be054b647490a3a6a339f3e7c0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -6549,24 +6489,25 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "num-integer" -version = "0.1.47" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] [[package]] name = "num-iter" -version = "0.1.46" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ + "autocfg", "num-integer", "num-traits", ] @@ -6577,7 +6518,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "num-bigint 0.4.8", + "num-bigint", "num-integer", "num-traits", "serde", @@ -6592,6 +6533,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "num_enum" version = "0.7.6" @@ -6611,7 +6562,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -6633,7 +6584,7 @@ dependencies = [ "chrono", "getrandom 0.2.17", "http", - "rand 0.8.8", + "rand 0.8.6", "serde", "serde_json", "serde_path_to_error", @@ -6657,7 +6608,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-foundation", ] @@ -6668,7 +6619,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "dispatch2", "libc", @@ -6681,7 +6632,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e34919aba0d701380d911702455038a8a3587467fe0141d6a71501e7ffe48" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -6701,7 +6652,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -6724,7 +6675,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", ] @@ -6745,7 +6696,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "dispatch2", "libc", "objc2", @@ -6789,28 +6740,29 @@ checksum = "4f933a4265d5cdad61d19bbdfc972ea5726d56cd8d3d57b8f2d3c365dd42bee9" [[package]] name = "openai-frontend" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "async-trait", "axum", "futures-core", "futures-util", + "mesh-llm-events", "mesh-llm-guardrails", "serde", "serde_json", "tokio", - "tokio-stream", "tracing", + "uuid", ] [[package]] name = "openssl" -version = "0.10.81" +version = "0.10.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" +checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "foreign-types", "libc", @@ -6826,7 +6778,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -6837,18 +6789,18 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-src" -version = "300.6.1+3.6.3" +version = "300.6.0+3.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46eb8fb9fb3b61ce1c0f8a026c4c1a0714d3a9e138e7fbde78753ce2babc3846" +checksum = "a8e8cbfd3a4a8c8f089147fd7aaa33cf8c7450c4d09f8f80698a0cf093abeff4" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.117" +version = "0.9.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" +checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" dependencies = [ "cc", "libc", @@ -6857,20 +6809,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "opentelemetry" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" -dependencies = [ - "futures-core", - "futures-sink", - "js-sys", - "pin-project-lite", - "thiserror 2.0.20", - "tracing", -] - [[package]] name = "opentelemetry" version = "0.32.0" @@ -6881,37 +6819,21 @@ dependencies = [ "futures-sink", "js-sys", "pin-project-lite", - "thiserror 2.0.20", + "thiserror 2.0.18", "tracing", ] [[package]] name = "opentelemetry-http" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331" dependencies = [ "async-trait", "bytes", "http", - "opentelemetry 0.31.0", - "reqwest 0.12.28", -] - -[[package]] -name = "opentelemetry-otlp" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" -dependencies = [ - "http", - "opentelemetry 0.31.0", - "opentelemetry-http", - "opentelemetry-proto 0.31.0", - "opentelemetry_sdk 0.31.0", - "prost 0.14.4", - "reqwest 0.12.28", - "thiserror 2.0.20", + "opentelemetry", + "reqwest 0.13.4", ] [[package]] @@ -6921,61 +6843,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35" dependencies = [ "http", - "opentelemetry 0.32.0", - "opentelemetry-proto 0.32.0", - "opentelemetry_sdk 0.32.1", - "prost 0.14.4", - "thiserror 2.0.20", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost 0.14.3", + "reqwest 0.13.4", + "thiserror 2.0.18", "tokio", "tonic", "tonic-types", ] -[[package]] -name = "opentelemetry-proto" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" -dependencies = [ - "base64 0.22.1", - "const-hex", - "opentelemetry 0.31.0", - "opentelemetry_sdk 0.31.0", - "prost 0.14.4", - "serde", - "serde_json", - "tonic", - "tonic-prost", -] - [[package]] name = "opentelemetry-proto" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638" dependencies = [ - "opentelemetry 0.32.0", - "opentelemetry_sdk 0.32.1", - "prost 0.14.4", + "base64 0.22.1", + "const-hex", + "opentelemetry", + "opentelemetry_sdk", + "prost 0.14.3", + "serde", "tonic", "tonic-prost", ] -[[package]] -name = "opentelemetry_sdk" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" -dependencies = [ - "futures-channel", - "futures-executor", - "futures-util", - "opentelemetry 0.31.0", - "percent-encoding", - "rand 0.9.5", - "thiserror 2.0.20", -] - [[package]] name = "opentelemetry_sdk" version = "0.32.1" @@ -6985,11 +6880,11 @@ dependencies = [ "futures-channel", "futures-executor", "futures-util", - "opentelemetry 0.32.0", + "opentelemetry", "percent-encoding", "portable-atomic", - "rand 0.9.5", - "thiserror 2.0.20", + "rand 0.9.4", + "thiserror 2.0.18", "tokio", "tokio-stream", ] @@ -7020,9 +6915,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "5.5.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c9e0d9b23589f26070720bac724174bfec1083e82f7854cdd0267518343c0" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" dependencies = [ "num-traits", ] @@ -7076,42 +6971,33 @@ dependencies = [ [[package]] name = "palette" -version = "0.7.7" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddeed8580d347d2abf3dcf06a5f0b3dc020258338526b277847cd4248a70fc64" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" dependencies = [ "approx", + "fast-srgb8", "libm", "palette_derive", - "palette_math", ] [[package]] name = "palette_derive" -version = "0.7.7" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88537020289b719d81be994ccf1bbf4990f477e2f69ee52fe3e45f43a02e56be" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.119", -] - -[[package]] -name = "palette_math" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6eb142958d64335fb0e345c5b9ead2ecd6fc438c307e9d7d3c4fd428dbaf12" -dependencies = [ - "libm", + "syn 2.0.117", ] [[package]] name = "papaya" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2442474a9404698c42509b8967f437249dbc7b50493e83020333d3943ec0ae" +checksum = "997ee03cd38c01469a7046643714f0ad28880bcb9e6679ff0666e24817ca19b7" dependencies = [ "equivalent", "seize", @@ -7212,9 +7098,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07a60cc7a4d00c91f95c685609d1d2f79050e6804b70ebedd7650f0b839bcf" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" dependencies = [ "memchr", "ucd-trie", @@ -7222,9 +7108,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a83744a5c8455b8b3e0dc5031362780a347c878bdd11584d1a8984228cc88d" +checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" dependencies = [ "pest", "pest_generator", @@ -7232,22 +7118,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd3451aa3de60d4b9a1e736885e4dea6b31617598026f12256ad566d63304a" +checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "pest_meta" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d3a0849e241d7dfce834c83b1c5edc8622009e8dd51a12ba1927c32f05496" +checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" dependencies = [ "pest", ] @@ -7259,7 +7145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset 0.5.7", - "indexmap 2.14.1", + "indexmap 2.14.0", ] [[package]] @@ -7270,7 +7156,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset 0.5.7", "hashbrown 0.15.5", - "indexmap 2.14.1", + "indexmap 2.14.0", ] [[package]] @@ -7310,7 +7196,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.8", + "rand 0.8.6", ] [[package]] @@ -7323,7 +7209,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -7352,7 +7238,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -7384,19 +7270,19 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.34" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plist" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" +checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" dependencies = [ "base64 0.22.1", - "indexmap 2.14.1", - "quick-xml 0.41.0", + "indexmap 2.14.0", + "quick-xml 0.39.4", "serde", "time", ] @@ -7407,11 +7293,11 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.9", + "miniz_oxide", ] [[package]] @@ -7453,9 +7339,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.15.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" dependencies = [ "serde", ] @@ -7471,9 +7357,9 @@ dependencies = [ [[package]] name = "portmapper" -version = "0.19.3" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca97242f016e090a25330613bc2382aab65eb22f9149dbe84d8f8e711d49a530" +checksum = "eb3713e4977408279158444a18c1a01ac9bf2e7eaf1fbfd1a19ac9cd18d90721" dependencies = [ "base64 0.22.1", "bytes", @@ -7486,7 +7372,7 @@ dependencies = [ "n0-future", "netwatch", "num_enum", - "rand 0.10.2", + "rand 0.10.1", "serde", "smallvec", "socket2", @@ -7519,14 +7405,14 @@ checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "potential_utf" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -7564,17 +7450,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.119", -] - -[[package]] -name = "prettyplease" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0" -dependencies = [ - "proc-macro2", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -7588,9 +7464,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.107" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -7602,7 +7478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e842efad9119158434d193c6682e2ebee4b44d6ad801d7b349623b3f57cdf55" dependencies = [ "futures", - "indexmap 2.14.1", + "indexmap 2.14.0", "nix 0.31.3", "tokio", "tracing", @@ -7617,9 +7493,9 @@ checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", - "bitflags 2.13.1", + "bitflags 2.13.0", "num-traits", - "rand 0.9.5", + "rand 0.9.4", "rand_chacha 0.9.0", "rand_xorshift", "regex-syntax", @@ -7640,12 +7516,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.14.4" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" dependencies = [ "bytes", - "prost-derive 0.14.4", + "prost-derive 0.14.3", ] [[package]] @@ -7660,30 +7536,30 @@ dependencies = [ "multimap", "once_cell", "petgraph 0.7.1", - "prettyplease 0.2.37", + "prettyplease", "prost 0.13.5", "prost-types 0.13.5", "regex", - "syn 2.0.119", + "syn 2.0.117", "tempfile", ] [[package]] name = "prost-build" -version = "0.14.4" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" +checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" dependencies = [ "heck", "itertools", "log", "multimap", "petgraph 0.8.3", - "prettyplease 0.2.37", - "prost 0.14.4", - "prost-types 0.14.4", + "prettyplease", + "prost 0.14.3", + "prost-types 0.14.3", "regex", - "syn 2.0.119", + "syn 2.0.117", "tempfile", ] @@ -7697,20 +7573,20 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "prost-derive" -version = "0.14.4" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -7737,11 +7613,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.14.4" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" dependencies = [ - "prost 0.14.4", + "prost 0.14.3", ] [[package]] @@ -7841,7 +7717,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "memchr", "pulldown-cmark-escape", "unicase", @@ -7855,9 +7731,9 @@ checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" [[package]] name = "pxfm" -version = "0.1.30" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" [[package]] name = "quanta" @@ -7898,18 +7774,18 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.41.0" +version = "0.39.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" dependencies = [ "memchr", ] [[package]] name = "quinn" -version = "0.11.11" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", "cfg_aliases", @@ -7919,7 +7795,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -7927,22 +7803,22 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.17" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "aws-lc-rs", "bytes", "getrandom 0.4.3", "lru-slab", - "rand 0.10.2", + "rand 0.10.1", "rand_pcg", "ring", "rustc-hash", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.20", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -7950,23 +7826,23 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.15" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.47" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -7995,9 +7871,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.8" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -8006,9 +7882,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -8016,11 +7892,11 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "chacha20 0.10.2", + "chacha20 0.10.0", "getrandom 0.4.3", "rand_core 0.10.1", ] @@ -8098,9 +7974,9 @@ dependencies = [ [[package]] name = "rapidhash" -version = "4.5.1" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da7e78a036ce858e8d55b7e7dc8ba3a88b78350fd2155d3591bbd966b58589e" +checksum = "32b266a82f4aa99bb5c25e28d11cc44ace63d91adbcbcee4d323e2ae3d49ef37" dependencies = [ "rustversion", ] @@ -8127,7 +8003,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "compact_str 0.9.1", "critical-section", "hashbrown 0.17.1", @@ -8137,7 +8013,7 @@ dependencies = [ "palette", "serde", "strum", - "thiserror 2.0.20", + "thiserror 2.0.18", "unicode-segmentation", "unicode-truncate", "unicode-width 0.2.2", @@ -8192,7 +8068,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "hashbrown 0.17.1", "indoc", "instability", @@ -8212,7 +8088,7 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", ] [[package]] @@ -8263,9 +8139,9 @@ dependencies = [ [[package]] name = "redis" -version = "1.6.0" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37a4ca5c6ca42aa3e6df2fd32b987a65d32a4c2159a6f3fe0fd1df306a2658f" +checksum = "bae41a63fd0b8a5372f82b21e810e09a316f5dd7efd96bf08e678fb240fc1918" dependencies = [ "arc-swap", "arcstr", @@ -8277,7 +8153,7 @@ dependencies = [ "futures-channel", "futures-util", "itoa", - "num-bigint 0.5.1", + "num-bigint", "percent-encoding", "pin-project-lite", "rustls", @@ -8298,7 +8174,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", ] [[package]] @@ -8309,34 +8185,34 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "ref-cast" -version = "1.0.27" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.27" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] name = "regex" -version = "1.13.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -8346,9 +8222,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.18" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -8363,9 +8239,9 @@ checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" [[package]] name = "regex-syntax" -version = "0.8.11" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" @@ -8376,7 +8252,6 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", - "futures-channel", "futures-core", "futures-util", "h2", @@ -8412,7 +8287,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams 0.4.2", "web-sys", - "webpki-roots 1.0.9", + "webpki-roots 1.0.7", ] [[package]] @@ -8424,6 +8299,7 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2", @@ -8470,7 +8346,7 @@ dependencies = [ "async-trait", "http", "reqwest 0.13.4", - "thiserror 2.0.20", + "thiserror 2.0.18", "tower-service", ] @@ -8511,14 +8387,14 @@ dependencies = [ "pastey", "pin-project-lite", "process-wrap", - "rand 0.10.2", + "rand 0.10.1", "reqwest 0.13.4", "rmcp-macros 1.8.0", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", "sse-stream", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -8536,17 +8412,17 @@ dependencies = [ "async-trait", "chrono", "futures", - "indexmap 2.14.1", + "indexmap 2.14.0", "oauth2", "pastey", "pin-project-lite", "process-wrap", "reqwest 0.13.4", "rmcp-macros 3.2.0", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -8565,7 +8441,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -8578,17 +8454,42 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 3.0.4", + "syn 3.0.3", ] [[package]] name = "rpassword" -version = "5.0.1" +version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" +checksum = "2da316a15f47e3d053de9cb2c439650bd8fa4aaeb9365f2e5f27f492ff73c196" dependencies = [ "libc", - "winapi", + "rtoolbox", + "windows-sys 0.61.2", +] + +[[package]] +name = "rtoolbox" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1efe12a1469752d0e6ff5ebec0b6ef4924cc5c4c71046b0ec730040535819d" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "rusqlite" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" +dependencies = [ + "bitflags 2.13.0", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink 0.10.0", + "libsqlite3-sys", + "smallvec", ] [[package]] @@ -8629,7 +8530,7 @@ dependencies = [ "serde_json", "sha2 0.10.9", "sysinfo 0.37.2", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "tokio", "tokio-stream", @@ -8638,9 +8539,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "2.1.3" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -8657,7 +8558,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -8670,7 +8571,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -8679,9 +8580,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.43" +version = "0.23.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" dependencies = [ "aws-lc-rs", "log", @@ -8695,9 +8596,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -8707,9 +8608,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.1" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -8744,9 +8645,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.15" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -8756,9 +8657,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.23" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rusty-fork" @@ -8844,9 +8745,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "chrono", "dyn-clone", @@ -8858,14 +8759,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98c67716b46af2f0b8cf752abc930f6f9aecfbf671ecfb531db8a31dbe4e2ba" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -8898,7 +8799,7 @@ version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ - "rand 0.8.8", + "rand 0.8.6", "secp256k1-sys 0.10.1", "serde", ] @@ -8909,8 +8810,8 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ - "bitcoin_hashes 0.14.101", - "rand 0.8.8", + "bitcoin_hashes 0.14.1", + "rand 0.8.6", "secp256k1-sys 0.10.1", ] @@ -8920,8 +8821,8 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c3c81b43dc2d8877c216a3fccf76677ee1ebccd429566d3e67447290d0c42b2" dependencies = [ - "bitcoin_hashes 0.14.101", - "rand 0.9.5", + "bitcoin_hashes 0.14.1", + "rand 0.9.4", "secp256k1-sys 0.11.0", ] @@ -8965,7 +8866,7 @@ dependencies = [ "hkdf 0.12.4", "num", "once_cell", - "rand 0.8.8", + "rand 0.8.6", "serde", "sha2 0.10.9", "zbus", @@ -8977,7 +8878,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -8990,7 +8891,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -9012,6 +8913,10 @@ name = "seize" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] [[package]] name = "semver" @@ -9039,9 +8944,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -9069,33 +8974,33 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] name = "serde_derive_internals" -version = "0.30.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -9104,7 +9009,7 @@ version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "itoa", "memchr", "serde", @@ -9125,13 +9030,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.21" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -9157,19 +9062,19 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.22.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" +checksum = "935177bb8c0cd8ca1a4e6d1a2ac8988bea69cab4f9d3a31311e012ad27868ea4" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bs58", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.14.1", + "indexmap 2.14.0", "jiff", "schemars 0.9.0", - "schemars 1.2.2", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -9178,14 +9083,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.22.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" +checksum = "1d607aa01a3cb0ad757d6fd216136910db3c97b102fe686585689615a02dbcdc" dependencies = [ - "darling 0.23.0", + "darling 0.24.1", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -9194,7 +9099,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "itoa", "ryu", "serde", @@ -9213,9 +9118,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.7" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if 1.0.4", "cpufeatures 0.2.17", @@ -9229,7 +9134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "digest 0.11.3", ] @@ -9257,7 +9162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "digest 0.11.3", ] @@ -9289,9 +9194,9 @@ dependencies = [ [[package]] name = "sherpa-onnx" -version = "1.13.7" +version = "1.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4ef11f6b23c916a8e36c3cf65201f796d0e6aa30182a18d4f798d0b7f62547" +checksum = "0b142d3f255cb4e4b7808ea25869db6f5714e0a3550da355234483b4db552055" dependencies = [ "serde", "serde_json", @@ -9300,21 +9205,20 @@ dependencies = [ [[package]] name = "sherpa-onnx-sys" -version = "1.13.7" +version = "1.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566aad07d0924a7ed897cc035cc67ad71cdfddb959717dbf445031d5d4b58d4d" +checksum = "ffc951af03dc0653c0622158ca8a585a6f2bc43b7b06048cf0e5b5020005c227" dependencies = [ - "bzip2 0.4.4", + "bzip2", "tar", "ureq", - "zip", ] [[package]] name = "shlex" -version = "2.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook" @@ -9364,15 +9268,15 @@ checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" [[package]] name = "simd-adler32" -version = "0.3.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "simd_cesu8" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" dependencies = [ "rustc_version", "simdutf8", @@ -9386,20 +9290,20 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "similar" -version = "3.2.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f66ca1f7aca2474dc10c942eb22feffc897735f54cd1db90138c2fddb490987" +checksum = "04d93e861ede2e497b47833469b8ec9d5c07fa4c78ce7a00f6eb7dd8168b4b3f" dependencies = [ "bstr", ] [[package]] name = "simple-dns" -version = "0.12.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b6f884fa9a8d48101774bfbd3aeb81e968dd22cffd19a372da69f183db22c1a" +checksum = "7a75cbde1bf934313596a004973e462f9a82caa814dcf1a5f507bdf51597eeb4" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", ] [[package]] @@ -9408,9 +9312,9 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ - "num-bigint 0.4.8", + "num-bigint", "num-traits", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", ] @@ -9428,8 +9332,8 @@ checksum = "0c6f73aeb92d671e0cc4dca167e59b2deb6387c375391bc99ee743f326994a2b" [[package]] name = "skippy-cache" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "blake3", @@ -9438,32 +9342,32 @@ dependencies = [ [[package]] name = "skippy-coordinator" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "skippy-ffi" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "libloading", ] [[package]] name = "skippy-metrics" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" [[package]] name = "skippy-protocol" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ - "prost 0.14.4", - "prost-build 0.14.4", + "prost 0.14.3", + "prost-build 0.14.3", "protoc-bin-vendored", "serde", "skippy-tokenizer", @@ -9471,8 +9375,8 @@ dependencies = [ [[package]] name = "skippy-runtime" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "libc", @@ -9483,10 +9387,19 @@ dependencies = [ "tokio", ] +[[package]] +name = "skippy-scheduler" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" +dependencies = [ + "skippy-runtime", + "thiserror 2.0.18", +] + [[package]] name = "skippy-server" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "ahash", "anyhow", @@ -9497,10 +9410,11 @@ dependencies = [ "clap", "futures-util", "libc", + "mesh-llm-events", "mesh-native-serving-plugin-api", "model-artifact", "openai-frontend", - "opentelemetry-proto 0.31.0", + "opentelemetry-proto", "serde", "serde_json", "sha2 0.10.9", @@ -9508,25 +9422,27 @@ dependencies = [ "skippy-metrics", "skippy-protocol", "skippy-runtime", + "skippy-scheduler", "skippy-tokenizer", + "skippy-topology", "socket2", "tokio", - "tokio-stream", "tonic", + "uuid", ] [[package]] name = "skippy-tokenizer" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", ] [[package]] name = "skippy-topology" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", "serde_json", @@ -9540,9 +9456,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] @@ -9560,9 +9476,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", "windows-sys 0.61.2", @@ -9582,23 +9498,23 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "spin" -version = "0.9.9" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] [[package]] name = "spin" -version = "0.10.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" [[package]] name = "spki" @@ -9663,8 +9579,8 @@ dependencies = [ "futures-io", "futures-util", "hashbrown 0.16.1", - "hashlink", - "indexmap 2.14.1", + "hashlink 0.11.0", + "indexmap 2.14.0", "log", "memchr", "percent-encoding", @@ -9673,13 +9589,13 @@ dependencies = [ "serde_json", "sha2 0.10.9", "smallvec", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", "url", "uuid", - "webpki-roots 1.0.9", + "webpki-roots 1.0.7", ] [[package]] @@ -9692,7 +9608,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -9715,8 +9631,8 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.119", - "thiserror 2.0.20", + "syn 2.0.117", + "thiserror 2.0.18", "tokio", "url", ] @@ -9727,7 +9643,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90b8020fe17c5f2c245bfa2505d7ef59c5604839527c740266ad2214acebea27" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "byteorder", "bytes", "chrono", @@ -9744,7 +9660,7 @@ dependencies = [ "sha1 0.11.0", "sha2 0.11.0", "sqlx-core", - "thiserror 2.0.20", + "thiserror 2.0.18", "tracing", "uuid", ] @@ -9757,7 +9673,7 @@ checksum = "87a2bdd6e83f6b3ea525ca9fee568030508b58355a43d0b2c1674d5f79dcd65e" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.13.1", + "bitflags 2.13.0", "byteorder", "chrono", "crc", @@ -9773,14 +9689,14 @@ dependencies = [ "log", "md-5", "memchr", - "rand 0.10.2", + "rand 0.10.1", "serde", "serde_json", "sha2 0.11.0", "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.20", + "thiserror 2.0.18", "tracing", "uuid", "whoami", @@ -9806,7 +9722,7 @@ dependencies = [ "percent-encoding", "serde", "sqlx-core", - "thiserror 2.0.20", + "thiserror 2.0.18", "tracing", "url", "uuid", @@ -9814,9 +9730,9 @@ dependencies = [ [[package]] name = "sse-stream" -version = "0.2.5" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c123f296ade4ec4b8b0f6162116e6629f5146922ca5ab40ca9d3c2e73ab4761e" +checksum = "f3962b63f038885f15bce2c6e02c0e7925c072f1ac86bb60fd44c5c6b762fb72" dependencies = [ "bytes", "futures-util", @@ -9882,7 +9798,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -10068,9 +9984,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.119" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -10079,9 +9995,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.4" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" dependencies = [ "proc-macro2", "quote", @@ -10105,7 +10021,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -10142,7 +10058,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -10202,7 +10118,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "parking_lot", "rustix 1.1.4", "signal-hook", @@ -10238,7 +10154,7 @@ checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" dependencies = [ "anyhow", "base64 0.22.1", - "bitflags 2.13.1", + "bitflags 2.13.0", "fancy-regex 0.11.0", "filedescriptor", "finl_unicode", @@ -10283,11 +10199,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.20", + "thiserror-impl 2.0.18", ] [[package]] @@ -10298,36 +10214,37 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] name = "thread_local" -version = "1.1.10" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if 1.0.4", ] [[package]] name = "time" -version = "0.3.55" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", + "itoa", "js-sys", "libc", "num-conv", @@ -10340,15 +10257,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.9" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.32" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -10365,9 +10282,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -10375,9 +10292,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.12.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -10407,7 +10324,7 @@ dependencies = [ "macro_rules_attribute", "monostate", "paste", - "rand 0.9.5", + "rand 0.9.4", "rayon", "rayon-cond", "regex", @@ -10415,7 +10332,7 @@ dependencies = [ "serde", "serde_json", "spm_precompiled", - "thiserror 2.0.20", + "thiserror 2.0.18", "unicode-normalization-alignments", "unicode-segmentation", "unicode_categories", @@ -10423,9 +10340,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.53.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -10449,13 +10366,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.2" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -10470,12 +10387,12 @@ dependencies = [ [[package]] name = "tokio-retry" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a129d95275ebf4c493ec53bf0f8cd95f5ac161bc4f381700809a54f595d4470" +checksum = "40f644c762e9d396831ae2f8935c954b0d758c4532e924bead0f666d0c1c8640" dependencies = [ "pin-project-lite", - "rand 0.10.2", + "rand 0.10.1", "tokio", ] @@ -10503,9 +10420,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.19" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -10547,25 +10464,24 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.19" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", "futures-util", - "libc", "pin-project-lite", "tokio", ] [[package]] name = "tokio-websockets" -version = "0.13.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52efb639344a7c6adb8e62c6f3d2c19c001ff1b79a5041ba1c6ed42e19c6aa5" +checksum = "dad543404f98bfc969aeb71994105c592acfc6c43323fddcd016bb208d1c65cb" dependencies = [ "aws-lc-rs", "base64 0.22.1", @@ -10575,7 +10491,7 @@ dependencies = [ "getrandom 0.4.3", "http", "httparse", - "rand 0.10.2", + "rand 0.10.1", "ring", "rustls-pki-types", "sha1_smol", @@ -10606,7 +10522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d01145a2c788d6aae4cd653afec1e8332534d7d783d01897cefcafe4428de992" dependencies = [ "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -10615,7 +10531,7 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "serde_core", "serde_spanned", "toml_datetime 0.7.5+spec-1.1.0", @@ -10626,17 +10542,17 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.4+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "serde_core", "serde_spanned", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] @@ -10659,31 +10575,31 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.13+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] name = "toml_parser" -version = "1.1.3+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] name = "toml_writer" -version = "1.1.2+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" @@ -10722,7 +10638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", - "prost 0.14.4", + "prost 0.14.3", "tonic", ] @@ -10732,8 +10648,8 @@ version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ab1b02061f83d519bba3caa167f88f261ef05720ab8ebc954ade70de3348e8" dependencies = [ - "prost 0.14.4", - "prost-types 0.14.4", + "prost 0.14.3", + "prost-types 0.14.3", "tonic", ] @@ -10745,7 +10661,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.14.1", + "indexmap 2.14.0", "pin-project-lite", "slab", "sync_wrapper", @@ -10764,7 +10680,7 @@ checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "async-compression", "base64 0.22.1", - "bitflags 2.13.1", + "bitflags 2.13.0", "bytes", "futures-core", "futures-util", @@ -10818,7 +10734,7 @@ checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", "symlink", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "tracing-subscriber", ] @@ -10831,7 +10747,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -10874,7 +10790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adbc64cba7137545b8044cb1fe9814f7aacf3c6b5f9b45be8bb5db538befdb26" dependencies = [ "js-sys", - "opentelemetry 0.32.0", + "opentelemetry", "smallvec", "tracing", "tracing-core", @@ -10931,11 +10847,11 @@ dependencies = [ "http", "httparse", "log", - "rand 0.9.5", + "rand 0.9.4", "rustls", "rustls-pki-types", - "sha1 0.10.7", - "thiserror 2.0.20", + "sha1 0.10.6", + "thiserror 2.0.18", "utf-8", ] @@ -10950,24 +10866,24 @@ dependencies = [ "http", "httparse", "log", - "rand 0.9.5", + "rand 0.9.4", "rustls", "rustls-pki-types", - "sha1 0.10.7", - "thiserror 2.0.20", + "sha1 0.10.6", + "thiserror 2.0.18", ] [[package]] name = "twox-hash" -version = "2.1.4" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" [[package]] name = "typenum" -version = "1.20.1" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "typewit" @@ -10998,7 +10914,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe" dependencies = [ - "rand 0.9.5", + "rand 0.9.4", "web-time", ] @@ -11052,9 +10968,9 @@ checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" -version = "1.13.3" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-truncate" @@ -11180,9 +11096,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.26.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "atomic", "getrandom 0.4.3", @@ -11263,9 +11179,9 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.4+wasi-0.2.12" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ "wit-bindgen", ] @@ -11281,9 +11197,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if 1.0.4", "once_cell", @@ -11294,9 +11210,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.77" +version = "0.4.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" dependencies = [ "js-sys", "wasm-bindgen", @@ -11304,9 +11220,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11314,22 +11230,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] @@ -11362,9 +11278,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.104" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" dependencies = [ "js-sys", "wasm-bindgen", @@ -11398,9 +11314,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.9" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] @@ -11411,14 +11327,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.9", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.9" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -11503,9 +11419,9 @@ dependencies = [ [[package]] name = "whoami" -version = "2.1.3" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626c4bac6755d76ffc12cb01b2eac751db1996b9e0041de9aa02c8c211ddc82c" +checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" dependencies = [ "libc", "libredox", @@ -11650,7 +11566,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -11661,7 +11577,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -12003,9 +11919,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] @@ -12026,16 +11942,16 @@ dependencies = [ "futures", "log", "serde", - "thiserror 2.0.20", + "thiserror 2.0.18", "windows 0.62.2", "windows-core 0.62.2", ] [[package]] name = "writeable" -version = "0.6.4" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "ws_stream_wasm" @@ -12050,7 +11966,7 @@ dependencies = [ "pharos", "rustc_version", "send_wrapper", - "thiserror 2.0.20", + "thiserror 2.0.18", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -12091,7 +12007,7 @@ dependencies = [ "http", "hyper", "more-asserts", - "rand 0.10.2", + "rand 0.10.1", "redb", "reqwest 0.13.4", "reqwest-middleware", @@ -12100,7 +12016,7 @@ dependencies = [ "serde_repr", "statrs", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-retry", "tokio_with_wasm", @@ -12131,12 +12047,12 @@ dependencies = [ "itertools", "lz4_flex", "more-asserts", - "rand 0.10.2", + "rand 0.10.1", "regex", "safe-transmute", "serde", "static_assertions", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tracing", @@ -12159,12 +12075,12 @@ dependencies = [ "http", "itertools", "more-asserts", - "rand 0.10.2", + "rand 0.10.1", "serde", "serde_json", "sha2 0.11.0", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tokio_with_wasm", @@ -12199,13 +12115,13 @@ dependencies = [ "more-asserts", "oneshot", "pin-project", - "rand 0.10.2", + "rand 0.10.1", "reqwest 0.13.4", "serde", "serde_json", "shellexpand", "sysinfo 0.38.4", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tokio_with_wasm", @@ -12219,9 +12135,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.29" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "xmltree" @@ -12234,24 +12150,15 @@ dependencies = [ [[package]] name = "xxhash-rust" -version = "0.8.18" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aee1b19627c7c60102ab80d3a9cbe18de90bfe03bfa6c3715447681f0e8c8af6" - -[[package]] -name = "xz2" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" -dependencies = [ - "lzma-sys", -] +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" [[package]] name = "yoke" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -12266,7 +12173,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", "synstructure", ] @@ -12288,10 +12195,10 @@ dependencies = [ "hex", "nix 0.29.0", "ordered-stream", - "rand 0.8.8", + "rand 0.8.6", "serde", "serde_repr", - "sha1 0.10.7", + "sha1 0.10.6", "static_assertions", "tracing", "uds_windows", @@ -12311,7 +12218,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", "zvariant_utils", ] @@ -12328,22 +12235,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.56" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.56" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] @@ -12363,7 +12270,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", "synstructure", ] @@ -12384,14 +12291,14 @@ checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] [[package]] name = "zerotrie" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -12400,9 +12307,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -12411,13 +12318,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.6" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.117", ] [[package]] @@ -12426,41 +12333,22 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" dependencies = [ - "aes", "arbitrary", - "bzip2 0.5.2", - "constant_time_eq 0.3.1", "crc32fast", "crossbeam-utils", - "deflate64", "displaydoc", "flate2", - "getrandom 0.3.4", - "hmac 0.12.1", - "indexmap 2.14.1", - "lzma-rs", + "indexmap 2.14.0", "memchr", - "pbkdf2", - "sha1 0.10.7", - "thiserror 2.0.20", - "time", - "xz2", - "zeroize", + "thiserror 2.0.18", "zopfli", - "zstd", ] -[[package]] -name = "zlib-rs" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12" - [[package]] name = "zmij" -version = "1.0.23" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zopfli" @@ -12474,39 +12362,11 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "zune-core" -version = "0.5.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-jpeg" @@ -12539,7 +12399,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", "zvariant_utils", ] @@ -12551,5 +12411,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.117", ] diff --git a/Justfile b/Justfile index ac4fd709bc..4c4908c588 100644 --- a/Justfile +++ b/Justfile @@ -211,8 +211,13 @@ _ensure-migrations: _ensure-services ./scripts/seed-local-community.sh # Run clippy on the desktop Tauri Rust crate +# Features are additive, so a single invocation lints only one cfg graph. +# Both graphs ship (release-windows builds without mesh-llm), so lint both: +# the default graph covers the `#[cfg(not(feature = "mesh-llm"))]` arms and +# the feature-enabled graph covers the mesh code. desktop-tauri-clippy: _ensure-sidecar-stubs cargo clippy --manifest-path {{desktop_tauri_manifest}} --workspace --all-targets -- -D warnings + cargo clippy --manifest-path {{desktop_tauri_manifest}} --workspace --all-targets --features mesh-llm -- -D warnings # Check the desktop Tauri Rust crate compiles desktop-tauri-check: _ensure-sidecar-stubs @@ -670,7 +675,11 @@ desktop-standalone *ARGS: _ensure-sidecar-stubs fi trap '../scripts/cleanup-instance-agents.sh "$INSTANCE_ID" || true' EXIT echo "Starting standalone desktop on Vite port ${BUZZ_VITE_PORT}; no relay services were started" - pnpm exec tauri dev --config "$BUZZ_TAURI_CONFIG" {{ARGS}} + FEATURES=() + if [[ -n "{{mesh}}" ]]; then + FEATURES=(--features mesh-llm) + fi + pnpm exec tauri dev ${FEATURES[@]+"${FEATURES[@]}"} --config "$BUZZ_TAURI_CONFIG" {{ARGS}} # Run the desktop app against the internal staging relay (installs deps + builds agent tools automatically) staging *ARGS: bootstrap _ensure-sidecar-stubs diff --git a/crates/buzz-acp/README.md b/crates/buzz-acp/README.md index 41d9a214bd..3d011eb8eb 100644 --- a/crates/buzz-acp/README.md +++ b/crates/buzz-acp/README.md @@ -270,6 +270,10 @@ Forum event kinds: 4. **Prompting** — When events are pending and no prompt is in flight for that channel, drains all queued events for the oldest channel into a single batched prompt via ACP `session/prompt`. 5. **Agent response** — The agent processes the prompt and uses the Buzz CLI (`send_message`, `get_messages`, etc.) to interact with Buzz. 6. **Recovery** — If the agent crashes, the harness respawns it. If the relay disconnects, the harness reconnects with a `since` filter to avoid missing events. + If the inbound queue overflows, the harness attempts replay for affected + subscriptions when capacity and relay quota permit, with at least five seconds + between attempts. Recovery depends on available relay history and the consumer + making progress; complete delivery is not guaranteed. Each channel has at most one prompt in flight. Multiple channels can be processed concurrently when agents > 1. diff --git a/crates/buzz-acp/src/lib.rs b/crates/buzz-acp/src/lib.rs index ddd594b142..cc2952a2f8 100644 --- a/crates/buzz-acp/src/lib.rs +++ b/crates/buzz-acp/src/lib.rs @@ -3005,6 +3005,7 @@ async fn tokio_main() -> Result<()> { Panic(tokio::task::JoinError), SteerAck(SteerAckEvent), Wake(u32, Result), + HoldDeadline, } loop { @@ -3146,6 +3147,8 @@ async fn tokio_main() -> Result<()> { } // Borrow result_rx and join_set simultaneously via split-borrow helper. + pool.retain_held_scopes(|scope| queue.has_pending_scope(scope)); + let hold_deadline = pool.next_hold_deadline(pool::HOLD_BUSY_OWNER_TIMEOUT); let pool_event: Option = { let (result_rx, join_set) = pool.rx_and_join_set(); tokio::select! { @@ -3188,6 +3191,9 @@ async fn tokio_main() -> Result<()> { _ => std::future::pending().await, } } => None, + _ = pool::AgentPool::wait_for_hold_deadline(hold_deadline), if pool_ready => { + Some(PoolEvent::HoldDeadline) + }, Some(Err(error)) = wake_tasks.join_next(), if !wake_tasks.is_empty() => { if let Some(attempt) = pool_lifecycle.waking_attempt() { let message = format!("pool wake task failed: {error}"); @@ -4021,6 +4027,21 @@ async fn tokio_main() -> Result<()> { } } } + Some(PoolEvent::HoldDeadline) => { + // A held thread must make progress even when every unrelated + // relay/timer source is quiet. The deadline is derived from + // the pool's first-held stamp, so this dispatch observes + // `ForkAfterHold` and claims an idle worker immediately. + for (scope, thread_tags) in dispatch_pending( + &mut pool, + &mut queue, + &ctx, + &mut last_activity, + observer.as_ref(), + ) { + typing_channels.insert(scope, thread_tags); + } + } None => {} // relay/heartbeat/shutdown branches handled inline above } } @@ -4412,7 +4433,7 @@ fn dispatch_pending( let mut held: Vec = Vec::new(); // One clock read for the whole cycle so every batch's bounded-hold window is // measured against the same instant. - let now = std::time::Instant::now(); + let now = tokio::time::Instant::now(); loop { let batch = match queue.flush_next() { Some(b) => b, @@ -4427,7 +4448,8 @@ fn dispatch_pending( // so an active channel cannot starve a sibling channel on a shared // worker. A held thread that outwaits the window forks a fresh session // rather than starve behind an unbounded turn. - match pool.hold_decision(&scope, now, pool::HOLD_BUSY_OWNER_TIMEOUT) { + let forked_after_hold = match pool.hold_decision(&scope, now, pool::HOLD_BUSY_OWNER_TIMEOUT) + { pool::HoldDecision::Hold { held_for, owner_index, @@ -4458,31 +4480,9 @@ fn dispatch_pending( pool::HoldDecision::ForkAfterHold { held_for, owner_index, - } => { - tracing::warn!( - channel = %channel_id, - scope = %scope.telemetry_label(), - owner_index, - held_for_secs = held_for.as_secs_f64(), - "busy-owner hold expired — forking fresh session on an idle worker" - ); - if let Some(observer) = observer { - observer.emit( - "busy_owner_hold_forked", - None, - &observer::context_for(Some(channel_id), None, None), - serde_json::json!({ - "scope": scope.telemetry_label(), - "ownerIndex": owner_index, - "heldForSecs": held_for.as_secs_f64(), - }), - ); - } - // Fall through to try_claim below (fork); record_scope_owner - // reassigns ownership to the new worker automatically. - } - pool::HoldDecision::Dispatch => {} - } + } => Some((held_for, owner_index)), + pool::HoldDecision::Dispatch => None, + }; let typing_scope = batch .events .last() @@ -4502,6 +4502,32 @@ fn dispatch_pending( break; } }; + // Consume a bounded hold only after a worker was actually claimed. + // If every slot is checked out, the expired stamp remains sticky and + // the worker-return event retries immediately instead of waiting for a + // fresh timeout window. + pool.clear_hold(&scope); + if let Some((held_for, owner_index)) = forked_after_hold { + tracing::warn!( + channel = %channel_id, + scope = %scope.telemetry_label(), + owner_index, + held_for_secs = held_for.as_secs_f64(), + "busy-owner hold expired — forking fresh session on an idle worker" + ); + if let Some(observer) = observer { + observer.emit( + "busy_owner_hold_forked", + None, + &observer::context_for(Some(channel_id), None, None), + serde_json::json!({ + "scope": scope.telemetry_label(), + "ownerIndex": owner_index, + "heldForSecs": held_for.as_secs_f64(), + }), + ); + } + } tracing::debug!(agent = agent.index, channel = %channel_id, scope = %scope.telemetry_label(), affinity_hit, "agent_claimed"); let recoverable_batch = match ctx.dedup_mode { @@ -4532,6 +4558,14 @@ fn dispatch_pending( let turn_id = Uuid::new_v4().to_string(); let task_turn_id = turn_id.clone(); + // Assign ownership before moving the worker into the task. If this is + // a bounded-hold fork, the new generation immediately invalidates the + // prior busy worker's copy when that worker eventually returns. + let owner_generation = pool.record_scope_owner(scope.clone(), agent.index); + agent + .state + .set_scope_owner_generation(scope.clone(), owner_generation); + let abort_handle = pool.join_set.spawn(async move { pool::run_prompt_task( agent, @@ -4558,9 +4592,6 @@ fn dispatch_pending( successful_steer_deliveries: HashSet::new(), }, ); - // Record this worker as the scope's session owner so a later dispatch - // while it is busy holds instead of forking a duplicate session. - pool.record_scope_owner(scope.clone(), agent_index); dispatched_channels.push((scope, typing_scope)); *last_activity = tokio::time::Instant::now(); } @@ -6235,7 +6266,7 @@ mod owner_control_command_tests { // The bounded hold decision stamps A's first-held time, then forks once // the window elapses rather than starving behind the busy owner. - let now = std::time::Instant::now(); + let now = tokio::time::Instant::now(); assert!( matches!( pool.hold_decision(&ta, now, pool::HOLD_BUSY_OWNER_TIMEOUT), @@ -6256,9 +6287,10 @@ mod owner_control_command_tests { "elapsed window => fork on an idle worker" ); assert!( - !pool.held_since_contains(&ta), - "fork clears the first-held stamp" + pool.held_since_contains(&ta), + "expired hold stays sticky until an idle worker is claimed" ); + pool.clear_hold(&ta); // A conversation scope never holds even with a busy recorded owner — // this is the cross-channel head-of-line-blocking regression guard. @@ -6290,6 +6322,55 @@ mod owner_control_command_tests { ); } + #[tokio::test] + async fn queue_cap_eviction_prunes_orphaned_hold_deadline() { + let mut pool = AgentPool::from_slots(vec![]); + let mut queue = EventQueue::new(DedupMode::Queue); + let channel_id = Uuid::new_v4(); + let held_scope = thread_scope(channel_id, &"a".repeat(64)); + let surviving_scope = thread_scope(channel_id, &"b".repeat(64)); + + pool.record_scope_owner(held_scope.clone(), 0); + let (tx, _rx) = tokio::sync::oneshot::channel(); + insert_task_meta(&mut pool, 0, surviving_scope.clone(), tx); + assert!(matches!( + pool.hold_decision( + &held_scope, + tokio::time::Instant::now(), + pool::HOLD_BUSY_OWNER_TIMEOUT + ), + pool::HoldDecision::Hold { .. } + )); + + let oldest = std::time::Instant::now() - Duration::from_secs(1); + queue.push(queue::QueuedEvent { + channel_id, + scope: held_scope.clone(), + event: make_event(KIND_STREAM_MESSAGE, "held", None), + received_at: oldest, + prompt_tag: "test".into(), + }); + for i in 0..500 { + queue.push(queue::QueuedEvent { + channel_id, + scope: surviving_scope.clone(), + event: make_event(KIND_STREAM_MESSAGE, &format!("new-{i}"), None), + received_at: std::time::Instant::now(), + prompt_tag: "test".into(), + }); + } + + assert!( + !queue.has_pending_scope(&held_scope), + "aggregate cap evicts the globally oldest scope" + ); + pool.retain_held_scopes(|scope| queue.has_pending_scope(scope)); + assert!( + !pool.held_since_contains(&held_scope), + "evicted scope cannot leave an immediately-ready deadline behind" + ); + } + #[test] fn project_owner_control_signs_only_addressable_project_events() { let keys = Keys::generate(); @@ -9370,6 +9451,15 @@ mod error_outcome_emission_tests { } } + fn bind_agent_scope_owner( + pool: &mut AgentPool, + agent: &mut OwnedAgent, + scope: scope::SessionScope, + ) { + let generation = pool.record_scope_owner(scope.clone(), agent.index); + agent.state.set_scope_owner_generation(scope, generation); + } + #[tokio::test] async fn successful_native_steer_is_transferred_to_live_session_delivery_state() { let channel_id = Uuid::new_v4(); @@ -9385,6 +9475,11 @@ mod error_outcome_emission_tests { ); let mut pool = AgentPool::from_slots(vec![None]); + bind_agent_scope_owner( + &mut pool, + &mut agent, + scope::SessionScope::Conversation { channel_id }, + ); let task_id = pool.join_set.spawn(async {}).id(); pool.task_map_mut().insert( task_id, @@ -9460,6 +9555,11 @@ mod error_outcome_emission_tests { ); let mut pool = AgentPool::from_slots(vec![None]); + bind_agent_scope_owner( + &mut pool, + &mut agent, + scope::SessionScope::Conversation { channel_id }, + ); let task_id = pool.join_set.spawn(async {}).id(); pool.task_map_mut().insert( task_id, @@ -10697,6 +10797,7 @@ mod error_outcome_emission_tests { .sessions .insert(session_scope.clone(), "healthy-session".into()); let mut pool = AgentPool::from_slots(vec![None]); + bind_agent_scope_owner(&mut pool, &mut agent, session_scope.clone()); let task_id = pool.join_set.spawn(async {}).id(); pool.task_map_mut().insert( task_id, diff --git a/crates/buzz-acp/src/pool.rs b/crates/buzz-acp/src/pool.rs index 06383d456d..dbeafedda7 100644 --- a/crates/buzz-acp/src/pool.rs +++ b/crates/buzz-acp/src/pool.rs @@ -141,9 +141,18 @@ pub struct SessionState { /// Per-scope successful-delivery state. Created with the ACP session and /// cleared atomically with every invalidation path. pub deliveries: HashMap, + /// Pool-assigned ownership generation for each scope. A worker returning + /// after another worker forked the scope carries an older generation; the + /// pool uses this fence to discard that stale provider session before the + /// worker becomes claimable again. + scope_owner_generations: HashMap, } impl SessionState { + pub(crate) fn set_scope_owner_generation(&mut self, scope: SessionScope, generation: u64) { + self.scope_owner_generations.insert(scope, generation); + } + /// Invalidate the session (and turn counter) for a specific prompt source. pub fn invalidate(&mut self, source: &PromptSource) { match source { @@ -165,6 +174,7 @@ impl SessionState { self.core_sections.remove(scope); self.canvas_sections.remove(scope); self.deliveries.remove(scope); + self.scope_owner_generations.remove(scope); self.sessions.remove(scope).is_some() } @@ -179,6 +189,7 @@ impl SessionState { .chain(self.core_sections.keys()) .chain(self.canvas_sections.keys()) .chain(self.deliveries.keys()) + .chain(self.scope_owner_generations.keys()) .filter(|s| s.channel_id() == *channel_id) .cloned() .collect::>() @@ -203,6 +214,7 @@ impl SessionState { self.core_sections.clear(); self.canvas_sections.clear(); self.deliveries.clear(); + self.scope_owner_generations.clear(); } pub(crate) fn mark_scope_delivery_success( @@ -336,13 +348,23 @@ pub struct AgentPool { /// cause another worker to open a duplicate session for the same thread. /// Best-effort: stale entries (rotation, crash/respawn) self-heal on the /// next dispatch and are pruned on channel-wide session invalidation. - session_owners: HashMap, + session_owners: HashMap, + /// Monotonic validity fence assigned whenever a scope is dispatched. The + /// generation distinguishes a newly forked owner from every older copy of + /// that scope's provider session. + next_scope_owner_generation: u64, /// First time each scope was held for a busy owner, so the bounded hold can /// expire and fork rather than starve behind an unbounded turn. Derived /// state: cleared on every dispatch/invalidation path, and only ever holds /// `Thread` scopes (the sole variant [`hold_decision`](Self::hold_decision) /// stamps). - held_since: HashMap, + held_since: HashMap, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +struct SessionOwner { + agent_index: usize, + generation: u64, } /// Result returned by a completed prompt task. @@ -830,14 +852,33 @@ impl AgentPool { join_set: JoinSet::new(), task_map: HashMap::new(), session_owners: HashMap::new(), + next_scope_owner_generation: 1, held_since: HashMap::new(), } } - /// Record which worker is handling `scope` so a later dispatch can detect a - /// busy owner and avoid opening a duplicate session on another worker. - pub fn record_scope_owner(&mut self, scope: SessionScope, agent_index: usize) { - self.session_owners.insert(scope, agent_index); + /// Record `agent_index` as the newest owner of `scope`, returning the + /// generation that the caller must install on the checked-out worker. + /// Returning workers are accepted only while this exact + /// `(worker, generation)` pair remains authoritative. + pub fn record_scope_owner(&mut self, scope: SessionScope, agent_index: usize) -> u64 { + let generation = self.next_scope_owner_generation; + self.next_scope_owner_generation = self.next_scope_owner_generation.wrapping_add(1); + if self.next_scope_owner_generation == 0 { + // Preserve zero as an unassigned sentinel. Reaching this requires + // 2^64 dispatches in one process, but resetting safely is cheap: + // every previously tagged session becomes stale on return/claim. + self.next_scope_owner_generation = 1; + self.session_owners.clear(); + } + self.session_owners.insert( + scope, + SessionOwner { + agent_index, + generation, + }, + ); + generation } /// True when this scope should be **held** (left queued) rather than @@ -854,16 +895,21 @@ impl AgentPool { return false; } match self.session_owners.get(scope) { - Some(&owner_idx) => self.task_map.values().any(|m| m.agent_index == owner_idx), + Some(owner) => self + .task_map + .values() + .any(|m| m.agent_index == owner.agent_index), None => false, } } /// Decide whether to hold `scope`'s batch for its busy session owner, fork it - /// after a bounded hold, or dispatch immediately. Stamps and clears the - /// first-held time internally so the bounded window survives across dispatch - /// cycles without a dedicated timer; `now` and `timeout` are injected for - /// testability. + /// after a bounded hold, or dispatch immediately. Stamps the first-held time + /// so the bounded window survives across dispatch cycles; `now` and + /// `timeout` are injected for testability. An expired + /// stamp remains sticky until [`clear_hold`](Self::clear_hold) confirms a + /// worker was successfully claimed, so pool exhaustion cannot restart the + /// bounded window. /// /// Gated on the scope variant, not the session policy: `Conversation` scopes /// (channel-policy channels and all DMs) never hold — a busy owner there means @@ -873,18 +919,21 @@ impl AgentPool { pub fn hold_decision( &mut self, scope: &SessionScope, - now: std::time::Instant, + now: tokio::time::Instant, timeout: Duration, ) -> HoldDecision { if !scope.is_thread() || !self.should_hold_for_busy_owner(scope) { self.held_since.remove(scope); return HoldDecision::Dispatch; } - let owner_index = self.session_owners.get(scope).copied().unwrap_or_default(); + let owner_index = self + .session_owners + .get(scope) + .map(|owner| owner.agent_index) + .unwrap_or_default(); let first = *self.held_since.entry(scope.clone()).or_insert(now); let held_for = now.saturating_duration_since(first); if held_for >= timeout { - self.held_since.remove(scope); HoldDecision::ForkAfterHold { held_for, owner_index, @@ -911,7 +960,7 @@ impl AgentPool { if let Some(scope) = scope { let idx = self.agents.iter().position(|slot| { slot.as_ref() - .map(|a| a.state.sessions.contains_key(scope)) + .map(|a| self.agent_owns_scope(a, scope)) .unwrap_or(false) }); if let Some(i) = idx { @@ -925,7 +974,27 @@ impl AgentPool { } /// Return an agent to its slot after a task completes. - pub fn return_agent(&mut self, agent: OwnedAgent) { + pub fn return_agent(&mut self, mut agent: OwnedAgent) { + let stale_scopes: Vec = agent + .state + .sessions + .keys() + .filter(|scope| !self.agent_owns_scope(&agent, scope)) + .cloned() + .collect(); + for scope in stale_scopes { + tracing::info!( + agent = agent.index, + scope = %scope.telemetry_label(), + "discarding stale session after ownership changed" + ); + agent.state.invalidate_scope(&scope); + } + let live_scopes: HashSet = agent.state.sessions.keys().cloned().collect(); + agent + .state + .scope_owner_generations + .retain(|scope, _| live_scopes.contains(scope)); let idx = agent.index; if self.agents[idx].is_some() { // This is a bug: two tasks returned the same agent index. Log it @@ -945,16 +1014,64 @@ impl AgentPool { self.agents.iter().any(|slot| slot.is_some()) } + /// Confirm that pending work for `scope` successfully claimed a worker. + /// + /// In particular, an expired busy-owner hold must not be consumed until + /// this point: `try_claim` can fail while every worker remains checked out. + pub(crate) fn clear_hold(&mut self, scope: &SessionScope) { + self.held_since.remove(scope); + } + + /// Remove derived hold stamps for scopes that no longer have pending work. + pub(crate) fn retain_held_scopes( + &mut self, + mut has_pending_work: impl FnMut(&SessionScope) -> bool, + ) { + self.held_since.retain(|scope, _| has_pending_work(scope)); + } + /// Whether any idle agent already has a session for `scope`. /// Used to compute `affinity_hit` before calling `try_claim`. pub fn has_session_for(&self, scope: &SessionScope) -> bool { self.agents.iter().any(|slot| { slot.as_ref() - .map(|a| a.state.sessions.contains_key(scope)) + .map(|a| self.agent_owns_scope(a, scope)) .unwrap_or(false) }) } + fn agent_owns_scope(&self, agent: &OwnedAgent, scope: &SessionScope) -> bool { + let Some(owner) = self.session_owners.get(scope) else { + return false; + }; + owner.agent_index == agent.index + && agent.state.scope_owner_generations.get(scope) == Some(&owner.generation) + && agent.state.sessions.contains_key(scope) + } + + /// Earliest scheduled wake for a currently held scope that can claim a + /// worker. A worker return wakes the main loop independently, so arming an + /// already-expired timer while every slot is checked out would only spin. + pub(crate) fn next_hold_deadline(&self, timeout: Duration) -> Option { + if !self.any_idle() { + return None; + } + self.held_since + .values() + .map(|held_since| *held_since + timeout) + .min() + } + + /// Sleep until a held scope's scheduled wake, or remain pending when no + /// scope is held. This is the future polled directly by the main + /// `select!`, kept here so paused-time tests exercise the production seam. + pub(crate) async fn wait_for_hold_deadline(deadline: Option) { + match deadline { + Some(deadline) => tokio::time::sleep_until(deadline).await, + None => std::future::pending().await, + } + } + /// Count of agents that are alive: idle OR checked out (have a task_map entry). /// /// Used to detect when all agents have exited so the caller can respawn. @@ -7461,9 +7578,16 @@ printf '%s\n' '{{"jsonrpc":"2.0","id":0,"result":{{"stopReason":"end_turn"}}}}'" agent.state.sessions.insert(ta.clone(), "sess-a".into()); agent.state.sessions.insert(tb.clone(), "sess-b".into()); let mut pool = AgentPool::from_slots(vec![Some(agent)]); - pool.record_scope_owner(ta.clone(), 0); - pool.record_scope_owner(tb.clone(), 0); - let now = std::time::Instant::now(); + let ta_generation = pool.record_scope_owner(ta.clone(), 0); + let tb_generation = pool.record_scope_owner(tb.clone(), 0); + let agent = pool.agents[0].as_mut().expect("idle test agent"); + agent + .state + .set_scope_owner_generation(ta.clone(), ta_generation); + agent + .state + .set_scope_owner_generation(tb.clone(), tb_generation); + let now = tokio::time::Instant::now(); pool.held_since.insert(ta.clone(), now); pool.held_since.insert(tb.clone(), now); @@ -7515,12 +7639,12 @@ printf '%s\n' '{{"jsonrpc":"2.0","id":0,"result":{{"stopReason":"end_turn"}}}}'" /// An idle agent (slot 0) holding a provider session for `scope`, so /// `has_session_for(scope)` is true. - async fn idle_agent_with_session(scope: SessionScope) -> OwnedAgent { + async fn idle_agent_with_session(index: usize, scope: SessionScope) -> OwnedAgent { let acp = AcpClient::spawn("bash", &["-c".into(), "sleep 10".into()], &[], false) .await .expect("spawn dummy ACP"); let mut agent = OwnedAgent { - index: 0, + index, acp, state: SessionState::default(), model_capabilities: None, @@ -7608,7 +7732,7 @@ printf '%s\n' '{{"jsonrpc":"2.0","id":0,"result":{{"stopReason":"end_turn"}}}}'" }, ]; - let base = std::time::Instant::now(); + let base = tokio::time::Instant::now(); for row in rows { let ch = Uuid::new_v4(); let scope = if row.is_thread { @@ -7617,12 +7741,19 @@ printf '%s\n' '{{"jsonrpc":"2.0","id":0,"result":{{"stopReason":"end_turn"}}}}'" conv(ch) }; let slots = if row.has_session { - vec![Some(idle_agent_with_session(scope.clone()).await)] + vec![Some(idle_agent_with_session(0, scope.clone()).await)] } else { vec![] }; let mut pool = AgentPool::from_slots(slots); - if row.owner_busy { + if row.has_session { + let generation = pool.record_scope_owner(scope.clone(), 0); + pool.agents[0] + .as_mut() + .expect("idle test agent") + .state + .set_scope_owner_generation(scope.clone(), generation); + } else if row.owner_busy { pool.record_scope_owner(scope.clone(), 1); mark_agent_busy(&mut pool, 1, thread_scope(ch, &"b".repeat(64))); } @@ -7648,8 +7779,12 @@ printf '%s\n' '{{"jsonrpc":"2.0","id":0,"result":{{"stopReason":"end_turn"}}}}'" _ => panic!("{}: expected {:?}, got {decision:?}", row.name, row.expect), } - // held_since holds the scope only while a Hold is outstanding. - if matches!(decision, HoldDecision::Hold { .. }) { + // An expired hold remains sticky until a worker is successfully + // claimed; only immediate dispatch clears it here. + if matches!( + decision, + HoldDecision::Hold { .. } | HoldDecision::ForkAfterHold { .. } + ) { assert!( pool.held_since.contains_key(&scope), "{}: hold stamps held_since", @@ -7665,6 +7800,159 @@ printf '%s\n' '{{"jsonrpc":"2.0","id":0,"result":{{"stopReason":"end_turn"}}}}'" } } + #[tokio::test(start_paused = true)] + async fn held_scope_deadline_wakes_a_quiet_dispatch_loop() { + let channel_id = Uuid::new_v4(); + let scope = thread_scope(channel_id, &"a".repeat(64)); + let idle_scope = thread_scope(channel_id, &"c".repeat(64)); + let idle_agent = idle_agent_with_session(0, idle_scope).await; + let mut pool = AgentPool::from_slots(vec![Some(idle_agent)]); + pool.record_scope_owner(scope.clone(), 1); + mark_agent_busy(&mut pool, 1, thread_scope(channel_id, &"b".repeat(64))); + + let started = tokio::time::Instant::now(); + assert!(matches!( + pool.hold_decision(&scope, started, HOLD_BUSY_OWNER_TIMEOUT), + HoldDecision::Hold { .. } + )); + let deadline = pool + .next_hold_deadline(HOLD_BUSY_OWNER_TIMEOUT) + .expect("held scope schedules an independent wake"); + let wake = AgentPool::wait_for_hold_deadline(Some(deadline)); + tokio::pin!(wake); + + tokio::time::advance(HOLD_BUSY_OWNER_TIMEOUT - Duration::from_millis(1)).await; + assert!( + tokio::time::timeout(Duration::ZERO, &mut wake) + .await + .is_err(), + "quiet loop stays asleep before deadline" + ); + tokio::time::advance(Duration::from_millis(1)).await; + wake.await; + + assert!(matches!( + pool.hold_decision(&scope, tokio::time::Instant::now(), HOLD_BUSY_OWNER_TIMEOUT), + HoldDecision::ForkAfterHold { .. } + )); + } + + #[tokio::test] + async fn expired_hold_survives_pool_exhaustion_until_a_worker_is_claimable() { + let channel_id = Uuid::new_v4(); + let scope = thread_scope(channel_id, &"a".repeat(64)); + let mut pool = AgentPool::from_slots(vec![None]); + pool.record_scope_owner(scope.clone(), 1); + mark_agent_busy(&mut pool, 1, thread_scope(channel_id, &"b".repeat(64))); + + let started = tokio::time::Instant::now(); + assert!(matches!( + pool.hold_decision(&scope, started, HOLD_BUSY_OWNER_TIMEOUT), + HoldDecision::Hold { .. } + )); + assert!(matches!( + pool.hold_decision( + &scope, + started + HOLD_BUSY_OWNER_TIMEOUT, + HOLD_BUSY_OWNER_TIMEOUT + ), + HoldDecision::ForkAfterHold { .. } + )); + assert!( + pool.held_since.contains_key(&scope), + "failed claim must not restart the timeout" + ); + assert_eq!( + pool.next_hold_deadline(HOLD_BUSY_OWNER_TIMEOUT), + None, + "an expired hold cannot spin while all workers are checked out" + ); + + let idle_scope = thread_scope(channel_id, &"c".repeat(64)); + pool.agents[0] = Some(idle_agent_with_session(0, idle_scope).await); + assert_eq!( + pool.next_hold_deadline(HOLD_BUSY_OWNER_TIMEOUT), + Some(started + HOLD_BUSY_OWNER_TIMEOUT), + "worker availability immediately re-arms the expired deadline" + ); + assert!(matches!( + pool.hold_decision( + &scope, + started + HOLD_BUSY_OWNER_TIMEOUT + Duration::from_secs(1), + HOLD_BUSY_OWNER_TIMEOUT + ), + HoldDecision::ForkAfterHold { .. } + )); + pool.clear_hold(&scope); + assert!(!pool.held_since.contains_key(&scope)); + } + + #[tokio::test] + async fn forked_scope_discards_stale_session_when_busy_owner_returns() { + let channel_id = Uuid::new_v4(); + let scope = thread_scope(channel_id, &"a".repeat(64)); + let busy_scope = thread_scope(channel_id, &"b".repeat(64)); + let old_owner = idle_agent_with_session(0, scope.clone()).await; + let replacement = idle_agent_with_session(1, busy_scope.clone()).await; + let mut pool = AgentPool::from_slots(vec![Some(old_owner), Some(replacement)]); + + let mut old_owner = pool.try_claim(None).expect("claim worker 0"); + let old_generation = pool.record_scope_owner(scope.clone(), old_owner.index); + old_owner + .state + .set_scope_owner_generation(scope.clone(), old_generation); + mark_agent_busy(&mut pool, old_owner.index, busy_scope); + + let started = tokio::time::Instant::now(); + assert!(matches!( + pool.hold_decision(&scope, started, HOLD_BUSY_OWNER_TIMEOUT), + HoldDecision::Hold { .. } + )); + assert!(matches!( + pool.hold_decision( + &scope, + started + HOLD_BUSY_OWNER_TIMEOUT, + HOLD_BUSY_OWNER_TIMEOUT + ), + HoldDecision::ForkAfterHold { .. } + )); + + let mut replacement = pool + .try_claim(Some(&scope)) + .expect("idle worker receives forked scope"); + pool.clear_hold(&scope); + assert_eq!(replacement.index, 1); + replacement + .state + .sessions + .insert(scope.clone(), "fresh-session".into()); + let fresh_generation = pool.record_scope_owner(scope.clone(), replacement.index); + replacement + .state + .set_scope_owner_generation(scope.clone(), fresh_generation); + + // Both turns return. Slot order must not make worker 0's old provider + // context claimable after worker 1 became the authoritative owner. + pool.return_agent(replacement); + pool.task_map + .retain(|_, meta| meta.agent_index != old_owner.index); + pool.return_agent(old_owner); + assert!( + !pool.agents[0] + .as_ref() + .expect("worker 0 returned") + .state + .sessions + .contains_key(&scope), + "return cleanup removes the old provider session" + ); + + let claimed = pool + .try_claim(Some(&scope)) + .expect("authoritative owner remains claimable"); + assert_eq!(claimed.index, 1, "next turn resumes the forked session"); + } + #[test] fn test_rotate_after_natural_completion_invalidates_channel_state() { let (mut s, ch_a, ch_b) = make_state(); @@ -10440,7 +10728,7 @@ done"# pool.invalidate_scope_session(&scopes[1]); pool.record_scope_owner(scopes[0].clone(), 0); pool.held_since - .insert(scopes[0].clone(), std::time::Instant::now()); + .insert(scopes[0].clone(), tokio::time::Instant::now()); assert_eq!( pool.switch_idle_agent_model(channel_id, "model-b", Some("pick".into())), IdleSwitchResult::Switched, diff --git a/crates/buzz-acp/src/queue.rs b/crates/buzz-acp/src/queue.rs index b2203f62f9..a419b78178 100644 --- a/crates/buzz-acp/src/queue.rs +++ b/crates/buzz-acp/src/queue.rs @@ -782,6 +782,22 @@ impl EventQueue { self.queues.len() } + /// Whether `scope` still has work that can be reconstructed into a batch. + /// + /// Busy-owner hold timestamps are derived from pending queue state. Queue + /// cap eviction can retire a scope without going through a pool cleanup + /// path, so the dispatch loop uses this seam to prune orphaned holds before + /// scheduling their deadline wakeups. + pub(crate) fn has_pending_scope(&self, scope: &SessionScope) -> bool { + self.queues + .get(scope) + .is_some_and(|queue| !queue.is_empty()) + || self + .cancelled_batches + .get(scope) + .is_some_and(|events| !events.is_empty()) + } + /// Number of queued events for a specific scope (or channel, treated as its /// conversation scope). Test-only. #[cfg(test)] diff --git a/crates/buzz-acp/src/relay.rs b/crates/buzz-acp/src/relay.rs index 23ed454fa2..a019e75834 100644 --- a/crates/buzz-acp/src/relay.rs +++ b/crates/buzz-acp/src/relay.rs @@ -1160,10 +1160,8 @@ struct BgState { /// On reconnect resubscribe, `since` = min(last_seen, channel_dropped_since). /// Cleared per-channel after a successful resubscribe. channel_dropped_since: HashMap, - /// Set by the backpressure handler when the event channel is full. - /// The main loop checks this flag and triggers a proactive resubscribe - /// (without waiting for a disconnect) so dropped events are replayed. - proactive_resubscribe_needed: bool, + /// Rate/fairness bookkeeping only; replay cursors retain baseline semantics. + recovery: recovery::RecoverySchedule, /// Unix timestamp captured just before the relay connection was established. /// Used as the floor `since` for membership notification replay so events /// predating this session are never re-delivered. @@ -1237,7 +1235,7 @@ impl BgState { membership_sub_active: false, observer_control_sub_active: false, channel_dropped_since: HashMap::new(), - proactive_resubscribe_needed: false, + recovery: recovery::RecoverySchedule::default(), startup_watermark: None, subscribe_since: HashMap::new(), rate_limit_gate: None, @@ -1298,6 +1296,9 @@ impl BgState { /// Prevents stale replay on re-subscribe and avoids unbounded state growth /// for channels that are removed and never re-added. fn clear_channel_state(&mut self, channel_id: &Uuid) { + self.recovery + .last_attempt + .remove(&channel_sub_id(*channel_id)); self.last_seen.remove(channel_id); self.subscribe_since.remove(channel_id); self.channel_dropped_since.remove(channel_id); @@ -1826,82 +1827,6 @@ async fn run_background_task( let mut drain_pacing_next: Option = None; loop { - if state.proactive_resubscribe_needed { - state.proactive_resubscribe_needed = false; - info!("proactive resubscribe triggered by backpressure event loss"); - // Proactive resubscribe runs on the EXISTING socket — do NOT clear the - // rate-limit gate or pending queues. - match resubscribe_after_reconnect( - &mut ws, - &mut cmd_rx, - &mut state, - &agent_pubkey_hex, - false, // existing socket — preserve gate state - ) - .await - { - ResubscribeResult::Ok => {} - ResubscribeResult::Shutdown => return, - ResubscribeResult::RetryConnection => { - warn!("proactive resubscribe had failures — triggering reconnect"); - let _ = event_tx.try_send(None); - match try_autonomous_reconnect( - &mut ws, - &mut cmd_rx, - &mut state, - &keys, - &relay_url, - &agent_pubkey_hex, - &event_tx, - &observer_control_tx, - auth_tag.as_ref(), - ) - .await - { - ReconnectOutcome::Ok => { - if matches!( - drain_post_reconnect( - &mut ws, - &mut cmd_rx, - &mut state, - &agent_pubkey_hex - ) - .await, - ReconnectOutcome::Shutdown - ) { - return; - } - } - ReconnectOutcome::Shutdown => return, - ReconnectOutcome::Failed => { - if matches!( - wait_for_reconnect( - &mut ws, - &mut cmd_rx, - &mut state, - &keys, - &relay_url, - &agent_pubkey_hex, - &event_tx, - &observer_control_tx, - true, - auth_tag.as_ref(), - ) - .await, - ReconnectOutcome::Shutdown - ) { - return; - } - } - } - ping_sent = false; - last_pong = Instant::now(); - connected_since = Instant::now(); - stable_logged = false; - } - } - } - // Drain pending subs, one REQ per pacing tick within the relay's // admission window. let drain_window_open = drain_pacing_next.is_none_or(|t| tokio::time::Instant::now() >= t); @@ -1982,7 +1907,11 @@ async fn run_background_task( } } + let recovery_at = recovery::ready_at(&mut state); tokio::select! { + _ = recovery::ready(&event_tx, recovery_at) => { + recovery::recover_one(&mut ws, &mut state, &event_tx, &agent_pubkey_hex).await; + } raw = ws.next() => { // Determine if the socket is lost. let socket_lost = match raw { @@ -2358,12 +2287,10 @@ async fn handle_ws_message( // replay starts early enough to re-deliver it. state.membership_dropped_since = Some(state.membership_dropped_since.map_or(ts, |d| d.min(ts))); - // Proactively trigger resubscribe without waiting for a disconnect. - state.proactive_resubscribe_needed = true; warn!( channel_id = %channel_uuid, ts, - "membership notification dropped (backpressure) — proactive resubscribe queued" + "membership notification dropped (backpressure) — targeted recovery pending" ); } Err(mpsc::error::TrySendError::Closed(_)) => return false, @@ -2400,12 +2327,10 @@ async fn handle_ws_message( .entry(channel_id) .and_modify(|d| *d = (*d).min(ts)) .or_insert(ts); - // Proactively trigger resubscribe without waiting for a disconnect. - state.proactive_resubscribe_needed = true; warn!( channel_id = %channel_id, ts, - "event channel full — dropping event for channel {channel_id} — proactive resubscribe queued" + "event channel full — dropping event for channel {channel_id} — targeted recovery pending" ); } Err(mpsc::error::TrySendError::Closed(_)) => { @@ -4248,6 +4173,11 @@ async fn wait_for_any_ok( } } +mod recovery; + +#[cfg(test)] +mod recovery_tests; + #[cfg(test)] mod tests { use super::*; @@ -4775,7 +4705,7 @@ mod tests { .expect("signing should succeed") } - async fn test_ws_pair() -> (WsStream, WebSocketStream) { + pub(super) async fn test_ws_pair() -> (WsStream, WebSocketStream) { let listener = tokio::net::TcpListener::bind("127.0.0.1:0") .await .expect("bind test websocket"); @@ -4792,7 +4722,7 @@ mod tests { (client, server.await.expect("join test websocket server")) } - async fn next_test_frame( + pub(super) async fn next_test_frame( server: &mut WebSocketStream, ) -> serde_json::Value { let message = timeout(Duration::from_secs(1), server.next()) @@ -5035,14 +4965,14 @@ mod tests { )); } - fn test_channel_filter() -> ChannelFilter { + pub(super) fn test_channel_filter() -> ChannelFilter { ChannelFilter { kinds: Some(vec![9]), require_mention: false, } } - fn seed_test_subscription(state: &mut BgState, channel_id: Uuid) { + pub(super) fn seed_test_subscription(state: &mut BgState, channel_id: Uuid) { apply_command_to_state( state, RelayCommand::Subscribe { diff --git a/crates/buzz-acp/src/relay/recovery.rs b/crates/buzz-acp/src/relay/recovery.rs new file mode 100644 index 0000000000..62da119a4b --- /dev/null +++ b/crates/buzz-acp/src/relay/recovery.rs @@ -0,0 +1,132 @@ +//! Overflow recovery is an attempted replay, not an EOSE/consumer receipt. +//! Keep the existing IDs and cursor retirement rules; bound when work is sent. +use super::*; + +pub(super) const RECOVERY_INTERVAL: Duration = Duration::from_secs(5); + +#[derive(Default)] +pub(super) struct RecoverySchedule { + next_attempt: Option, + pub(super) last_attempt: HashMap, +} + +/// Attempt at most one affected subscription, with space for replay to arrive. +/// Failed writes retain the loss cursor and are paced too. No EOSE is interpreted +/// as completion: overlapping requests keep their existing stable wire IDs. +pub(super) async fn recover_one( + ws: &mut WsStream, + state: &mut BgState, + event_tx: &mpsc::Sender>, + agent_pubkey_hex: &str, +) { + let now = tokio::time::Instant::now(); + if event_tx.is_closed() + || event_tx.capacity() < event_tx.max_capacity().div_ceil(2) + || state.recovery.next_attempt.is_some_and(|next| now < next) + || state.check_rate_gate().is_some() + { + return; + } + + let channel = next_channel(state); + let Some(channel) = channel else { return }; + let sub = channel.map_or_else(|| MEMBERSHIP_NOTIF_SUB_ID.to_owned(), channel_sub_id); + state.recovery.last_attempt.insert(sub.clone(), now); + info!(subscription = sub, "attempting targeted overflow replay"); + + if let Some(ch) = channel { + if let Some(filter) = state.active_filters.get(&ch).cloned() { + let since = state.channel_since(&ch); + if send_subscribe(ws, state, ch, agent_pubkey_hex, since, &filter).await { + // Baseline retirement point: REQ write, NOT proven delivery. + // New overflow after this attempt creates another pending cursor. + state.channel_dropped_since.remove(&ch); + } + } + } else { + let since = match (state.membership_dropped_since, state.membership_last_seen) { + (Some(d), Some(l)) => Some(d.min(l)), + (Some(d), None) => Some(d), + (None, Some(l)) => Some(l), + (None, None) => state.startup_watermark, + }; + if send_membership_subscribe(ws, agent_pubkey_hex, since).await { + state.membership_dropped_since = None; + } + } + // Pace from the end of a potentially backpressured write. No catch-up burst. + // The existing bounded write timeout and read/ping owner detect socket loss. + state.recovery.next_attempt = Some(tokio::time::Instant::now() + RECOVERY_INTERVAL); +} + +/// No timer or capacity waiter when another authority owns all pending loss. +/// Only actual attempts advance the cooldown; closed gates wake at expiry. +pub(super) fn ready_at(state: &mut BgState) -> Option { + next_channel(state)?; + Some( + state + .recovery + .next_attempt + .unwrap_or_else(tokio::time::Instant::now) + .max( + state + .check_rate_gate() + .unwrap_or_else(tokio::time::Instant::now), + ), + ) +} + +/// Select-local readiness, not a send or a reservation carried across reads. +/// The socket task is the sole producer. `select!` drops this future (including +/// partial permits) BEFORE handling another frame/command, so live try_send +/// never competes with a recovery reservation. Receives only add capacity. +/// Keep this future inside select!: awaiting it alone would block the reader; +/// persisting it across iterations would steal capacity from live delivery. +pub(super) async fn ready( + event_tx: &mpsc::Sender>, + at: Option, +) { + if let Some(at) = at { + if tokio::time::Instant::now() < at { + tokio::time::sleep_until(at).await; + } + // Use the channel's own race-free capacity wake, not periodic samples. + // Return ALL permits before recover_one rechecks capacity and intent. + if let Ok(permits) = event_tx + .reserve_many(event_tx.max_capacity().div_ceil(2)) + .await + { + drop(permits); + return; + } + } + // No loss or a closed receiver: no immediate-ready/error wake loop. + std::future::pending::<()>().await; +} + +fn next_channel(state: &BgState) -> Option> { + // One record per active intent, not per loss or per request generation. + // Least recently attempted prevents a repeatedly overflowing channel from + // starving other channels or membership. Missing filters fail closed. + state + .channel_dropped_since + .keys() + .filter(|ch| { + state.active_subscriptions.contains_key(ch) + && state.active_filters.contains_key(ch) + && !state.rate_limited_pending.contains_key(ch) + && !state.resubscribe_retry.contains(ch) + }) + .copied() + .map(Some) + .chain( + (state.membership_sub_active + && state.membership_dropped_since.is_some() + && !state.membership_resub_needed) + .then_some(None), + ) + .min_by_key(|ch| { + let sub = ch.map_or_else(|| MEMBERSHIP_NOTIF_SUB_ID.to_owned(), channel_sub_id); + (state.recovery.last_attempt.get(&sub).copied(), sub) + }) +} diff --git a/crates/buzz-acp/src/relay/recovery_tests.rs b/crates/buzz-acp/src/relay/recovery_tests.rs new file mode 100644 index 0000000000..4e51a0c614 --- /dev/null +++ b/crates/buzz-acp/src/relay/recovery_tests.rs @@ -0,0 +1,388 @@ +//! Bounded synthetic WebSocket fixtures; no relay service, proxy or real agent. +use super::tests::{next_test_frame, seed_test_subscription, test_channel_filter, test_ws_pair}; +use super::*; + +fn fixture_event(channel: Uuid, n: u64, kind: u16) -> Event { + let keys = + Keys::parse("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); + EventBuilder::new(Kind::Custom(kind), format!("synthetic-{n}")) + .tags([Tag::parse(["h", &channel.to_string()]).unwrap()]) + .custom_created_at(nostr::Timestamp::from(1_000 + n)) + .sign_with_keys(&keys) + .unwrap() +} + +async fn dispatch( + client: &mut WsStream, + state: &mut BgState, + tx: &mpsc::Sender>, + frame: Value, +) { + let (control_tx, _control_rx) = mpsc::channel(1); + assert!( + handle_ws_message( + Message::Text(frame.to_string().into()), + client, + tx, + &control_tx, + state, + &Keys::generate(), + "ws://127.0.0.1:1", + "synthetic-agent", + None, + ) + .await + ); +} + +#[tokio::test] +async fn repeated_overflow_recovers_only_affected_channel_after_capacity() { + let (mut client, mut server) = test_ws_pair().await; + let mut state = BgState::new(); + let channels: Vec<_> = (0..18).map(|_| Uuid::new_v4()).collect(); + for ch in &channels { + seed_test_subscription(&mut state, *ch); + } + let ch = channels[0]; + let sub = channel_sub_id(ch); + let (tx, mut rx) = mpsc::channel(256); + // Relay history is newest-first; the oldest dropped event must survive + // a watermark already advanced by much newer successfully-enqueued events. + let events: Vec<_> = (0..320).rev().map(|n| fixture_event(ch, n, 9)).collect(); + for event in &events { + dispatch(&mut client, &mut state, &tx, json!(["EVENT", sub, event])).await; + recovery::recover_one(&mut client, &mut state, &tx, "synthetic-agent").await; + } + assert_eq!(rx.len(), 256); + assert_eq!(state.channel_dropped_since[&ch], 1_000); + assert!(timeout(Duration::from_millis(30), server.next()) + .await + .is_err()); + for event in &events[..256] { + assert_eq!(rx.recv().await.unwrap().unwrap().event.id, event.id); + } + recovery::recover_one(&mut client, &mut state, &tx, "synthetic-agent").await; + let req = next_test_frame(&mut server).await; + assert_eq!(req[0], "REQ"); + assert_eq!(req[1], sub); + assert_eq!(req[2]["#h"], json!([ch.to_string()])); + assert_eq!(req[2]["kinds"], json!([9])); + assert_eq!(req[2]["since"], 995); + // Concurrent timer ticks / duplicate arrivals cannot replace the replay. + for _ in 0..40 { + recovery::recover_one(&mut client, &mut state, &tx, "synthetic-agent").await; + } + assert!(timeout(Duration::from_millis(30), server.next()) + .await + .is_err()); + for event in &events { + dispatch(&mut client, &mut state, &tx, json!(["EVENT", sub, event])).await; + } + dispatch(&mut client, &mut state, &tx, json!(["EOSE", sub])).await; + assert_eq!(rx.len(), 64, "delivered IDs must remain deduplicated"); + for event in &events[256..] { + assert_eq!(rx.recv().await.unwrap().unwrap().event.id, event.id); + } + assert_eq!(state.channel_since(&ch), Some(1_319)); + recovery::recover_one(&mut client, &mut state, &tx, "synthetic-agent").await; + assert!(timeout(Duration::from_millis(30), server.next()) + .await + .is_err()); + let live = fixture_event(ch, 400, 9); + dispatch(&mut client, &mut state, &tx, json!(["EVENT", sub, live])).await; + assert_eq!(rx.recv().await.unwrap().unwrap().event.id, live.id); + println!("18 subscriptions; 320 newest-first arrivals; 64 losses coalesced; 0 REQ while full; 1 targeted REQ; 320 unique deliveries + live"); +} + +#[tokio::test] +async fn socket_owner_services_ping_shutdown_and_coalesces_overflow_ticks() { + let (client, mut server) = test_ws_pair().await; + let (tx, mut rx) = mpsc::channel(1); + let (control_tx, _control_rx) = mpsc::channel(1); + let (cmd_tx, cmd_rx) = mpsc::channel(64); + let task = tokio::spawn(run_background_task( + client, + VecDeque::new(), + tx, + control_tx, + cmd_rx, + Keys::generate(), + "ws://127.0.0.1:1".into(), + "synthetic-agent".into(), + None, + )); + let channels: Vec<_> = (0..18).map(|_| Uuid::new_v4()).collect(); + for ch in &channels { + cmd_tx + .send(RelayCommand::Subscribe { + channel_id: *ch, + filter: test_channel_filter(), + replay_since: Some(1_000), + }) + .await + .unwrap(); + } + let mut subscriptions = 0; + while subscriptions < 18 { + let frame = timeout(Duration::from_secs(2), server.next()) + .await + .unwrap() + .unwrap() + .unwrap(); + match frame { + Message::Text(text) => { + let req: Value = serde_json::from_str(&text).unwrap(); + assert_eq!(req[0], "REQ"); + server + .send(Message::Text(json!(["EOSE", req[1]]).to_string().into())) + .await + .unwrap(); + subscriptions += 1; + } + Message::Ping(payload) => server.send(Message::Pong(payload)).await.unwrap(), + other => panic!("unexpected {other:?}"), + } + } + let sub = channel_sub_id(channels[0]); + for n in 0..40 { + server + .send(Message::Text( + json!(["EVENT", sub, fixture_event(channels[0], n, 9)]) + .to_string() + .into(), + )) + .await + .unwrap(); + } + server.send(Message::Ping(vec![42].into())).await.unwrap(); + timeout(Duration::from_secs(2), async { + loop { + match server.next().await.unwrap().unwrap() { + Message::Ping(payload) => server.send(Message::Pong(payload)).await.unwrap(), + Message::Pong(payload) => { + assert_eq!(payload.as_ref(), &[42]); + break; + } + other => panic!("no immediate all-channel recovery before ping: {other:?}"), + } + } + }) + .await + .unwrap(); + // Wait across a recovery tick with the consumer still full. + assert!(socket_frame(&mut server, Duration::from_millis(5_100)) + .await + .is_none()); + rx.recv().await.unwrap().unwrap(); + let frame = timeout(Duration::from_secs(6), server.next()) + .await + .unwrap() + .unwrap() + .unwrap(); + let req: Value = serde_json::from_str(frame.to_text().unwrap()).unwrap(); + assert_eq!(req[1], sub); + assert_eq!(req[2]["since"], 996); + assert!(timeout(Duration::from_millis(100), server.next()) + .await + .is_err()); + // Sustained lag: each replay is followed by another burst, without EOSE. + // Recovery must stay paced, not permanently stall or sweep healthy channels. + for round in 1..=3 { + let started = tokio::time::Instant::now(); + for n in round * 40..(round + 1) * 40 { + server + .send(Message::Text( + json!(["EVENT", sub, fixture_event(channels[0], n, 9)]) + .to_string() + .into(), + )) + .await + .unwrap(); + } + server.send(Message::Ping(vec![43].into())).await.unwrap(); + let pong = timeout(Duration::from_secs(1), server.next()) + .await + .unwrap() + .unwrap() + .unwrap(); + assert!( + matches!(pong, Message::Pong(_)), + "recovery preempted ping: {pong:?}" + ); + rx.recv().await.unwrap().unwrap(); + let frame = timeout(Duration::from_secs(6), server.next()) + .await + .unwrap() + .unwrap() + .unwrap(); + let req: Value = serde_json::from_str(frame.to_text().unwrap()).unwrap(); + assert_eq!(req[1], sub, "healthy channels must not be swept"); + assert!( + started.elapsed() >= Duration::from_secs(4), + "unpaced repeat" + ); + } + cmd_tx.send(RelayCommand::Shutdown).await.unwrap(); + timeout(Duration::from_secs(1), task) + .await + .unwrap() + .unwrap(); + println!("socket-owner seam: 18 live REQs, 39 coalesced losses, PONG while full, zero recovery across full-capacity timer tick, four paced targeted REQs over sustained lag without EOSE, responsive shutdown"); +} + +#[tokio::test] +async fn recovery_is_fair_and_paced_even_with_new_loss_and_stale_eose() { + let (mut client, mut server) = test_ws_pair().await; + let mut state = BgState::new(); + let channels = [Uuid::new_v4(), Uuid::new_v4()]; + for ch in channels { + seed_test_subscription(&mut state, ch); + state.channel_dropped_since.insert(ch, 600); + } + state.membership_sub_active = true; + state.membership_dropped_since = Some(500); + let (tx, _rx) = mpsc::channel(1); + let mut visited = HashSet::new(); + for round in 0..9 { + timeout( + Duration::from_millis(100), + recovery::ready(&tx, recovery::ready_at(&mut state)), + ) + .await + .unwrap(); + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + let req = next_test_frame(&mut server).await; + let sub = req[1].as_str().unwrap(); + if round < 3 { + assert!(visited.insert(sub.to_owned()), "starved intent"); + } + if sub == MEMBERSHIP_NOTIF_SUB_ID { + assert_eq!(req[2]["since"], 495); + state.membership_dropped_since = Some(500); + } else { + let ch = channel_id_from_sub_id(sub).unwrap(); + assert_eq!(req[2]["since"], 595); + state.channel_dropped_since.insert(ch, 600); + } + // Neither stale nor current EOSE creates completion state or erases loss. + dispatch(&mut client, &mut state, &tx, json!(["EOSE", sub])).await; + for _ in 0..30 { + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + } + assert!(timeout(Duration::from_millis(1), server.next()) + .await + .is_err()); + advance_clock(recovery::RECOVERY_INTERVAL).await; + } + for ch in channels { + state.active_subscriptions.remove(&ch); + state.clear_channel_state(&ch); + assert!(!state + .recovery + .last_attempt + .contains_key(&channel_sub_id(ch))); + } + assert_eq!(state.recovery.last_attempt.len(), 1); +} + +#[tokio::test] +async fn gate_headroom_failed_writes_and_reconnect_preserve_pending_attempts() { + let (mut client, mut server) = test_ws_pair().await; + let mut state = BgState::new(); + let ch = Uuid::new_v4(); + seed_test_subscription(&mut state, ch); + state.channel_dropped_since.insert(ch, 700); + let (tx, mut rx) = mpsc::channel(4); + for _ in 0..3 { + tx.try_send(None).unwrap(); + } + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + assert!(state.recovery.last_attempt.is_empty()); + rx.recv().await; + state.rate_limit_gate = Some(tokio::time::Instant::now() + Duration::from_secs(10)); + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + assert!(state.recovery.last_attempt.is_empty()); + advance_clock(Duration::from_secs(10)).await; + // Close locally, so the actual production writer fails deterministically. + client.close(None).await.unwrap(); + server.next().await; + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + assert_eq!(state.channel_dropped_since[&ch], 700); + let attempted = state.recovery.last_attempt.clone(); + for _ in 0..30 { + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + } + assert_eq!(state.recovery.last_attempt, attempted); + advance_clock(recovery::RECOVERY_INTERVAL).await; + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + assert_ne!( + state.recovery.last_attempt, attempted, + "failed write must be retried" + ); + assert_eq!(state.channel_dropped_since[&ch], 700); + + let (mut client, mut server) = test_ws_pair().await; + let (_cmd_tx, mut cmd_rx) = mpsc::channel(1); + assert!(matches!( + resubscribe_after_reconnect(&mut client, &mut cmd_rx, &mut state, "agent", true,).await, + ResubscribeResult::Ok + )); + let req = next_test_frame(&mut server).await; + assert_eq!(req[1], channel_sub_id(ch)); + assert_eq!(req[2]["since"], 695); + assert!(!state.channel_dropped_since.contains_key(&ch)); + // This is deliberately the baseline write-retirement contract, not a receipt. +} + +async fn advance_clock(duration: Duration) { + tokio::time::pause(); + tokio::time::advance(duration).await; + tokio::time::resume(); +} + +#[tokio::test] +async fn blocked_recovery_write_is_bounded_and_retains_loss() { + let (mut client, _stalled_server) = test_ws_pair().await; + let mut state = BgState::new(); + let ch = Uuid::new_v4(); + seed_test_subscription(&mut state, ch); + // Bounded 16MB JSON request exceeds loopback TCP buffering. The server does + // not read it. This tests the real production write/timeout, not a mock sink. + state.active_filters.get_mut(&ch).unwrap().kinds = Some(vec![9; 8_000_000]); + state.channel_dropped_since.insert(ch, 700); + let (tx, _rx) = mpsc::channel(1); + let started = tokio::time::Instant::now(); + timeout( + Duration::from_secs(15), + recovery::recover_one(&mut client, &mut state, &tx, "agent"), + ) + .await + .unwrap(); + assert!(started.elapsed() >= Duration::from_secs(WS_SEND_TIMEOUT_SECS)); + assert_eq!(state.channel_dropped_since[&ch], 700); + let attempted = state.recovery.last_attempt.clone(); + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + assert_eq!(state.recovery.last_attempt, attempted); +} + +// Keep the fixture responsive to independent client keepalives while checking +// recovery traffic. Wall-clock scheduling may deliver the initial ping late. +async fn socket_frame( + server: &mut WebSocketStream, + duration: Duration, +) -> Option { + let deadline = tokio::time::Instant::now() + duration; + loop { + match tokio::time::timeout_at(deadline, server.next()).await { + Err(_) => return None, + Ok(Some(Ok(Message::Ping(payload)))) => { + server.send(Message::Pong(payload)).await.unwrap(); + } + Ok(Some(Ok(frame))) => return Some(frame), + other => panic!("unexpected socket state: {other:?}"), + } + } +} + +#[path = "recovery_wake_tests.rs"] +mod wake; diff --git a/crates/buzz-acp/src/relay/recovery_wake_tests.rs b/crates/buzz-acp/src/relay/recovery_wake_tests.rs new file mode 100644 index 0000000000..de27c7d06c --- /dev/null +++ b/crates/buzz-acp/src/relay/recovery_wake_tests.rs @@ -0,0 +1,507 @@ +//! Capacity-wake boundaries and the independently reproduced R1 schedule. +use super::*; + +// Reviewer-authored, exact-source comparison of recurring headroom at the socket owner. +// A small periodically refilled queue is empty for most of each five-second period. +async fn review_count_until( + server: &mut WebSocketStream, + deadline: tokio::time::Instant, +) -> usize { + let mut count = 0; + while tokio::time::Instant::now() < deadline { + let remaining = deadline.saturating_duration_since(tokio::time::Instant::now()); + match socket_frame(server, remaining).await { + None => break, + Some(Message::Text(text)) => { + let frame: Value = serde_json::from_str(&text).unwrap(); + assert_eq!(frame[0], "REQ"); + count += 1; + } + other => panic!("unexpected {other:?}"), + } + } + count +} + +async fn review_barrier(server: &mut WebSocketStream) -> usize { + server.send(Message::Ping(vec![77].into())).await.unwrap(); + let mut count = 0; + loop { + match socket_frame(server, Duration::from_secs(2)).await.unwrap() { + Message::Pong(payload) => { + assert_eq!(payload.as_ref(), &[77]); + return count; + } + Message::Text(text) => { + let frame: Value = serde_json::from_str(&text).unwrap(); + assert_eq!(frame[0], "REQ"); + count += 1; + } + other => panic!("unexpected {other:?}"), + } + } +} + +#[tokio::test] +async fn review_recurring_headroom_between_ticks_gets_an_attempt() { + let (client, mut server) = test_ws_pair().await; + let (tx, mut rx) = mpsc::channel(1); + let (control_tx, _control_rx) = mpsc::channel(1); + let (cmd_tx, cmd_rx) = mpsc::channel(8); + let start = tokio::time::Instant::now(); + let task = tokio::spawn(run_background_task( + client, + VecDeque::new(), + tx, + control_tx, + cmd_rx, + Keys::generate(), + "ws://127.0.0.1:1".into(), + "agent".into(), + None, + )); + let ch = Uuid::new_v4(); + let sub = channel_sub_id(ch); + cmd_tx + .send(RelayCommand::Subscribe { + channel_id: ch, + filter: test_channel_filter(), + replay_since: Some(1000), + }) + .await + .unwrap(); + let frame = socket_frame(&mut server, Duration::from_secs(2)) + .await + .unwrap(); + let req: Value = serde_json::from_str(frame.to_text().unwrap()).unwrap(); + assert_eq!(req[1], sub); + let lost = fixture_event(ch, 1, 9); + for event in [fixture_event(ch, 0, 9), lost.clone()] { + server + .send(Message::Text( + json!(["EVENT", sub, event]).to_string().into(), + )) + .await + .unwrap(); + } + let mut attempts = review_barrier(&mut server).await; + assert_eq!(rx.len(), 1); + rx.recv().await.unwrap().unwrap(); + for round in 1..=4 { + // Headroom until 1s before the tick; then only one live arrival, no new + // overflow. The queue stays full across the tick and drains 0.5s later. + attempts += review_count_until( + &mut server, + start + Duration::from_millis(round * 5000 - 1000), + ) + .await; + assert_eq!(rx.len(), 0); + server + .send(Message::Text( + json!(["EVENT", sub, fixture_event(ch, 10 + round, 9)]) + .to_string() + .into(), + )) + .await + .unwrap(); + attempts += review_barrier(&mut server).await; + assert_eq!(rx.len(), 1); + attempts += review_count_until( + &mut server, + start + Duration::from_millis(round * 5000 + 500), + ) + .await; + rx.recv().await.unwrap().unwrap(); + } + println!("REVIEW periodic consumer: 4 full-at-tick windows, empty >=3.5s each period, recovery_requests={attempts}"); + assert_eq!( + attempts, 1, + "recurring headroom must not strand the first attempt" + ); + // Return the missing event using the actual requested stable subscription. + server + .send(Message::Text( + json!(["EVENT", sub, lost]).to_string().into(), + )) + .await + .unwrap(); + assert_eq!(review_barrier(&mut server).await, 0); + assert_eq!(rx.recv().await.unwrap().unwrap().event.id, lost.id); + let after = review_count_until(&mut server, start + Duration::from_millis(25_500)).await; + assert_eq!( + after, 0, + "no timer churn or extra requests after successful write" + ); + println!( + "REVIEW continuous-headroom control: additional_requests={after}; missing event delivered" + ); + cmd_tx.send(RelayCommand::Shutdown).await.unwrap(); + timeout(Duration::from_secs(2), task) + .await + .unwrap() + .unwrap(); +} + +/// Same real socket owner as production, with no control of its internal state. +struct Owner { + server: WebSocketStream, + rx: mpsc::Receiver>, + cmd: mpsc::Sender, + task: tokio::task::JoinHandle<()>, + ch: Uuid, +} + +impl Owner { + async fn new(capacity: usize) -> Self { + let (client, server) = test_ws_pair().await; + let (tx, rx) = mpsc::channel(capacity); + let (control_tx, _control_rx) = mpsc::channel(1); + let (cmd, cmd_rx) = mpsc::channel(8); + let task = tokio::spawn(run_background_task( + client, + VecDeque::new(), + tx, + control_tx, + cmd_rx, + Keys::generate(), + "ws://127.0.0.1:1".into(), + "agent".into(), + None, + )); + let mut owner = Self { + server, + rx, + cmd, + task, + ch: Uuid::new_v4(), + }; + owner.subscribe().await; + owner + } + + async fn subscribe(&mut self) { + self.cmd + .send(RelayCommand::Subscribe { + channel_id: self.ch, + filter: test_channel_filter(), + replay_since: Some(1000), + }) + .await + .unwrap(); + let req = self.request(Duration::from_secs(2)).await; + assert_eq!(req[1], channel_sub_id(self.ch)); + } + + async fn event(&mut self, n: u64) { + self.server + .send(Message::Text( + json!([ + "EVENT", + channel_sub_id(self.ch), + fixture_event(self.ch, n, 9) + ]) + .to_string() + .into(), + )) + .await + .unwrap(); + } + + async fn request(&mut self, duration: Duration) -> Value { + let frame = socket_frame(&mut self.server, duration) + .await + .expect("recovery not woken"); + let req: Value = serde_json::from_str(frame.to_text().unwrap()).unwrap(); + assert_eq!(req[0], "REQ"); + req + } + + async fn shutdown(self) { + self.cmd.send(RelayCommand::Shutdown).await.unwrap(); + timeout(Duration::from_secs(1), self.task) + .await + .unwrap() + .unwrap(); + } +} + +#[tokio::test] +async fn capacity_flapping_cannot_storm_or_delay_an_allowed_attempt() { + let mut owner = Owner::new(1).await; + owner.event(0).await; + owner.event(1).await; + assert_eq!(review_barrier(&mut owner.server).await, 0); + owner.rx.recv().await.unwrap(); + let first = owner.request(Duration::from_millis(500)).await; + let first_at = tokio::time::Instant::now(); + assert_eq!(first[2]["since"], 996); + // New loss, then rapid full/empty transitions during the attempt cooldown. + // No socket activity or capacity transition may reset or bypass that bound. + for n in 1..=20 { + owner.event(n * 2).await; + owner.event(n * 2 + 1).await; + assert_eq!(review_barrier(&mut owner.server).await, 0); + owner.rx.recv().await.unwrap(); + assert!(socket_frame(&mut owner.server, Duration::from_millis(10)) + .await + .is_none()); + } + let req = owner.request(Duration::from_secs(6)).await; + assert_eq!(req[1], channel_sub_id(owner.ch)); + // Arrival timestamps approximate send completion; leave tolerance for TCP. + assert!(first_at.elapsed() >= Duration::from_millis(4_900)); + assert!(first_at.elapsed() < Duration::from_secs(6)); + assert_eq!(req[2]["since"], 998); + assert!(socket_frame(&mut owner.server, Duration::from_millis(100)) + .await + .is_none()); + owner.shutdown().await; +} + +#[tokio::test] +async fn partial_capacity_wait_does_not_steal_live_slots_and_cancels_on_unsubscribe() { + let mut owner = Owner::new(5).await; // odd capacity: threshold rounds UP to 3 + for n in 0..6 { + owner.event(n).await; + } + assert_eq!(review_barrier(&mut owner.server).await, 0); + owner.rx.recv().await.unwrap(); // partial reservation, insufficient for replay + assert!(socket_frame(&mut owner.server, Duration::from_millis(30)) + .await + .is_none()); + owner.event(6).await; + assert_eq!(review_barrier(&mut owner.server).await, 0); + assert_eq!( + owner.rx.len(), + 5, + "select must release partial permits BEFORE try_send" + ); + for _ in 0..2 { + owner.rx.recv().await.unwrap(); + } + assert!(socket_frame(&mut owner.server, Duration::from_millis(30)) + .await + .is_none()); + owner.rx.recv().await.unwrap(); // exactly three slots free, prompt capacity wake + let req = owner.request(Duration::from_millis(500)).await; + assert_eq!(req[2]["since"], 1000); + assert_eq!( + owner + .rx + .recv() + .await + .unwrap() + .unwrap() + .event + .created_at + .as_secs(), + 1004 + ); + assert_eq!( + owner + .rx + .recv() + .await + .unwrap() + .unwrap() + .event + .created_at + .as_secs(), + 1006 + ); + + // Wait out cooldown then create another pending loss and partial reservation. + tokio::time::sleep(recovery::RECOVERY_INTERVAL).await; + for n in 7..13 { + owner.event(n).await; + } + assert_eq!(review_barrier(&mut owner.server).await, 0); + owner.rx.recv().await.unwrap(); + assert!(socket_frame(&mut owner.server, Duration::from_millis(30)) + .await + .is_none()); + owner + .cmd + .send(RelayCommand::Unsubscribe { + channel_id: owner.ch, + }) + .await + .unwrap(); + let close = socket_frame(&mut owner.server, Duration::from_secs(1)) + .await + .unwrap(); + let close: Value = serde_json::from_str(close.to_text().unwrap()).unwrap(); + assert_eq!(close[0], "CLOSE"); + while owner.rx.try_recv().is_ok() {} + assert!(socket_frame(&mut owner.server, Duration::from_millis(100)) + .await + .is_none()); + owner.subscribe().await; + assert!(socket_frame(&mut owner.server, Duration::from_millis(100)) + .await + .is_none()); + // A re-added intent can record and recover fresh loss immediately. + for n in 20..26 { + owner.event(n).await; + } + assert_eq!(review_barrier(&mut owner.server).await, 0); + while owner.rx.try_recv().is_ok() {} + let req = owner.request(Duration::from_millis(500)).await; + assert_eq!(req[2]["since"], 1020); + owner.shutdown().await; +} + +#[tokio::test] +async fn shutdown_and_transport_loss_cancel_a_capacity_wait() { + let mut owner = Owner::new(1).await; + owner.event(0).await; + owner.event(1).await; + assert_eq!(review_barrier(&mut owner.server).await, 0); + // Full queue cannot block commands or processing an actual socket close. + owner.server.close(None).await.unwrap(); + owner.shutdown().await; + let mut owner = Owner::new(1).await; + owner.event(0).await; + owner.event(1).await; + assert_eq!(review_barrier(&mut owner.server).await, 0); + owner.shutdown().await; +} + +#[tokio::test] +async fn readiness_gate_ownership_and_attempt_deadlines_are_not_polling_ticks() { + let (mut client, mut server) = test_ws_pair().await; + let mut state = BgState::new(); + let ch = Uuid::new_v4(); + seed_test_subscription(&mut state, ch); + let (tx, mut rx) = mpsc::channel(4); + assert!(recovery::ready_at(&mut state).is_none()); + state.channel_dropped_since.insert(ch, 700); + state + .rate_limited_pending + .insert(ch, tokio::time::Instant::now()); + assert!(recovery::ready_at(&mut state).is_none()); + state.rate_limited_pending.clear(); + state.resubscribe_retry.insert(ch); + assert!(recovery::ready_at(&mut state).is_none()); + state.resubscribe_retry.clear(); + state.rate_limit_gate = Some(tokio::time::Instant::now() + Duration::from_millis(80)); + let at = recovery::ready_at(&mut state); + assert_eq!(at, state.rate_limit_gate); + assert!(timeout(Duration::from_millis(20), recovery::ready(&tx, at)) + .await + .is_err()); + timeout(Duration::from_millis(200), recovery::ready(&tx, at)) + .await + .unwrap(); + recovery::recover_one(&mut client, &mut state, &tx, "agent").await; + next_test_frame(&mut server).await; + state.channel_dropped_since.insert(ch, 800); + let at = recovery::ready_at(&mut state).unwrap(); + let remaining = at.saturating_duration_since(tokio::time::Instant::now()); + assert!(remaining > Duration::from_millis(4900)); + // Neither new loss nor an intervening gate shorter than cooldown delays it. + state.rate_limit_gate = Some(tokio::time::Instant::now() + Duration::from_millis(10)); + assert_eq!(recovery::ready_at(&mut state), Some(at)); + state.rate_limit_gate = Some(at + Duration::from_secs(1)); + assert_eq!(recovery::ready_at(&mut state), state.rate_limit_gate); + advance_clock(Duration::from_secs(6)).await; + // Cancellation releases partial permits. No hidden reservation survives it. + for _ in 0..3 { + tx.try_send(None).unwrap(); + } + assert!(timeout( + Duration::from_millis(20), + recovery::ready(&tx, recovery::ready_at(&mut state)) + ) + .await + .is_err()); + assert_eq!(tx.capacity(), 1); + rx.recv().await.unwrap(); + timeout( + Duration::from_millis(100), + recovery::ready(&tx, recovery::ready_at(&mut state)), + ) + .await + .unwrap(); + assert_eq!(tx.capacity(), 2); + drop(rx); + assert!(timeout( + Duration::from_millis(20), + recovery::ready(&tx, recovery::ready_at(&mut state)) + ) + .await + .is_err()); +} + +#[tokio::test] +async fn readiness_uses_channel_wakes_without_idle_churn_or_lost_capacity() { + use std::future::Future; + use std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }; + use std::task::{Context, Wake, Waker}; + #[derive(Default)] + struct Wakes(AtomicUsize); + impl Wake for Wakes { + fn wake(self: Arc) { + self.0.fetch_add(1, Ordering::SeqCst); + } + fn wake_by_ref(self: &Arc) { + self.0.fetch_add(1, Ordering::SeqCst); + } + } + let wakes = Arc::new(Wakes::default()); + let waker = Waker::from(wakes.clone()); + let mut cx = Context::from_waker(&waker); + let (tx, mut rx) = mpsc::channel(4); + for _ in 0..4 { + tx.try_send(None).unwrap(); + } + let mut idle = Box::pin(recovery::ready(&tx, None)); + assert!(idle.as_mut().poll(&mut cx).is_pending()); + rx.recv().await.unwrap(); + rx.recv().await.unwrap(); + assert_eq!( + wakes.0.load(Ordering::SeqCst), + 0, + "no loss: no capacity subscription" + ); + drop(idle); + // Capacity freed before registration cannot be lost; ready on first poll. + let now = Some(tokio::time::Instant::now()); + let mut ready = Box::pin(recovery::ready(&tx, now)); + assert!(ready.as_mut().poll(&mut cx).is_ready()); + assert_eq!(tx.capacity(), 2, "successful readiness returns all permits"); + drop(ready); + for _ in 0..2 { + tx.try_send(None).unwrap(); + } + let mut ready = Box::pin(recovery::ready(&tx, now)); + assert!(ready.as_mut().poll(&mut cx).is_pending()); + assert_eq!(wakes.0.load(Ordering::SeqCst), 0); + rx.recv().await.unwrap(); + assert_eq!( + wakes.0.load(Ordering::SeqCst), + 0, + "below threshold: do not wake" + ); + rx.recv().await.unwrap(); + assert_eq!( + wakes.0.load(Ordering::SeqCst), + 1, + "threshold: channel wakes its waiter" + ); + assert!(ready.as_mut().poll(&mut cx).is_ready()); + assert_eq!(tx.capacity(), 2); + drop(ready); + drop(rx); + let mut closed = Box::pin(recovery::ready(&tx, now)); + let before = wakes.0.load(Ordering::SeqCst); + assert!(closed.as_mut().poll(&mut cx).is_pending()); + assert_eq!( + wakes.0.load(Ordering::SeqCst), + before, + "closed: no self-wake loop" + ); +} diff --git a/crates/buzz-agent/Cargo.toml b/crates/buzz-agent/Cargo.toml index f883c2ae68..7b3a55af0b 100644 --- a/crates/buzz-agent/Cargo.toml +++ b/crates/buzz-agent/Cargo.toml @@ -48,11 +48,11 @@ path = "tests/bin/auth_worker.rs" # the token cache used by inference and the desktop model picker. buzz-model-catalog = { path = "../buzz-model-catalog" } # Keep all GDK crates on the exact same Goose revision so shared types stay unified. -goose-agent = { git = "https://github.com/aaif-goose/goose", rev = "5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" } -goose-provider-types = { git = "https://github.com/aaif-goose/goose", rev = "5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" } -goose-context-management = { git = "https://github.com/aaif-goose/goose", rev = "5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" } -goose-sdk-types = { git = "https://github.com/aaif-goose/goose", rev = "5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" } -goose-providers = { git = "https://github.com/aaif-goose/goose", rev = "5a9a13b72aaf8f9aa17ce064bd4d4d761d656982" } +goose-agent = { git = "https://github.com/aaif-goose/goose", rev = "2f2c92c24c1438cef142476ee6507df82e6c3fba" } +goose-provider-types = { git = "https://github.com/aaif-goose/goose", rev = "2f2c92c24c1438cef142476ee6507df82e6c3fba" } +goose-context-management = { git = "https://github.com/aaif-goose/goose", rev = "2f2c92c24c1438cef142476ee6507df82e6c3fba" } +goose-sdk-types = { git = "https://github.com/aaif-goose/goose", rev = "2f2c92c24c1438cef142476ee6507df82e6c3fba" } +goose-providers = { git = "https://github.com/aaif-goose/goose", rev = "2f2c92c24c1438cef142476ee6507df82e6c3fba" } tokio-util = { version = "0.7", features = ["rt"] } futures = "0.3" anyhow = "1" diff --git a/crates/buzz-agent/README.md b/crates/buzz-agent/README.md index 7847a0905a..60429942bd 100644 --- a/crates/buzz-agent/README.md +++ b/crates/buzz-agent/README.md @@ -255,7 +255,7 @@ lifecycle hook — see [MCP_DRIVEN_HOOKS.md](../../docs/MCP_DRIVEN_HOOKS.md). | Block Gateway | `openai` | `POST {base}/chat/completions` | gpt-5, claude | | OpenRouter | `openrouter` | `POST {base}/chat/completions` | anything they route (extended-thinking replay, provider-agnostic tool calling) | | Databricks | `databricks` | `POST {host}/serving-endpoints/{model}/invocations` | goose-claude-4-6-sonnet | -| Databricks AI Gateway v2 | `databricks_v2` | `POST {host}/ai-gateway/{provider}/v1/...` | workspace endpoints and Unity Catalog model-service FQNs; UC FQNs use MLflow Chat Completions | +| Databricks AI Gateway v2 | `databricks_v2` | `POST {host}/ai-gateway/{provider}/v1/...` | workspace endpoints and Unity Catalog model-service FQNs; UC GPT-5+ services use OpenAI Responses; other UC FQNs use MLflow Chat Completions | The optional `DATABRICKS_MODEL_FILTER` applies only to model discovery. Each comma-separated entry is trimmed and matched against the complete raw ID with case-sensitive `*` (zero or more characters) and `?` (one Unicode character) semantics; patterns are OR-ed. Unset or blank preserves the full authenticated catalog. A nonblank value containing no usable patterns is rejected. This controls picker visibility only; Databricks and Unity Catalog permissions remain the authorization boundary. A filtered-empty result is authoritative and does not restore the built-in fallback models. diff --git a/crates/buzz-model-catalog/src/model_capabilities.rs b/crates/buzz-model-catalog/src/model_capabilities.rs index 53f2d290ff..18a4726012 100644 --- a/crates/buzz-model-catalog/src/model_capabilities.rs +++ b/crates/buzz-model-catalog/src/model_capabilities.rs @@ -292,8 +292,8 @@ fn prefix_matches(token: &str, s: &str) -> bool { /// /// Databricks Unity Catalog model-service names are catalog data, not model /// family hints. Both capability interpreters use this shape check before -/// family matching so suffixes such as `kimi-k3` cannot inherit endpoint -/// capabilities accidentally. +/// family matching so services cannot inherit endpoint capabilities accidentally. +/// GPT-5+ services have a route-only Responses exception. pub(crate) fn is_databricks_model_service_fqn(model: &str) -> bool { let mut components = model.split('.'); let (Some(catalog), Some(schema), Some(service)) = @@ -308,16 +308,35 @@ pub(crate) fn is_databricks_model_service_fqn(model: &str) -> bool { }) && components.next().is_none() } +/// Route GPT-5+ UC services to Responses without borrowing endpoint effort facts. +/// Match the first family token in the service only, preserving the existing +/// boundary semantics (e.g. `claude-gpt-5` is not a GPT service). +fn fqn_requires_responses(model: &str) -> bool { + let Some(service) = model.rsplit('.').next() else { + return false; + }; + let lower = service.to_ascii_lowercase(); + let stripped = strip_catalog_prefix(&lower, &manifest().family_tokens); + let Some(version) = stripped.strip_prefix("gpt-") else { + return false; + }; + let digits = version.bytes().take_while(u8::is_ascii_digit).count(); + let (major, suffix) = version.split_at(digits); + if suffix.starts_with(|c: char| c.is_ascii_alphanumeric()) { + return false; + } + major.parse::().is_ok_and(|major| major >= 5) +} + /// Resolve the capability profile for a `(provider, raw_model_id)` pair. pub fn resolve(provider: &str, raw_model_id: &str) -> CapabilityResult { let m = manifest(); let canon = canonical_provider(provider); let blank = raw_model_id.trim().is_empty(); - // Unity Catalog FQNs are neutral model-service identities. Resolve them - // through the concrete-unknown fallback before any suffix can match a - // provider family rule. Routing and effort normalization then share this - // one answer in Rust and TypeScript. + // FQNs keep neutral effort capabilities, but GPT-5+ service names need + // Responses for tools with reasoning. Only inspect the service component: + // catalog/schema names must never choose a model protocol. let model_service_fqn = canon == "databricks_v2" && is_databricks_model_service_fqn(raw_model_id); @@ -394,7 +413,11 @@ pub fn resolve(provider: &str, raw_model_id: &str) -> CapabilityResult { thinking_mode: state.thinking_mode, supported_efforts: &state.supported_efforts, default_effort: state.default_effort, - databricks_v2_wire_route: state.databricks_v2_wire_route, + databricks_v2_wire_route: if model_service_fqn && fqn_requires_responses(raw_model_id) { + DatabricksV2Route::OpenaiResponses + } else { + state.databricks_v2_wire_route + }, normalization_policy: state.normalization_policy, registry_label: None, } @@ -724,6 +747,25 @@ mod tests { Q::Vector { id: "boundary-claude-3-digit-run-anthropic-probe", provider: "anthropic", raw_model_id: "claude-35", note: Some("Probes whether the claude-3 prefix binds a longer digit run ('35').") }, Q::Vector { id: "boundary-claude-opus-4-70-anthropic-probe", provider: "anthropic", raw_model_id: "claude-opus-4-70", note: Some("Probes whether the claude-opus-4-7 prefix binds a longer digit run ('70').") }, Q::Vector { id: "boundary-gpt-5-1234-openai-probe", provider: "openai", raw_model_id: "gpt-5-1234", note: Some("Probes a 4-digit run after the gpt-5 stem.") }, + Q::Section { group: "Databricks FQN GPT-5+ Responses routing", note: Some("Only the service component selects Responses; effort capabilities remain neutral.") }, + Q::Vector { id: "dbv2-fqn-responses-0", provider: "databricks_v2", raw_model_id: "catalog.schema.goose-gpt-6-astra", note: None }, + Q::Vector { id: "dbv2-fqn-responses-1", provider: "databricks_v2", raw_model_id: "catalog.schema.goose-gpt-5", note: None }, + Q::Vector { id: "dbv2-fqn-responses-2", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-5-5", note: None }, + Q::Vector { id: "dbv2-fqn-responses-3", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-10", note: None }, + Q::Vector { id: "dbv2-fqn-responses-4", provider: "databricks_v2", raw_model_id: "catalog.schema.GOOSE-GPT-6-ASTRA", note: None }, + Q::Vector { id: "dbv2-fqn-responses-5", provider: "databricks_v2", raw_model_id: "gpt-6.schema.other", note: None }, + Q::Vector { id: "dbv2-fqn-responses-6", provider: "databricks_v2", raw_model_id: "catalog.gpt-5.other", note: None }, + Q::Vector { id: "dbv2-fqn-responses-7", provider: "databricks_v2", raw_model_id: "catalog.schema.claude-gpt-6", note: None }, + Q::Vector { id: "dbv2-fqn-responses-8", provider: "databricks_v2", raw_model_id: "catalog.schema.my-gpt-6-astra", note: None }, + Q::Vector { id: "dbv2-fqn-responses-9", provider: "databricks_v2", raw_model_id: "catalog.schema.mygpt-6-astra", note: None }, + Q::Vector { id: "dbv2-fqn-responses-10", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-4", note: None }, + Q::Vector { id: "dbv2-fqn-responses-11", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-4o", note: None }, + Q::Vector { id: "dbv2-fqn-responses-12", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-6x", note: None }, + Q::Vector { id: "dbv2-fqn-responses-13", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-oss-120b", note: None }, + Q::Vector { id: "dbv2-fqn-responses-14", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-", note: None }, + Q::Vector { id: "dbv2-fqn-responses-15", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-4294967296", note: None }, + Q::Vector { id: "dbv2-fqn-responses-16", provider: "databricks_v2", raw_model_id: "catalog.schema.gpt-6", note: None }, + Q::Vector { id: "dbv2-fqn-responses-17", provider: "databricks_v2", raw_model_id: "catalog.schema.kimi-k3", note: None }, Q::Section { group: "Databricks UC model-family humanization probes (#6918 follow-up)", note: Some("Exact-record and UC-FQN strip probes for the Gemini/DeepSeek/GLM/Grok/Llama/Qwen/Gemma/Inkling families surfaced by UC discovery.") }, Q::Vector { id: "dbv2-gemini-3-1-flash-image-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gemini-3-1-flash-image", note: Some("Probes the Gemini 3.1 Flash Image endpoint record and label.") }, Q::Vector { id: "dbv2-gemini-3-5-flash-exact-record-probe", provider: "databricks_v2", raw_model_id: "databricks-gemini-3-5-flash", note: Some("Probes the Gemini 3.5 Flash endpoint record and label.") }, @@ -844,7 +886,7 @@ mod tests { } #[test] - fn corpus_has_exactly_140_executable_vectors() { + fn corpus_has_exactly_158_executable_vectors() { // Locks the vector count so a silent INPUTS edit can't quietly drop // coverage; must equal the gate in the TS harness // (modelCapabilitiesCorpus.test.mjs). @@ -853,7 +895,7 @@ mod tests { .filter(|q| matches!(q, Q::Vector { .. })) .count(); assert_eq!( - vectors, 140, + vectors, 158, "corpus executable-vector count changed; update this gate deliberately" ); } diff --git a/crates/buzz-model-catalog/tests/fqn_capabilities.rs b/crates/buzz-model-catalog/tests/fqn_capabilities.rs new file mode 100644 index 0000000000..9bf1e44c9b --- /dev/null +++ b/crates/buzz-model-catalog/tests/fqn_capabilities.rs @@ -0,0 +1,63 @@ +//! UC route selection must change only the route, never effort or model identity. +use buzz_model_catalog::model_capabilities::{resolve, DatabricksV2Route}; + +#[test] +fn gpt_fqn_route_preserves_neutral_capabilities() { + let fallback = resolve("databricks_v2", "catalog.schema.unknown"); + for model in [ + "catalog.schema.goose-gpt-6-astra", + "catalog.schema.gpt-5", + "catalog.schema.goose-gpt-5-5", + "catalog.schema.gpt-10", + "catalog.schema.GOOSE-GPT-6-ASTRA", + "catalog.schema.team-gpt-6-astra", + ] { + let got = resolve(" DATABRICKS-V2 ", model); + assert_eq!( + got.databricks_v2_wire_route, + DatabricksV2Route::OpenaiResponses, + "{model}" + ); + assert_eq!(got.thinking_mode, fallback.thinking_mode, "{model}"); + assert_eq!(got.supported_efforts, fallback.supported_efforts, "{model}"); + assert_eq!(got.default_effort, fallback.default_effort, "{model}"); + assert_eq!( + got.normalization_policy, fallback.normalization_policy, + "{model}" + ); + assert_eq!(got.registry_label, None, "{model}"); + } +} + +#[test] +fn unrelated_fqns_do_not_select_responses() { + for model in [ + "gpt-6.schema.other", + "catalog.gpt-5.other", + "catalog.schema.claude-gpt-6", + "catalog.schema.mygpt-6-astra", + "catalog.schema.gpt-4", + "catalog.schema.gpt-4o", + "catalog.schema.gpt-6x", + "catalog.schema.gpt-oss-120b", + "catalog.schema.gpt-", + "catalog.schema.gpt-6", + "catalog.schema.gpt-4294967296", + "catalog.schema.kimi-k3", + ] { + assert_eq!( + resolve("databricks_v2", model).databricks_v2_wire_route, + DatabricksV2Route::MlflowChat, + "{model}" + ); + } + // The new rule is not an endpoint-family or cross-provider capability change. + assert_eq!( + resolve("databricks_v2", "goose-gpt-6-astra").databricks_v2_wire_route, + DatabricksV2Route::MlflowChat + ); + assert_eq!( + resolve("openai", "catalog.schema.goose-gpt-6-astra").databricks_v2_wire_route, + DatabricksV2Route::NotApplicable + ); +} diff --git a/crates/buzz-relay/Cargo.toml b/crates/buzz-relay/Cargo.toml index deb2e7e16a..d022bcab01 100644 --- a/crates/buzz-relay/Cargo.toml +++ b/crates/buzz-relay/Cargo.toml @@ -86,8 +86,8 @@ async-compression = { version = "0.4.42", features = ["tokio", "gzip"] } dev = ["buzz-auth/dev"] [dev-dependencies] -mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.75.1", package = "mesh-llm-sdk", default-features = false, features = ["client", "serving"] } -mesh-llm-host-runtime = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.75.1", package = "mesh-llm-host-runtime", default-features = false, features = ["dynamic-native-runtime"] } +mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.76.0-rc9", package = "mesh-llm-sdk", default-features = false, features = ["client", "serving"] } +mesh-llm-host-runtime = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.76.0-rc9", package = "mesh-llm-host-runtime", default-features = false, features = ["dynamic-native-runtime"] } # Relay-driven mesh lifecycle smoke (examples/mesh_relay_lifecycle_smoke.rs): # the relay client for discovery notes and the exact ed25519 the mesh owner # keys use for binding verification. diff --git a/desktop/package.json b/desktop/package.json index 914b759113..fb8e313871 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -1,7 +1,7 @@ { "name": "buzz", "private": true, - "version": "0.5.22", + "version": "0.5.23", "type": "module", "scripts": { "dev": "vite", diff --git a/desktop/scripts/tauri-command.mjs b/desktop/scripts/tauri-command.mjs index dc1d8691e9..bc53d607e7 100644 --- a/desktop/scripts/tauri-command.mjs +++ b/desktop/scripts/tauri-command.mjs @@ -36,11 +36,28 @@ export function runTauriCommand(args) { // Tauri runs beforeBuildCommand and then consumes frontendDist. Give the // entire invocation a private directory so concurrent OSS/internal packages // cannot replace one another's assets between those two operations. - const invocationRoot = mkdtempSync( + let invocationRoot = mkdtempSync( path.join(tmpdir(), "buzz-tauri-package-assets-"), ); + // `frontendDist` deserializes into an untagged enum whose first variant is a + // URL, and a Windows absolute path parses as one -- `C:` becomes the scheme. + // Tauri then embeds zero assets, exits 0, and the app boots to + // ERR_FILE_NOT_FOUND. Hand it a path relative to the config's own directory, + // which can never parse as a URL. If the temp dir is on another drive there + // is no relative form, so put the scratch root beside the config instead. + const configDir = path.join(desktopRoot, "src-tauri"); + const relativeTo = (root) => + path.relative(configDir, path.join(root, "dist")); + if (path.isAbsolute(relativeTo(invocationRoot))) { + rmSync(invocationRoot, { recursive: true, force: true }); + invocationRoot = mkdtempSync( + path.join(desktopRoot, ".buzz-tauri-package-assets-"), + ); + } const frontendDist = path.join(invocationRoot, "dist"); - const outputOverride = JSON.stringify({ build: { frontendDist } }); + const outputOverride = JSON.stringify({ + build: { frontendDist: relativeTo(invocationRoot) }, + }); try { const delimiterIndex = args.indexOf("--"); diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index ea68f05559..952f08ef83 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -52,13 +52,13 @@ dependencies = [ [[package]] name = "aes" -version = "0.9.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" +checksum = "f1fc76eaeac4c9164506c466d4ffdd8ec9d0c5bf57ee97177c4d8eceb3a0e138" dependencies = [ "cipher 0.5.2", "cpubits", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", ] [[package]] @@ -91,9 +91,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.5" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -105,7 +105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda177466b9524d59f1b12f0dd30b68696788e9992a7e959021c4a0ed96fcf59" dependencies = [ "base64 0.22.1", - "bitflags 2.13.1", + "bitflags 2.13.0", "home", "libc", "log", @@ -150,7 +150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d" dependencies = [ "alsa-sys", - "bitflags 2.13.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "libc", ] @@ -167,9 +167,9 @@ dependencies = [ [[package]] name = "android_system_properties" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] @@ -290,6 +290,12 @@ dependencies = [ "password-hash", ] +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + [[package]] name = "arrayvec" version = "0.7.8" @@ -389,7 +395,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -418,20 +424,20 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.92" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] name = "async-utility" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "188f83b9a198af8c336e505611edb00d6d2ac5c694241c5a4f9a12316938cfe9" +checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151" dependencies = [ "futures-util", "gloo-timers", @@ -510,12 +516,12 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atomic-write-file" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae67d5c03ee972c101a1d8db3ddbf8a9c819ad1ea9d6fd9cd385605547b60edb" +checksum = "84790c55b5704b0d35130bf16a4ce22a8e70eb0ea773522557524d9a4852663d" dependencies = [ - "nix 0.31.3", - "rand 0.10.2", + "nix 0.30.1", + "rand 0.9.4", ] [[package]] @@ -531,7 +537,7 @@ dependencies = [ "serde", "serde_json", "url", - "webpki-roots 1.0.9", + "webpki-roots 1.0.8", ] [[package]] @@ -600,16 +606,16 @@ dependencies = [ "quick-xml 0.38.4", "rust-ini", "serde", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "url", ] [[package]] name = "aws-lc-rs" -version = "1.18.1" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" +checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" dependencies = [ "aws-lc-sys", "zeroize", @@ -617,9 +623,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.45.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" +checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" dependencies = [ "cc", "cmake", @@ -634,7 +640,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "838b36c8dc927b6db1b6c6b8f5d05865f2213550b9e83bf92fa99ed6525472c0" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -664,7 +670,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sha1 0.10.7", + "sha1 0.10.6", "sync_wrapper", "tokio", "tokio-tungstenite 0.29.0", @@ -701,7 +707,7 @@ checksum = "7aa268c23bfbbd2c4363b9cd302a4f504fb2a9dfe7e3451d66f35dd392e20aca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -806,13 +812,20 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitcoin-consensus-encoding" -version = "1.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6712f9c6fd6785b3b270884e57c441c403dc5d7e19ca45368c97c7a1de3000ec" +checksum = "b2d6094e2a1ba3c93b5a596fe5a10d1a10c3c6e06785cde89f693a044c01aa40" dependencies = [ - "bitcoin-internals", - "hex-conservative 1.2.0", - "serde", + "bitcoin-internals 0.5.0", +] + +[[package]] +name = "bitcoin-internals" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a30a22d1f112dde8e16be7b45c63645dc165cef254f835b3e1e9553e485cfa64" +dependencies = [ + "hex-conservative 0.3.2", ] [[package]] @@ -837,7 +850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2" dependencies = [ "bitcoin-io", - "hex-conservative 0.2.3", + "hex-conservative 0.2.2", "serde", ] @@ -848,7 +861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5304e53726dbe5f93141535e102ed97b5bf4714fbecefdda8f9fb98d7fdaff0e" dependencies = [ "bitcoin-consensus-encoding", - "bitcoin-internals", + "bitcoin-internals 0.6.0", "hex-conservative 1.2.0", "serde", ] @@ -861,9 +874,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "serde_core", ] @@ -879,15 +892,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.7" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ + "arrayref", "arrayvec", "cc", "cfg-if 1.0.4", - "constant_time_eq 0.4.2", - "cpufeatures 0.3.1", + "constant_time_eq", + "cpufeatures 0.3.0", ] [[package]] @@ -929,9 +943,9 @@ dependencies = [ [[package]] name = "blocking" -version = "1.7.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ "async-channel", "async-task", @@ -948,25 +962,27 @@ checksum = "e79769241dcd44edf79a732545e8b5cec84c247ac060f5252cd51885d093a8fc" [[package]] name = "bon" -version = "3.10.0" +version = "3.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3fac94a66da67200398458a25412bcc3f9b6443b5119a6cad9cf3ccfcd8cc6" +checksum = "a602c73c7b0148ec6d12af6fd5cc7a46e2eacc8878271a999abac56eed12f561" dependencies = [ "bon-macros", + "rustversion", ] [[package]] name = "bon-macros" -version = "3.10.0" +version = "3.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4654961ad0494e4774c5c60b4cb4cd0ae9b9d92d039d901638b1dba97ebebf5" +checksum = "6dee98b0db6a962de883bf5d20362dee4d7ca0d12fe39a7c6c73c844e1cd7c1f" dependencies = [ - "darling 0.24.1", + "darling 0.23.0", "ident_case", - "prettyplease 0.3.0", + "prettyplease", "proc-macro2", "quote", - "syn 3.0.4", + "rustversion", + "syn 2.0.118", ] [[package]] @@ -1001,9 +1017,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.13.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" dependencies = [ "memchr", "regex-automata", @@ -1024,14 +1040,14 @@ dependencies = [ "chrono", "hex", "hmac 0.13.0", - "nostr 0.44.8", + "nostr 0.44.7", "percent-encoding", "rand 0.10.2", "serde", "serde_json", "sha2 0.11.0", "subtle", - "thiserror 2.0.20", + "thiserror 2.0.18", "url", "uuid", "zeroize", @@ -1039,7 +1055,7 @@ dependencies = [ [[package]] name = "buzz-desktop" -version = "0.5.22" +version = "0.5.23" dependencies = [ "anyhow", "arboard", @@ -1079,7 +1095,7 @@ dependencies = [ "mesh-llm-sdk", "mesh-llm-system", "neteq", - "nostr 0.44.8", + "nostr 0.44.7", "notify-rust", "objc2", "objc2-app-kit", @@ -1148,14 +1164,14 @@ dependencies = [ "imagesize", "infer", "mp4", - "nostr 0.44.8", + "nostr 0.44.7", "quick-xml 0.38.4", "rust-s3", "serde", "serde_json", "sha2 0.11.0", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tracing", @@ -1192,7 +1208,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -1200,10 +1216,10 @@ name = "buzz-sdk" version = "0.1.0" dependencies = [ "buzz-core", - "nostr 0.44.8", + "nostr 0.44.7", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "uuid", ] @@ -1240,9 +1256,9 @@ name = "buzz-ws-client" version = "0.1.0" dependencies = [ "futures-util", - "nostr 0.44.8", + "nostr 0.44.7", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-tungstenite 0.29.0", "tracing", @@ -1257,9 +1273,9 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" -version = "1.25.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -1292,15 +1308,6 @@ dependencies = [ "libc", ] -[[package]] -name = "bzip2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" -dependencies = [ - "bzip2-sys", -] - [[package]] name = "bzip2" version = "0.6.1" @@ -1326,7 +1333,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cairo-sys-rs", "glib", "libc", @@ -1347,9 +1354,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.5" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0" dependencies = [ "serde_core", ] @@ -1374,7 +1381,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -1407,9 +1414,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.4.4" +version = "1.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "f5d6cac793997bd970000024b2934968efe83b382de4fdcf4fcb46b6ee4ad996" dependencies = [ "find-msvc-tools", "jobserver", @@ -1481,12 +1488,12 @@ dependencies = [ [[package]] name = "chacha20" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "rand_core 0.10.1", ] @@ -1540,9 +1547,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.6" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -1550,9 +1557,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.6" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -1562,14 +1569,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.4" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -1608,7 +1615,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -1634,9 +1641,9 @@ dependencies = [ [[package]] name = "combine" -version = "4.6.8" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "memchr", @@ -1725,19 +1732,13 @@ checksum = "18f12cc9948ed9604230cdddc7c86e270f9401ccbe3c2e98a4378c5e7632212f" [[package]] name = "const_panic" -version = "0.2.17" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9603f79528ece8163c496f8932121cb36cfe46259e9c907bb3d8205139d7caa3" +checksum = "e262cdaac42494e3ae34c43969f9cdeb7da178bdb4b66fa6a1ea2edb4c8ae652" dependencies = [ "typewit", ] -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - [[package]] name = "constant_time_eq" version = "0.4.2" @@ -1755,9 +1756,9 @@ dependencies = [ [[package]] name = "cookie" -version = "0.18.2" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ "time", "version_check", @@ -1765,9 +1766,9 @@ dependencies = [ [[package]] name = "cordyceps" -version = "0.3.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9ab7e0ca1d179628fa0172b2b97203c7fa0cd81be2448bd446fb9559ca9261" +checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" dependencies = [ "loom", "tracing", @@ -1805,7 +1806,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-graphics-types", "foreign-types 0.5.0", @@ -1818,7 +1819,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "libc", ] @@ -1829,7 +1830,7 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d5d7dca3ebcf65a035582c9ad4385371a9d9ee6537474d2a278f4e1e475bb58" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "libc", "objc2-audio-toolbox", "objc2-core-audio", @@ -1893,33 +1894,18 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" - [[package]] name = "crc32fast" -version = "1.5.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if 1.0.4", ] @@ -1970,7 +1956,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "crossterm_winapi", "mio", "parking_lot", @@ -1986,7 +1972,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "crossterm_winapi", "derive_more", "document-features", @@ -2031,7 +2017,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array", - "rand_core 0.10.1", ] [[package]] @@ -2093,7 +2078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2118,9 +2103,9 @@ dependencies = [ [[package]] name = "ctor" -version = "1.0.13" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914a755b7c2d4af2bdcff7ce1739e2db9a1b81a9b07123d8015786ae03c0980d" +checksum = "fb22e947478ccf9dc44d8922042c677a63fbb88f2cb468521d1145816e5087cb" dependencies = [ "link-section", "linktime-proc-macro", @@ -2184,12 +2169,12 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "5.0.0" +version = "5.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23" +checksum = "4f359e08ca85e7bd759e1fd933ff2bccd81864c60a8fba0e259c7f822b0924bf" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "curve25519-dalek-derive", "digest 0.11.3", "fiat-crypto 0.3.0", @@ -2208,7 +2193,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2231,16 +2216,6 @@ dependencies = [ "darling_macro 0.23.0", ] -[[package]] -name = "darling" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" -dependencies = [ - "darling_core 0.24.1", - "darling_macro 0.24.1", -] - [[package]] name = "darling_core" version = "0.20.11" @@ -2252,7 +2227,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2265,20 +2240,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.119", -] - -[[package]] -name = "darling_core" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" -dependencies = [ - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -2289,7 +2251,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2300,18 +2262,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.119", -] - -[[package]] -name = "darling_macro" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" -dependencies = [ - "darling_core 0.24.1", - "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -2331,15 +2282,15 @@ checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" [[package]] name = "data-encoding" -version = "2.11.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "data-encoding-macro" -version = "0.1.21" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6a127ecbb3c4632e1525380e04c0c3fcf8dcb44d32a79ea290d8a36906edcd8" +checksum = "3259c913752a86488b501ed8680446a5ed2d5aeac6e596cb23ba3800768ea32c" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -2347,12 +2298,12 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.19" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54e03a951783e8b327515db3f2a2fd0e3bed362a96b066f341ce66ed49b4ead" +checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" dependencies = [ "data-encoding", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -2391,37 +2342,6 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2" -[[package]] -name = "defmt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" -dependencies = [ - "bitflags 1.3.2", - "defmt-macros", -] - -[[package]] -name = "defmt-macros" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" -dependencies = [ - "defmt-parser", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "defmt-parser" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" -dependencies = [ - "thiserror 2.0.20", -] - [[package]] name = "deltae" version = "0.3.2" @@ -2456,7 +2376,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2477,7 +2397,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2487,7 +2407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2509,7 +2429,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.119", + "syn 2.0.118", "unicode-xid", ] @@ -2570,7 +2490,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -2578,13 +2498,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -2607,7 +2527,7 @@ checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2702,9 +2622,9 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "earshot" -version = "1.2.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afea66474c4036a7e5fa4b072a3b0a09cd0b01f00134da3115d76b7cc5899f03" +checksum = "7984231f8b4c72eb3b88c70040dc1e4ff6803fa9169e93c0ac465942d74fa36a" [[package]] name = "ed25519" @@ -2723,7 +2643,7 @@ version = "3.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60" dependencies = [ - "curve25519-dalek 5.0.0", + "curve25519-dalek 5.0.0-rc.0", "ed25519", "rand_core 0.10.1", "serde", @@ -2735,9 +2655,9 @@ dependencies = [ [[package]] name = "either" -version = "1.18.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "embed-resource" @@ -2748,7 +2668,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", "vswhom", "winreg 0.55.0", ] @@ -2788,13 +2708,13 @@ checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" [[package]] name = "enum-assoc" -version = "1.4.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0590c4a94da3372e83493b956755a6e2266830b6e4e3b101afe66e3f39477b91" +checksum = "3ed8956bd5c1f0415200516e78ff07ec9e16415ade83c056c230d7b7ea0d55b7" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -2815,7 +2735,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -2847,9 +2767,9 @@ dependencies = [ [[package]] name = "error-code" -version = "3.4.0" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5343afd4a8365a643ac588dab4cf234a190c7f6c88c9f6dd6ffe00837661b7" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" [[package]] name = "esaxx-rs" @@ -2868,10 +2788,11 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.2" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ + "concurrent-queue", "parking", "pin-project-lite", ] @@ -2925,6 +2846,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "faster-hex" version = "0.10.0" @@ -2937,9 +2864,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fax" @@ -3001,9 +2928,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "finl_unicode" @@ -3025,12 +2952,12 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.10" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", - "miniz_oxide 0.9.1", + "miniz_oxide", "zlib-rs", ] @@ -3042,7 +2969,7 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.9", + "spin 0.9.8", ] [[package]] @@ -3084,13 +3011,13 @@ dependencies = [ [[package]] name = "foreign-types-macros" -version = "0.2.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -3132,9 +3059,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -3155,7 +3082,7 @@ dependencies = [ "diatomic-waker", "futures-core", "pin-project-lite", - "spin 0.10.1", + "spin 0.10.0", ] [[package]] @@ -3176,9 +3103,9 @@ checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-executor" -version = "0.3.34" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -3212,7 +3139,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.3", ] [[package]] @@ -3408,11 +3335,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if 1.0.4", - "js-sys", "libc", "r-efi 5.3.0", "wasip2", - "wasm-bindgen", ] [[package]] @@ -3498,7 +3423,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -3507,7 +3432,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "futures-channel", "futures-core", "futures-executor", @@ -3535,7 +3460,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -3550,9 +3475,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.4" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "global-hotkey" @@ -3566,7 +3491,7 @@ dependencies = [ "objc2-app-kit", "once_cell", "serde", - "thiserror 2.0.20", + "thiserror 2.0.18", "windows-sys 0.59.0", "x11rb", "xkeysym", @@ -3574,9 +3499,9 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.20" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", "bstr", @@ -3657,14 +3582,14 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "h2" -version = "0.4.19" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", @@ -3672,7 +3597,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.14.1", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -3781,9 +3706,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -3793,9 +3718,18 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-conservative" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3fef046dca3ca91ee1408a8c1b80ab777e80a4d308d1bf4e7adb3fcb047e08" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex-conservative" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830e599c2904b08f0834ee6337d8fe8f0ed4a63b5d9e7a7f49c0ffa06d08d360" dependencies = [ "arrayvec", ] @@ -3811,18 +3745,16 @@ dependencies = [ [[package]] name = "hf-xet" -version = "1.6.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c237ef4fb0ce1962a5117f8bd8c74454b41629826a9df17d14a1840ca18f0754" +checksum = "2ba6e94f549dbe76ced2c56ada52958e63f9056afabb21f74aae1b5777c8cd5d" dependencies = [ - "anyhow", "async-trait", "bytes", "http", "more-asserts", "serde", - "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tokio_with_wasm", @@ -3855,7 +3787,7 @@ dependencies = [ "jni 0.22.4", "rand 0.10.2", "rustls", - "thiserror 2.0.20", + "thiserror 2.0.18", "tinyvec", "tokio", "tokio-rustls", @@ -3877,7 +3809,7 @@ dependencies = [ "prefix-trie", "rand 0.10.2", "ring", - "thiserror 2.0.20", + "thiserror 2.0.18", "tinyvec", "tracing", "url", @@ -3905,7 +3837,7 @@ dependencies = [ "rustls", "smallvec", "system-configuration", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-rustls", "tracing", @@ -3959,9 +3891,9 @@ dependencies = [ [[package]] name = "http" -version = "1.5.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -3969,9 +3901,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.1.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", @@ -3979,9 +3911,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.5" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", @@ -4010,18 +3942,18 @@ checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" [[package]] name = "hybrid-array" -version = "0.4.14" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "typenum", ] [[package]] name = "hyper" -version = "1.11.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -4052,7 +3984,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.9", + "webpki-roots 1.0.8", ] [[package]] @@ -4145,9 +4077,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", @@ -4159,9 +4091,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -4172,9 +4104,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -4186,17 +4118,16 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", @@ -4207,15 +4138,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.3.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -4337,9 +4268,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.1", @@ -4386,15 +4317,15 @@ dependencies = [ [[package]] name = "instability" -version = "0.3.13" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf84e73fa6f27f299dec58e13223cf70db80da872eb921d4f6138342a0eabc8" +checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" dependencies = [ - "darling 0.24.1", + "darling 0.23.0", "indoc", "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -4424,18 +4355,18 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.12.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" dependencies = [ "serde", ] [[package]] name = "iroh" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329552fad4e46b5ccb4439d5635216f6289eec2c46f3fde4bc732d762694b9e5" +checksum = "460de6bc52163b41b1646931f2897e5ab986f0966ade444467fec25024751a72" dependencies = [ "backon", "blake3", @@ -4484,11 +4415,11 @@ dependencies = [ [[package]] name = "iroh-base" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ccf4cde68a02ef03c0095ab2c031c6adfe508f3bc8e7c258558a027ebe64a8e" +checksum = "6be73e16ee21c923aca9b3121aaa0db936f7c7ecc156ff47b8dac944c68d59a8" dependencies = [ - "curve25519-dalek 5.0.0", + "curve25519-dalek 5.0.0-rc.0", "data-encoding", "data-encoding-macro", "derive_more", @@ -4503,9 +4434,9 @@ dependencies = [ [[package]] name = "iroh-dns" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a41224eb0140a5c519935d4073fc6b236d174080be401f9bf7da126b2ee3aa4" +checksum = "46f6a9b39d18e6345f5c151afd299f2488e2cb5c520fe41b107b6bd3dc4c3349" dependencies = [ "arc-swap", "cfg_aliases 0.2.2", @@ -4549,14 +4480,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "iroh-relay" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5f6f07e2c9b0c4bc82e2864be09f4aea4320165d5316e668616dbc822f428a" +checksum = "24bd586cf927f7b700f56ec3639b53cb5fa901ce284784051ff71092bfbf8193" dependencies = [ "blake3", "bytes", @@ -4593,7 +4524,7 @@ dependencies = [ "tokio-websockets", "tracing", "url", - "webpki-roots 1.0.9", + "webpki-roots 1.0.8", "ws_stream_wasm", ] @@ -4660,59 +4591,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "jiff" -version = "0.2.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" -dependencies = [ - "defmt", - "jiff-core", - "jiff-static", - "jiff-tzdb-platform", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", - "windows-link 0.2.1", -] - -[[package]] -name = "jiff-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" -dependencies = [ - "defmt", -] - -[[package]] -name = "jiff-static" -version = "0.2.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" -dependencies = [ - "jiff-core", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "jiff-tzdb" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" - -[[package]] -name = "jiff-tzdb-platform" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" -dependencies = [ - "jiff-tzdb", -] - [[package]] name = "jni" version = "0.21.1" @@ -4741,7 +4619,7 @@ dependencies = [ "jni-sys 0.4.1", "log", "simd_cesu8", - "thiserror 2.0.20", + "thiserror 2.0.18", "walkdir", "windows-link 0.2.1", ] @@ -4756,7 +4634,7 @@ dependencies = [ "quote", "rustc_version", "simd_cesu8", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -4784,7 +4662,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -4799,9 +4677,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if 1.0.4", "futures-util", @@ -4820,16 +4698,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "json5" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733a844dbd6fef128e98cb4487b887cb55454d92cd9994b1bafe004fabbe670c" -dependencies = [ - "serde", - "ucd-trie", -] - [[package]] name = "jsonptr" version = "0.6.3" @@ -4848,7 +4716,7 @@ checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" dependencies = [ "hashbrown 0.16.1", "portable-atomic", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -4857,7 +4725,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "serde", "unicode-segmentation", ] @@ -4940,9 +4808,9 @@ checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" [[package]] name = "libc" -version = "0.2.189" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libdbus-sys" @@ -4982,9 +4850,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.23" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d8f1ea3f21fd3405dcaf6c9b5c1630af9afc422d9073ea39c5f6d6c772e08ed" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] @@ -5002,24 +4870,24 @@ dependencies = [ [[package]] name = "line-clipping" -version = "0.3.8" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e752191d037c44ad111a8caa762921926658402f01cc1253f7bef2020ece4f5e" +checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", ] [[package]] name = "link-section" -version = "0.19.3" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c29a617ce3df32c08497bdc1ab6e2376e0b17948ac166a2fbe5977c5954cd9" +checksum = "e333fe507b738576d6da5bb3f1a7d7a1c80307ed9ef31624c057d844c19c93e9" [[package]] name = "linktime-proc-macro" -version = "0.2.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e57c38c1e860fd37c604281cdfb1dd2216977fd76a50f85ba2f388ef3219616" +checksum = "8c7b0a3383c2a1002d11349c92c85a666a5fb679e96c79d782cf0dbe557fd6ee" [[package]] name = "linux-raw-sys" @@ -5035,9 +4903,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "litrs" @@ -5056,9 +4924,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.34" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "logos" @@ -5081,7 +4949,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -5108,9 +4976,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.18.3" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d317b4b9eb398e6acce275758ec6125535505e7a146fb1a9b8bda2451b0ff4c" +checksum = "0b6180140927ee907000b0aa540091f6ea512ead4447c92b8fc35bc72788a5a6" dependencies = [ "hashbrown 0.17.1", ] @@ -5130,16 +4998,6 @@ dependencies = [ "twox-hash", ] -[[package]] -name = "lzma-rs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" -dependencies = [ - "byteorder", - "crc", -] - [[package]] name = "lzma-rust2" version = "0.16.5" @@ -5149,17 +5007,6 @@ dependencies = [ "sha2 0.11.0", ] -[[package]] -name = "lzma-sys" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "mac-addr" version = "0.3.0" @@ -5277,7 +5124,7 @@ checksum = "746873a384ad60adc5db74471dfaba74bd278afbdcfd81db93fafcdfc8b5ca0c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -5324,18 +5171,18 @@ dependencies = [ [[package]] name = "mesh-llm-api-client" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "hex", "mesh-llm-client", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "mesh-llm-api-server" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "mesh-llm-api-client", @@ -5345,21 +5192,18 @@ dependencies = [ [[package]] name = "mesh-llm-build-info" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" [[package]] name = "mesh-llm-client" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "async-trait", "base64 0.22.1", "bytes", - "crypto_box", - "ed25519-dalek", - "hex", "httparse", "iroh", "mesh-llm-identity", @@ -5369,12 +5213,10 @@ dependencies = [ "model-artifact", "nostr-sdk", "prost 0.14.4", - "rand 0.10.2", "rustls", "serde", "serde_json", - "sha2 0.10.9", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "uuid", @@ -5382,8 +5224,8 @@ dependencies = [ [[package]] name = "mesh-llm-config" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "dirs", @@ -5392,14 +5234,14 @@ dependencies = [ "serde", "skippy-protocol", "toml 0.9.12+spec-1.1.0", - "toml_edit 0.25.13+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", "url", ] [[package]] name = "mesh-llm-embedded-runtime" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "mesh-llm-host-runtime", @@ -5408,20 +5250,25 @@ dependencies = [ [[package]] name = "mesh-llm-events" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", + "chrono", "clap", "crossterm 0.28.1", + "libc", "ratatui", + "serde", "serde_json", + "tracing", + "uuid", ] [[package]] name = "mesh-llm-gpu-bench" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", "serde_json", @@ -5430,8 +5277,8 @@ dependencies = [ [[package]] name = "mesh-llm-guardrails" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", "serde_json", @@ -5439,8 +5286,8 @@ dependencies = [ [[package]] name = "mesh-llm-hardware-profile" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "mesh-llm-native-runtime", ] @@ -5465,7 +5312,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.11.0", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-retry", "tokio-util", @@ -5476,8 +5323,8 @@ dependencies = [ [[package]] name = "mesh-llm-host-runtime" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "argon2", @@ -5499,7 +5346,6 @@ dependencies = [ "http-body-util", "httparse", "iroh", - "json5", "keyring", "libc", "mdns-sd", @@ -5511,6 +5357,7 @@ dependencies = [ "mesh-llm-guardrails", "mesh-llm-hf-hub", "mesh-llm-identity", + "mesh-llm-log-store", "mesh-llm-native-runtime", "mesh-llm-node", "mesh-llm-plugin", @@ -5540,11 +5387,10 @@ dependencies = [ "rmcp", "rpassword", "rustls", - "schemars 1.2.2", + "schemars 1.2.1", "semver", "serde", "serde_json", - "serde_yaml", "sha2 0.10.9", "skippy-coordinator", "skippy-ffi", @@ -5556,7 +5402,7 @@ dependencies = [ "tabwriter", "tar", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-stream", "toml 0.9.12+spec-1.1.0", @@ -5564,14 +5410,16 @@ dependencies = [ "tracing-subscriber", "url", "urlencoding", + "uuid", + "windows-sys 0.61.2", "zeroize", "zip 2.4.2", ] [[package]] name = "mesh-llm-identity" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "argon2", "base64 0.22.1", @@ -5586,14 +5434,32 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "thiserror 2.0.20", + "thiserror 2.0.18", "zeroize", ] +[[package]] +name = "mesh-llm-log-store" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" +dependencies = [ + "chrono", + "data-encoding", + "hex", + "mesh-llm-events", + "rusqlite", + "serde", + "serde_json", + "sha2 0.10.9", + "thiserror 2.0.18", + "uuid", + "windows-sys 0.61.2", +] + [[package]] name = "mesh-llm-native-runtime" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "serde", @@ -5603,8 +5469,8 @@ dependencies = [ [[package]] name = "mesh-llm-node" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "mesh-llm-types", @@ -5617,8 +5483,8 @@ dependencies = [ [[package]] name = "mesh-llm-plugin" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "async-trait", @@ -5626,7 +5492,7 @@ dependencies = [ "prost-build 0.14.4", "protoc-bin-vendored", "rmcp", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", "tokio", @@ -5634,8 +5500,8 @@ dependencies = [ [[package]] name = "mesh-llm-plugin-manager" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "dirs", @@ -5653,8 +5519,8 @@ dependencies = [ [[package]] name = "mesh-llm-protocol" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "hex", @@ -5666,8 +5532,8 @@ dependencies = [ [[package]] name = "mesh-llm-release-footer" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "hex", "sha2 0.10.9", @@ -5675,16 +5541,19 @@ dependencies = [ [[package]] name = "mesh-llm-routing" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ + "blake3", "iroh", + "serde", + "serde_json", ] [[package]] name = "mesh-llm-runtime-install" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "dirs", @@ -5706,8 +5575,8 @@ dependencies = [ [[package]] name = "mesh-llm-sdk" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "mesh-llm-api-client", @@ -5721,8 +5590,8 @@ dependencies = [ [[package]] name = "mesh-llm-skills" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "dirs", @@ -5732,8 +5601,8 @@ dependencies = [ [[package]] name = "mesh-llm-system" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "chrono", @@ -5759,8 +5628,8 @@ dependencies = [ [[package]] name = "mesh-llm-types" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "hex", "serde", @@ -5770,13 +5639,13 @@ dependencies = [ [[package]] name = "mesh-llm-ui" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" [[package]] name = "mesh-mixture-of-agents" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "async-trait", "mesh-llm-guardrails", @@ -5789,18 +5658,19 @@ dependencies = [ [[package]] name = "mesh-native-serving-plugin-api" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" [[package]] name = "mesh-native-serving-plugin-host" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "libloading 0.8.9", "mesh-native-serving-plugin-api", "skippy-server", + "skippy-tokenizer", ] [[package]] @@ -5822,7 +5692,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -5872,21 +5742,11 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "miniz_oxide" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" -dependencies = [ - "adler2", - "simd-adler32", -] - [[package]] name = "mio" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "log", @@ -5905,8 +5765,8 @@ dependencies = [ [[package]] name = "model-artifact" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "async-trait", @@ -5916,26 +5776,29 @@ dependencies = [ [[package]] name = "model-hf" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "async-trait", "chrono", "dirs", + "libc", "mesh-llm-hf-hub", "model-artifact", "model-ref", + "rustls", "serde", "serde_json", "sha2 0.10.9", "tokio", + "tracing", ] [[package]] name = "model-package" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "bytes", @@ -5954,16 +5817,16 @@ dependencies = [ [[package]] name = "model-ref" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", ] [[package]] name = "model-resolver" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "model-artifact", @@ -5974,9 +5837,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.16" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4293f18e7567a1caf3c584855554377025c65e0aa445344d04171f5ad63d19b9" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -6008,7 +5871,7 @@ checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -6058,7 +5921,7 @@ dependencies = [ "once_cell", "png 0.18.1", "serde", - "thiserror 2.0.20", + "thiserror 2.0.18", "windows-sys 0.61.2", ] @@ -6070,9 +5933,9 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "n0-error" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c59ea174675ce6bc196878851e5049e11b8b1f9af3ba87e4d6df8d828bb001" +checksum = "c37e81176a83a77d2514528b91bdafc70ef88aab428f0e1b91aebb8d99888895" dependencies = [ "n0-error-macros", "spez", @@ -6086,7 +5949,7 @@ checksum = "e2acd8b070213b0299282f884b4beba4e7b52d624fdcd504a3ad3665390c11e1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -6159,7 +6022,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "jni-sys 0.3.1", "log", "ndk-sys", @@ -6185,9 +6048,9 @@ dependencies = [ [[package]] name = "negentropy" -version = "0.5.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81c353b400a5503efdcf398f11a83fb7aa84f59f5d76fc4bf5bbc1e4f5366caa" +checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d" [[package]] name = "netdev" @@ -6203,9 +6066,9 @@ dependencies = [ "libc", "mac-addr", "ndk-context", - "netlink-packet-core 0.8.2", - "netlink-packet-route 0.31.0", - "netlink-sys 0.8.8", + "netlink-packet-core", + "netlink-packet-route", + "netlink-sys", "objc2", "objc2-core-foundation", "objc2-core-wlan", @@ -6216,30 +6079,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "netdev" -version = "0.46.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4db4135b187ddae3b6813c4f9d9ac9d5181859fa6a08b4e006c63a130974ed62" -dependencies = [ - "block2", - "dispatch2", - "dlopen2", - "ipnet", - "jni 0.21.1", - "libc", - "mac-addr", - "ndk-context", - "netlink-packet-core 0.9.0", - "netlink-packet-route 0.33.0", - "netlink-sys 0.9.0", - "objc2-core-foundation", - "objc2-system-configuration", - "once_cell", - "plist", - "windows-sys 0.61.2", -] - [[package]] name = "neteq" version = "0.8.3" @@ -6255,57 +6094,37 @@ dependencies = [ [[package]] name = "netlink-packet-core" -version = "0.8.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b897d7bd4f0af82e68d40d0344cf37e97f9c97ddf74a098de3e4da05e96ca395" +checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" dependencies = [ "paste", ] -[[package]] -name = "netlink-packet-core" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6e2daf9a8c2e21302714706860a0e6be02e03d17294ecc66b354ea7d4059dd" - [[package]] name = "netlink-packet-route" version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2288fcb784eb3defd5fb16f4c4160d5f477de192eac730f43e1d11c24d9a007" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "libc", "log", - "netlink-packet-core 0.8.2", -] - -[[package]] -name = "netlink-packet-route" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d48ffc8b73a506e1ff0878528c72668f2bfbc3d875b6be890a96be5d0d5576" -dependencies = [ - "bitflags 2.13.1", - "libc", - "log", - "netlink-packet-core 0.9.0", - "zerocopy", + "netlink-packet-core", ] [[package]] name = "netlink-proto" -version = "0.12.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93af8261786086024cd5e96e0a991dd65ced07bbf7c233a487bbc96b971d5539" +checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128" dependencies = [ "bytes", - "futures-channel", - "futures-util", + "futures", "log", - "netlink-packet-core 0.8.2", - "netlink-sys 0.8.8", - "thiserror 2.0.20", + "netlink-packet-core", + "netlink-sys", + "thiserror 2.0.18", ] [[package]] @@ -6321,22 +6140,11 @@ dependencies = [ "tokio", ] -[[package]] -name = "netlink-sys" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c99d38e00b420df49e940fe0826e667c3dad82ac68eb4c2bbf754c1c14a83a10" -dependencies = [ - "bytes", - "libc", - "log", -] - [[package]] name = "netwatch" -version = "0.19.3" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39da9cad5f23aa43401f09497d3b280e51b5feba115d9ffbf38ca35d6ff95e96" +checksum = "4d9cbe01741347ef750d743d6690603f5eed8341e679fb51c8e629337aa11976" dependencies = [ "atomic-waker", "bytes", @@ -6348,12 +6156,11 @@ dependencies = [ "n0-error", "n0-future", "n0-watcher", - "netdev 0.45.0", - "netdev 0.46.2", - "netlink-packet-core 0.8.2", - "netlink-packet-route 0.31.0", + "netdev", + "netlink-packet-core", + "netlink-packet-route", "netlink-proto", - "netlink-sys 0.8.8", + "netlink-sys", "noq-udp", "objc2-core-foundation", "objc2-system-configuration", @@ -6382,7 +6189,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases 0.1.1", "libc", @@ -6394,20 +6201,32 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases 0.2.2", "libc", "memoffset", ] +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.13.0", + "cfg-if 1.0.4", + "cfg_aliases 0.2.2", + "libc", +] + [[package]] name = "nix" version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases 0.2.2", "libc", @@ -6434,9 +6253,9 @@ dependencies = [ [[package]] name = "noq" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e6c57353d26be91a242f0ec96073066c4481a03f6be874daafb18902394515" +checksum = "09e4bb6601fa543c110d8957813267d5a8d775a0f8fbaccf1f615d06ba9b10da" dependencies = [ "bytes", "cfg_aliases 0.2.2", @@ -6447,7 +6266,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -6456,9 +6275,9 @@ dependencies = [ [[package]] name = "noq-proto" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a46813e306c29c4f86357b6ffa39a8e1c97bb274b9a296a19a56d62e4111225" +checksum = "baa7b5ccd819a9c68a0d955e67a881032d09b1a17219b1f90b0997a0888e1a15" dependencies = [ "aes-gcm", "aws-lc-rs", @@ -6476,7 +6295,7 @@ dependencies = [ "rustls-pki-types", "slab", "sorted-index-buffer", - "thiserror 2.0.20", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -6484,9 +6303,9 @@ dependencies = [ [[package]] name = "noq-udp" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b56d621ed2c1773b5356ab39cc68c819f8d0103f7493d8661c4a5f5f8ea55f40" +checksum = "02bba20e097a5a16cd0ad14ec882fae1e80a092a124e9422fc4dddd92e96a647" dependencies = [ "cfg_aliases 0.2.2", "libc", @@ -6497,9 +6316,9 @@ dependencies = [ [[package]] name = "nostr" -version = "0.44.8" +version = "0.44.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ff7b77ef428b40aa2834a6acbae38a0e104c98b306208ca4b87a420d579a4b" +checksum = "c7d3d987ea7078dc36947cde532637c472a229426702e4331dd7667325378bd9" dependencies = [ "base64 0.22.1", "bech32 0.11.1", @@ -6517,14 +6336,13 @@ dependencies = [ "serde_json", "unicode-normalization", "url", - "zeroize", ] [[package]] name = "nostr" -version = "0.45.4" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67bacf4195a119bc55d576ec6b54cc103723cb46fff5f907b8bdac8fd29ac4a0" +checksum = "5dde8c76076d334409d86c2e1db3e97abe5deb8cb92744f939cbc1fa45bd69e7" dependencies = [ "base64 0.22.1", "bech32 0.12.0", @@ -6551,7 +6369,7 @@ version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b1fdb9fcba732e32719662afad1b267e50322dbe89e506017ec13f24361bddf" dependencies = [ - "nostr 0.45.4", + "nostr 0.45.1", "opaquerr", ] @@ -6561,15 +6379,15 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa07539e52a71cb91fe0d693facaa298f03fcf9edcd66a521094e18e286e2336" dependencies = [ - "nostr 0.45.4", + "nostr 0.45.1", "opaquerr", ] [[package]] name = "nostr-sdk" -version = "0.45.2" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245f8642b10feecb0a40739a886ca1850e3be4e35dc6592b806ec437403ab9c9" +checksum = "26c86342f367bd9b173ec4a697e936e3a82d6dad5b4aa06c0d35d9b4f88a8e72" dependencies = [ "async-utility", "async-wsocket", @@ -6577,7 +6395,7 @@ dependencies = [ "futures", "lru", "negentropy", - "nostr 0.45.4", + "nostr 0.45.1", "nostr-database", "nostr-gossip", "opaquerr", @@ -6599,7 +6417,7 @@ dependencies = [ "mac-notification-sys", "serde", "tauri-winrt-notification", - "zbus 5.19.0", + "zbus 5.17.0", ] [[package]] @@ -6667,14 +6485,14 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "num-integer" -version = "0.1.47" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] @@ -6727,10 +6545,10 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 3.5.0", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -6758,7 +6576,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-core-foundation", @@ -6772,7 +6590,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "libc", "objc2", "objc2-core-audio", @@ -6797,7 +6615,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-foundation", ] @@ -6821,7 +6639,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", ] @@ -6841,7 +6659,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "dispatch2", "libc", @@ -6854,7 +6672,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "dispatch2", "objc2", "objc2-core-foundation", @@ -6887,7 +6705,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -6899,7 +6717,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e34919aba0d701380d911702455038a8a3587467fe0141d6a71501e7ffe48" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -6928,7 +6746,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -6951,7 +6769,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", ] @@ -6962,7 +6780,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f112d1746737b0da274ef79a23aac283376f335f4095a083a267a082f21db0c0" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-app-kit", "objc2-foundation", @@ -6974,7 +6792,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -6986,7 +6804,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", ] @@ -7007,7 +6825,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "dispatch2", "libc", "objc2", @@ -7021,7 +6839,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-cloud-kit", @@ -7042,7 +6860,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-foundation", @@ -7054,7 +6872,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-app-kit", @@ -7098,9 +6916,9 @@ checksum = "4f933a4265d5cdad61d19bbdfc972ea5726d56cd8d3d57b8f2d3c365dd42bee9" [[package]] name = "open" -version = "5.4.2" +version = "5.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade3be4664bc1ef537ce133015f04c176b737815c2ba9fd60edf212d6e90dd55" +checksum = "cd8d3b65c44123a56e0133d2cd06ce4361bd3ca99d41198b2f25e3c3db9b8b4a" dependencies = [ "dunce", "is-wsl", @@ -7109,19 +6927,20 @@ dependencies = [ [[package]] name = "openai-frontend" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "async-trait", "axum", "futures-core", "futures-util", + "mesh-llm-events", "mesh-llm-guardrails", "serde", "serde_json", "tokio", - "tokio-stream", "tracing", + "uuid", ] [[package]] @@ -7130,7 +6949,7 @@ version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "foreign-types 0.3.2", "libc", @@ -7146,7 +6965,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -7179,36 +6998,36 @@ dependencies = [ [[package]] name = "opentelemetry" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" +checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682" dependencies = [ "futures-core", "futures-sink", "js-sys", "pin-project-lite", - "thiserror 2.0.20", + "thiserror 2.0.18", "tracing", ] [[package]] name = "opentelemetry-http" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331" dependencies = [ "async-trait", "bytes", "http", "opentelemetry", - "reqwest 0.12.28", + "reqwest 0.13.4", ] [[package]] name = "opentelemetry-otlp" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" +checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35" dependencies = [ "http", "opentelemetry", @@ -7216,15 +7035,15 @@ dependencies = [ "opentelemetry-proto", "opentelemetry_sdk", "prost 0.14.4", - "reqwest 0.12.28", - "thiserror 2.0.20", + "reqwest 0.13.4", + "thiserror 2.0.18", ] [[package]] name = "opentelemetry-proto" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638" dependencies = [ "base64 0.22.1", "const-hex", @@ -7232,24 +7051,24 @@ dependencies = [ "opentelemetry_sdk", "prost 0.14.4", "serde", - "serde_json", "tonic", "tonic-prost", ] [[package]] name = "opentelemetry_sdk" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +checksum = "9b59f80e1ac4d5ff7a2db8fb6c80badb7f0f3f858211fba08dd9aaec750894f9" dependencies = [ "futures-channel", "futures-executor", "futures-util", "opentelemetry", "percent-encoding", - "rand 0.9.5", - "thiserror 2.0.20", + "portable-atomic", + "rand 0.9.4", + "thiserror 2.0.18", ] [[package]] @@ -7344,40 +7163,31 @@ dependencies = [ "objc2-osa-kit", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "palette" -version = "0.7.7" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddeed8580d347d2abf3dcf06a5f0b3dc020258338526b277847cd4248a70fc64" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" dependencies = [ "approx", + "fast-srgb8", "libm", "palette_derive", - "palette_math", ] [[package]] name = "palette_derive" -version = "0.7.7" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88537020289b719d81be994ccf1bbf4990f477e2f69ee52fe3e45f43a02e56be" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.119", -] - -[[package]] -name = "palette_math" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6eb142958d64335fb0e345c5b9ead2ecd6fc438c307e9d7d3c4fd428dbaf12" -dependencies = [ - "libm", + "syn 2.0.118", ] [[package]] @@ -7407,9 +7217,9 @@ dependencies = [ [[package]] name = "papaya" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2442474a9404698c42509b8967f437249dbc7b50493e83020333d3943ec0ae" +checksum = "997ee03cd38c01469a7046643714f0ad28880bcb9e6679ff0666e24817ca19b7" dependencies = [ "equivalent", "seize", @@ -7510,9 +7320,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07a60cc7a4d00c91f95c685609d1d2f79050e6804b70ebedd7650f0b839bcf" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" dependencies = [ "memchr", "ucd-trie", @@ -7520,9 +7330,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a83744a5c8455b8b3e0dc5031362780a347c878bdd11584d1a8984228cc88d" +checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" dependencies = [ "pest", "pest_generator", @@ -7530,22 +7340,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd3451aa3de60d4b9a1e736885e4dea6b31617598026f12256ad566d63304a" +checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "pest_meta" -version = "2.9.0" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d3a0849e241d7dfce834c83b1c5edc8622009e8dd51a12ba1927c32f05496" +checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" dependencies = [ "pest", ] @@ -7557,7 +7367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset 0.5.7", - "indexmap 2.14.1", + "indexmap 2.14.0", ] [[package]] @@ -7568,7 +7378,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset 0.5.7", "hashbrown 0.15.5", - "indexmap 2.14.1", + "indexmap 2.14.0", ] [[package]] @@ -7629,7 +7439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared 0.11.3", - "rand 0.8.8", + "rand 0.8.6", ] [[package]] @@ -7652,7 +7462,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -7665,7 +7475,7 @@ dependencies = [ "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -7703,7 +7513,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -7735,9 +7545,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.34" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plist" @@ -7746,7 +7556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" dependencies = [ "base64 0.22.1", - "indexmap 2.14.1", + "indexmap 2.14.0", "quick-xml 0.41.0", "serde", "time", @@ -7762,7 +7572,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.9", + "miniz_oxide", ] [[package]] @@ -7771,11 +7581,11 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.9", + "miniz_oxide", ] [[package]] @@ -7817,9 +7627,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.15.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" dependencies = [ "serde", ] @@ -7856,9 +7666,9 @@ dependencies = [ [[package]] name = "portmapper" -version = "0.19.3" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca97242f016e090a25330613bc2382aab65eb22f9149dbe84d8f8e711d49a530" +checksum = "eb3713e4977408279158444a18c1a01ac9bf2e7eaf1fbfd1a19ac9cd18d90721" dependencies = [ "base64 0.22.1", "bytes", @@ -7904,14 +7714,14 @@ checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "potential_utf" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -7924,9 +7734,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppmd-rust" -version = "1.4.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e9219bcb9d7aca6b2f63c83cf100cf78bcd619ac46e6ecbd0dd90869a39345d" +checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24" [[package]] name = "ppv-lite86" @@ -7961,17 +7771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.119", -] - -[[package]] -name = "prettyplease" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0" -dependencies = [ - "proc-macro2", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -8009,7 +7809,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.13+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", ] [[package]] @@ -8038,9 +7838,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.107" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -8052,7 +7852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e842efad9119158434d193c6682e2ebee4b44d6ad801d7b349623b3f57cdf55" dependencies = [ "futures", - "indexmap 2.14.1", + "indexmap 2.14.0", "nix 0.31.3", "tokio", "tracing", @@ -8065,9 +7865,9 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "num-traits", - "rand 0.9.5", + "rand 0.9.4", "rand_chacha 0.9.0", "rand_xorshift", "regex-syntax", @@ -8106,11 +7906,11 @@ dependencies = [ "multimap", "once_cell", "petgraph 0.7.1", - "prettyplease 0.2.37", + "prettyplease", "prost 0.13.5", "prost-types 0.13.5", "regex", - "syn 2.0.119", + "syn 2.0.118", "tempfile", ] @@ -8125,11 +7925,11 @@ dependencies = [ "log", "multimap", "petgraph 0.8.3", - "prettyplease 0.2.37", + "prettyplease", "prost 0.14.4", "prost-types 0.14.4", "regex", - "syn 2.0.119", + "syn 2.0.118", "tempfile", ] @@ -8143,7 +7943,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -8156,7 +7956,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -8326,7 +8126,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -8334,9 +8134,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.17" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "aws-lc-rs", "bytes", @@ -8349,7 +8149,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.20", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -8371,9 +8171,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.47" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -8392,9 +8192,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.8" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -8403,9 +8203,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -8417,7 +8217,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "chacha20 0.10.2", + "chacha20 0.10.1", "getrandom 0.4.3", "rand_core 0.10.1", ] @@ -8516,7 +8316,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "compact_str 0.9.1", "critical-section", "hashbrown 0.17.1", @@ -8526,7 +8326,7 @@ dependencies = [ "palette", "serde", "strum", - "thiserror 2.0.20", + "thiserror 2.0.18", "unicode-segmentation", "unicode-truncate", "unicode-width 0.2.2", @@ -8581,7 +8381,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "hashbrown 0.17.1", "indoc", "instability", @@ -8662,7 +8462,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", ] [[package]] @@ -8673,34 +8473,34 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "ref-cast" -version = "1.0.27" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.27" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] name = "regex" -version = "1.13.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" dependencies = [ "aho-corasick", "memchr", @@ -8710,9 +8510,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.18" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" dependencies = [ "aho-corasick", "memchr", @@ -8740,7 +8540,6 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", - "futures-channel", "futures-core", "futures-util", "h2", @@ -8776,7 +8575,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams 0.4.2", "web-sys", - "webpki-roots 1.0.9", + "webpki-roots 1.0.8", ] [[package]] @@ -8835,7 +8634,7 @@ dependencies = [ "async-trait", "http", "reqwest 0.13.4", - "thiserror 2.0.20", + "thiserror 2.0.18", "tower-service", ] @@ -8912,11 +8711,11 @@ dependencies = [ "rand 0.10.2", "reqwest 0.13.4", "rmcp-macros", - "schemars 1.2.2", + "schemars 1.2.1", "serde", "serde_json", "sse-stream", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -8935,7 +8734,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -8951,24 +8750,35 @@ dependencies = [ "rand_distr", "rtrb", "symphonia", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "rpassword" -version = "5.0.1" +version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" +checksum = "2da316a15f47e3d053de9cb2c439650bd8fa4aaeb9365f2e5f27f492ff73c196" dependencies = [ "libc", - "winapi", + "rtoolbox", + "windows-sys 0.61.2", +] + +[[package]] +name = "rtoolbox" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1efe12a1469752d0e6ff5ebec0b6ef4924cc5c4c71046b0ec730040535819d" +dependencies = [ + "libc", + "windows-sys 0.61.2", ] [[package]] name = "rtrb" -version = "0.3.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fae8ee26b0371a29a77d2b2d6b3ae13aa81def6f9bf1b1b92a32d279a5e709b7" +checksum = "4ade083ccbb4bf536df69d1f6432cc23deb7acccff86b183f3923a6fd56a1153" [[package]] name = "rubato" @@ -8992,7 +8802,7 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -9038,7 +8848,7 @@ dependencies = [ "serde_json", "sha2 0.10.9", "sysinfo 0.37.2", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "tokio", "tokio-stream", @@ -9080,7 +8890,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -9093,7 +8903,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -9113,9 +8923,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.43" +version = "0.23.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" dependencies = [ "aws-lc-rs", "log", @@ -9141,9 +8951,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -9178,9 +8988,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.15" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -9281,14 +9091,14 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "chrono", "dyn-clone", "ref-cast", - "schemars_derive 1.2.2", + "schemars_derive 1.2.1", "serde", "serde_json", ] @@ -9301,20 +9111,20 @@ checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" dependencies = [ "proc-macro2", "quote", - "serde_derive_internals 0.29.1", - "syn 2.0.119", + "serde_derive_internals", + "syn 2.0.118", ] [[package]] name = "schemars_derive" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98c67716b46af2f0b8cf752abc930f6f9aecfbf671ecfb531db8a31dbe4e2ba" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" dependencies = [ "proc-macro2", "quote", - "serde_derive_internals 0.30.0", - "syn 3.0.4", + "serde_derive_internals", + "syn 2.0.118", ] [[package]] @@ -9347,7 +9157,7 @@ version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ - "rand 0.8.8", + "rand 0.8.6", "secp256k1-sys", "serde", ] @@ -9359,7 +9169,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes 0.14.101", - "rand 0.8.8", + "rand 0.8.6", "secp256k1-sys", ] @@ -9385,7 +9195,7 @@ dependencies = [ "hkdf", "num", "once_cell", - "rand 0.8.8", + "rand 0.8.6", "serde", "sha2 0.10.9", "zbus 4.4.0", @@ -9397,7 +9207,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -9410,7 +9220,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -9432,6 +9242,10 @@ name = "seize" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] [[package]] name = "selectors" @@ -9439,7 +9253,7 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "cssparser", "derive_more", "log", @@ -9482,9 +9296,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -9514,22 +9328,22 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -9540,25 +9354,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", -] - -[[package]] -name = "serde_derive_internals" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] name = "serde_json" -version = "1.0.151" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", @@ -9580,13 +9383,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.21" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -9621,19 +9424,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.22.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" dependencies = [ "base64 0.22.1", "bs58", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.14.1", - "jiff", + "indexmap 2.14.0", "schemars 0.9.0", - "schemars 1.2.2", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -9642,14 +9444,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.22.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" dependencies = [ "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -9658,7 +9460,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "itoa", "ryu", "serde", @@ -9705,7 +9507,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -9719,9 +9521,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.7" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if 1.0.4", "cpufeatures 0.2.17", @@ -9735,7 +9537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "digest 0.11.3", ] @@ -9754,6 +9556,7 @@ dependencies = [ "cfg-if 1.0.4", "cpufeatures 0.2.17", "digest 0.10.7", + "sha2-asm", ] [[package]] @@ -9763,10 +9566,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.3.1", + "cpufeatures 0.3.0", "digest 0.11.3", ] +[[package]] +name = "sha2-asm" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b845214d6175804686b2bd482bcffe96651bb2d1200742b712003504a2dac1ab" +dependencies = [ + "cc", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -9805,9 +9617,9 @@ dependencies = [ [[package]] name = "sherpa-onnx" -version = "1.13.7" +version = "1.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4ef11f6b23c916a8e36c3cf65201f796d0e6aa30182a18d4f798d0b7f62547" +checksum = "0b142d3f255cb4e4b7808ea25869db6f5714e0a3550da355234483b4db552055" dependencies = [ "serde", "serde_json", @@ -9816,14 +9628,13 @@ dependencies = [ [[package]] name = "sherpa-onnx-sys" -version = "1.13.7" +version = "1.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566aad07d0924a7ed897cc035cc67ad71cdfddb959717dbf445031d5d4b58d4d" +checksum = "ffc951af03dc0653c0622158ca8a585a6f2bc43b7b06048cf0e5b5020005c227" dependencies = [ "bzip2 0.4.4", "tar", "ureq", - "zip 2.4.2", ] [[package]] @@ -9881,15 +9692,15 @@ checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" [[package]] name = "simd-adler32" -version = "0.3.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "simd_cesu8" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" dependencies = [ "rustc_version", "simdutf8", @@ -9903,11 +9714,11 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "simple-dns" -version = "0.12.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b6f884fa9a8d48101774bfbd3aeb81e968dd22cffd19a372da69f183db22c1a" +checksum = "7a75cbde1bf934313596a004973e462f9a82caa814dcf1a5f507bdf51597eeb4" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", ] [[package]] @@ -9918,8 +9729,8 @@ checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "skippy-cache" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "blake3", @@ -9928,29 +9739,29 @@ dependencies = [ [[package]] name = "skippy-coordinator" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "skippy-ffi" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "libloading 0.8.9", ] [[package]] name = "skippy-metrics" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" [[package]] name = "skippy-protocol" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "prost 0.14.4", "prost-build 0.14.4", @@ -9961,8 +9772,8 @@ dependencies = [ [[package]] name = "skippy-runtime" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "anyhow", "libc", @@ -9973,10 +9784,19 @@ dependencies = [ "tokio", ] +[[package]] +name = "skippy-scheduler" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" +dependencies = [ + "skippy-runtime", + "thiserror 2.0.18", +] + [[package]] name = "skippy-server" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "ahash", "anyhow", @@ -9987,6 +9807,7 @@ dependencies = [ "clap", "futures-util", "libc", + "mesh-llm-events", "mesh-native-serving-plugin-api", "model-artifact", "openai-frontend", @@ -9998,25 +9819,27 @@ dependencies = [ "skippy-metrics", "skippy-protocol", "skippy-runtime", + "skippy-scheduler", "skippy-tokenizer", + "skippy-topology", "socket2", "tokio", - "tokio-stream", "tonic", + "uuid", ] [[package]] name = "skippy-tokenizer" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", ] [[package]] name = "skippy-topology" -version = "0.75.1" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.75.1#3295c902d4c4f859aaadf9240042ffdaf06dd07e" +version = "0.76.0-rc9" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?tag=v0.76.0-rc9#9f192c9d821991ba43d79bb15fd2f2f12e597571" dependencies = [ "serde", "serde_json", @@ -10030,9 +9853,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.0" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket-pktinfo" @@ -10047,9 +9870,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.5" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", "windows-sys 0.61.2", @@ -10117,23 +9940,23 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "spin" -version = "0.9.9" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] [[package]] name = "spin" -version = "0.10.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" [[package]] name = "spki" @@ -10159,9 +9982,9 @@ dependencies = [ [[package]] name = "sse-stream" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c123f296ade4ec4b8b0f6162116e6629f5146922ca5ab40ca9d3c2e73ab4761e" +checksum = "39f24a9b78c40b90817bbcd1821c74ddfd74916aadd29403d001532a9195532d" dependencies = [ "bytes", "futures-util", @@ -10255,7 +10078,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -10266,9 +10089,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "swift-rs" -version = "1.0.8" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45c444e496845d3f2a351146bff59aae4975b2280238df1dfaa0c7d1846f38e" +checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" dependencies = [ "base64 0.21.7", "serde", @@ -10452,9 +10275,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.119" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -10463,9 +10286,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.4" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" dependencies = [ "proc-macro2", "quote", @@ -10489,7 +10312,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -10526,7 +10349,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -10575,7 +10398,7 @@ version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "block2", "core-foundation 0.10.1", "core-graphics", @@ -10611,13 +10434,13 @@ dependencies = [ [[package]] name = "tao-macros" -version = "0.1.4" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7eeb6d99155545da6150a1795945f16ac9c178deb2a5f2e74d776107bd5849" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -10678,7 +10501,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tray-icon", "url", @@ -10727,9 +10550,9 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "syn 2.0.119", + "syn 2.0.118", "tauri-utils", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "url", "uuid", @@ -10745,7 +10568,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", "tauri-codegen", "tauri-utils", ] @@ -10768,9 +10591,9 @@ dependencies = [ [[package]] name = "tauri-plugin-deep-link" -version = "2.4.10" +version = "2.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d489b8ecceae1cd09f6e1f7606f2095ac721cc8d54cf2f0e6bb377cc52cff6" +checksum = "70ee75bc5627f77bfdf40c913255ebc258117b10ebe2b2239a1a1cf40b0b58aa" dependencies = [ "dunce", "plist", @@ -10780,7 +10603,7 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-utils", - "thiserror 2.0.20", + "thiserror 2.0.18", "tracing", "url", "windows-registry 0.5.3", @@ -10789,9 +10612,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.7.3" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61854a36651aa48381e5e209f69a01273b77f3f9f91f0c430b1b98d33bd47229" +checksum = "65981abb771e74e571a38196c3baa11c459379164791eba0e67abc1a5fac9884" dependencies = [ "log", "raw-window-handle", @@ -10801,15 +10624,15 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror 2.0.20", + "thiserror 2.0.18", "url", ] [[package]] name = "tauri-plugin-fs" -version = "2.5.2" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de22eef34fd78c0da050e748710edd50bf127e651d02ea1b2bfada1523cc5c51" +checksum = "b7ecc274121aca0c036a2b42d1cbe83d368d348f54e0bb8a735c2b1548e8f371" dependencies = [ "anyhow", "dunce", @@ -10824,8 +10647,8 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-utils", - "thiserror 2.0.20", - "toml 1.1.4+spec-1.1.0", + "thiserror 2.0.18", + "toml 1.1.2+spec-1.1.0", "url", ] @@ -10841,33 +10664,33 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] name = "tauri-plugin-notification" -version = "2.4.0" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2fd40946aef810c4be9fd33a2d1b9b397cb79042b2d21c81a0a8f204354fd1" +checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc" dependencies = [ "log", "notify-rust", - "rand 0.9.5", + "rand 0.9.4", "serde", "serde_json", "serde_repr", "tauri", "tauri-plugin", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "url", ] [[package]] name = "tauri-plugin-opener" -version = "2.5.5" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60d60366174b745b4ef5824b8bbc1c457fd08f0ce101ff643c0a49181a9f4e91" +checksum = "17e1bea14edce6b793a04e2417e3fd924b9bc4faae83cdee7d714156cceeed29" dependencies = [ "dunce", "glob", @@ -10879,10 +10702,10 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.20", + "thiserror 2.0.18", "url", "windows 0.61.3", - "zbus 5.19.0", + "zbus 5.17.0", ] [[package]] @@ -10897,26 +10720,25 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" -version = "2.4.4" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0cb5c412a5071b69bab6a6df1583cbb89460d4a83b6a24769b08d15b6b1e1" +checksum = "5c8f29386f5e9fdc699182388a33ee80a56de436d91b67459e86afef426282af" dependencies = [ "serde", "serde_json", "tauri", "tauri-plugin-deep-link", - "thiserror 2.0.20", - "tokio", + "thiserror 2.0.18", "tracing", "windows-sys 0.60.2", - "zbus 5.19.0", + "zbus 5.17.0", ] [[package]] name = "tauri-plugin-updater" -version = "2.11.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28d8cabdeb0564f03ae261963de4bc3d98321cd3d213e76a81b7d344e5df606" +checksum = "806d9dac662c2e4594ff03c647a552f2c9bd544e7d0f683ec58f872f952ce4af" dependencies = [ "base64 0.22.1", "dirs", @@ -10937,7 +10759,7 @@ dependencies = [ "tauri", "tauri-plugin", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "tokio", "url", @@ -10951,13 +10773,13 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73736611e14142408d15353e21e3cca2f12a3cfb523ad0ce85999b6d2ef1a704" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "log", "serde", "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.20", + "thiserror 2.0.18", ] [[package]] @@ -10978,7 +10800,7 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "thiserror 2.0.20", + "thiserror 2.0.18", "url", "webkit2gtk", "webview2-com", @@ -11041,8 +10863,8 @@ dependencies = [ "serde_json", "serde_with", "swift-rs", - "thiserror 2.0.20", - "toml 1.1.4+spec-1.1.0", + "thiserror 2.0.18", + "toml 1.1.2+spec-1.1.0", "url", "urlpattern", "uuid", @@ -11057,7 +10879,7 @@ checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6" dependencies = [ "dunce", "embed-resource", - "toml 1.1.4+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", ] [[package]] @@ -11066,7 +10888,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed071c670382e85fc2f48ae706492d8c338f4f89bf72520d32f8abfe880aade" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", "windows 0.61.3", "windows-version", ] @@ -11099,7 +10921,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "parking_lot", "rustix 1.1.4", "signal-hook 0.3.18", @@ -11135,7 +10957,7 @@ checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" dependencies = [ "anyhow", "base64 0.22.1", - "bitflags 2.13.1", + "bitflags 2.13.0", "fancy-regex 0.11.0", "filedescriptor", "finl_unicode", @@ -11180,11 +11002,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.20", + "thiserror-impl 2.0.18", ] [[package]] @@ -11195,25 +11017,25 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] name = "thread_local" -version = "1.1.10" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if 1.0.4", ] @@ -11234,9 +11056,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.55" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", "js-sys", @@ -11257,9 +11079,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.32" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", @@ -11276,9 +11098,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -11286,9 +11108,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.12.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -11318,7 +11140,7 @@ dependencies = [ "macro_rules_attribute", "monostate", "paste", - "rand 0.9.5", + "rand 0.9.4", "rayon", "rayon-cond", "regex", @@ -11326,7 +11148,7 @@ dependencies = [ "serde", "serde_json", "spm_precompiled", - "thiserror 2.0.20", + "thiserror 2.0.18", "unicode-normalization-alignments", "unicode-segmentation", "unicode_categories", @@ -11334,9 +11156,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.53.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -11360,13 +11182,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.2" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -11414,9 +11236,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.19" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -11458,15 +11280,14 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.19" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", "futures-sink", "futures-util", - "libc", "pin-project-lite", "tokio", ] @@ -11516,7 +11337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d01145a2c788d6aae4cd653afec1e8332534d7d783d01897cefcafe4428de992" dependencies = [ "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -11537,7 +11358,7 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "serde_core", "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", @@ -11548,17 +11369,17 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.4+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "serde_core", "serde_spanned 1.1.1", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] @@ -11594,7 +11415,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "toml_datetime 0.6.3", "winnow 0.5.40", ] @@ -11605,7 +11426,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.3", @@ -11614,31 +11435,31 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.13+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ - "indexmap 2.14.1", + "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] name = "toml_parser" -version = "1.1.3+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] name = "toml_writer" -version = "1.1.2+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" @@ -11688,7 +11509,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.14.1", + "indexmap 2.14.0", "pin-project-lite", "slab", "sync_wrapper", @@ -11705,7 +11526,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "bytes", "futures-util", "http", @@ -11749,7 +11570,7 @@ checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", "symlink", - "thiserror 2.0.20", + "thiserror 2.0.18", "time", "tracing-subscriber", ] @@ -11762,7 +11583,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -11829,9 +11650,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.24.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045979e3f037cd18ad1cb2a419dfda133c5c29c9f3453370079f2255d46c257e" +checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc" dependencies = [ "crossbeam-channel", "dirs", @@ -11845,7 +11666,7 @@ dependencies = [ "once_cell", "png 0.18.1", "serde", - "thiserror 2.0.20", + "thiserror 2.0.18", "windows-sys 0.61.2", ] @@ -11877,11 +11698,11 @@ dependencies = [ "http", "httparse", "log", - "rand 0.9.5", + "rand 0.9.4", "rustls", "rustls-pki-types", - "sha1 0.10.7", - "thiserror 2.0.20", + "sha1 0.10.6", + "thiserror 2.0.18", "utf-8", ] @@ -11896,18 +11717,18 @@ dependencies = [ "http", "httparse", "log", - "rand 0.9.5", + "rand 0.9.4", "rustls", "rustls-pki-types", - "sha1 0.10.7", - "thiserror 2.0.20", + "sha1 0.10.6", + "thiserror 2.0.18", ] [[package]] name = "twox-hash" -version = "2.1.4" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" [[package]] name = "typed-path" @@ -11956,7 +11777,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe" dependencies = [ - "rand 0.9.5", + "rand 0.9.4", "web-time", ] @@ -12186,9 +12007,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.26.0" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ "atomic", "getrandom 0.4.3", @@ -12230,7 +12051,7 @@ checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -12269,7 +12090,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5924018406ce0063cd67f8e008104968b74b563ee1b85dde3ed1f7cb87d3dbd" dependencies = [ "arrayvec", - "bitflags 2.13.1", + "bitflags 2.13.0", "cursor-icon", "log", "memchr", @@ -12338,9 +12159,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if 1.0.4", "once_cell", @@ -12351,9 +12172,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.77" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -12361,9 +12182,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -12371,22 +12192,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] @@ -12419,9 +12240,9 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.17" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38a91b4eaddff87b1cd1074985e3713da4af2c49742d1b356b2c01670a67a078" +checksum = "016ccf01d1c58b6f8999612813e17c9b2390f7d70671428869913310f83f54b8" dependencies = [ "cc", "downcast-rs", @@ -12436,7 +12257,7 @@ version = "0.31.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "rustix 1.1.4", "wayland-backend", "wayland-scanner", @@ -12448,7 +12269,7 @@ version = "0.32.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -12460,7 +12281,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -12489,9 +12310,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.104" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -12509,9 +12330,9 @@ dependencies = [ [[package]] name = "web_atoms" -version = "0.2.6" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba8b815c1b593dc0baf78dd0f4fc8fdb2de53198fb1163738093e9a311c33fb3" +checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297" dependencies = [ "phf 0.13.1", "phf_codegen 0.13.1", @@ -12581,9 +12402,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.9" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" +checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" dependencies = [ "rustls-pki-types", ] @@ -12594,14 +12415,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.9", + "webpki-roots 1.0.8", ] [[package]] name = "webpki-roots" -version = "1.0.9" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" dependencies = [ "rustls-pki-types", ] @@ -12628,7 +12449,7 @@ checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -12637,7 +12458,7 @@ version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.18", "windows 0.61.3", "windows-core 0.61.2", ] @@ -12722,9 +12543,9 @@ dependencies = [ [[package]] name = "whoami" -version = "2.1.3" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626c4bac6755d76ffc12cb01b2eac751db1996b9e0041de9aa02c8c211ddc82c" +checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" dependencies = [ "libc", "libredox", @@ -12893,7 +12714,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -12904,7 +12725,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -13338,9 +13159,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" [[package]] name = "winnow" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] @@ -13380,7 +13201,7 @@ dependencies = [ "log", "os_pipe", "rustix 1.1.4", - "thiserror 2.0.20", + "thiserror 2.0.18", "tree_magic_mini", "wayland-backend", "wayland-client", @@ -13398,16 +13219,16 @@ dependencies = [ "futures", "log", "serde", - "thiserror 2.0.20", + "thiserror 2.0.18", "windows 0.62.2", "windows-core 0.62.2", ] [[package]] name = "writeable" -version = "0.6.4" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wry" @@ -13442,7 +13263,7 @@ dependencies = [ "sha2 0.10.9", "soup3", "tao-macros", - "thiserror 2.0.20", + "thiserror 2.0.18", "url", "webkit2gtk", "webkit2gtk-sys", @@ -13466,7 +13287,7 @@ dependencies = [ "pharos", "rustc_version", "send_wrapper", - "thiserror 2.0.20", + "thiserror 2.0.18", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -13532,9 +13353,9 @@ dependencies = [ [[package]] name = "xet-client" -version = "1.6.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b8da8cc70aa2e3c500c0400e012df82c656ab9fca47f9f939fffc5afd89aca" +checksum = "b45fc10a88b05d4824d7fc0f97d04c13eaea98da5e8032194b8a0cbdab942090" dependencies = [ "anyhow", "async-trait", @@ -13544,6 +13365,7 @@ dependencies = [ "futures", "http", "hyper", + "lazy_static", "more-asserts", "rand 0.10.2", "redb", @@ -13554,7 +13376,7 @@ dependencies = [ "serde_repr", "statrs", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-retry", "tokio_with_wasm", @@ -13568,9 +13390,9 @@ dependencies = [ [[package]] name = "xet-core-structures" -version = "1.6.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73503c223783dccc864abde22115e09d12f190448a0baf58ab2c54bc709e2f99" +checksum = "eb39bc5e0478e8f03e15f08b0a396f197fcfa2ef5027da666fd100c806bf0ea3" dependencies = [ "async-trait", "base64 0.22.1", @@ -13583,6 +13405,7 @@ dependencies = [ "getrandom 0.4.3", "heapify", "itertools", + "lazy_static", "lz4_flex", "more-asserts", "rand 0.10.2", @@ -13590,7 +13413,7 @@ dependencies = [ "safe-transmute", "serde", "static_assertions", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tracing", @@ -13601,9 +13424,9 @@ dependencies = [ [[package]] name = "xet-data" -version = "1.6.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89052ec5dec2187cad30b86af92cc24fd61c4a57a795f1ff7ff5f38d49184eb" +checksum = "e428a3b9667c1d0d335a4c77407c04d3a3e6c4f228aee364a1b56ed94cf861ca" dependencies = [ "anyhow", "async-trait", @@ -13612,13 +13435,14 @@ dependencies = [ "gearhash", "http", "itertools", + "lazy_static", "more-asserts", "rand 0.10.2", "serde", "serde_json", - "sha2 0.11.0", + "sha2 0.10.9", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tokio_with_wasm", @@ -13633,9 +13457,9 @@ dependencies = [ [[package]] name = "xet-runtime" -version = "1.6.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af5c60d5eed38ab4c576f4421bae835e7bd07631fb381705605529d2015c106b" +checksum = "e8e1f8cfa256029d1bba7860ca12bfd145f17aa7aede5d968e9c304047656be1" dependencies = [ "anyhow", "async-trait", @@ -13643,12 +13467,13 @@ dependencies = [ "chrono", "colored", "const-str", - "ctor 1.0.13", + "ctor 1.0.8", "dirs", "futures", "git-version", "humantime", "konst", + "lazy_static", "libc", "more-asserts", "oneshot", @@ -13659,7 +13484,7 @@ dependencies = [ "serde_json", "shellexpand", "sysinfo 0.38.4", - "thiserror 2.0.20", + "thiserror 2.0.18", "tokio", "tokio-util", "tokio_with_wasm", @@ -13679,9 +13504,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.29" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "xmltree" @@ -13692,15 +13517,6 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "xz2" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" -dependencies = [ - "lzma-sys", -] - [[package]] name = "yoke" version = "0.8.3" @@ -13720,7 +13536,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", "synstructure", ] @@ -13742,10 +13558,10 @@ dependencies = [ "hex", "nix 0.29.0", "ordered-stream", - "rand 0.8.8", + "rand 0.8.6", "serde", "serde_repr", - "sha1 0.10.7", + "sha1 0.10.6", "static_assertions", "tracing", "uds_windows", @@ -13758,9 +13574,9 @@ dependencies = [ [[package]] name = "zbus" -version = "5.19.0" +version = "5.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db4be7c075cb421e4b7ee645541604239bd243ba7c357511f4ff3a74b555907" +checksum = "a28b97f866896a4be7aefd2b5a8e01bb6773d19a775d54ab28b4d094b9a4480e" dependencies = [ "async-broadcast", "async-executor", @@ -13785,10 +13601,10 @@ dependencies = [ "uds_windows", "uuid", "windows-sys 0.61.2", - "winnow 1.0.4", - "zbus_macros 5.19.0", - "zbus_names 4.3.4", - "zvariant 5.15.0", + "winnow 1.0.3", + "zbus_macros 5.17.0", + "zbus_names 4.3.3", + "zvariant 5.13.0", ] [[package]] @@ -13800,23 +13616,23 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", "zvariant_utils 2.1.0", ] [[package]] name = "zbus_macros" -version = "5.19.0" +version = "5.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2990635d09ade6df1868f72f8cac69a876a90981e8bd3c40b1be413f8dc88f40" +checksum = "5e05ad887425eecf5e8384dc2406a4a9313eb73468712fc1cdea362eb4fe0469" dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 3.0.4", - "zbus_names 4.3.4", - "zvariant 5.15.0", - "zvariant_utils 4.2.0", + "syn 2.0.118", + "zbus_names 4.3.3", + "zvariant 5.13.0", + "zvariant_utils 3.5.0", ] [[package]] @@ -13832,42 +13648,33 @@ dependencies = [ [[package]] name = "zbus_names" -version = "4.3.4" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e" -dependencies = [ - "serde", - "winnow 1.0.4", - "zvariant 5.15.0", -] - -[[package]] -name = "zcheapstr" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1afec51604565183aeb5c54c20aeab286120d4e4460f7f76e3e8bb8c0d99473" +checksum = "1039ca249fee9559680f3a9f05b55e0761fee51af4f6c1e7d8c1f31e549721d2" dependencies = [ "serde", + "winnow 1.0.3", + "zvariant 5.13.0", ] [[package]] name = "zerocopy" -version = "0.8.56" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.56" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] @@ -13887,7 +13694,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", "synstructure", ] @@ -13908,14 +13715,14 @@ checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "zerotrie" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -13924,9 +13731,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -13935,13 +13742,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.6" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 2.0.118", ] [[package]] @@ -13950,28 +13757,15 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" dependencies = [ - "aes 0.8.4", "arbitrary", - "bzip2 0.5.2", - "constant_time_eq 0.3.1", "crc32fast", "crossbeam-utils", - "deflate64", "displaydoc", "flate2", - "getrandom 0.3.4", - "hmac 0.12.1", - "indexmap 2.14.1", - "lzma-rs", + "indexmap 2.14.0", "memchr", - "pbkdf2 0.12.2", - "sha1 0.10.7", - "thiserror 2.0.20", - "time", - "xz2", - "zeroize", + "thiserror 2.0.18", "zopfli", - "zstd", ] [[package]] @@ -13982,7 +13776,7 @@ checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" dependencies = [ "arbitrary", "crc32fast", - "indexmap 2.14.1", + "indexmap 2.14.0", "memchr", ] @@ -13992,15 +13786,15 @@ version = "8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" dependencies = [ - "aes 0.9.3", + "aes 0.9.1", "bzip2 0.6.1", - "constant_time_eq 0.4.2", + "constant_time_eq", "crc32fast", "deflate64", "flate2", "getrandom 0.4.3", "hmac 0.13.0", - "indexmap 2.14.1", + "indexmap 2.14.0", "lzma-rust2", "memchr", "pbkdf2 0.13.0", @@ -14015,15 +13809,15 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.7" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12" +checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5" [[package]] name = "zmij" -version = "1.0.23" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zopfli" @@ -14067,9 +13861,9 @@ dependencies = [ [[package]] name = "zune-core" -version = "0.5.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-jpeg" @@ -14095,17 +13889,16 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.15.0" +version = "5.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1d34c27cc6cdd1f458427519dd6b8612f7b7e3f7b9a0b2355d041dda9869147" +checksum = "7cf057bb00bf5c9ad77abb6147b0ca4818236a1858416e9d988e40d6322fefa7" dependencies = [ "endi", "enumflags2", "serde", - "winnow 1.0.4", - "zcheapstr", - "zvariant_derive 5.15.0", - "zvariant_utils 4.2.0", + "winnow 1.0.3", + "zvariant_derive 5.13.0", + "zvariant_utils 3.5.0", ] [[package]] @@ -14117,21 +13910,21 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", "zvariant_utils 2.1.0", ] [[package]] name = "zvariant_derive" -version = "5.15.0" +version = "5.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864155e69b4352db0c7f374917bf45d1e0c8d17659c8b3dbf9795f3673f8c497" +checksum = "8118ca6bda77bfc0ab51d660db0c955f2505eef854c9a449435bccb616933b31" dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 3.0.4", - "zvariant_utils 4.2.0", + "syn 2.0.118", + "zvariant_utils 3.5.0", ] [[package]] @@ -14142,18 +13935,18 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.118", ] [[package]] name = "zvariant_utils" -version = "4.2.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad0294361a320b694a328460dc73add56c306150f5cb6bfafc44446120008a3" +checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7" dependencies = [ "proc-macro2", "quote", "serde", - "syn 3.0.4", - "winnow 1.0.4", + "syn 2.0.118", + "winnow 1.0.3", ] diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index 7c314e4284..bd7987ea71 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -7,7 +7,7 @@ members = ["crates/buzz-terminal"] [package] name = "buzz-desktop" -version = "0.5.22" +version = "0.5.23" description = "Buzz desktop app" authors = ["you"] edition = "2021" @@ -120,15 +120,15 @@ buzz_voice_pkg = { package = "buzz-voice", path = "../../crates/buzz-voice" } buzz_terminal = { package = "buzz-terminal", path = "crates/buzz-terminal" } buzz_ws_client_pkg = { package = "buzz-ws-client", path = "../../crates/buzz-ws-client" } portable-pty = "0.9" -iroh = { version = "1.0.2", optional = true } -mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.75.1", package = "mesh-llm-sdk", default-features = false, features = ["client", "serving"], optional = true } -mesh-llm-host-runtime = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.75.1", package = "mesh-llm-host-runtime", default-features = false, features = ["dynamic-native-runtime"], optional = true } +iroh = { version = "1.0.3", optional = true } +mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.76.0-rc9", package = "mesh-llm-sdk", default-features = false, features = ["client", "serving"], optional = true } +mesh-llm-host-runtime = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.76.0-rc9", package = "mesh-llm-host-runtime", default-features = false, features = ["dynamic-native-runtime"], optional = true } # Model catalog + hardware survey for the Share-compute model picker (same # diagnose pattern as mesh-console). Lib name of mesh-llm-client is mesh_client. -mesh-llm-client = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.75.1", package = "mesh-llm-client", optional = true } -mesh-llm-node = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.75.1", package = "mesh-llm-node", optional = true } -mesh-llm-system = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.75.1", package = "mesh-llm-system", optional = true } -mesh-llm-events = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.75.1", package = "mesh-llm-events", optional = true } +mesh-llm-client = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.76.0-rc9", package = "mesh-llm-client", optional = true } +mesh-llm-node = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.76.0-rc9", package = "mesh-llm-node", optional = true } +mesh-llm-system = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.76.0-rc9", package = "mesh-llm-system", optional = true } +mesh-llm-events = { git = "https://github.com/Mesh-LLM/mesh-llm.git", tag = "v0.76.0-rc9", package = "mesh-llm-events", optional = true } base64 = "0.22" sha2 = "0.11" tar = "0.4" diff --git a/desktop/src-tauri/src/commands/link_preview.rs b/desktop/src-tauri/src/commands/link_preview.rs index b781f8d9e6..a746cc8059 100644 --- a/desktop/src-tauri/src/commands/link_preview.rs +++ b/desktop/src-tauri/src/commands/link_preview.rs @@ -10,6 +10,8 @@ use reqwest::{ use serde::Serialize; use url::Url; +#[path = "link_preview_cancellation.rs"] +mod cancellation; #[path = "link_preview_image_retry.rs"] mod image_retry; #[path = "link_preview_rate_limit.rs"] @@ -17,15 +19,19 @@ mod rate_limit; #[path = "link_preview_youtube.rs"] mod youtube; -use rate_limit::{image_host_cooldown_remaining, retry_after_duration, set_image_host_cooldown}; +use rate_limit::{ + image_host_cooldown_remaining, image_host_gate, retry_after_duration, set_image_host_cooldown, +}; const MAX_PREVIEW_FETCH_BYTES: usize = 256 * 1024; const MAX_IMAGE_FETCH_BYTES: usize = 2 * 1024 * 1024; const MAX_IMAGE_DIMENSION: u32 = 4096; const MAX_IMAGE_PIXELS: u64 = 16_000_000; const MAX_SANITIZED_DIMENSION: u32 = 1200; -const PREVIEW_FETCH_TIMEOUT: Duration = Duration::from_secs(4); -const PREVIEW_TOTAL_TIMEOUT: Duration = Duration::from_secs(10); +const TRANSPORT_CONNECT_TIMEOUT: Duration = Duration::from_secs(15); +const TRANSPORT_IDLE_TIMEOUT: Duration = Duration::from_secs(30); +const DNS_RESOLUTION_TIMEOUT: Duration = Duration::from_secs(15); +const MAX_INLINE_IMAGE_COOLDOWN: Duration = Duration::from_secs(30); const MAX_REDIRECTS: usize = 3; const MAX_METADATA_CHARS: usize = 180; const MAX_METADATA_DESCRIPTION_CHARS: usize = 280; @@ -55,27 +61,46 @@ pub struct LinkPreviewMetadata { #[tauri::command] pub async fn fetch_link_preview_metadata( href: String, + request_id: Option, ) -> Result, String> { - tokio::time::timeout( - PREVIEW_TOTAL_TIMEOUT, - fetch_link_preview_metadata_inner(href), - ) - .await - .map_err(|_| "link preview request timed out".to_string())? + let cancellation = cancellation::begin(request_id.as_deref()); + let result = match cancellation { + Some(cancellation) => { + tokio::select! { + result = fetch_link_preview_metadata_for_url(href) => result, + () = cancellation.cancelled() => Err("link preview request cancelled".to_string()), + } + } + None => fetch_link_preview_metadata_for_url(href).await, + }; + cancellation::finish(request_id.as_deref()); + result } -async fn fetch_link_preview_metadata_inner( +/// Cancel renderer-owned metadata work, including an in-flight response body. +#[tauri::command] +pub fn cancel_link_preview_metadata(request_id: String) { + cancellation::cancel(&request_id); +} + +/// Release a renderer's cancellation record after its invocation settles. +#[tauri::command] +pub fn release_link_preview_metadata(request_id: String) { + cancellation::finish(Some(&request_id)); +} + +async fn fetch_link_preview_metadata_for_url( href: String, ) -> Result, String> { let mut url = Url::parse(href.trim()).map_err(|error| format!("invalid URL: {error}"))?; - validate_public_https_url(&url).await?; + validate_metadata_url(&url).await?; if youtube::is_video_url(&url) { return youtube::fetch_oembed_metadata(&url).await; } for redirect_count in 0..=MAX_REDIRECTS { - let response = send_pinned_request(&url, "text/html,application/xhtml+xml;q=0.9").await?; + let response = send_metadata_request(&url, "text/html,application/xhtml+xml;q=0.9").await?; if response.status().is_redirection() { if redirect_count == MAX_REDIRECTS { @@ -90,7 +115,7 @@ async fn fetch_link_preview_metadata_inner( url = url .join(location) .map_err(|error| format!("invalid link preview redirect: {error}"))?; - validate_public_https_url(&url).await?; + validate_metadata_url(&url).await?; continue; } @@ -107,28 +132,15 @@ async fn fetch_link_preview_metadata_inner( let (image_result, favicon_result) = tokio::join!( async { match image_url { - Some(image_url) => Some( - tokio::time::timeout( - PREVIEW_FETCH_TIMEOUT, - fetch_sanitized_image_with_retry(image_url, false), - ) - .await - .unwrap_or(Err(ImageFetchError::Transient { - retry_after: None, - retry_inline: false, - })), - ), + Some(image_url) => { + Some(fetch_sanitized_image_with_retry(image_url, false).await) + } None => None, } }, async { match favicon_url { - Some(favicon_url) => tokio::time::timeout( - PREVIEW_FETCH_TIMEOUT, - fetch_sanitized_image(favicon_url, true), - ) - .await - .ok(), + Some(favicon_url) => Some(fetch_sanitized_image(favicon_url, true).await), None => None, } } @@ -166,6 +178,15 @@ fn apply_image_result( } } +async fn validate_metadata_url(url: &Url) -> Result<(), String> { + #[cfg(test)] + if METADATA_TEST_SERVER.try_with(|_| ()).is_ok() { + return Ok(()); + } + + validate_public_https_url(url).await +} + async fn validate_public_https_url(url: &Url) -> Result<(), String> { if url.scheme() != "https" || url.username() != "" || url.password().is_some() { return Err("link previews require an HTTPS URL without credentials".to_string()); @@ -182,11 +203,15 @@ async fn validate_public_https_url(url: &Url) -> Result<(), String> { async fn resolve_public_addresses(host: &str) -> Result, String> { let host = host.to_string(); - let addresses = tokio::net::lookup_host((host.as_str(), 443)) - .await - .map_err(|error| format!("link preview DNS resolution failed: {error}"))? - .map(|address| address.ip()) - .collect::>(); + let addresses = tokio::time::timeout( + DNS_RESOLUTION_TIMEOUT, + tokio::net::lookup_host((host.as_str(), 443)), + ) + .await + .map_err(|_| "link preview DNS resolution timed out".to_string())? + .map_err(|error| format!("link preview DNS resolution failed: {error}"))? + .map(|address| address.ip()) + .collect::>(); if addresses.is_empty() { return Err("link preview DNS resolution returned no addresses".to_string()); @@ -198,6 +223,25 @@ async fn resolve_public_addresses(host: &str) -> Result, String> { Ok(addresses) } +#[cfg(test)] +tokio::task_local! { + static METADATA_TEST_SERVER: std::net::SocketAddr; +} + +async fn send_metadata_request(url: &Url, accept: &str) -> Result { + #[cfg(test)] + if let Ok(address) = METADATA_TEST_SERVER.try_with(|address| *address) { + return reqwest::Client::new() + .get(format!("http://{address}{}", url.path())) + .header(ACCEPT, accept) + .send() + .await + .map_err(|error| format!("link preview test request failed: {error}")); + } + + send_pinned_request(url, accept).await +} + async fn send_pinned_request(url: &Url, accept: &str) -> Result { let host = url .host_str() @@ -211,6 +255,8 @@ async fn send_pinned_request(url: &Url, accept: &str) -> Result Result bool { + if *waited_for_cooldown { + return false; + } + *waited_for_cooldown = true; + tokio::time::sleep(retry_after).await; + true +} + +fn retryable_image_cooldown( + url: &Url, + retry_after: Option, + waited_for_cooldown: &mut bool, +) -> Option { + let retry_after = retry_after?; + if *waited_for_cooldown { + return None; + } + set_image_host_cooldown(url, retry_after); + if retry_after > MAX_INLINE_IMAGE_COOLDOWN { + return None; + } + *waited_for_cooldown = true; + Some(retry_after) +} + async fn fetch_sanitized_image( - mut url: Url, + url: Url, preserve_transparency: bool, ) -> Result<(String, String), ImageFetchError> { - validate_public_https_url(&url) + fetch_sanitized_image_using( + url, + preserve_transparency, + |url| async move { validate_public_https_url(&url).await }, + |url, accept| async move { send_pinned_request(&url, accept).await }, + ) + .await +} + +async fn fetch_sanitized_image_using( + mut url: Url, + preserve_transparency: bool, + mut validate_url: V, + mut send_request: F, +) -> Result<(String, String), ImageFetchError> +where + V: FnMut(Url) -> VFut, + VFut: std::future::Future>, + F: FnMut(Url, &'static str) -> Fut, + Fut: std::future::Future>, +{ + validate_url(url.clone()) .await .map_err(|_| ImageFetchError::Rejected)?; - for redirect_count in 0..=MAX_REDIRECTS { + let mut redirect_count = 0; + let mut waited_for_cooldown = false; + while redirect_count <= MAX_REDIRECTS { if let Some(retry_after) = image_host_cooldown_remaining(&url) { - return Err(ImageFetchError::Transient { - retry_after: Some(retry_after), - retry_inline: false, - }); + if retry_after > MAX_INLINE_IMAGE_COOLDOWN + || !wait_for_image_host_cooldown(&mut waited_for_cooldown, retry_after).await + { + return Err(ImageFetchError::Transient { + retry_after: Some(retry_after), + retry_inline: false, + }); + } + continue; } - let response = send_pinned_request(&url, "image/jpeg,image/png,image/webp") + + let host_gate = image_host_gate(&url); + let host_guard = host_gate.lock().await; + if image_host_cooldown_remaining(&url).is_some() { + continue; + } + let response = send_request(url.clone(), "image/jpeg,image/png,image/webp") .await .map_err(|_| ImageFetchError::Transient { retry_after: None, - retry_inline: true, + retry_inline: !waited_for_cooldown, })?; if response.status().is_redirection() { if redirect_count == MAX_REDIRECTS { @@ -370,9 +479,10 @@ async fn fetch_sanitized_image( .and_then(|value| value.to_str().ok()) .ok_or(ImageFetchError::Rejected)?; url = url.join(location).map_err(|_| ImageFetchError::Rejected)?; - validate_public_https_url(&url) + validate_url(url.clone()) .await .map_err(|_| ImageFetchError::Rejected)?; + redirect_count += 1; continue; } if !response.status().is_success() { @@ -383,12 +493,18 @@ async fn fetch_sanitized_image( || status.is_server_error() { let retry_after = retry_after_duration(&response); - if let Some(retry_after) = retry_after { - set_image_host_cooldown(&url, retry_after); + if let Some(retry_after) = + retryable_image_cooldown(&url, retry_after, &mut waited_for_cooldown) + { + drop(host_guard); + tokio::time::sleep(retry_after).await; + continue; } return Err(ImageFetchError::Transient { retry_after, - retry_inline: status != reqwest::StatusCode::TOO_MANY_REQUESTS, + retry_inline: retry_after.is_none() + && status != reqwest::StatusCode::TOO_MANY_REQUESTS + && !waited_for_cooldown, }); } return Err(ImageFetchError::Rejected); @@ -677,315 +793,5 @@ fn decode_html_entities(value: &str) -> String { } #[cfg(test)] -mod tests { - use super::rate_limit::MAX_IMAGE_RETRY_AFTER; - use super::{ - apply_image_result, declares_animation, extract_favicon_url, extract_image_url, - extract_link_preview_metadata, is_html_response, read_bytes_prefix, retry_after_duration, - sanitize_image, ImageFetchError, LinkPreviewImageFetchState, LinkPreviewMetadata, - MAX_METADATA_DESCRIPTION_CHARS, - }; - use axum::{body::Body, http::Response, routing::get, Router}; - use base64::Engine as _; - use bytes::Bytes; - use futures_util::stream; - use image::{DynamicImage, ImageFormat, Rgb, RgbImage, Rgba, RgbaImage}; - use std::{convert::Infallible, io::Cursor}; - use url::Url; - - async fn test_response(router: Router, path: &str) -> reqwest::Response { - let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); - let address = listener.local_addr().unwrap(); - tokio::spawn(async move { - axum::serve(listener, router).await.unwrap(); - }); - reqwest::get(format!("http://{address}{path}")) - .await - .unwrap() - } - - #[test] - fn metadata_prefers_open_graph_and_reads_site_name() { - let html = r#" - - - Fallback"#; - assert_eq!( - extract_link_preview_metadata(html), - Some(LinkPreviewMetadata { - title: "Rich previews & cards".to_string(), - site_name: Some("Buzz".to_string()), - description: Some("Safe & useful previews".to_string()), - image_data_url: None, - image_domain: None, - image_fetch_state: LinkPreviewImageFetchState::None, - image_retry_after_ms: None, - favicon_data_url: None, - }) - ); - } - - #[test] - fn image_results_preserve_absence_and_classify_recovery() { - let mut metadata = extract_link_preview_metadata("Preview result").unwrap(); - apply_image_result(&mut metadata, None); - assert_eq!(metadata.image_fetch_state, LinkPreviewImageFetchState::None); - - apply_image_result( - &mut metadata, - Some(Err(ImageFetchError::Transient { - retry_after: Some(std::time::Duration::from_secs(15)), - retry_inline: false, - })), - ); - assert_eq!( - metadata.image_fetch_state, - LinkPreviewImageFetchState::TransientFailure - ); - assert_eq!(metadata.image_retry_after_ms, Some(15_000)); - - apply_image_result( - &mut metadata, - Some(Ok(( - "data:image/jpeg;base64,abc".to_string(), - "images.example.com".to_string(), - ))), - ); - assert_eq!( - metadata.image_fetch_state, - LinkPreviewImageFetchState::Image - ); - assert_eq!(metadata.image_domain.as_deref(), Some("images.example.com")); - } - - #[test] - fn metadata_falls_back_to_twitter_then_title() { - assert_eq!( - extract_link_preview_metadata("") - .map(|metadata| metadata.title), - Some("Tweet title".to_string()) - ); - assert_eq!( - extract_link_preview_metadata(" Plain title ") - .map(|metadata| metadata.title), - Some("Plain title".to_string()) - ); - } - - #[test] - fn metadata_preserves_description_line_breaks() { - let html = r#" - "#; - assert_eq!( - extract_link_preview_metadata(html).and_then(|metadata| metadata.description), - Some("First paragraph.\n\nAgents:\n- One\n- Two".to_string()) - ); - } - - #[test] - fn metadata_description_supports_standard_x_posts() { - let description = "x".repeat(MAX_METADATA_DESCRIPTION_CHARS + 1); - let html = format!( - r#""# - ); - let extracted = extract_link_preview_metadata(&html) - .and_then(|metadata| metadata.description) - .unwrap(); - assert_eq!(extracted.chars().count(), MAX_METADATA_DESCRIPTION_CHARS); - } - - #[test] - fn favicon_metadata_resolves_relative_icon_links() { - let page = Url::parse("https://example.com/articles/one").unwrap(); - let html = r#" - "#; - assert_eq!( - extract_favicon_url(html, &page).unwrap().as_str(), - "https://example.com/favicon.png" - ); - } - - #[test] - fn favicon_metadata_prefers_a_supported_raster_candidate() { - let page = Url::parse("https://github.com/block/buzz").unwrap(); - let html = r#" - - "#; - assert_eq!( - extract_favicon_url(html, &page).unwrap().as_str(), - "https://assets.example/favicon.png" - ); - } - - #[test] - fn favicon_metadata_uses_touch_icon_before_unsupported_ico() { - let page = Url::parse("https://twitter.com/tellaho").unwrap(); - let html = r#" - "#; - assert_eq!( - extract_favicon_url(html, &page).unwrap().as_str(), - "https://twitter.com/apple-touch-icon.png" - ); - } - - #[test] - fn image_metadata_resolves_relative_urls_and_prefers_open_graph() { - let page = Url::parse("https://example.com/articles/one").unwrap(); - let html = r#" - "#; - assert_eq!( - extract_image_url(html, &page).unwrap().as_str(), - "https://example.com/preview.png" - ); - } - - #[tokio::test] - async fn oversized_html_uses_metadata_within_the_bounded_prefix() { - const LIMIT: usize = 256; - let metadata = r#""#; - let body = format!("{metadata}{}", "x".repeat(LIMIT)); - let response = test_response( - Router::new().route( - "/declared", - get(move || { - let body = body.clone(); - async move { - Response::builder() - .header("content-type", "text/html") - .body(Body::from(body)) - .unwrap() - } - }), - ), - "/declared", - ) - .await; - assert!(response - .content_length() - .is_some_and(|size| size > LIMIT as u64)); - assert!(is_html_response(&response)); - - let prefix = read_bytes_prefix(response, LIMIT).await.unwrap(); - assert_eq!(prefix.len(), LIMIT); - let html = String::from_utf8_lossy(&prefix); - assert_eq!( - extract_link_preview_metadata(&html).map(|metadata| metadata.title), - Some("Prefix title".to_string()) - ); - assert!(extract_image_url(&html, &Url::parse("https://example.com").unwrap()).is_some()); - } - - #[tokio::test] - async fn image_retry_after_uses_bounded_delta_seconds() { - let response = test_response( - Router::new().route( - "/rate-limited", - get(|| async { - Response::builder() - .status(429) - .header("retry-after", "900") - .body(Body::empty()) - .unwrap() - }), - ), - "/rate-limited", - ) - .await; - assert_eq!( - retry_after_duration(&response), - Some(std::time::Duration::from_secs(900)) - ); - - let response = test_response( - Router::new().route( - "/excessive", - get(|| async { - Response::builder() - .status(429) - .header("retry-after", "7200") - .body(Body::empty()) - .unwrap() - }), - ), - "/excessive", - ) - .await; - assert_eq!(retry_after_duration(&response), Some(MAX_IMAGE_RETRY_AFTER)); - } - - #[tokio::test] - async fn oversized_chunked_html_ignores_metadata_beyond_the_bounded_prefix() { - const LIMIT: usize = 256; - let response = test_response( - Router::new().route( - "/chunked", - get(|| async { - let chunks = stream::iter([ - Ok::<_, Infallible>(Bytes::from(vec![b'x'; LIMIT])), - Ok(Bytes::from_static( - br#""#, - )), - ]); - Response::builder() - .header("content-type", "text/html") - .body(Body::from_stream(chunks)) - .unwrap() - }), - ), - "/chunked", - ) - .await; - assert_eq!(response.content_length(), None); - - let prefix = read_bytes_prefix(response, LIMIT).await.unwrap(); - assert_eq!(prefix.len(), LIMIT); - let html = String::from_utf8_lossy(&prefix); - assert_eq!(extract_link_preview_metadata(&html), None); - assert_eq!( - extract_image_url(&html, &Url::parse("https://example.com").unwrap()), - None - ); - } - - #[test] - fn sanitizer_rejects_mime_mismatch_and_outputs_static_jpeg() { - let source = DynamicImage::ImageRgb8(RgbImage::from_pixel(2, 2, Rgb([10, 20, 30]))); - let mut png = Cursor::new(Vec::new()); - source.write_to(&mut png, ImageFormat::Png).unwrap(); - assert!(sanitize_image(png.get_ref(), "image/jpeg", false).is_err()); - let sanitized = sanitize_image(png.get_ref(), "image/png", false).unwrap(); - assert!(sanitized.starts_with("data:image/jpeg;base64,")); - } - - #[test] - fn favicon_sanitizer_preserves_png_transparency() { - let source = DynamicImage::ImageRgba8(RgbaImage::from_pixel(2, 2, Rgba([36, 41, 47, 0]))); - let mut png = Cursor::new(Vec::new()); - source.write_to(&mut png, ImageFormat::Png).unwrap(); - - let sanitized = sanitize_image(png.get_ref(), "image/png", true).unwrap(); - assert!(sanitized.starts_with("data:image/png;base64,")); - let encoded = sanitized.split_once(',').unwrap().1; - let bytes = base64::engine::general_purpose::STANDARD - .decode(encoded) - .unwrap(); - assert!(image::load_from_memory(&bytes).unwrap().color().has_alpha()); - } - - #[test] - fn animation_markers_are_rejected_before_decode() { - let mut apng = b"\x89PNG\r\n\x1a\n".to_vec(); - apng.extend_from_slice(b"junkacTLjunk"); - assert!(declares_animation(&apng, ImageFormat::Png)); - - let mut webp = b"RIFF\x00\x00\x00\x00WEBPVP8X\x0a\x00\x00\x00".to_vec(); - webp.push(0x02); - assert!(declares_animation(&webp, ImageFormat::WebP)); - } - - #[test] - fn metadata_requires_a_non_empty_title() { - assert_eq!(extract_link_preview_metadata(" "), None); - assert_eq!(extract_link_preview_metadata(""), None); - } -} +#[path = "link_preview_tests.rs"] +mod tests; diff --git a/desktop/src-tauri/src/commands/link_preview_cancellation.rs b/desktop/src-tauri/src/commands/link_preview_cancellation.rs new file mode 100644 index 0000000000..38be2b3a38 --- /dev/null +++ b/desktop/src-tauri/src/commands/link_preview_cancellation.rs @@ -0,0 +1,89 @@ +use std::{ + collections::HashMap, + sync::{LazyLock, Mutex}, +}; + +use tokio_util::sync::CancellationToken; + +#[derive(Default)] +struct LinkPreviewCancellations { + tokens: HashMap, +} + +impl LinkPreviewCancellations { + fn begin(&mut self, request_id: &str) -> CancellationToken { + if let Some(cancellation) = self.tokens.get(request_id).cloned() { + return cancellation; + } + let cancellation = CancellationToken::new(); + self.tokens + .insert(request_id.to_string(), cancellation.clone()); + cancellation + } + + fn cancel(&mut self, request_id: &str) { + self.tokens + .entry(request_id.to_string()) + .or_default() + .cancel(); + } + + fn finish(&mut self, request_id: &str) { + self.tokens.remove(request_id); + } +} + +static LINK_PREVIEW_CANCELLATIONS: LazyLock> = + LazyLock::new(|| Mutex::new(LinkPreviewCancellations::default())); + +pub(super) fn begin(request_id: Option<&str>) -> Option { + let request_id = request_id?; + LINK_PREVIEW_CANCELLATIONS + .lock() + .ok() + .map(|mut fetches| fetches.begin(request_id)) +} + +pub(super) fn cancel(request_id: &str) { + if let Ok(mut fetches) = LINK_PREVIEW_CANCELLATIONS.lock() { + fetches.cancel(request_id); + } +} + +pub(super) fn finish(request_id: Option<&str>) { + let Some(request_id) = request_id else { + return; + }; + if let Ok(mut fetches) = LINK_PREVIEW_CANCELLATIONS.lock() { + fetches.finish(request_id); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cancellation_before_begin_is_retained() { + let mut fetches = LinkPreviewCancellations::default(); + fetches.cancel("cancel-before-begin"); + + let cancellation = fetches.begin("cancel-before-begin"); + + assert!(cancellation.is_cancelled()); + fetches.finish("cancel-before-begin"); + assert!(fetches.tokens.is_empty()); + } + + #[test] + fn cancellation_reaches_active_owner() { + let mut fetches = LinkPreviewCancellations::default(); + let cancellation = fetches.begin("active-fetch"); + + fetches.cancel("active-fetch"); + + assert!(cancellation.is_cancelled()); + fetches.finish("active-fetch"); + assert!(fetches.tokens.is_empty()); + } +} diff --git a/desktop/src-tauri/src/commands/link_preview_rate_limit.rs b/desktop/src-tauri/src/commands/link_preview_rate_limit.rs index c3f7ed7188..46032fc5f0 100644 --- a/desktop/src-tauri/src/commands/link_preview_rate_limit.rs +++ b/desktop/src-tauri/src/commands/link_preview_rate_limit.rs @@ -1,16 +1,31 @@ use std::{ - collections::HashMap, - sync::{Mutex, OnceLock}, - time::{Duration, Instant}, + collections::{hash_map::DefaultHasher, HashMap}, + hash::{Hash, Hasher}, + sync::{LazyLock, Mutex, OnceLock}, + time::Duration, }; use reqwest::header::RETRY_AFTER; +use tokio::{sync::Mutex as AsyncMutex, time::Instant}; use url::Url; pub(super) const MAX_IMAGE_RETRY_AFTER: Duration = Duration::from_secs(60 * 60); const MAX_IMAGE_HOST_COOLDOWNS: usize = 128; +const IMAGE_HOST_GATE_COUNT: usize = 64; static IMAGE_HOST_COOLDOWNS: OnceLock>> = OnceLock::new(); +// A bounded stripe table serializes image requests by host without retaining an +// unbounded attacker-controlled hostname map. Hash collisions only make two +// unrelated hosts wait for one another; they never weaken the host boundary. +static IMAGE_HOST_GATES: LazyLock<[AsyncMutex<()>; IMAGE_HOST_GATE_COUNT]> = + LazyLock::new(|| std::array::from_fn(|_| AsyncMutex::new(()))); + +pub(super) fn image_host_gate(url: &Url) -> &'static AsyncMutex<()> { + let mut hasher = DefaultHasher::new(); + url.host_str().unwrap_or_default().hash(&mut hasher); + let index = (hasher.finish() as usize) % IMAGE_HOST_GATE_COUNT; + &IMAGE_HOST_GATES[index] +} pub(super) fn retry_after_duration(response: &reqwest::Response) -> Option { response diff --git a/desktop/src-tauri/src/commands/link_preview_tests.rs b/desktop/src-tauri/src/commands/link_preview_tests.rs new file mode 100644 index 0000000000..05ab0eec2c --- /dev/null +++ b/desktop/src-tauri/src/commands/link_preview_tests.rs @@ -0,0 +1,604 @@ +use super::rate_limit::MAX_IMAGE_RETRY_AFTER; +use super::{ + apply_image_result, cancel_link_preview_metadata, declares_animation, extract_favicon_url, + extract_image_url, extract_link_preview_metadata, fetch_link_preview_metadata, + fetch_sanitized_image_using, is_html_response, read_bytes_prefix, retry_after_duration, + retryable_image_cooldown, sanitize_image, ImageFetchError, LinkPreviewImageFetchState, + LinkPreviewMetadata, MAX_INLINE_IMAGE_COOLDOWN, MAX_METADATA_DESCRIPTION_CHARS, +}; +use axum::{body::Body, http::Response, routing::get, Router}; +use base64::Engine as _; +use bytes::Bytes; +use futures_util::stream; +use image::{DynamicImage, ImageFormat, Rgb, RgbImage, Rgba, RgbaImage}; +use std::{ + convert::Infallible, + io::Cursor, + sync::{Arc, Mutex}, +}; +use tokio::sync::oneshot; +use url::Url; + +async fn start_test_server(router: Router) -> std::net::SocketAddr { + let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); + let address = listener.local_addr().unwrap(); + tokio::spawn(async move { + axum::serve(listener, router).await.unwrap(); + }); + address +} + +async fn test_response(router: Router, path: &str) -> reqwest::Response { + let address = start_test_server(router).await; + reqwest::get(format!("http://{address}{path}")) + .await + .unwrap() +} + +#[tokio::test(start_paused = true)] +async fn metadata_pipeline_remains_pending_beyond_former_aggregate_deadline() { + let (request_started_tx, request_started_rx) = oneshot::channel::<()>(); + let request_started_tx = Arc::new(Mutex::new(Some(request_started_tx))); + let (release_response_tx, release_response_rx) = oneshot::channel::<()>(); + let release_response_rx = Arc::new(Mutex::new(Some(release_response_rx))); + let address = start_test_server(Router::new().route( + "/preview", + get(move || { + let request_started_tx = Arc::clone(&request_started_tx); + let release_response_rx = Arc::clone(&release_response_rx); + async move { + request_started_tx + .lock() + .unwrap() + .take() + .unwrap() + .send(()) + .unwrap(); + let release_response_rx = release_response_rx.lock().unwrap().take().unwrap(); + release_response_rx.await.unwrap(); + Response::builder() + .header("content-type", "text/html") + .body(Body::from("User-paced metadata")) + .unwrap() + } + }), + )) + .await; + let fetch = tokio::spawn(super::METADATA_TEST_SERVER.scope( + address, + fetch_link_preview_metadata("https://user-paced.example/preview".to_string(), None), + )); + + request_started_rx.await.unwrap(); + tokio::time::advance(std::time::Duration::from_secs(11)).await; + assert!(!fetch.is_finished()); + + release_response_tx.send(()).unwrap(); + let metadata = fetch.await.unwrap().unwrap().unwrap(); + assert_eq!(metadata.title, "User-paced metadata"); +} + +#[tokio::test] +async fn metadata_command_cancellation_drops_an_in_flight_response() { + let (request_started_tx, request_started_rx) = oneshot::channel::<()>(); + let request_started_tx = Arc::new(Mutex::new(Some(request_started_tx))); + let (_release_response_tx, release_response_rx) = oneshot::channel::<()>(); + let release_response_rx = Arc::new(Mutex::new(Some(release_response_rx))); + let address = start_test_server(Router::new().route( + "/preview", + get(move || { + let request_started_tx = Arc::clone(&request_started_tx); + let release_response_rx = Arc::clone(&release_response_rx); + async move { + request_started_tx + .lock() + .unwrap() + .take() + .unwrap() + .send(()) + .unwrap(); + let release_response_rx = release_response_rx.lock().unwrap().take().unwrap(); + let _ = release_response_rx.await; + Response::builder() + .header("content-type", "text/html") + .body(Body::from("Too late")) + .unwrap() + } + }), + )) + .await; + let request_id = "cancel-in-flight".to_string(); + let fetch = tokio::spawn(super::METADATA_TEST_SERVER.scope( + address, + fetch_link_preview_metadata( + "https://cancel.example/preview".to_string(), + Some(request_id.clone()), + ), + )); + + request_started_rx.await.unwrap(); + cancel_link_preview_metadata(request_id); + + assert_eq!( + fetch.await.unwrap(), + Err("link preview request cancelled".to_string()) + ); +} + +#[tokio::test(start_paused = true)] +async fn first_rate_limit_and_queued_host_request_share_one_cooldown_boundary() { + let cooldown = std::time::Duration::from_secs(20); + let rate_limited_path = "/rate-limited.png"; + let success_path = "/success.png"; + let url = Url::parse(&format!( + "https://rate-limit-regression.example{rate_limited_path}" + )) + .unwrap(); + let attempts = Arc::new(Mutex::new(0)); + let collision_attempts = Arc::new(Mutex::new(0)); + let image = DynamicImage::ImageRgb8(RgbImage::from_pixel(2, 2, Rgb([10, 20, 30]))); + let mut png = Cursor::new(Vec::new()); + image.write_to(&mut png, ImageFormat::Png).unwrap(); + let image_bytes = png.into_inner(); + let server_attempts = Arc::clone(&attempts); + let address = start_test_server(Router::new().route( + "/{image}", + get( + move |axum::extract::Path(image): axum::extract::Path| { + let image_bytes = image_bytes.clone(); + let server_attempts = Arc::clone(&server_attempts); + async move { + if image == "rate-limited.png" { + let attempt = { + let mut attempts = server_attempts.lock().unwrap(); + *attempts += 1; + *attempts + }; + if attempt == 1 { + return Response::builder() + .status(429) + .header("retry-after", cooldown.as_secs()) + .body(Body::empty()) + .unwrap(); + } + } + Response::builder() + .header("content-type", "image/png") + .body(Body::from(image_bytes)) + .unwrap() + } + }, + ), + )) + .await; + let test_client = reqwest::Client::new(); + let request = move |url: Url, _accept: &'static str| { + let test_client = test_client.clone(); + async move { + test_client + .get(format!("http://{address}{}", url.path())) + .send() + .await + .map_err(|error| error.to_string()) + } + }; + let collision_request = { + let collision_attempts = Arc::clone(&collision_attempts); + let test_client = reqwest::Client::new(); + move |url: Url, _accept: &'static str| { + let collision_attempts = Arc::clone(&collision_attempts); + let test_client = test_client.clone(); + async move { + *collision_attempts.lock().unwrap() += 1; + test_client + .get(format!("http://{address}{}", url.path())) + .send() + .await + .map_err(|error| error.to_string()) + } + } + }; + let validate = |_url: Url| async { Ok(()) }; + let first = tokio::spawn(fetch_sanitized_image_using( + url.clone(), + false, + validate, + request.clone(), + )); + while super::image_host_cooldown_remaining(&url).is_none() { + tokio::task::yield_now().await; + } + assert!(!first.is_finished()); + assert_eq!(*attempts.lock().unwrap(), 1); + assert_eq!(super::image_host_cooldown_remaining(&url), Some(cooldown)); + + let colliding_url = (0..10_000) + .map(|index| { + Url::parse(&format!("https://collision-{index}.example{success_path}")).unwrap() + }) + .find(|candidate| { + std::ptr::eq( + super::image_host_gate(candidate), + super::image_host_gate(&url), + ) + }) + .expect("a different host sharing the bounded gate stripe"); + + let (collision_started_tx, collision_started_rx) = oneshot::channel(); + tokio::spawn(async move { + let collision = + fetch_sanitized_image_using(colliding_url, false, validate, collision_request); + tokio::pin!(collision); + assert!(futures_util::poll!(&mut collision).is_pending()); + collision_started_tx.send(()).ok(); + assert!(collision.await.is_ok()); + }); + collision_started_rx.await.unwrap(); + assert_eq!(*collision_attempts.lock().unwrap(), 1); + assert_eq!(*attempts.lock().unwrap(), 1); + + let queued = tokio::spawn(fetch_sanitized_image_using(url, false, validate, request)); + tokio::task::yield_now().await; + assert!(!queued.is_finished()); + assert_eq!(*attempts.lock().unwrap(), 1); + + tokio::time::advance(cooldown - std::time::Duration::from_millis(1)).await; + assert!(!first.is_finished()); + assert!(!queued.is_finished()); + assert_eq!(*attempts.lock().unwrap(), 1); + + tokio::time::advance(std::time::Duration::from_millis(1)).await; + let (first, queued) = tokio::join!(first, queued); + assert!(first.unwrap().is_ok()); + assert!(queued.unwrap().is_ok()); + assert_eq!(*attempts.lock().unwrap(), 3); +} + +#[tokio::test(start_paused = true)] +async fn transport_failure_after_cooldown_does_not_renew_wait_on_outer_retry() { + let cooldown = std::time::Duration::from_secs(20); + let url = Url::parse("https://transport-after-cooldown.example/image.png").unwrap(); + super::set_image_host_cooldown(&url, cooldown); + let attempts = Arc::new(Mutex::new(0)); + + let result = super::image_retry::retry_transient_image_fetch(|| { + let url = url.clone(); + let attempts = Arc::clone(&attempts); + async move { + fetch_sanitized_image_using( + url, + false, + |_url| async { Ok(()) }, + move |_url, _accept| { + let attempts = Arc::clone(&attempts); + async move { + *attempts.lock().unwrap() += 1; + Err("connection failed".to_string()) + } + }, + ) + .await + } + }) + .await; + + assert_eq!( + result, + Err(ImageFetchError::Transient { + retry_after: None, + retry_inline: false, + }) + ); + assert_eq!(*attempts.lock().unwrap(), 1); +} + +#[test] +fn image_cooldown_wait_is_short_and_one_shot() { + let url = Url::parse("https://bounded-cooldown.example/image.png").unwrap(); + let mut waited = false; + assert_eq!( + retryable_image_cooldown(&url, Some(MAX_INLINE_IMAGE_COOLDOWN), &mut waited,), + Some(MAX_INLINE_IMAGE_COOLDOWN) + ); + assert!(waited); + assert_eq!( + retryable_image_cooldown(&url, Some(MAX_INLINE_IMAGE_COOLDOWN), &mut waited,), + None + ); + let excessive_url = Url::parse("https://excessive-cooldown.example/image.png").unwrap(); + let mut excessive_waited = false; + assert_eq!( + retryable_image_cooldown( + &excessive_url, + Some(MAX_INLINE_IMAGE_COOLDOWN + std::time::Duration::from_secs(1)), + &mut excessive_waited, + ), + None + ); + assert!(!excessive_waited); +} + +#[test] +fn metadata_prefers_open_graph_and_reads_site_name() { + let html = r#" + + + Fallback"#; + assert_eq!( + extract_link_preview_metadata(html), + Some(LinkPreviewMetadata { + title: "Rich previews & cards".to_string(), + site_name: Some("Buzz".to_string()), + description: Some("Safe & useful previews".to_string()), + image_data_url: None, + image_domain: None, + image_fetch_state: LinkPreviewImageFetchState::None, + image_retry_after_ms: None, + favicon_data_url: None, + }) + ); +} + +#[test] +fn image_results_preserve_absence_and_classify_recovery() { + let mut metadata = extract_link_preview_metadata("Preview result").unwrap(); + apply_image_result(&mut metadata, None); + assert_eq!(metadata.image_fetch_state, LinkPreviewImageFetchState::None); + + apply_image_result( + &mut metadata, + Some(Err(ImageFetchError::Transient { + retry_after: Some(std::time::Duration::from_secs(15)), + retry_inline: false, + })), + ); + assert_eq!( + metadata.image_fetch_state, + LinkPreviewImageFetchState::TransientFailure + ); + assert_eq!(metadata.image_retry_after_ms, Some(15_000)); + + apply_image_result( + &mut metadata, + Some(Ok(( + "data:image/jpeg;base64,abc".to_string(), + "images.example.com".to_string(), + ))), + ); + assert_eq!( + metadata.image_fetch_state, + LinkPreviewImageFetchState::Image + ); + assert_eq!(metadata.image_domain.as_deref(), Some("images.example.com")); +} + +#[test] +fn metadata_falls_back_to_twitter_then_title() { + assert_eq!( + extract_link_preview_metadata("") + .map(|metadata| metadata.title), + Some("Tweet title".to_string()) + ); + assert_eq!( + extract_link_preview_metadata(" Plain title ") + .map(|metadata| metadata.title), + Some("Plain title".to_string()) + ); +} + +#[test] +fn metadata_preserves_description_line_breaks() { + let html = r#" + "#; + assert_eq!( + extract_link_preview_metadata(html).and_then(|metadata| metadata.description), + Some("First paragraph.\n\nAgents:\n- One\n- Two".to_string()) + ); +} + +#[test] +fn metadata_description_supports_standard_x_posts() { + let description = "x".repeat(MAX_METADATA_DESCRIPTION_CHARS + 1); + let html = format!( + r#""# + ); + let extracted = extract_link_preview_metadata(&html) + .and_then(|metadata| metadata.description) + .unwrap(); + assert_eq!(extracted.chars().count(), MAX_METADATA_DESCRIPTION_CHARS); +} + +#[test] +fn favicon_metadata_resolves_relative_icon_links() { + let page = Url::parse("https://example.com/articles/one").unwrap(); + let html = r#" + "#; + assert_eq!( + extract_favicon_url(html, &page).unwrap().as_str(), + "https://example.com/favicon.png" + ); +} + +#[test] +fn favicon_metadata_prefers_a_supported_raster_candidate() { + let page = Url::parse("https://github.com/block/buzz").unwrap(); + let html = r#" + + "#; + assert_eq!( + extract_favicon_url(html, &page).unwrap().as_str(), + "https://assets.example/favicon.png" + ); +} + +#[test] +fn favicon_metadata_uses_touch_icon_before_unsupported_ico() { + let page = Url::parse("https://twitter.com/tellaho").unwrap(); + let html = r#" + "#; + assert_eq!( + extract_favicon_url(html, &page).unwrap().as_str(), + "https://twitter.com/apple-touch-icon.png" + ); +} + +#[test] +fn image_metadata_resolves_relative_urls_and_prefers_open_graph() { + let page = Url::parse("https://example.com/articles/one").unwrap(); + let html = r#" + "#; + assert_eq!( + extract_image_url(html, &page).unwrap().as_str(), + "https://example.com/preview.png" + ); +} + +#[tokio::test] +async fn oversized_html_uses_metadata_within_the_bounded_prefix() { + const LIMIT: usize = 256; + let metadata = r#""#; + let body = format!("{metadata}{}", "x".repeat(LIMIT)); + let response = test_response( + Router::new().route( + "/declared", + get(move || { + let body = body.clone(); + async move { + Response::builder() + .header("content-type", "text/html") + .body(Body::from(body)) + .unwrap() + } + }), + ), + "/declared", + ) + .await; + assert!(response + .content_length() + .is_some_and(|size| size > LIMIT as u64)); + assert!(is_html_response(&response)); + + let prefix = read_bytes_prefix(response, LIMIT).await.unwrap(); + assert_eq!(prefix.len(), LIMIT); + let html = String::from_utf8_lossy(&prefix); + assert_eq!( + extract_link_preview_metadata(&html).map(|metadata| metadata.title), + Some("Prefix title".to_string()) + ); + assert!(extract_image_url(&html, &Url::parse("https://example.com").unwrap()).is_some()); +} + +#[tokio::test] +async fn image_retry_after_uses_bounded_delta_seconds() { + let response = test_response( + Router::new().route( + "/rate-limited", + get(|| async { + Response::builder() + .status(429) + .header("retry-after", "900") + .body(Body::empty()) + .unwrap() + }), + ), + "/rate-limited", + ) + .await; + assert_eq!( + retry_after_duration(&response), + Some(std::time::Duration::from_secs(900)) + ); + + let response = test_response( + Router::new().route( + "/excessive", + get(|| async { + Response::builder() + .status(429) + .header("retry-after", "7200") + .body(Body::empty()) + .unwrap() + }), + ), + "/excessive", + ) + .await; + assert_eq!(retry_after_duration(&response), Some(MAX_IMAGE_RETRY_AFTER)); +} + +#[tokio::test] +async fn oversized_chunked_html_ignores_metadata_beyond_the_bounded_prefix() { + const LIMIT: usize = 256; + let response = test_response( + Router::new().route( + "/chunked", + get(|| async { + let chunks = stream::iter([ + Ok::<_, Infallible>(Bytes::from(vec![b'x'; LIMIT])), + Ok(Bytes::from_static( + br#""#, + )), + ]); + Response::builder() + .header("content-type", "text/html") + .body(Body::from_stream(chunks)) + .unwrap() + }), + ), + "/chunked", + ) + .await; + assert_eq!(response.content_length(), None); + + let prefix = read_bytes_prefix(response, LIMIT).await.unwrap(); + assert_eq!(prefix.len(), LIMIT); + let html = String::from_utf8_lossy(&prefix); + assert_eq!(extract_link_preview_metadata(&html), None); + assert_eq!( + extract_image_url(&html, &Url::parse("https://example.com").unwrap()), + None + ); +} + +#[test] +fn sanitizer_rejects_mime_mismatch_and_outputs_static_jpeg() { + let source = DynamicImage::ImageRgb8(RgbImage::from_pixel(2, 2, Rgb([10, 20, 30]))); + let mut png = Cursor::new(Vec::new()); + source.write_to(&mut png, ImageFormat::Png).unwrap(); + assert!(sanitize_image(png.get_ref(), "image/jpeg", false).is_err()); + let sanitized = sanitize_image(png.get_ref(), "image/png", false).unwrap(); + assert!(sanitized.starts_with("data:image/jpeg;base64,")); +} + +#[test] +fn favicon_sanitizer_preserves_png_transparency() { + let source = DynamicImage::ImageRgba8(RgbaImage::from_pixel(2, 2, Rgba([36, 41, 47, 0]))); + let mut png = Cursor::new(Vec::new()); + source.write_to(&mut png, ImageFormat::Png).unwrap(); + + let sanitized = sanitize_image(png.get_ref(), "image/png", true).unwrap(); + assert!(sanitized.starts_with("data:image/png;base64,")); + let encoded = sanitized.split_once(',').unwrap().1; + let bytes = base64::engine::general_purpose::STANDARD + .decode(encoded) + .unwrap(); + assert!(image::load_from_memory(&bytes).unwrap().color().has_alpha()); +} + +#[test] +fn animation_markers_are_rejected_before_decode() { + let mut apng = b"\x89PNG\r\n\x1a\n".to_vec(); + apng.extend_from_slice(b"junkacTLjunk"); + assert!(declares_animation(&apng, ImageFormat::Png)); + + let mut webp = b"RIFF\x00\x00\x00\x00WEBPVP8X\x0a\x00\x00\x00".to_vec(); + webp.push(0x02); + assert!(declares_animation(&webp, ImageFormat::WebP)); +} + +#[test] +fn metadata_requires_a_non_empty_title() { + assert_eq!(extract_link_preview_metadata(" "), None); + assert_eq!(extract_link_preview_metadata(""), None); +} diff --git a/desktop/src-tauri/src/commands/link_preview_youtube.rs b/desktop/src-tauri/src/commands/link_preview_youtube.rs index a0a5a753dc..b759046d8f 100644 --- a/desktop/src-tauri/src/commands/link_preview_youtube.rs +++ b/desktop/src-tauri/src/commands/link_preview_youtube.rs @@ -5,8 +5,8 @@ use url::Url; use super::{ apply_image_result, fetch_sanitized_image, normalize_metadata_description, - normalize_metadata_text, read_limited_bytes, send_pinned_request, ImageFetchError, - LinkPreviewImageFetchState, LinkPreviewMetadata, PREVIEW_FETCH_TIMEOUT, + normalize_metadata_text, read_limited_bytes, send_pinned_request, LinkPreviewImageFetchState, + LinkPreviewMetadata, }; const MAX_OEMBED_FETCH_BYTES: usize = 64 * 1024; @@ -54,17 +54,7 @@ pub(super) async fn fetch_oembed_metadata( return Ok(None); }; let image_result = match thumbnail_url { - Some(thumbnail_url) => Some( - tokio::time::timeout( - PREVIEW_FETCH_TIMEOUT, - fetch_sanitized_image(thumbnail_url, false), - ) - .await - .unwrap_or(Err(ImageFetchError::Transient { - retry_after: None, - retry_inline: false, - })), - ), + Some(thumbnail_url) => Some(fetch_sanitized_image(thumbnail_url, false).await), None => None, }; apply_image_result(&mut metadata, image_result); diff --git a/desktop/src-tauri/src/commands/workspace.rs b/desktop/src-tauri/src/commands/workspace.rs index 418f994fb3..c01c8473d9 100644 --- a/desktop/src-tauri/src/commands/workspace.rs +++ b/desktop/src-tauri/src/commands/workspace.rs @@ -353,7 +353,7 @@ pub async fn apply_workspace( } } }); - return Ok(()); + Ok(()) } #[cfg(not(feature = "mesh-llm"))] @@ -372,9 +372,11 @@ pub async fn apply_workspace( return Ok(()); } - assert_current_apply_generation(&state.workspace_apply_generation, apply_generation)?; - - Ok(()) + #[cfg(not(feature = "mesh-llm"))] + { + assert_current_apply_generation(&state.workspace_apply_generation, apply_generation)?; + Ok(()) + } } #[cfg(test)] diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index 12082a2a82..e3ac45953d 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -600,6 +600,8 @@ pub fn run() { get_relay_http_url, get_media_proxy_port, fetch_link_preview_metadata, + cancel_link_preview_metadata, + release_link_preview_metadata, discover_acp_auth_methods, discover_acp_providers, discover_git_bash_prerequisite, diff --git a/desktop/src-tauri/src/managed_agents/global_config/tests.rs b/desktop/src-tauri/src/managed_agents/global_config/tests.rs index 5f39b7b75f..5331b77e27 100644 --- a/desktop/src-tauri/src/managed_agents/global_config/tests.rs +++ b/desktop/src-tauri/src/managed_agents/global_config/tests.rs @@ -509,7 +509,7 @@ fn inherited_shared_compute_translates_to_supported_agent_transport() { ); assert_eq!( effective.env.get("BUZZ_AGENT_MODEL").map(String::as_str), - Some("auto") + Some(super::super::RELAY_MESH_VIRTUAL_MODEL_ID) ); assert_eq!( effective diff --git a/desktop/src-tauri/src/managed_agents/relay_mesh.rs b/desktop/src-tauri/src/managed_agents/relay_mesh.rs index 3858212bbb..b6d5e33f30 100644 --- a/desktop/src-tauri/src/managed_agents/relay_mesh.rs +++ b/desktop/src-tauri/src/managed_agents/relay_mesh.rs @@ -66,6 +66,21 @@ pub fn apply_relay_mesh_env( // survives (see `insert_default_if_unset`, and the copy-forward list in // `relay_mesh_process_env` that preserves it through the spawn path). insert_default_if_unset(env, "BUZZ_AGENT_REQUIRE_REPLY", "1"); + // A local mesh prefills a cold multi-ten-thousand-token prompt at a few + // hundred tokens/second, so the first turn of a large session legitimately + // runs for minutes with no bytes on the wire (`stream: false`). MeshLLM's + // own frontend gives such a request 600 s before it aborts + // (`OpenAiFrontendConfig::DEFAULT_BACKEND_TIMEOUT`); buzz-agent's 240 s + // default abandons it at four minutes, so the client gives up on work the + // server is still doing and retries it — adding load to a box that is + // already prefilling. Seat the client just above the server's budget so the + // mesh's own error is what surfaces, rather than a client-side abort racing + // it. Measured: an 88,318-token cold prompt on an M5 Max returns 200 at + // 503 s. Remote providers keep the 240 s default; only mesh moves. + // A default, not policy — an explicit user value survives via + // `insert_default_if_unset` and the copy-forward list in + // `relay_mesh_process_env`. + insert_default_if_unset(env, "BUZZ_AGENT_LLM_TIMEOUT_SECS", "660"); // Deliberately no BUZZ_AGENT_THINKING_EFFORT default: mesh translates // `reasoning_effort` into the chat template's `enable_thinking` flag, so any // value we pick overrides each model's own template default — and the right @@ -102,6 +117,10 @@ pub fn relay_mesh_process_env( for key in [ "BUZZ_AGENT_MAX_OUTPUT_TOKENS", "BUZZ_AGENT_THINKING_EFFORT", + // Same reason as `BUZZ_AGENT_REQUIRE_REPLY` below: without the + // copy-forward, an explicit user timeout is re-defaulted to 660 by + // `apply_relay_mesh_env`. + "BUZZ_AGENT_LLM_TIMEOUT_SECS", // Must be copied forward for the user's value to survive: this map is // written onto the command *after* the layered user env, so a key absent // here is re-defaulted by `apply_relay_mesh_env` below and an explicit @@ -270,6 +289,74 @@ mod tests { ); } + /// MeshLLM's frontend allows a backend call 600 s + /// (`OpenAiFrontendConfig::DEFAULT_BACKEND_TIMEOUT`). buzz-agent's 240 s + /// default abandons a healthy cold prefill long before the server does and + /// retries it, so the client budget must sit above the server's. + #[test] + fn native_provider_outlasts_the_mesh_backend_timeout() { + let mut env = BTreeMap::new(); + apply_relay_mesh_env( + &mut env, + Some(RELAY_MESH_PROVIDER_ID), + Some(RELAY_MESH_AUTO_MODEL_ID), + ); + + let seconds: u64 = env + .get("BUZZ_AGENT_LLM_TIMEOUT_SECS") + .expect("mesh seeds a client timeout") + .parse() + .expect("timeout is whole seconds"); + assert!( + seconds > 600, + "client budget ({seconds}s) must outlast the mesh frontend's 600s backend timeout" + ); + } + + #[test] + fn native_provider_preserves_explicit_llm_timeout() { + let mut env = + BTreeMap::from([("BUZZ_AGENT_LLM_TIMEOUT_SECS".to_string(), "90".to_string())]); + apply_relay_mesh_env( + &mut env, + Some(RELAY_MESH_PROVIDER_ID), + Some(RELAY_MESH_AUTO_MODEL_ID), + ); + + assert_eq!( + env.get("BUZZ_AGENT_LLM_TIMEOUT_SECS").map(String::as_str), + Some("90"), + "an explicit timeout is a user decision, not a value to re-default" + ); + } + + /// Same spawn-ordering hazard as the reply guard: without the copy-forward + /// in `relay_mesh_process_env`, the user's value is re-defaulted here. + #[test] + fn process_env_preserves_explicit_llm_timeout() { + let effective_env = + BTreeMap::from([("BUZZ_AGENT_LLM_TIMEOUT_SECS".to_string(), "90".to_string())]); + + let env = relay_mesh_process_env(&effective_env, "Gemma-4"); + + assert_eq!( + env.get("BUZZ_AGENT_LLM_TIMEOUT_SECS").map(String::as_str), + Some("90") + ); + } + + #[test] + fn non_mesh_provider_leaves_llm_timeout_unset() { + let mut env = BTreeMap::new(); + apply_relay_mesh_env(&mut env, Some("anthropic"), Some("claude-haiku-4.5")); + + assert_eq!( + env.get("BUZZ_AGENT_LLM_TIMEOUT_SECS"), + None, + "remote providers keep buzz-agent's own default" + ); + } + #[test] fn non_mesh_provider_leaves_reply_guard_unset() { let mut env = BTreeMap::new(); diff --git a/desktop/src-tauri/src/managed_agents/restore.rs b/desktop/src-tauri/src/managed_agents/restore.rs index 5b79ccac27..d29bec4a78 100644 --- a/desktop/src-tauri/src/managed_agents/restore.rs +++ b/desktop/src-tauri/src/managed_agents/restore.rs @@ -545,22 +545,6 @@ pub(crate) fn spawn_pending_profile_reconciliations(app: &tauri::AppHandle, work } } -#[cfg(test)] -mod profile_reconcile_tests { - use super::profile_reconcile_completed; - use crate::commands::ProfileReconcileOutcome; - - #[test] - fn skipped_reconciliation_never_retires_pending_work() { - assert!(profile_reconcile_completed( - ProfileReconcileOutcome::Reconciled - )); - assert!(!profile_reconcile_completed( - ProfileReconcileOutcome::SkippedDisabled - )); - } -} - #[cfg(feature = "mesh-llm")] fn persist_restore_error( app: &tauri::AppHandle, @@ -578,3 +562,19 @@ fn persist_restore_error( record.last_error = Some(error); save_managed_agents(app, &records) } + +#[cfg(test)] +mod profile_reconcile_tests { + use super::profile_reconcile_completed; + use crate::commands::ProfileReconcileOutcome; + + #[test] + fn skipped_reconciliation_never_retires_pending_work() { + assert!(profile_reconcile_completed( + ProfileReconcileOutcome::Reconciled + )); + assert!(!profile_reconcile_completed( + ProfileReconcileOutcome::SkippedDisabled + )); + } +} diff --git a/desktop/src-tauri/src/mesh_llm/catalog.rs b/desktop/src-tauri/src/mesh_llm/catalog.rs index 1a11fcfcd1..eb5d0c1cf1 100644 --- a/desktop/src-tauri/src/mesh_llm/catalog.rs +++ b/desktop/src-tauri/src/mesh_llm/catalog.rs @@ -13,38 +13,50 @@ use mesh_llm_system::hardware; use mesh_llm_system::vram::{format_rated_capacity, rated_capacity_gb}; /// Buzz-curated tier picks. These are the models we know survive the agent -/// harness on shared compute — deliberately non-reasoning instruction models, -/// so agents stay snappy instead of burning hidden reasoning tokens. +/// harness on shared compute. /// -/// The large pick is resolved through mesh-llm's remote catalog -/// (huggingface.co/datasets/meshllm/catalog), so it does not need to exist in -/// the compiled `MODEL_CATALOG`; the entry is synthesized below. -const CURATED_LARGE: &str = "unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M"; -const CURATED_LARGE_ALIAS: &str = "gemma-4-26B-A4B-it-UD-Q4_K_M"; -const CURATED_LARGE_SIZE: &str = "17GB"; -const CURATED_LARGE_FILE: &str = "gemma-4-26B-A4B-it-UD-Q4_K_M.gguf"; -const CURATED_LARGE_DESCRIPTION: &str = - "Gemma 4 26B MoE (4B active) — Buzz default for 64GB+ machines"; +/// The recommended ladder follows rated unified memory: +/// - below 32 GB: Gemma 4 E4B; +/// - 32 GB through the rated classes below 64 GB: Qwen3.5 9B; +/// - 64 GB and above: Qwen3.8 27B. +/// +/// The Qwen entries are canonicalized from mesh-llm's compiled +/// `MODEL_CATALOG` rather than synthesized. +const CURATED_LARGE: &str = "unsloth/Qwen3.8-27B-GGUF:Q4_K_M"; +const CURATED_LARGE_ALIAS: &str = "Qwen3.8-27B-Q4_K_M"; +const CURATED_MEDIUM: &str = "unsloth/Qwen3.5-9B-GGUF:Q4_K_M"; +const CURATED_MEDIUM_ALIAS: &str = "Qwen3.5-9B-Vision-Q4_K_M"; const CURATED_SMALL: &str = "unsloth/gemma-4-E4B-it-GGUF:Q4_K_M"; const CURATED_SMALL_ALIAS: &str = "Gemma-4-E4B-it-Q4_K_M"; -/// Rated-capacity boundary between the two curated tiers, in GB (marketing -/// capacity — a "64GB" Mac rates as 64 even though usable AI memory is less). +/// Superseded large alias retained only to preserve the historical string +/// canonicalization contract. Availability in a particular Mesh runtime is +/// determined by that runtime's compiled catalog. +const LEGACY_LARGE: &str = "unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M"; +const LEGACY_LARGE_ALIAS: &str = "gemma-4-26B-A4B-it-UD-Q4_K_M"; +/// Rated-capacity boundary for the balanced Qwen3.5 9B tier. +const CURATED_MEDIUM_MIN_RATED_GB: u64 = 32; +/// Qwen3.8 27B is recommended for 64 GB-and-larger rated capacity classes, +/// leaving substantial headroom beyond its observed working footprint for KV +/// cache and runtime use. const CURATED_LARGE_MIN_RATED_GB: u64 = 64; /// The Buzz-curated recommendation for a machine's rated memory capacity. fn buzz_recommended_model(rated_gb: Option) -> &'static str { match rated_gb { Some(gb) if gb >= CURATED_LARGE_MIN_RATED_GB => CURATED_LARGE, - _ => CURATED_SMALL, + Some(gb) if gb >= CURATED_MEDIUM_MIN_RATED_GB => CURATED_MEDIUM, + Some(_) | None => CURATED_SMALL, } } -/// Convert Buzz's pre-0.74 curated package aliases into the canonical model +/// Convert Buzz's historical curated package aliases into the canonical model /// ids advertised and accepted by Mesh's OpenAI ingress. pub(crate) fn canonical_curated_model_id(model_id: &str) -> &str { match model_id.trim() { CURATED_SMALL_ALIAS => CURATED_SMALL, + CURATED_MEDIUM_ALIAS => CURATED_MEDIUM, CURATED_LARGE_ALIAS => CURATED_LARGE, + LEGACY_LARGE_ALIAS => LEGACY_LARGE, other => other, } } @@ -172,31 +184,14 @@ fn build_catalog( }) .collect(); - // The compiled MODEL_CATALOG does not know the Buzz large pick; it - // resolves through mesh-llm's remote catalog at download time. Synthesize - // its entry so the picker can offer it. - if !entries.iter().any(|e| e.name == CURATED_LARGE) { - let size_gb = parse_size_gb(CURATED_LARGE_SIZE); - entries.push(MeshCatalogEntry { - fit: fit_code(size_gb, vram_gb), - installed: is_installed(CURATED_LARGE_FILE, CURATED_LARGE) - || is_installed(CURATED_LARGE_FILE, CURATED_LARGE_ALIAS), - recommended: false, - curated: false, - name: CURATED_LARGE.to_string(), - size: CURATED_LARGE_SIZE.to_string(), - size_gb, - description: CURATED_LARGE_DESCRIPTION.to_string(), - }); - } - let recommended = Some(buzz_recommended_model(rated_capacity_gb(vram_bytes)).to_string()); for entry in &mut entries { entry.recommended = recommended.as_deref() == Some(entry.name.as_str()); - // Both curated tiers are always offered: the recommended one for this - // machine plus the other pick (e.g. the small one as an explicit - // lighter choice on big machines). - entry.curated = entry.name == CURATED_LARGE || entry.name == CURATED_SMALL; + // All curated tiers are always offered: the recommendation plus + // lighter and heavier alternatives appropriate to other machine tiers. + entry.curated = entry.name == CURATED_LARGE + || entry.name == CURATED_MEDIUM + || entry.name == CURATED_SMALL; } entries.sort_by(|a, b| { @@ -269,20 +264,31 @@ mod tests { } #[test] - fn recommendation_follows_buzz_curated_tiers() { + fn recommendation_follows_buzz_curated_ladder() { assert_eq!(CURATED_SMALL, "unsloth/gemma-4-E4B-it-GGUF:Q4_K_M"); - assert_eq!(CURATED_LARGE, "unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M"); - // 64GB+ rated machines get the large curated pick. + assert_eq!(CURATED_MEDIUM, "unsloth/Qwen3.5-9B-GGUF:Q4_K_M"); + assert_eq!(CURATED_LARGE, "unsloth/Qwen3.8-27B-GGUF:Q4_K_M"); + + // Qwen3.8 is recommended for 64 GB-and-larger rated capacity classes. let large = build_catalog(None, 64_000_000_000, 64.0, &[]); assert_eq!(large.recommended.as_deref(), Some(CURATED_LARGE)); + let large_80 = build_catalog(None, 80_000_000_000, 80.0, &[]); + assert_eq!(large_80.recommended.as_deref(), Some(CURATED_LARGE)); let big = build_catalog(None, 128_000_000_000, 128.0, &[]); assert_eq!(big.recommended.as_deref(), Some(CURATED_LARGE)); - // Below the boundary: the small curated pick — never a reasoning - // model, never sub-4B guesswork. - let small = build_catalog(None, 32_000_000_000, 32.0, &[]); + + // The balanced Qwen3.5 tier covers every rated class from 32 GB up + // to (but not including) 64 GB. + let medium = build_catalog(None, 32_000_000_000, 32.0, &[]); + assert_eq!(medium.recommended.as_deref(), Some(CURATED_MEDIUM)); + let medium_max = build_catalog(None, 48_000_000_000, 48.0, &[]); + assert_eq!(medium_max.recommended.as_deref(), Some(CURATED_MEDIUM)); + + // Smaller and unknown machines use the light Gemma tier. + let small = build_catalog(None, 24_000_000_000, 24.0, &[]); assert_eq!(small.recommended.as_deref(), Some(CURATED_SMALL)); - let tiny = build_catalog(None, 16_000_000_000, 16.0, &[]); - assert_eq!(tiny.recommended.as_deref(), Some(CURATED_SMALL)); + let unknown = build_catalog(None, 0, 0.0, &[]); + assert_eq!(unknown.recommended.as_deref(), Some(CURATED_SMALL)); } #[test] @@ -291,10 +297,15 @@ mod tests { canonical_curated_model_id(CURATED_SMALL_ALIAS), CURATED_SMALL ); + assert_eq!( + canonical_curated_model_id(CURATED_MEDIUM_ALIAS), + CURATED_MEDIUM + ); assert_eq!( canonical_curated_model_id(CURATED_LARGE_ALIAS), CURATED_LARGE ); + assert_eq!(canonical_curated_model_id(LEGACY_LARGE_ALIAS), LEGACY_LARGE); assert_eq!( canonical_curated_model_id("other/model:Q4"), "other/model:Q4" @@ -304,14 +315,17 @@ mod tests { #[test] fn curated_picks_lead_the_catalog() { let catalog = build_catalog(None, 96_000_000_000, 96.0, &[]); - // Recommended curated entry first, the other curated pick second, - // advanced entries after. + // Recommended curated entry first, then the other two curated tiers, + // with advanced entries after them. assert_eq!(catalog.entries[0].name, CURATED_LARGE); assert!(catalog.entries[0].recommended && catalog.entries[0].curated); - assert_eq!(catalog.entries[1].name, CURATED_SMALL); + assert_eq!(catalog.entries[1].name, CURATED_MEDIUM); assert!(catalog.entries[1].curated && !catalog.entries[1].recommended); - assert!(catalog.entries[2..].iter().all(|e| !e.curated)); - // The synthesized large pick carries a real size for fit ranking. + assert_eq!(catalog.entries[2].name, CURATED_SMALL); + assert!(catalog.entries[2].curated && !catalog.entries[2].recommended); + assert!(catalog.entries[3..].iter().all(|e| !e.curated)); + // The large pick comes from the compiled catalog with a real size, so + // fit ranking is meaningful rather than a placeholder. assert!(catalog.entries[0].size_gb > 10.0); } diff --git a/desktop/src-tauri/src/mesh_llm/mod.rs b/desktop/src-tauri/src/mesh_llm/mod.rs index e206c53886..daab3c4b1c 100644 --- a/desktop/src-tauri/src/mesh_llm/mod.rs +++ b/desktop/src-tauri/src/mesh_llm/mod.rs @@ -34,9 +34,9 @@ mod usage; pub use usage::{serving_usage_from_payload, MeshServingUsage}; mod transport_policy; +use transport_policy::{iroh_relay_mode, sdk_iroh_relay_config, validate_advertised_endpoint}; #[cfg(test)] -use transport_policy::iroh_relay_mode_from; -use transport_policy::{iroh_relay_mode, validate_advertised_endpoint, IrohRelayMode}; +use transport_policy::{iroh_relay_mode_from, IrohRelayMode}; use mesh_llm_sdk::{client, serve, EmbeddedNodeHandle, MeshDiscoveryMode, TrustPolicy}; use serde::{Deserialize, Serialize}; @@ -376,13 +376,10 @@ impl DesktopMeshRuntime { if let Some(mesh_name) = request.mesh_name.as_deref() { builder = builder.mesh_name(mesh_name); } - builder = match iroh_relay_mode()? { - IrohRelayMode::Disabled => builder.disable_iroh_relays(true), - IrohRelayMode::Default => builder.disable_iroh_relays(false), - IrohRelayMode::Custom(urls) => builder - .disable_iroh_relays(false) - .iroh_relays(urls.into_iter().map(|url| url.to_string())), - }; + let (disable_iroh_relays, iroh_relays) = sdk_iroh_relay_config(iroh_relay_mode()?); + builder = builder + .disable_iroh_relays(disable_iroh_relays) + .iroh_relays(iroh_relays); if let Some(max_vram_gb) = request.max_vram_gb { builder = builder.max_vram_gb(max_vram_gb as f64); } @@ -416,13 +413,10 @@ impl DesktopMeshRuntime { if let Some(mesh_name) = request.mesh_name.as_deref() { builder = builder.mesh_name(mesh_name); } - builder = match iroh_relay_mode()? { - IrohRelayMode::Disabled => builder.disable_iroh_relays(true), - IrohRelayMode::Default => builder.disable_iroh_relays(false), - IrohRelayMode::Custom(urls) => builder - .disable_iroh_relays(false) - .iroh_relays(urls.into_iter().map(|url| url.to_string())), - }; + let (disable_iroh_relays, iroh_relays) = sdk_iroh_relay_config(iroh_relay_mode()?); + builder = builder + .disable_iroh_relays(disable_iroh_relays) + .iroh_relays(iroh_relays); if let Some(join_token) = request.join_token.as_deref() { builder = builder.join_token(join_token); } diff --git a/desktop/src-tauri/src/mesh_llm/recovery.rs b/desktop/src-tauri/src/mesh_llm/recovery.rs index 6398f47250..a8b5584fd5 100644 --- a/desktop/src-tauri/src/mesh_llm/recovery.rs +++ b/desktop/src-tauri/src/mesh_llm/recovery.rs @@ -443,6 +443,7 @@ mod tests { id: pubkey.to_string(), display_name: pubkey.to_string(), avatar_url: None, + description: None, system_prompt: String::new(), runtime: None, model: None, diff --git a/desktop/src-tauri/src/mesh_llm/transport_policy.rs b/desktop/src-tauri/src/mesh_llm/transport_policy.rs index 122bffd60e..24e5156295 100644 --- a/desktop/src-tauri/src/mesh_llm/transport_policy.rs +++ b/desktop/src-tauri/src/mesh_llm/transport_policy.rs @@ -43,6 +43,22 @@ pub(super) fn iroh_relay_mode_from(raw: Option<&str>) -> anyhow::Result (bool, Vec) { + match mode { + IrohRelayMode::Disabled => (true, Vec::new()), + IrohRelayMode::Default => ( + false, + MESH_LLM_DEFAULT_RELAYS + .iter() + .map(|url| (*url).to_string()) + .collect(), + ), + IrohRelayMode::Custom(urls) => { + (false, urls.into_iter().map(|url| url.to_string()).collect()) + } + } +} + fn parse_configured_relay_url(raw: &str) -> anyhow::Result { let parsed = url::Url::parse(raw) .map_err(|error| anyhow::anyhow!("invalid relay URL {raw:?}: {error}"))?; @@ -205,9 +221,11 @@ fn validate_transport(transport: &TransportAddr, mode: &IrohRelayMode) -> anyhow /// mesh-llm serving node (they are not in iroh's own prod relay map). /// /// Kept in sync with `effective_relay_urls(RelayPolicy::DefaultPublic, &[])`. -const MESH_LLM_DEFAULT_RELAYS: &[&str] = &[ +pub(super) const MESH_LLM_DEFAULT_RELAYS: &[&str] = &[ "https://usw1-2.relay.michaelneale.mesh-llm.iroh.link./", "https://aps1-1.relay.michaelneale.mesh-llm.iroh.link./", + "https://euc1-1.relay.michaelneale.mesh-llm.iroh.link./", + "https://use1-1.relay.michaelneale.mesh-llm.iroh.link./", ]; /// Whether `relay` is one of mesh-llm's baked-in default public relays. @@ -327,6 +345,27 @@ mod tests { } } + #[test] + fn sdk_default_relays_are_exactly_the_trusted_default_relays() { + let (disabled, configured) = sdk_iroh_relay_config(IrohRelayMode::Default); + assert!(!disabled); + let configured = configured + .into_iter() + .map(|url| url.parse::().expect("SDK relay URL must parse")) + .collect::>(); + let trusted = MESH_LLM_DEFAULT_RELAYS + .iter() + .map(|url| { + url.parse::() + .expect("trusted relay URL must parse") + }) + .collect::>(); + assert_eq!(configured, trusted); + assert!(configured + .iter() + .all(|relay| relay_allowed(relay, &IrohRelayMode::Default))); + } + #[test] fn endpoint_with_one_good_and_one_junk_candidate_is_sanitized() { // A mesh-llm endpoint can advertise a usable relay alongside an diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index d69fb0a238..71c5fc2e04 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Buzz", - "version": "0.5.22", + "version": "0.5.23", "identifier": "xyz.block.buzz.app", "build": { "beforeDevCommand": { diff --git a/desktop/src/features/agents/AGENTS.md b/desktop/src/features/agents/AGENTS.md index dfb9c0ed49..7f1f73b175 100644 --- a/desktop/src/features/agents/AGENTS.md +++ b/desktop/src/features/agents/AGENTS.md @@ -306,7 +306,7 @@ with a TypeScript lookup table or an id comparison in a component. refresh only local persona/team/managed-agent caches; they must never invalidate the remote relay directory. -17. **Databricks model discovery has one shared catalog authority.** Desktop and ACP call the shared `buzz-agent` discovery library; Desktop passes the effective merged `DATABRICKS_MODEL_FILTER` explicitly, and the library applies it to raw workspace endpoint IDs and Unity Catalog model-service FQNs after the additive union. A successful filtered-empty catalog is authoritative: it stays empty, disables switching, and never falls through to configured or known-model fallback. UC FQNs are catalog data and always use the MLflow Chat Completions route, regardless of family-looking text in their components. Global Defaults preserves the discovered model ID as the selected value while its closed trigger renders the provider-scoped display label; do not force the raw persisted ID over that label. +17. **Databricks model discovery has one shared catalog authority.** Desktop and ACP call the shared `buzz-agent` discovery library; Desktop passes the effective merged `DATABRICKS_MODEL_FILTER` explicitly, and the library applies it to raw workspace endpoint IDs and Unity Catalog model-service FQNs after the additive union. A successful filtered-empty catalog is authoritative: it stays empty, disables switching, and never falls through to configured or known-model fallback. UC FQNs retain neutral effort capabilities. A boundary-matched GPT-5-or-newer family in the service-name component selects OpenAI Responses so tools can coexist with reasoning; other FQNs use MLflow Chat Completions. Catalog/schema components never influence routing. Keep this route-only rule identical in the Rust and TypeScript capability interpreters. Global Defaults preserves the discovered model ID as the selected value while its closed trigger renders the provider-scoped display label; do not force the raw persisted ID over that label. ## Channel-only runtime controls diff --git a/desktop/src/features/agents/ui/modelCapabilities.ts b/desktop/src/features/agents/ui/modelCapabilities.ts index f2c8de6035..d6866c5c7e 100644 --- a/desktop/src/features/agents/ui/modelCapabilities.ts +++ b/desktop/src/features/agents/ui/modelCapabilities.ts @@ -302,6 +302,19 @@ function isDatabricksModelServiceFqn(model: string): boolean { ); } +// Mirror fqn_requires_responses: routing is the only inferred FQN capability. +function fqnRequiresResponses(model: string): boolean { + const service = model.split(".").at(-1) ?? ""; + const stripped = stripCatalogPrefix( + service.toLowerCase(), + MANIFEST.family_tokens, + ); + const match = /^gpt-([0-9]+)(?:$|[^a-z0-9])/.exec(stripped); + if (!match) return false; + const major = Number(match[1]); + return major >= 5 && major <= 0xffffffff; +} + /** * Resolve the capability profile for a `(provider, rawModelId)` pair. * @@ -315,8 +328,8 @@ export function resolveModelCapabilities( ): CapabilityResult { const canon = canonicalizeProvider(provider); const blank = rawModelId.trim().length === 0; - // Unity Catalog FQNs are neutral model-service identities. Resolve them - // through the concrete-unknown fallback before suffix family matching. + // FQNs keep neutral effort capabilities; only GPT-5+ service names + // select Responses. Catalog/schema names never choose the protocol. const modelServiceFqn = canon === "databricks_v2" && isDatabricksModelServiceFqn(rawModelId); @@ -370,7 +383,11 @@ export function resolveModelCapabilities( // 3. Provider fallback (blank vs. concrete-unknown); never carries a label. const pair = fallbackPair(canon); const state = blank ? pair.blank : pair.concrete_unknown; - return toResult(state, state.databricks_v2_wire_route, null); + const route = + modelServiceFqn && fqnRequiresResponses(rawModelId) + ? "openai-responses" + : state.databricks_v2_wire_route; + return toResult(state, route, null); } /** Authoritative list of known Databricks v2 model ids, sourced from the manifest. */ diff --git a/desktop/src/features/agents/ui/modelCapabilitiesCorpus.test.mjs b/desktop/src/features/agents/ui/modelCapabilitiesCorpus.test.mjs index e0d150cc4f..21baf6b64b 100644 --- a/desktop/src/features/agents/ui/modelCapabilitiesCorpus.test.mjs +++ b/desktop/src/features/agents/ui/modelCapabilitiesCorpus.test.mjs @@ -25,10 +25,10 @@ const corpus = JSON.parse(readFileSync(fileURLToPath(corpusUrl), "utf8")); // (`_group`) are skipped. Mirrors the Rust corpus filter. const executable = corpus.filter((entry) => entry.expect != null); -test("corpus has exactly 140 executable vectors", () => { +test("corpus has exactly 158 executable vectors", () => { // Locks the vector count so a silent corpus edit can't quietly drop coverage; // must equal the gate in the Rust suite (model_capabilities.rs). - assert.equal(executable.length, 140); + assert.equal(executable.length, 158); }); test("registry label aliases refuse an unprefixed query", () => { diff --git a/desktop/src/features/messages/lib/linkPreviewPreparationStore.test.mjs b/desktop/src/features/messages/lib/linkPreviewPreparationStore.test.mjs index 293fb63e15..7153ff3851 100644 --- a/desktop/src/features/messages/lib/linkPreviewPreparationStore.test.mjs +++ b/desktop/src/features/messages/lib/linkPreviewPreparationStore.test.mjs @@ -1,5 +1,7 @@ import assert from "node:assert/strict"; -import test from "node:test"; +import { after, before, test } from "node:test"; + +import { JSDOM } from "jsdom"; import { __linkPreviewPreparationTest, @@ -12,6 +14,29 @@ import { const first = { href: "https://example.com/first" }; const second = { href: "https://example.com/second" }; const firstTag = ["link-preview", "snapshot", first.href]; +const dom = new JSDOM("", { + url: "http://localhost", +}); +const ipcHandlers = new Map(); + +before(() => { + Object.assign(globalThis, { + document: dom.window.document, + HTMLElement: dom.window.HTMLElement, + window: dom.window, + }); + dom.window.__TAURI_INTERNALS__ = { + invoke: (cmd, args) => { + const handler = ipcHandlers.get(cmd); + return handler + ? handler(args) + : Promise.reject(new Error(`unmocked Tauri command: ${cmd}`)); + }, + transformCallback: () => Math.random(), + }; +}); + +after(() => dom.window.close()); function deferred() { let resolve; @@ -41,6 +66,7 @@ function seed( test.afterEach(() => { __linkPreviewPreparationTest.reset(); + ipcHandlers.clear(); }); test("adopts one in-flight job for the same canonical URL", () => { @@ -223,6 +249,60 @@ test("Skip after completion cannot replace finalized tags", async () => { }); }); +test("expired settled work replaced by a pending retry keeps deadline and Skip", async () => { + const expiredTag = ["link-preview", "snapshot", first.href, "expired"]; + const pendingRetry = deferred(); + let fetchCalls = 0; + ipcHandlers.set("fetch_link_preview_metadata", () => { + fetchCalls += 1; + return pendingRetry.promise; + }); + ipcHandlers.set("cancel_link_preview_metadata", () => Promise.resolve()); + ipcHandlers.set("release_link_preview_metadata", () => Promise.resolve()); + + const seedExpiredFallback = () => + seed( + first, + Promise.resolve(expiredTag), + true, + Date.now() - 5 * 60_000, + expiredTag, + expiredTag, + ); + + seedExpiredFallback(); + const timeoutPreparation = prepareBackgroundLinkPreviews([first], 0); + assert.ok(timeoutPreparation); + assert.equal( + __linkPreviewPreparationTest.jobs.get(first.href)?.settled, + false, + ); + assert.equal( + fetchCalls, + 1, + "the expired job was replaced through production I/O", + ); + assert.deepEqual(await timeoutPreparation.promise, { + status: "ready", + tags: [], + }); + + seedExpiredFallback(); + const skipPreparation = prepareBackgroundLinkPreviews([first], 1_000); + assert.ok(skipPreparation); + assert.equal( + __linkPreviewPreparationTest.jobs.get(first.href)?.settled, + false, + ); + skipPreparation.skip(); + assert.deepEqual(await skipPreparation.promise, { + status: "ready", + tags: [], + }); + + pendingRetry.resolve(null); +}); + test("already-settled partial results contain only successful tags", async () => { seed(first, Promise.resolve(firstTag), true); seed(second, Promise.resolve(null), true); @@ -272,3 +352,18 @@ test("reset cancels pending preparations instead of authorizing send", async () assert.deepEqual(await preparation.promise, { status: "cancelled" }); }); + +test("Skip aborts an abandoned in-flight preview job", async () => { + const pending = deferred(); + seed(first, pending.promise); + const job = __linkPreviewPreparationTest.jobs.get(first.href); + + const preparation = prepareBackgroundLinkPreviews([first], 1_000); + assert.ok(preparation); + preparation.skip(); + + assert.deepEqual(await preparation.promise, { status: "ready", tags: [] }); + assert.equal(job.controller.signal.aborted, true); + assert.equal(__linkPreviewPreparationTest.jobs.has(first.href), false); + pending.resolve(null); +}); diff --git a/desktop/src/features/messages/lib/linkPreviewPreparationStore.ts b/desktop/src/features/messages/lib/linkPreviewPreparationStore.ts index d61750fcd8..a4f1273ecf 100644 --- a/desktop/src/features/messages/lib/linkPreviewPreparationStore.ts +++ b/desktop/src/features/messages/lib/linkPreviewPreparationStore.ts @@ -9,6 +9,7 @@ import { } from "@/shared/lib/linkPreviewSnapshot"; import { loadLinkPreviewMetadata, + type LinkPreviewMetadata, resolveLinkPreview, } from "@/shared/lib/useResolvedLinkPreviews"; @@ -27,6 +28,7 @@ type PreviewJob = { type BackgroundPreviewTask = { cancel: () => void; + hrefs: Set; id: number; skip: () => void; }; @@ -113,7 +115,26 @@ async function buildSnapshot( signal: AbortSignal, onMetadataReady: (tag: string[]) => void, ): Promise { - const metadata = await loadLinkPreviewMetadata(candidate.href); + const metadataLoad = loadLinkPreviewMetadata(candidate.href); + let settleAbortedMetadata: (() => void) | null = null; + const abortedMetadata = new Promise((resolve) => { + settleAbortedMetadata = () => resolve(null); + }); + const cancelMetadata = () => { + metadataLoad.cancel(); + settleAbortedMetadata?.(); + }; + signal.addEventListener("abort", cancelMetadata, { once: true }); + if (signal.aborted) cancelMetadata(); + let metadata: LinkPreviewMetadata | null; + try { + metadata = await Promise.race([metadataLoad.promise, abortedMetadata]); + } catch { + return null; + } finally { + signal.removeEventListener("abort", cancelMetadata); + metadataLoad.cancel(); + } if (signal.aborted || !metadata) return null; const preview = resolveLinkPreview(candidate, metadata); if (!preview.snapshotReady) return null; @@ -265,12 +286,15 @@ export function prepareBackgroundLinkPreviews( skip, }); + const preparations = external.map((candidate) => + prepareLinkPreview(candidate), + ); const pending = external.some( (candidate) => !jobs.get(candidate.href)?.settled, ); if (!pending) { return preparedSend( - Promise.all(external.map(prepareLinkPreview)).then((tags) => ({ + Promise.all(preparations).then((tags) => ({ status: "ready" as const, tags: tags.filter((tag): tag is string[] => tag !== null), })), @@ -288,27 +312,45 @@ export function prepareBackgroundLinkPreviews( let finish: ((result: BackgroundLinkPreviewResult) => void) | null = null; let terminal = false; let timer: ReturnType | null = null; - const complete = (result: BackgroundLinkPreviewResult) => { + const complete = ( + result: BackgroundLinkPreviewResult, + abortUnobservedJobs = false, + ) => { if (terminal) return; terminal = true; if (timer !== null) clearTimeout(timer); tasks.delete(taskId); + if (abortUnobservedJobs) { + for (const candidate of external) { + const observedByAnotherSend = [...tasks.values()].some((task) => + task.hrefs.has(candidate.href), + ); + if (!observedByAnotherSend) { + invalidateLinkPreviewPreparation(candidate.href); + } + } + } publishSnapshot(); finish?.(result); }; const promise = new Promise((resolve) => { finish = resolve; }); - const cancel = () => complete({ status: "cancelled" }); - const skip = () => complete({ status: "ready", tags: [] }); - tasks.set(taskId, { cancel, id: taskId, skip }); + const cancel = () => complete({ status: "cancelled" }, true); + const skip = () => complete({ status: "ready", tags: [] }, true); + tasks.set(taskId, { + cancel, + hrefs: new Set(external.map((candidate) => candidate.href)), + id: taskId, + skip, + }); publishSnapshot(); timer = setTimeout( - () => complete({ status: "ready", tags: availableTags() }), + () => complete({ status: "ready", tags: availableTags() }, true), timeoutMs, ); - void Promise.all(external.map(prepareLinkPreview)).then((tags) => { + void Promise.all(preparations).then((tags) => { complete({ status: "ready", tags: tags.filter((tag): tag is string[] => tag !== null), diff --git a/desktop/src/protectedFeatures/tauriCommand.test.mjs b/desktop/src/protectedFeatures/tauriCommand.test.mjs index e3e1532af4..0902be92b4 100644 --- a/desktop/src/protectedFeatures/tauriCommand.test.mjs +++ b/desktop/src/protectedFeatures/tauriCommand.test.mjs @@ -10,6 +10,7 @@ const desktopRoot = path.resolve( path.dirname(fileURLToPath(import.meta.url)), "../..", ); +const configDir = path.join(desktopRoot, "src-tauri"); const wrapper = path.join(desktopRoot, "scripts/tauri-command.mjs"); const fakeCli = path.join(tmpdir(), `buzz-fake-tauri-${process.pid}.mjs`); @@ -20,14 +21,21 @@ import path from "node:path"; const args = process.argv.slice(2); const configIndex = args.lastIndexOf("--config"); const override = JSON.parse(args[configIndex + 1]); -const output = override.build.frontendDist; -mkdirSync(output, { recursive: true }); -writeFileSync(path.join(output, "variant.txt"), process.env.VITE_BUZZ_BESTIE); +const configured = override.build.frontendDist; +// Tauri resolves frontendDist against the directory holding tauri.conf.json +// (config_parent.join(path) in tauri-codegen), not against the process cwd. +const output = path.resolve(process.env.BUZZ_TEST_CONFIG_DIR, configured); +// Write through the producer path the wrapper publishes and read back through +// the config-resolved consumer path. Doing both against one path would make the +// fake agree with itself no matter where the wrapper pointed frontendDist. +const producer = process.env.BUZZ_PROTECTED_BUILD_OUTPUT; +mkdirSync(producer, { recursive: true }); +writeFileSync(path.join(producer, "variant.txt"), process.env.VITE_BUZZ_BESTIE); await new Promise((resolve) => setTimeout(resolve, 100)); const observed = readFileSync(path.join(output, "variant.txt"), "utf8"); writeFileSync( process.env.BUZZ_TEST_RESULT, - JSON.stringify({ args, output, observed }), + JSON.stringify({ args, configured, output, observed }), ); `, ); @@ -42,6 +50,7 @@ function packageVariant(variant, result, runnerArguments = []) { env: { ...process.env, BUZZ_TAURI_CLI_ENTRYPOINT: fakeCli, + BUZZ_TEST_CONFIG_DIR: configDir, BUZZ_TEST_RESULT: result, VITE_BUZZ_BESTIE: variant, }, @@ -92,6 +101,30 @@ test("private config precedes Cargo runner arguments", async () => { assert.equal(invocation.args[delimiterIndex + 1], "--locked"); assert.equal( JSON.parse(invocation.args[privateConfigIndex + 1]).build.frontendDist, - invocation.output, + invocation.configured, ); }); + +test("private frontendDist is never mistaken for a URL", async () => { + const result = path.join( + tmpdir(), + `buzz-tauri-frontend-dist-${process.pid}.json`, + ); + await packageVariant("0", result); + const invocation = JSON.parse(readFileSync(result, "utf8")); + + // `FrontendDist` is an untagged enum whose first variant is `Url(Url)`, and + // tauri-codegen embeds *no assets without erroring* for that variant. A + // Windows absolute path parses as a URL -- `C:` becomes the scheme -- so an + // absolute frontendDist produces a UI-less app that still exits 0. + assert.ok( + !path.isAbsolute(invocation.configured), + `frontendDist must stay relative, got ${invocation.configured}`, + ); + // Rust's `url` crate and Node's `URL` both implement the WHATWG standard, so + // this is the same parse serde performs. It only rejects absolute paths on + // Windows, which is why the assertion above carries the check on Linux/macOS. + assert.throws(() => new URL(invocation.configured)); + // The relative path still has to reach the directory the wrapper published. + assert.equal(invocation.observed, "0"); +}); diff --git a/desktop/src/shared/lib/useResolvedLinkPreviews.test.mjs b/desktop/src/shared/lib/useResolvedLinkPreviews.test.mjs index e413f9c7c2..2681148903 100644 --- a/desktop/src/shared/lib/useResolvedLinkPreviews.test.mjs +++ b/desktop/src/shared/lib/useResolvedLinkPreviews.test.mjs @@ -6,6 +6,7 @@ import { JSDOM } from "jsdom"; import { __linkPreviewMetadataTest, fetchBuzzEntityMetadata, + loadLinkPreviewMetadata, isBuzzEntityPreview, resetLinkPreviewMetadataCache, resolveLinkPreview, @@ -33,6 +34,16 @@ function metadata(overrides = {}) { }; } +function deferred() { + let reject; + let resolve; + const promise = new Promise((resolvePromise, rejectPromise) => { + reject = rejectPromise; + resolve = resolvePromise; + }); + return { promise, reject, resolve }; +} + test("pending external metadata reserves the image treatment", () => { assert.deepEqual(resolveLinkPreview(preview, undefined), { ...preview, @@ -140,14 +151,14 @@ test("metadata loader retries transient images after the server cooldown", async }); assert.equal( - (await loader.load(preview.href)).metadata?.imageFetchState, + (await loader.load(preview.href).promise).metadata?.imageFetchState, "transient_failure", ); assert.equal(calls, 1); now += 10_000; assert.equal( - (await loader.load(preview.href)).metadata?.imageFetchState, + (await loader.load(preview.href).promise).metadata?.imageFetchState, "image", ); assert.equal(calls, 2); @@ -165,12 +176,15 @@ test("metadata loader retries rejected requests after the negative-cache TTL", a now: () => now, }); - assert.equal((await loader.load(preview.href)).metadata, null); - assert.equal((await loader.load(preview.href)).metadata, null); + assert.equal((await loader.load(preview.href).promise).metadata, null); + assert.equal((await loader.load(preview.href).promise).metadata, null); assert.equal(calls, 1); now += 5 * 60_000; - assert.deepEqual((await loader.load(preview.href)).metadata, metadata()); + assert.deepEqual( + (await loader.load(preview.href).promise).metadata, + metadata(), + ); assert.equal(calls, 2); }); @@ -191,10 +205,10 @@ test("metadata loader coalesces fragment variants and bounds concurrency", async }); await Promise.all([ - loader.load("https://example.com/one#first"), - loader.load("https://example.com/one#second"), - loader.load("https://example.com/two"), - loader.load("https://example.com/three"), + loader.load("https://example.com/one#first").promise, + loader.load("https://example.com/one#second").promise, + loader.load("https://example.com/two").promise, + loader.load("https://example.com/three").promise, ]); assert.equal(calls, 3); @@ -504,12 +518,15 @@ test("invalidateNegative drops a cached null miss so the next load refetches", a now: () => now, }); - assert.equal((await loader.load(preview.href)).metadata, null); + assert.equal((await loader.load(preview.href).promise).metadata, null); assert.equal(calls, 1); loader.invalidateNegative(preview.href); nextResult = metadata(); - assert.deepEqual((await loader.load(preview.href)).metadata, metadata()); + assert.deepEqual( + (await loader.load(preview.href).promise).metadata, + metadata(), + ); assert.equal(calls, 2); }); @@ -538,7 +555,7 @@ test("invalidateNegative drops a cached transient failure so the next load refet }); assert.equal( - (await loader.load(preview.href)).metadata?.imageFetchState, + (await loader.load(preview.href).promise).metadata?.imageFetchState, "transient_failure", ); assert.equal(calls, 1); @@ -547,7 +564,7 @@ test("invalidateNegative drops a cached transient failure so the next load refet // the cooldown — is what forces the refetch. loader.invalidateNegative(preview.href); assert.equal( - (await loader.load(preview.href)).metadata?.imageFetchState, + (await loader.load(preview.href).promise).metadata?.imageFetchState, "image", ); assert.equal(calls, 2); @@ -566,11 +583,17 @@ test("invalidateNegative leaves a healthy cached hit untouched", async () => { now: () => now, }); - assert.deepEqual((await loader.load(preview.href)).metadata, metadata()); + assert.deepEqual( + (await loader.load(preview.href).promise).metadata, + metadata(), + ); assert.equal(calls, 1); loader.invalidateNegative(preview.href); - assert.deepEqual((await loader.load(preview.href)).metadata, metadata()); + assert.deepEqual( + (await loader.load(preview.href).promise).metadata, + metadata(), + ); assert.equal(calls, 1); }); @@ -599,10 +622,74 @@ test("invalidateNegative leaves an in-flight fetch untouched", async () => { assert.equal(calls, 1, "no redundant fetch started by the bust"); releaseFetch(); - assert.deepEqual((await pending).metadata, metadata()); + assert.deepEqual((await pending.promise).metadata, metadata()); assert.equal(calls, 1, "the original in-flight fetch resolved, not a retry"); }); +test("an orphaned metadata load is cancelled after its re-entry grace period", async () => { + let cancelled = false; + const loader = __linkPreviewMetadataTest.createMetadataLoader({ + fetcher: (_href, signal) => + new Promise((_resolve, reject) => { + signal.addEventListener( + "abort", + () => { + cancelled = true; + reject(new Error("cancelled")); + }, + { once: true }, + ); + }), + }); + + const load = loader.load(preview.href); + const rejection = assert.rejects(load.promise, /cancelled/); + load.cancel(); + await new Promise((resolve) => setTimeout(resolve, 1_050)); + assert.equal(cancelled, true); + await rejection; +}); + +test("new metadata demand immediately reclaims slots from orphaned loads", async () => { + const started = []; + const cancelled = []; + const releases = new Map(); + const loader = __linkPreviewMetadataTest.createMetadataLoader({ + concurrency: 2, + fetcher: (href, signal) => + new Promise((resolve, reject) => { + started.push(href); + releases.set(href, () => resolve(metadata())); + signal.addEventListener( + "abort", + () => { + cancelled.push(href); + reject(new Error("cancelled")); + }, + { once: true }, + ); + }), + }); + + const firstHref = "https://example.com/stalled-one"; + const secondHref = "https://example.com/stalled-two"; + const thirdHref = "https://example.com/ordinary"; + const first = loader.load(firstHref); + const second = loader.load(secondHref); + const firstSettled = first.promise.catch(() => undefined); + const secondSettled = second.promise.catch(() => undefined); + first.cancel(); + second.cancel(); + + const third = loader.load(thirdHref); + await new Promise((resolve) => setImmediate(resolve)); + assert.deepEqual(started, [firstHref, secondHref, thirdHref]); + assert.deepEqual(new Set(cancelled), new Set([firstHref, secondHref])); + releases.get(thirdHref)(); + assert.deepEqual((await third.promise).metadata, metadata()); + await Promise.all([firstSettled, secondSettled]); +}); + // ── Hook-level regression: retained resolved-state invalidation on re-entry ─── // // The loader tests above prove `invalidateNegative` drops the SHARED loader @@ -899,3 +986,146 @@ test("hook clears a re-entered negative even when the shared cache holds an in-f ipcHandlers.clear(); } }); + +test("preparation abort releases only its own shared metadata lease", async () => { + const { prepareLinkPreview, resetLinkPreviewPreparations } = await import( + "../../features/messages/lib/linkPreviewPreparationStore.ts" + ); + + resetLinkPreviewMetadataCache(); + resetLinkPreviewPreparations(); + ipcHandlers.clear(); + + const href = "https://example.com/shared-pending"; + let fetchRequest; + const cancelledRequestIds = []; + ipcHandlers.set("fetch_link_preview_metadata", (args) => { + const request = deferred(); + fetchRequest = { ...args, ...request }; + return request.promise; + }); + ipcHandlers.set("cancel_link_preview_metadata", ({ requestId }) => { + cancelledRequestIds.push(requestId); + return Promise.resolve(); + }); + ipcHandlers.set("release_link_preview_metadata", () => Promise.resolve()); + + try { + const composerLoad = loadLinkPreviewMetadata(href); + const preparation = prepareLinkPreview({ ...hookPreview, href }); + await new Promise((resolve) => setImmediate(resolve)); + assert.ok(fetchRequest, "shared metadata reached the native fetch seam"); + + resetLinkPreviewPreparations(); + assert.equal(await preparation, null); + await new Promise((resolve) => setTimeout(resolve, 1_050)); + assert.deepEqual( + cancelledRequestIds, + [], + "preparation listener plus finally must not release the composer lease", + ); + + fetchRequest.resolve(metadata()); + assert.deepEqual(await composerLoad.promise, metadata()); + + const finalHref = `${href}/final`; + const finalLoad = loadLinkPreviewMetadata(finalHref); + await new Promise((resolve) => setImmediate(resolve)); + const finalRequest = fetchRequest; + const finalRejection = assert.rejects(finalLoad.promise); + finalLoad.cancel(); + finalLoad.cancel(); + await new Promise((resolve) => setTimeout(resolve, 1_050)); + assert.deepEqual( + cancelledRequestIds, + [finalRequest.requestId], + "one final consumer release permits native abort", + ); + finalRequest.reject(new Error("cancelled by test native seam")); + await finalRejection; + } finally { + resetLinkPreviewPreparations(); + resetLinkPreviewMetadataCache(); + ipcHandlers.clear(); + } +}); + +test("removing two stalled previews cancels native work and admits a third URL", async () => { + const { act, cleanup, renderHook } = await import("@testing-library/react"); + const { useResolvedLinkPreviews } = await import( + "./useResolvedLinkPreviews.ts" + ); + + resetLinkPreviewMetadataCache(); + ipcHandlers.clear(); + + const firstPreview = { + ...hookPreview, + href: "https://example.com/stalled-one", + }; + const secondPreview = { + ...hookPreview, + href: "https://example.com/stalled-two", + }; + const thirdPreview = { ...hookPreview, href: "https://example.com/ordinary" }; + const pending = new Map(); + const started = []; + const cancelled = []; + + ipcHandlers.set("fetch_link_preview_metadata", ({ href, requestId }) => { + started.push(href); + return new Promise((resolve, reject) => { + pending.set(requestId, { href, reject, resolve }); + }); + }); + ipcHandlers.set("cancel_link_preview_metadata", ({ requestId }) => { + const request = pending.get(requestId); + if (!request) return Promise.resolve(); + cancelled.push(request.href); + pending.delete(requestId); + request.reject(new Error("cancelled by test native seam")); + return Promise.resolve(); + }); + ipcHandlers.set("release_link_preview_metadata", () => Promise.resolve()); + + const flushScheduledLoads = async () => { + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, 0)); + }); + }; + + const hook = renderHook(({ previews }) => useResolvedLinkPreviews(previews), { + initialProps: { previews: [firstPreview, secondPreview] }, + }); + + try { + await flushScheduledLoads(); + assert.deepEqual(started, [firstPreview.href, secondPreview.href]); + + hook.rerender({ previews: [thirdPreview] }); + await flushScheduledLoads(); + assert.deepEqual( + new Set(cancelled), + new Set([firstPreview.href, secondPreview.href]), + ); + assert.deepEqual(started, [ + firstPreview.href, + secondPreview.href, + thirdPreview.href, + ]); + + const third = [...pending.values()].find( + (request) => request.href === thirdPreview.href, + ); + assert.ok(third, "third URL reached the native fetch seam"); + await act(async () => { + third.resolve(metadata()); + await new Promise((resolve) => setTimeout(resolve, 0)); + }); + assert.equal(hook.result.current[0].title, "A story"); + } finally { + hook.unmount(); + cleanup(); + ipcHandlers.clear(); + } +}); diff --git a/desktop/src/shared/lib/useResolvedLinkPreviews.ts b/desktop/src/shared/lib/useResolvedLinkPreviews.ts index 4591d54e7d..5111929b3e 100644 --- a/desktop/src/shared/lib/useResolvedLinkPreviews.ts +++ b/desktop/src/shared/lib/useResolvedLinkPreviews.ts @@ -51,6 +51,10 @@ type MetadataLoadResult = MetadataCacheEntry & { const DEFAULT_TRANSIENT_RETRY_MS = 30_000; const NULL_METADATA_RETRY_MS = 5 * 60_000; const MAX_CONCURRENT_METADATA_FETCHES = 2; +// Keep a just-removed request cacheable through a brief edit/re-entry gap, but +// never let unobserved native work linger indefinitely. New queued demand +// reclaims these loads immediately rather than waiting for this grace period. +const ORPHANED_METADATA_LOAD_GRACE_MS = 1_000; /** * React may flush an interaction-triggered effect before the browser paints. @@ -107,29 +111,70 @@ function metadataExpiry( return now + retryAfterMs; } +type PendingMetadataLoad = { + controller: AbortController; + consumers: number; + orphanTimer: ReturnType | null; + promise: Promise; +}; + +type MetadataCacheValue = MetadataCacheEntry | PendingMetadataLoad; + +function isPendingMetadataLoad( + value: MetadataCacheValue, +): value is PendingMetadataLoad { + return "promise" in value; +} + +function abortError(): DOMException { + return new DOMException("Link preview fetch cancelled", "AbortError"); +} + function createTaskScheduler(concurrency: number) { - const pending: Array<() => void> = []; + const pending: Array<{ + reject: (reason?: unknown) => void; + run: () => void; + signal: AbortSignal; + }> = []; let active = 0; const drain = () => { while (active < concurrency) { - const run = pending.shift(); - if (!run) return; + const next = pending.shift(); + if (!next) return; + if (next.signal.aborted) { + next.reject(abortError()); + continue; + } active += 1; - run(); + next.run(); } }; - return (task: () => Promise): Promise => + return (task: () => Promise, signal: AbortSignal): Promise => new Promise((resolve, reject) => { - pending.push(() => { - void task() - .then(resolve, reject) - .finally(() => { - active -= 1; - drain(); - }); - }); + const entry = { + reject, + signal, + run: () => { + signal.removeEventListener("abort", cancelPending); + void task() + .then(resolve, reject) + .finally(() => { + active -= 1; + drain(); + }); + }, + }; + const cancelPending = () => { + const index = pending.indexOf(entry); + if (index < 0) return; + pending.splice(index, 1); + reject(abortError()); + drain(); + }; + signal.addEventListener("abort", cancelPending, { once: true }); + pending.push(entry); drain(); }); } @@ -140,20 +185,20 @@ function createMetadataLoader({ now = Date.now, }: { concurrency?: number; - fetcher: (href: string) => Promise; + fetcher: ( + href: string, + signal: AbortSignal, + ) => Promise; now?: () => number; }) { - const cache = new Map< - string, - MetadataCacheEntry | Promise - >(); + const cache = new Map(); const schedule = createTaskScheduler(Math.max(1, concurrency)); let generation = 0; const peek = (href: string): MetadataLoadResult | undefined => { const key = metadataCacheKey(href); const cached = cache.get(key); - if (!cached || cached instanceof Promise) return undefined; + if (!cached || isPendingMetadataLoad(cached)) return undefined; if (cached.expiresAt !== null && cached.expiresAt <= now()) { cache.delete(key); return undefined; @@ -161,32 +206,116 @@ function createMetadataLoader({ return { key, ...cached }; }; - const load = (href: string): Promise => { + const abortPending = (key: string, pending: PendingMetadataLoad) => { + if (pending.orphanTimer !== null) clearTimeout(pending.orphanTimer); + pending.orphanTimer = null; + if (cache.get(key) === pending) cache.delete(key); + pending.controller.abort(); + }; + + const release = (key: string, pending: PendingMetadataLoad) => { + if (pending.consumers <= 0) return; + pending.consumers -= 1; + if ( + pending.consumers > 0 || + pending.orphanTimer !== null || + cache.get(key) !== pending + ) { + return; + } + pending.orphanTimer = setTimeout( + () => abortPending(key, pending), + ORPHANED_METADATA_LOAD_GRACE_MS, + ); + }; + + const createRelease = (key: string, pending: PendingMetadataLoad) => { + let released = false; + return () => { + if (released) return; + released = true; + release(key, pending); + }; + }; + + const abortOrphanedLoads = (exceptKey: string) => { + for (const [key, cached] of cache) { + if ( + key !== exceptKey && + isPendingMetadataLoad(cached) && + cached.consumers === 0 + ) { + abortPending(key, cached); + } + } + }; + + const load = ( + href: string, + ): { cancel: () => void; promise: Promise } => { const key = metadataCacheKey(href); const cached = cache.get(key); - if (cached instanceof Promise) return cached; + if (cached && isPendingMetadataLoad(cached)) { + if (cached.orphanTimer !== null) clearTimeout(cached.orphanTimer); + cached.orphanTimer = null; + cached.consumers += 1; + return { + cancel: createRelease(key, cached), + promise: cached.promise, + }; + } if (cached) { if (cached.expiresAt === null || cached.expiresAt > now()) { - return Promise.resolve({ key, ...cached }); + return { + cancel: () => undefined, + promise: Promise.resolve({ key, ...cached }), + }; } cache.delete(key); } + abortOrphanedLoads(key); const requestGeneration = generation; - const promise = schedule(() => fetcher(href)) - .catch(() => null) + const controller = new AbortController(); + const pending: PendingMetadataLoad = { + controller, + consumers: 1, + orphanTimer: null, + promise: Promise.resolve({ + expiresAt: null, + key, + metadata: null, + }), + }; + pending.promise = schedule( + () => fetcher(href, controller.signal), + controller.signal, + ) + .catch((error) => { + if (controller.signal.aborted) throw error; + return null; + }) .then((metadata) => { + if (pending.orphanTimer !== null) clearTimeout(pending.orphanTimer); + pending.orphanTimer = null; const entry = { expiresAt: metadataExpiry(metadata, now()), metadata, }; - if (requestGeneration === generation) { + if ( + requestGeneration === generation && + cache.get(key) === pending && + !controller.signal.aborted + ) { cache.set(key, entry); } return { key, ...entry }; }); - cache.set(key, promise); - return promise; + cache.set(key, pending); + return { + cancel: createRelease(key, pending), + promise: pending.promise, + }; }; return { @@ -205,7 +334,7 @@ function createMetadataLoader({ invalidateNegative(href: string): boolean { const key = metadataCacheKey(href); const cached = cache.get(key); - if (!cached || cached instanceof Promise) return false; + if (!cached || isPendingMetadataLoad(cached)) return false; if (!isNegativeMetadata(cached.metadata)) return false; cache.delete(key); return true; @@ -214,6 +343,9 @@ function createMetadataLoader({ peek, reset() { generation += 1; + for (const [key, cached] of cache) { + if (isPendingMetadataLoad(cached)) abortPending(key, cached); + } cache.clear(); }, }; @@ -221,13 +353,57 @@ function createMetadataLoader({ function fetchLinkPreviewMetadata( href: string, + signal: AbortSignal, ): Promise { - return invokeTauri( + const requestId = crypto.randomUUID(); + const startedAt = performance.now(); + const logResult = ( + result: LinkPreviewMetadata | null, + ): LinkPreviewMetadata | null => { + if (import.meta.env?.DEV) { + console.info("[link-preview] metadata fetch completed", { + href, + elapsedMs: Math.round(performance.now() - startedAt), + result: result === null ? "miss" : "hit", + imageFetchState: result?.imageFetchState ?? "none", + imageRetryAfterMs: result?.imageRetryAfterMs ?? null, + hasImage: Boolean(result?.imageDataUrl && result.imageDomain), + hasFavicon: Boolean(result?.faviconDataUrl), + }); + } + return result; + }; + const logFailure = (error: unknown): never => { + if (import.meta.env?.DEV) { + console.warn("[link-preview] metadata fetch failed", { + href, + elapsedMs: Math.round(performance.now() - startedAt), + error, + }); + } + throw error; + }; + + const request = invokeTauri( "fetch_link_preview_metadata", { href, + requestId, }, ); + const onAbort = () => { + void invokeTauri("cancel_link_preview_metadata", { requestId }).catch( + () => undefined, + ); + }; + signal.addEventListener("abort", onAbort, { once: true }); + if (signal.aborted) onAbort(); + return request.then(logResult, logFailure).finally(() => { + signal.removeEventListener("abort", onAbort); + void invokeTauri("release_link_preview_metadata", { requestId }).catch( + () => undefined, + ); + }); } const metadataLoader = createMetadataLoader({ @@ -235,10 +411,15 @@ const metadataLoader = createMetadataLoader({ }); /** Share the same deduplicated metadata job between composer rendering and send preparation. */ -export async function loadLinkPreviewMetadata( - href: string, -): Promise { - return (await metadataLoader.load(href)).metadata; +export function loadLinkPreviewMetadata(href: string): { + cancel: () => void; + promise: Promise; +} { + const load = metadataLoader.load(href); + return { + cancel: load.cancel, + promise: load.promise.then((result) => result.metadata), + }; } type EntityEventFetcher = ( filter: Parameters[0], @@ -348,14 +529,19 @@ export async function fetchBuzzEntityMetadata( } const entityMetadataLoader = createMetadataLoader({ - fetcher: fetchBuzzEntityMetadata, + fetcher: (href) => fetchBuzzEntityMetadata(href), }); /** Share deduplicated relay-native entity metadata across cards and inline tooltips. */ export async function loadBuzzEntityMetadata( href: string, ): Promise { - return (await entityMetadataLoader.load(href)).metadata; + const load = entityMetadataLoader.load(href); + try { + return (await load.promise).metadata; + } finally { + load.cancel(); + } } /** Clear ephemeral metadata when the active relay/community changes. */ @@ -622,15 +808,19 @@ export function useResolvedLinkPreviews( cancelScheduledLoads.push( scheduleAfterPaint(() => { - void loader.load(preview.href).then((result) => { - if (cancelled) return; - setResolvedMetadata((current) => - current[result.key] === result.metadata - ? current - : { ...current, [result.key]: result.metadata }, - ); - scheduleRetry(result, loader); - }); + const load = loader.load(preview.href); + cancelScheduledLoads.push(load.cancel); + void load.promise + .then((result) => { + if (cancelled) return; + setResolvedMetadata((current) => + current[result.key] === result.metadata + ? current + : { ...current, [result.key]: result.metadata }, + ); + scheduleRetry(result, loader); + }) + .catch(() => undefined); }), ); } diff --git a/mobile/lib/app.dart b/mobile/lib/app.dart index d87982bac2..9f3724fd2d 100644 --- a/mobile/lib/app.dart +++ b/mobile/lib/app.dart @@ -374,9 +374,11 @@ class App extends HookConsumerWidget { // Above the navigator, so a burst keeps playing over a pushed thread page // or a modal sheet — the same reason desktop pins its canvas to the // viewport rather than to the message row. - builder: (context, child) => MobileHuddleShell( - navigatorKey: _mobileRootNavigatorKey, - child: EmojiBurstOverlay(child: child ?? const SizedBox.shrink()), + builder: (context, child) => AppMarkdownTheme( + child: MobileHuddleShell( + navigatorKey: _mobileRootNavigatorKey, + child: EmojiBurstOverlay(child: child ?? const SizedBox.shrink()), + ), ), home: authState.when( loading: () => const _SplashScreen(), diff --git a/mobile/lib/features/channels/agent_activity/transcript_item_widget.dart b/mobile/lib/features/channels/agent_activity/transcript_item_widget.dart index 74b2322e34..b2f515a888 100644 --- a/mobile/lib/features/channels/agent_activity/transcript_item_widget.dart +++ b/mobile/lib/features/channels/agent_activity/transcript_item_widget.dart @@ -72,6 +72,10 @@ class _MessageItemWidget extends StatelessWidget { style: context.textTheme.bodyMedium?.copyWith( color: context.colors.onSurface, ), + // No link handler here, so an autolinked URL would draw as a + // link and do nothing when tapped. Transcript URLs stay text, + // as they were before gpt_markdown started autolinking. + autolink: false, ), ], ), @@ -143,6 +147,8 @@ class _ThoughtItemWidget extends HookWidget { style: context.textTheme.bodySmall?.copyWith( color: context.colors.onSurfaceVariant, ), + // As above: no link handler on this surface either. + autolink: false, ), ], ], diff --git a/mobile/lib/features/channels/message_content.dart b/mobile/lib/features/channels/message_content.dart index c9aa72599f..b94954c00c 100644 --- a/mobile/lib/features/channels/message_content.dart +++ b/mobile/lib/features/channels/message_content.dart @@ -7,7 +7,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:gpt_markdown/gpt_markdown.dart'; -import 'package:gpt_markdown/custom_widgets/markdown_config.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import 'package:open_filex/open_filex.dart'; import 'package:path_provider/path_provider.dart'; @@ -266,6 +265,9 @@ class MessageContent extends HookConsumerWidget { finalContent, style: style, followLinkColor: false, + // normalizeBareLinks() already turns bare URLs into Markdown links; + // gpt_markdown 1.2.0 autolinks by default, so both would run. + autolink: false, codeBuilder: (context, name, code, closed) => _MessageCodeBlock(name: name, code: code), linkBuilder: (context, linkText, url, linkStyle) => _buildLink( @@ -279,7 +281,7 @@ class MessageContent extends HookConsumerWidget { resolvedChannelTap, resolvedChannelNames, ), - imageBuilder: (context, imageUrl) => + imageBuilder: (context, imageUrl, _, _) => _buildMedia(context, imageUrl, imetaByUrl[imageUrl]), textAlign: textAlign, maxLines: maxLines, @@ -721,9 +723,9 @@ class _MessageCodeBlock extends HookWidget { } final codeBaseStyle = TextStyle( - fontFamily: 'GeistMono', - fontSize: 13, - height: 1.5, + fontFamily: CodeStyle.fontFamily, + fontSize: CodeStyle.fontSize, + height: CodeStyle.lineHeight, color: context.colors.onSurface, ); final isDark = context.theme.brightness == Brightness.dark; @@ -735,11 +737,9 @@ class _MessageCodeBlock extends HookWidget { return Container( margin: const EdgeInsets.only(top: Grid.half), decoration: BoxDecoration( - color: context.colors.surfaceContainerHighest.withValues(alpha: 0.6), + color: CodeStyle.background(context.colors), borderRadius: BorderRadius.circular(12), - border: Border.all( - color: context.colors.outline.withValues(alpha: 0.7), - ), + border: Border.all(color: CodeStyle.border(context.colors)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/mobile/lib/shared/custom_emoji/custom_emoji_render.dart b/mobile/lib/shared/custom_emoji/custom_emoji_render.dart index feede9aec8..bbfdd25603 100644 --- a/mobile/lib/shared/custom_emoji/custom_emoji_render.dart +++ b/mobile/lib/shared/custom_emoji/custom_emoji_render.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:gpt_markdown/gpt_markdown.dart'; -import 'package:gpt_markdown/custom_widgets/markdown_config.dart'; import '../relay/relay.dart'; diff --git a/mobile/lib/shared/theme/app_markdown_theme.dart b/mobile/lib/shared/theme/app_markdown_theme.dart new file mode 100644 index 0000000000..27e5060901 --- /dev/null +++ b/mobile/lib/shared/theme/app_markdown_theme.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:gpt_markdown/gpt_markdown.dart'; + +import 'app_theme.dart'; +import 'code_style.dart'; + +/// States the app's code style on every `GptMarkdown` below it and leaves the +/// rest of the Markdown theme as it already was. +/// +/// Registering a [GptMarkdownThemeData] as a `ThemeExtension` would be the +/// shorter route, but its factory is not a partial override: it builds a fresh +/// stock Material theme and fills every heading, rule and highlight field from +/// it, so registering one stops `GptMarkdownTheme.of` deriving those from the +/// app. Restating them in the extension does not close the gap either — the +/// ambient headings carry the localized text geometry, which exists only once +/// `Theme.of` has run and a `ThemeData` factory cannot see. Overriding the one +/// field on the ambient theme is what leaves non-code Markdown untouched. +class AppMarkdownTheme extends StatelessWidget { + const AppMarkdownTheme({super.key, required this.child}); + + final Widget child; + + @override + Widget build(BuildContext context) { + final scheme = Theme.of(context).colorScheme; + return GptMarkdownTheme( + gptThemeData: GptMarkdownTheme.of(context).copyWith( + // Inline code is otherwise drawn in gpt_markdown's own bundled face, at + // its own size, tinted from `onSurface`. Stating the app's code style + // gives every Markdown surface the face, size and chip colours a fenced + // code block already uses. + inlineCode: InlineCodeStyle( + fontFamily: CodeStyle.fontFamily, + fontSizeFactor: CodeStyle.fontSizeFactor, + color: scheme.onSurface, + backgroundColor: CodeStyle.background(scheme), + borderColor: CodeStyle.border(scheme), + // A chip is small, so it takes the smallest step of the app's radius + // scale rather than the `Radii.card` a block uses. + borderRadius: const Radius.circular(Radii.xs), + ).resolve(scheme), + ), + child: child, + ); + } +} diff --git a/mobile/lib/shared/theme/code_style.dart b/mobile/lib/shared/theme/code_style.dart new file mode 100644 index 0000000000..3ed667f44c --- /dev/null +++ b/mobile/lib/shared/theme/code_style.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +import 'message_typography.dart'; + +/// The app's own code style — one place stating the mono face, its size and +/// the colours a code surface is drawn with. +/// +/// Two surfaces render code and they have to read as one family: the fenced +/// block in `MessageContent`, and the inline chip `gpt_markdown` paints from +/// the `InlineCodeStyle` declared in `AppTheme`. Both take their values from +/// here, so neither can drift from the other by editing one copy. +abstract final class CodeStyle { + /// The mono face, already used by the composer and by code blocks. + static const fontFamily = 'GeistMono'; + + /// Code size at message body scale. + static const fontSize = 13.0; + + /// Line height of code text. + static const lineHeight = 1.5; + + /// [fontSize] stated against the message body size, for APIs that scale code + /// relative to the text around it rather than fixing a point size. Keeping + /// it a ratio means code follows the body if that size ever changes. + static final fontSizeFactor = fontSize / messageBodyTextStyle.fontSize!; + + /// Fill behind a code surface. + static Color background(ColorScheme scheme) => + scheme.surfaceContainerHighest.withValues(alpha: 0.6); + + /// Outline around a code surface. + static Color border(ColorScheme scheme) => + scheme.outline.withValues(alpha: 0.7); +} diff --git a/mobile/lib/shared/theme/theme.dart b/mobile/lib/shared/theme/theme.dart index eacd1ea780..55615b5b73 100644 --- a/mobile/lib/shared/theme/theme.dart +++ b/mobile/lib/shared/theme/theme.dart @@ -1,8 +1,10 @@ export 'accent_colors.dart'; export 'adaptive_theme.dart'; export 'app_colors.dart'; +export 'app_markdown_theme.dart'; export 'app_theme.dart'; export 'buzz_theme.dart'; +export 'code_style.dart'; export 'color_scheme.dart'; export 'community_theme_preference.dart'; export 'community_theme_provider.dart'; diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 8b190dcb03..0632d4a8df 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -620,10 +620,10 @@ packages: dependency: "direct main" description: name: gpt_markdown - sha256: "5c565a438e569b3b546023d0d4eccccf87e260a3289a17c4e241c41d5e7545df" + sha256: "42887afaf5c7a71348221048a6c1e34c9836703ee0e6b4865e789253fcaa204a" url: "https://pub.dev" source: hosted - version: "1.1.6" + version: "1.2.1" gtk: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index a5166bfa07..e6806b29d1 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -27,7 +27,7 @@ dependencies: nostr: ^2.0.0 pointycastle: ^4.0.0 url_launcher: ^6.3.2 - gpt_markdown: ^1.1.6 + gpt_markdown: ^1.2.1 highlight: ^0.7.0 intl: ^0.20.2 uuid: ^4.5.1 diff --git a/mobile/test/features/channels/agent_activity/transcript_item_widget_test.dart b/mobile/test/features/channels/agent_activity/transcript_item_widget_test.dart new file mode 100644 index 0000000000..20524e9a2d --- /dev/null +++ b/mobile/test/features/channels/agent_activity/transcript_item_widget_test.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:gpt_markdown/custom_widgets/link_button.dart'; +import 'package:buzz/features/channels/agent_activity/observer_models.dart'; +import 'package:buzz/features/channels/agent_activity/transcript_item_widget.dart'; +import 'package:buzz/shared/theme/theme.dart'; + +Widget _testable(Widget child) { + return MaterialApp( + theme: AppTheme.light(), + home: Scaffold(body: SingleChildScrollView(child: child)), + ); +} + +void main() { + // Neither transcript surface passes a link handler, so an autolinked bare + // URL would draw as a link and then do nothing when tapped. They stay text. + testWidgets('leaves a bare URL in a message as plain text', (tester) async { + await tester.pumpWidget( + _testable( + TranscriptItemWidget( + item: MessageItem( + id: 'm1', + role: 'assistant', + title: 'Assistant', + text: 'Report is at https://example.com/report today.', + timestamp: '2026-08-29T09:00:00Z', + ), + ), + ), + ); + + expect(find.byType(LinkButton), findsNothing); + }); + + testWidgets('leaves a bare URL in a thought as plain text', (tester) async { + await tester.pumpWidget( + _testable( + TranscriptItemWidget( + item: ThoughtItem( + id: 't1', + title: 'Thinking', + text: 'Checking https://example.com/report first.', + timestamp: '2026-08-29T09:00:00Z', + ), + ), + ), + ); + + expect(find.byType(LinkButton), findsNothing); + }); +} diff --git a/mobile/test/features/channels/message_content_custom_emoji_test.dart b/mobile/test/features/channels/message_content_custom_emoji_test.dart index 3059af9a93..c43ed614c6 100644 --- a/mobile/test/features/channels/message_content_custom_emoji_test.dart +++ b/mobile/test/features/channels/message_content_custom_emoji_test.dart @@ -111,8 +111,12 @@ void main() { ) async { await tester.pumpWidget(_testable('`:wave:` :unknown:wave:')); expect(find.byType(CustomEmojiImage), findsOneWidget); + // A paragraph holding inline code renders through BidiRichText, a RichText + // subclass, and `find.byType` matches the exact runtime type only. final text = tester - .widgetList(find.byType(RichText)) + .widgetList( + find.byWidgetPredicate((widget) => widget is RichText), + ) .map((widget) => widget.text.toPlainText()) .join(); expect(text, contains(':wave:')); diff --git a/mobile/test/features/channels/message_content_test.dart b/mobile/test/features/channels/message_content_test.dart index aaf6a5973b..8fe47e8803 100644 --- a/mobile/test/features/channels/message_content_test.dart +++ b/mobile/test/features/channels/message_content_test.dart @@ -45,7 +45,8 @@ Widget _testable( data: MediaQuery.of( context, ).copyWith(disableAnimations: disableAnimations), - child: Scaffold(body: child), + // The app states its code style here, above the navigator. + child: AppMarkdownTheme(child: Scaffold(body: child)), ), ), ), @@ -2813,6 +2814,50 @@ Photos expect(_allRichText(tester), isNot(contains('**'))); }); + testWidgets('renders inline code in the app code style', (tester) async { + // The message surfaces pass this style in; the widget's own fallback + // is the smaller `bodyMedium`, which would move the expected size. + await tester.pumpWidget( + _testable( + const MessageContent( + content: 'Run `just test` now', + baseStyle: messageBodyTextStyle, + ), + ), + ); + + // gpt_markdown tags inline code with a CodeTextSpan carrying both the + // resolved text style and the colours the chip behind it is painted + // with. It renders through BidiRichText, a RichText subclass, so + // find.byType(RichText) would miss it. + final codeSpans = []; + for (final rich in tester.widgetList( + find.byWidgetPredicate((widget) => widget is RichText), + )) { + rich.text.visitChildren((span) { + if (span is CodeTextSpan && span.text == 'just test') { + codeSpans.add(span); + } + return true; + }); + } + + expect(codeSpans, hasLength(1)); + final code = codeSpans.single; + const scheme = lightColorScheme; + + // Face, size and ink — the values a fenced code block is drawn with, + // not the package's bundled mono at its own 0.94 of the body size. + expect(code.style?.fontFamily, CodeStyle.fontFamily); + expect(code.style?.fontSize, closeTo(CodeStyle.fontSize, 0.001)); + expect(code.style?.color, scheme.onSurface); + + // Chip fill and outline come from the app's code surface rather than + // the package's `onSurface` tints. + expect(code.codeStyle.backgroundColor, CodeStyle.background(scheme)); + expect(code.codeStyle.borderColor, CodeStyle.border(scheme)); + }); + testWidgets('renders code block between paragraphs', (tester) async { await tester.pumpWidget( _testable( diff --git a/mobile/test/shared/theme/app_markdown_theme_test.dart b/mobile/test/shared/theme/app_markdown_theme_test.dart new file mode 100644 index 0000000000..26ae369821 --- /dev/null +++ b/mobile/test/shared/theme/app_markdown_theme_test.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:gpt_markdown/gpt_markdown.dart'; +import 'package:buzz/shared/theme/app_markdown_theme.dart'; +import 'package:buzz/shared/theme/app_theme.dart'; +import 'package:buzz/shared/theme/code_style.dart'; + +/// The Markdown theme a widget reads under [theme], with [wrapped] deciding +/// whether the app states its code style above it. +Future _markdownTheme( + WidgetTester tester, + ThemeData theme, { + required bool wrapped, +}) async { + late GptMarkdownThemeData read; + final reader = Builder( + builder: (context) { + read = GptMarkdownTheme.of(context); + return const SizedBox.shrink(); + }, + ); + + await tester.pumpWidget( + MaterialApp( + theme: theme, + home: wrapped ? AppMarkdownTheme(child: reader) : reader, + ), + ); + // MaterialApp animates a theme change, so the first frame after a pump can + // still carry the previous one. + await tester.pumpAndSettle(); + return read; +} + +void main() { + testWidgets('states inline code and leaves the rest of Markdown alone', ( + tester, + ) async { + for (final theme in [AppTheme.light(), AppTheme.dark()]) { + final ambient = await _markdownTheme(tester, theme, wrapped: false); + final stated = await _markdownTheme(tester, theme, wrapped: true); + + // Headings, rules and the rest keep the values gpt_markdown derives from + // the app theme: a code-only change must not restyle anything else. + expect(stated.h1, ambient.h1); + expect(stated.h2, ambient.h2); + expect(stated.h3, ambient.h3); + expect(stated.h4, ambient.h4); + expect(stated.h5, ambient.h5); + expect(stated.h6, ambient.h6); + expect(stated.hrLineColor, ambient.hrLineColor); + expect(stated.hrLineThickness, ambient.hrLineThickness); + expect(stated.hrLinePadding, ambient.hrLinePadding); + expect(stated.highlightColor, ambient.highlightColor); + expect(stated.linkColor, ambient.linkColor); + expect(stated.linkHoverColor, ambient.linkHoverColor); + expect( + stated.autoAddDividerLineAfterH1, + ambient.autoAddDividerLineAfterH1, + ); + expect(stated.styleSheet, ambient.styleSheet); + + // Inline code is the whole of the difference. + final scheme = theme.colorScheme; + expect(stated.inlineCode.fontFamily, CodeStyle.fontFamily); + expect(stated.inlineCode.color, scheme.onSurface); + expect(stated.inlineCode.backgroundColor, CodeStyle.background(scheme)); + expect(stated.inlineCode.borderColor, CodeStyle.border(scheme)); + expect( + ambient.inlineCode.fontFamily, + isNot(CodeStyle.fontFamily), + reason: 'the package default is what this widget exists to replace', + ); + } + }); +} diff --git a/scripts/normative-corpus.json b/scripts/normative-corpus.json index b75e4eb0d5..cb0ff4ae27 100644 --- a/scripts/normative-corpus.json +++ b/scripts/normative-corpus.json @@ -2347,6 +2347,370 @@ "registry_label": null } }, + { + "_group": "Databricks FQN GPT-5+ Responses routing", + "_note": "Only the service component selects Responses; effort capabilities remain neutral." + }, + { + "id": "dbv2-fqn-responses-0", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.goose-gpt-6-astra", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "openai-responses", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-1", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.goose-gpt-5", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "openai-responses", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-2", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-5-5", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "openai-responses", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-3", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-10", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "openai-responses", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-4", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.GOOSE-GPT-6-ASTRA", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "openai-responses", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-5", + "provider": "databricks_v2", + "raw_model_id": "gpt-6.schema.other", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-6", + "provider": "databricks_v2", + "raw_model_id": "catalog.gpt-5.other", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-7", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.claude-gpt-6", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-8", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.my-gpt-6-astra", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "openai-responses", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-9", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.mygpt-6-astra", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-10", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-4", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-11", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-4o", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-12", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-6x", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-13", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-oss-120b", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-14", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-15", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-4294967296", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-16", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.gpt-6", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, + { + "id": "dbv2-fqn-responses-17", + "provider": "databricks_v2", + "raw_model_id": "catalog.schema.kimi-k3", + "expect": { + "thinking_mode": "none", + "supported_efforts": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_effort": "medium", + "databricks_v2_wire_route": "mlflow-chat", + "normalization_policy": "openai-clamp-max-to-xhigh", + "registry_label": null + } + }, { "_group": "Databricks UC model-family humanization probes (#6918 follow-up)", "_note": "Exact-record and UC-FQN strip probes for the Gemini/DeepSeek/GLM/Grok/Llama/Qwen/Gemma/Inkling families surfaced by UC discovery."