diff --git a/Cargo.lock b/Cargo.lock index afb474a2dc..90b347ea4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,7 +103,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -114,7 +114,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -271,7 +271,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -306,7 +306,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -360,6 +360,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + [[package]] name = "atomic-destructor" version = "0.3.0" @@ -505,7 +514,7 @@ checksum = "7aa268c23bfbbd2c4363b9cd302a4f504fb2a9dfe7e3451d66f35dd392e20aca" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -554,15 +563,30 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec 0.6.3", +] + [[package]] name = "bit-set" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "bit-vec", + "bit-vec 0.8.0", ] +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bit-vec" version = "0.8.0" @@ -588,9 +612,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "serde_core", ] @@ -695,7 +725,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 2.0.117", ] [[package]] @@ -1173,6 +1203,12 @@ dependencies = [ "url", ] +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + [[package]] name = "bytemuck" version = "1.25.0" @@ -1227,6 +1263,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfb" version = "0.7.3" @@ -1347,7 +1389,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1398,7 +1440,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1428,6 +1470,20 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "compact_str" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" +dependencies = [ + "castaway", + "cfg-if 1.0.4", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "compression-codecs" version = "0.4.38" @@ -1690,7 +1746,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags", + "bitflags 2.13.0", "crossterm_winapi", "mio", "parking_lot", @@ -1700,6 +1756,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags 2.13.0", + "crossterm_winapi", + "derive_more", + "document-features", + "mio", + "parking_lot", + "rustix 1.1.4", + "signal-hook", + "signal-hook-mio", + "winapi", +] + [[package]] name = "crossterm_winapi" version = "0.9.1" @@ -1764,6 +1838,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "csscolorparser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" +dependencies = [ + "lab", + "phf", +] + [[package]] name = "csv" version = "1.4.0" @@ -1836,12 +1920,12 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "5.0.0-pre.6" +version = "5.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" +checksum = "4f359e08ca85e7bd759e1fd933ff2bccd81864c60a8fba0e259c7f822b0924bf" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.2.17", + "cpufeatures 0.3.0", "curve25519-dalek-derive", "digest 0.11.3", "fiat-crypto 0.3.0", @@ -1860,7 +1944,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1894,7 +1978,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.117", ] [[package]] @@ -1907,7 +1991,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.117", ] [[package]] @@ -1918,7 +2002,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1929,7 +2013,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1969,7 +2053,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" dependencies = [ "data-encoding", - "syn", + "syn 2.0.117", ] [[package]] @@ -2032,6 +2116,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "deltae" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" + [[package]] name = "der" version = "0.8.0" @@ -2061,7 +2151,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2082,7 +2172,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2092,7 +2182,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn", + "syn 2.0.117", ] [[package]] @@ -2114,7 +2204,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 2.0.117", "unicode-xid", ] @@ -2174,7 +2264,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2183,7 +2273,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -2197,7 +2287,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2220,6 +2310,15 @@ dependencies = [ "const-random", ] +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -2266,11 +2365,11 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "3.0.0-pre.7" +version = "3.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20449acd54b660981ae5caa2bcb56d1fe7f25f2e37a38ec507400fab034d4bb6" +checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60" dependencies = [ - "curve25519-dalek 5.0.0-pre.6", + "curve25519-dalek 5.0.0-rc.0", "ed25519", "rand_core 0.10.1", "serde", @@ -2324,7 +2423,7 @@ checksum = "3ed8956bd5c1f0415200516e78ff07ec9e16415ade83c056c230d7b7ea0d55b7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2345,7 +2444,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2361,7 +2460,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2374,6 +2473,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + [[package]] name = "evalexpr" version = "11.3.1" @@ -2412,6 +2520,22 @@ dependencies = [ "smallvec", ] +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set 0.5.3", + "regex", +] + +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "fastrand" version = "2.4.1" @@ -2439,6 +2563,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + [[package]] name = "filetime" version = "0.2.29" @@ -2455,6 +2590,18 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "finl_unicode" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9844ddc3a6e533d62bba727eb6c28b5d360921d5175e9ff0f1e621a5c590a4d5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -2634,7 +2781,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2686,8 +2833,8 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.2.1", - "windows-result 0.4.1", + "windows-link 0.1.3", + "windows-result 0.3.4", ] [[package]] @@ -2804,7 +2951,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -3002,7 +3149,7 @@ dependencies = [ "http", "idna", "ipnet", - "jni", + "jni 0.22.4", "rand 0.10.1", "rustls", "thiserror 2.0.18", @@ -3022,7 +3169,7 @@ dependencies = [ "data-encoding", "idna", "ipnet", - "jni", + "jni 0.22.4", "once_cell", "prefix-trie", "rand 0.10.1", @@ -3045,7 +3192,7 @@ dependencies = [ "hickory-proto", "ipconfig", "ipnet", - "jni", + "jni 0.22.4", "moka", "ndk-context", "once_cell", @@ -3277,7 +3424,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core 0.61.2", ] [[package]] @@ -3502,6 +3649,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + [[package]] name = "infer" version = "0.19.0" @@ -3521,6 +3677,19 @@ dependencies = [ "generic-array", ] +[[package]] +name = "instability" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" +dependencies = [ + "darling 0.23.0", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "instant" version = "0.1.13" @@ -3557,9 +3726,9 @@ dependencies = [ [[package]] name = "iroh" -version = "1.0.0-rc.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98e206e3d3f2642f5c08c413755fc0ac19b54ae1a656af88be03454ce3ed2e6" +checksum = "5fca9b4b462c343ff88fc0af4096c186f939b602a0bc08723536ef2c31c93971" dependencies = [ "backon", "blake3", @@ -3594,7 +3763,6 @@ dependencies = [ "rustc-hash", "rustls", "rustls-pki-types", - "rustls-webpki", "serde", "smallvec", "strum", @@ -3605,36 +3773,32 @@ dependencies = [ "tracing", "url", "wasm-bindgen-futures", - "webpki-roots 1.0.7", ] [[package]] name = "iroh-base" -version = "1.0.0-rc.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af93d67701c00c504982154569192ad384738c0450ba1196930314b955100552" +checksum = "830a582cd54410dc1aa71d4786a82c3297d7b0165accd8b6dbbb3b240b48140d" dependencies = [ - "curve25519-dalek 5.0.0-pre.6", + "curve25519-dalek 5.0.0-rc.0", "data-encoding", "data-encoding-macro", "derive_more", - "digest 0.11.3", "ed25519-dalek", "getrandom 0.4.2", "n0-error", "rand 0.10.1", "serde", - "sha2 0.11.0", "url", "zeroize", - "zeroize_derive", ] [[package]] name = "iroh-dns" -version = "1.0.0-rc.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de4112c91eb64094d77df9d3112606dcf7ff216421afccd2dc762fda5a7b2879" +checksum = "516e4eedc38e33ab69a6bd325520332dc3d67b25454e2d590ebb84a25240dd9a" dependencies = [ "arc-swap", "cfg_aliases", @@ -3644,8 +3808,8 @@ dependencies = [ "n0-error", "n0-future", "ndk-context", + "portable-atomic", "rand 0.10.1", - "reqwest 0.13.3", "rustls", "simple-dns", "strum", @@ -3656,9 +3820,9 @@ dependencies = [ [[package]] name = "iroh-metrics" -version = "1.0.0-rc.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d102597d0ee523f17fdb672c532395e634dbe945429284c811430d63bacc0d8a" +checksum = "291065721ad7c477b972e581bbc528df031dc8eb5e39fe1ff3300ae5dfb157ef" dependencies = [ "iroh-metrics-derive", "itoa", @@ -3671,21 +3835,21 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" -version = "1.0.0-rc.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c8e0c97f1dc787107f388433c349397c565572fe6406d600ff7bb7b7fe3b30" +checksum = "1ae5f0c4405d1fbc9fb16ff422ca40620e93dc36c30ecaba0c2aee3992b7bd48" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] name = "iroh-relay" -version = "1.0.0-rc.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54f490405e42dd2ecf16be18a3587d2665401e94a498094f12322eaa6d5ebb2b" +checksum = "8149bb6a57126225a07d6928846d82dcedfd24ea0f863ef7b2eb475e1d726354" dependencies = [ "blake3", "bytes", @@ -3748,6 +3912,22 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if 1.0.4", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "jni" version = "0.22.4" @@ -3757,7 +3937,7 @@ dependencies = [ "cfg-if 1.0.4", "combine", "jni-macros", - "jni-sys", + "jni-sys 0.4.1", "log", "simd_cesu8", "thiserror 2.0.18", @@ -3775,7 +3955,16 @@ dependencies = [ "quote", "rustc_version", "simd_cesu8", - "syn", + "syn 2.0.117", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", ] [[package]] @@ -3794,7 +3983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -3829,6 +4018,17 @@ dependencies = [ "ucd-trie", ] +[[package]] +name = "kasuari" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" +dependencies = [ + "hashbrown 0.16.1", + "portable-atomic", + "thiserror 2.0.18", +] + [[package]] name = "keyring" version = "3.6.3" @@ -3863,6 +4063,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e037a2e1d8d5fdbd49b16a4ea09d5d6401c1f29eca5ff29d03d3824dba16256a" +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + [[package]] name = "lazy_static" version = "1.5.0" @@ -3912,6 +4118,12 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libredox" version = "0.1.17" @@ -3931,6 +4143,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "line-clipping" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" +dependencies = [ + "bitflags 2.13.0", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -3949,6 +4170,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + [[package]] name = "lock_api" version = "0.4.14" @@ -4013,6 +4240,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3d25b0e0b648a86960ac23b7ad4abb9717601dec6f66c165f5b037f3f03065f" +[[package]] +name = "mac_address" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" +dependencies = [ + "nix 0.29.0", + "winapi", +] + [[package]] name = "matchers" version = "0.2.0" @@ -4036,7 +4273,7 @@ checksum = "746873a384ad60adc5db74471dfaba74bd278afbdcfd81db93fafcdfc8b5ca0c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4076,6 +4313,12 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memmem" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" + [[package]] name = "memoffset" version = "0.9.1" @@ -4087,8 +4330,8 @@ dependencies = [ [[package]] name = "mesh-llm-api-client" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "hex", "mesh-llm-client", @@ -4097,8 +4340,8 @@ dependencies = [ [[package]] name = "mesh-llm-api-server" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "mesh-llm-api-client", @@ -4106,10 +4349,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "mesh-llm-build-info" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" + [[package]] name = "mesh-llm-client" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -4140,8 +4388,8 @@ dependencies = [ [[package]] name = "mesh-llm-config" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "dirs", @@ -4151,12 +4399,13 @@ dependencies = [ "skippy-protocol", "toml 0.9.12+spec-1.1.0", "toml_edit", + "url", ] [[package]] name = "mesh-llm-embedded-runtime" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "mesh-llm-host-runtime", @@ -4165,18 +4414,20 @@ dependencies = [ [[package]] name = "mesh-llm-events" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "clap", + "crossterm 0.28.1", + "ratatui", "serde_json", ] [[package]] name = "mesh-llm-gpu-bench" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "cc", @@ -4188,8 +4439,8 @@ dependencies = [ [[package]] name = "mesh-llm-guardrails" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "serde", "serde_json", @@ -4197,16 +4448,16 @@ dependencies = [ [[package]] name = "mesh-llm-hardware-profile" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "mesh-llm-native-runtime", ] [[package]] name = "mesh-llm-host-runtime" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "argon2", @@ -4217,7 +4468,7 @@ dependencies = [ "chacha20poly1305", "chrono", "clap", - "crossterm", + "crossterm 0.28.1", "crypto_box", "dirs", "ed25519-dalek", @@ -4228,12 +4479,14 @@ dependencies = [ "http", "http-body-util", "httparse", + "if-addrs", "iroh", "json5", "keyring", "libc", "mdns-sd", "mesh-llm-api-server", + "mesh-llm-build-info", "mesh-llm-client", "mesh-llm-config", "mesh-llm-events", @@ -4278,6 +4531,7 @@ dependencies = [ "skippy-runtime", "skippy-server", "skippy-topology", + "socket2", "tabwriter", "tar", "tempfile", @@ -4295,8 +4549,8 @@ dependencies = [ [[package]] name = "mesh-llm-identity" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "argon2", "base64", @@ -4317,8 +4571,8 @@ dependencies = [ [[package]] name = "mesh-llm-native-runtime" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "serde", @@ -4328,8 +4582,8 @@ dependencies = [ [[package]] name = "mesh-llm-node" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "mesh-llm-types", @@ -4342,8 +4596,8 @@ dependencies = [ [[package]] name = "mesh-llm-plugin" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -4359,8 +4613,8 @@ dependencies = [ [[package]] name = "mesh-llm-plugin-manager" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "dirs", @@ -4377,8 +4631,8 @@ dependencies = [ [[package]] name = "mesh-llm-protocol" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "hex", @@ -4390,22 +4644,23 @@ dependencies = [ [[package]] name = "mesh-llm-routing" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "iroh", ] [[package]] name = "mesh-llm-runtime-install" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "dirs", "flate2", "futures-util", "hex", + "mesh-llm-build-info", "mesh-llm-hardware-profile", "mesh-llm-native-runtime", "reqwest 0.12.28", @@ -4420,8 +4675,8 @@ dependencies = [ [[package]] name = "mesh-llm-sdk" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "mesh-llm-api-client", @@ -4435,8 +4690,8 @@ dependencies = [ [[package]] name = "mesh-llm-skills" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "dirs", @@ -4446,8 +4701,8 @@ dependencies = [ [[package]] name = "mesh-llm-system" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "chrono", @@ -4455,6 +4710,7 @@ dependencies = [ "dirs", "hex", "libc", + "mesh-llm-build-info", "mesh-llm-gpu-bench", "reqwest 0.12.28", "semver", @@ -4468,8 +4724,8 @@ dependencies = [ [[package]] name = "mesh-llm-types" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "hex", "serde", @@ -4479,13 +4735,13 @@ dependencies = [ [[package]] name = "mesh-llm-ui" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" [[package]] name = "mesh-mixture-of-agents" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "async-trait", "mesh-llm-guardrails", @@ -4571,6 +4827,12 @@ dependencies = [ "rxml", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -4595,8 +4857,8 @@ dependencies = [ [[package]] name = "model-artifact" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -4606,8 +4868,8 @@ dependencies = [ [[package]] name = "model-hf" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -4624,8 +4886,8 @@ dependencies = [ [[package]] name = "model-package" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "bytes", @@ -4644,16 +4906,16 @@ dependencies = [ [[package]] name = "model-ref" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "serde", ] [[package]] name = "model-resolver" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "model-artifact", @@ -4717,9 +4979,9 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "n0-error" -version = "1.0.0-rc.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223e946a84aa91644507a6b7865cfebbb9a231ace499041c747ab0fd30408212" +checksum = "c37e81176a83a77d2514528b91bdafc70ef88aab428f0e1b91aebb8d99888895" dependencies = [ "n0-error-macros", "spez", @@ -4727,13 +4989,13 @@ dependencies = [ [[package]] name = "n0-error-macros" -version = "1.0.0-rc.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565305a21e6b3bf26640ad98f05a0fda12d3ab4315394566b52a7bddb8b34828" +checksum = "e2acd8b070213b0299282f884b4beba4e7b52d624fdcd504a3ad3665390c11e1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -4759,9 +5021,9 @@ dependencies = [ [[package]] name = "n0-watcher" -version = "1.0.0-rc.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928d8039a66cce5efcfd35e88b32d3defc8eba630b3ac451522997f563956a52" +checksum = "bbc618745ad0b7414b149d0517ad8b5573b2fb4d4e2717add3d2446ce1fdd826" dependencies = [ "derive_more", "n0-error", @@ -4799,19 +5061,22 @@ checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d" [[package]] name = "netdev" -version = "0.43.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bacaf873ee4eab5646f99b381b271ec75e716902a67cf962c0f328c5eb5bfb" +checksum = "569dfbdd2efd771b24ec9bb57f956e04d4fbfc72f62b2f11961723f9b3f4b020" dependencies = [ "block2", "dispatch2", "dlopen2", "ipnet", + "jni 0.21.1", "libc", "mac-addr", + "ndk-context", "netlink-packet-core", - "netlink-packet-route 0.29.0", + "netlink-packet-route", "netlink-sys", + "objc2", "objc2-core-foundation", "objc2-core-wlan", "objc2-foundation", @@ -4832,23 +5097,11 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9854ea6ad14e3f4698a7f03b65bce0833dd2d81d594a0e4a984170537146b6" -dependencies = [ - "bitflags", - "libc", - "log", - "netlink-packet-core", -] - -[[package]] -name = "netlink-packet-route" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8919612f6028ab4eacbbfe1234a9a43e3722c6e0915e7ff519066991905092" +checksum = "e2288fcb784eb3defd5fb16f4c4160d5f477de192eac730f43e1d11c24d9a007" dependencies = [ - "bitflags", + "bitflags 2.13.0", "libc", "log", "netlink-packet-core", @@ -4883,14 +5136,15 @@ dependencies = [ [[package]] name = "netwatch" -version = "0.17.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bfbba77b994ce69f1d40fc66fd8abbd23df62ce4aea61fbb34d638106a2549" +checksum = "4d9cbe01741347ef750d743d6690603f5eed8341e679fb51c8e629337aa11976" dependencies = [ "atomic-waker", "bytes", "cfg_aliases", "derive_more", + "ipnet", "js-sys", "libc", "n0-error", @@ -4898,7 +5152,7 @@ dependencies = [ "n0-watcher", "netdev", "netlink-packet-core", - "netlink-packet-route 0.30.0", + "netlink-packet-route", "netlink-proto", "netlink-sys", "noq-udp", @@ -4923,7 +5177,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases", "libc", @@ -4936,17 +5190,27 @@ version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases", "libc", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "noq" -version = "1.0.0-rc.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22739e0831e40f5ab7d6ac5317ed80bfe5fb3f44be57d23fa2eea8bff83fb303" +checksum = "4bf95190af1bd4a00a10e8255ca0c8ddd9e9a9f5e79151d7a7eb6d56aff5dc89" dependencies = [ "bytes", "cfg_aliases", @@ -4966,9 +5230,9 @@ dependencies = [ [[package]] name = "noq-proto" -version = "1.0.0-rc.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cee32450cf726b223ac4154003c93cb52fbde159ab1240990e88945bf3ae35e" +checksum = "aa6c890013591e709a3e45dd53501351b7e27e7ff3c7e9fc3dce43e300e7e9d3" dependencies = [ "aes-gcm", "bytes", @@ -4993,9 +5257,9 @@ dependencies = [ [[package]] name = "noq-udp" -version = "1.0.0-rc.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78633d1fe1bde91d12bcabb230ac9edb890857414c6d44f3212e0d309525b5ff" +checksum = "3137a52df66c20090a889828d1c655f21f52294cba64e5c4fbb04fc83eee7c8e" dependencies = [ "cfg_aliases", "libc", @@ -5096,7 +5360,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5139,10 +5403,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] -name = "num-integer" -version = "0.1.46" +name = "num-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] @@ -5208,7 +5483,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -5235,7 +5510,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags", + "bitflags 2.13.0", "block2", "dispatch2", "libc", @@ -5248,7 +5523,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e34919aba0d701380d911702455038a8a3587467fe0141d6a71501e7ffe48" dependencies = [ - "bitflags", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -5268,7 +5543,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -5291,7 +5566,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" dependencies = [ - "bitflags", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", ] @@ -5312,7 +5587,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" dependencies = [ - "bitflags", + "bitflags 2.13.0", "dispatch2", "libc", "objc2", @@ -5350,8 +5625,8 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openai-frontend" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "async-trait", "axum", @@ -5371,7 +5646,7 @@ version = "0.10.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" dependencies = [ - "bitflags", + "bitflags 2.13.0", "cfg-if 1.0.4", "foreign-types", "libc", @@ -5387,7 +5662,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -5561,6 +5836,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "ordered-multimap" version = "0.7.3" @@ -5590,6 +5874,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "palette" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +dependencies = [ + "approx", + "fast-srgb8", + "libm", + "palette_derive", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "papaya" version = "0.2.4" @@ -5683,13 +5991,55 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pest_meta" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" +dependencies = [ + "pest", +] + [[package]] name = "petgraph" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ - "fixedbitset", + "fixedbitset 0.5.7", "hashbrown 0.15.5", "indexmap", ] @@ -5714,6 +6064,16 @@ dependencies = [ "phf_shared", ] +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared", +] + [[package]] name = "phf_generator" version = "0.11.3" @@ -5734,7 +6094,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -5763,7 +6123,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -5818,7 +6178,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags", + "bitflags 2.13.0", "crc32fast", "fdeflate", "flate2", @@ -5873,9 +6233,9 @@ dependencies = [ [[package]] name = "portmapper" -version = "0.17.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aec2a8809e3f7dba624776bb223da9fed49c413c60b3bef21aadcb67a5e35944" +checksum = "eb3713e4977408279158444a18c1a01ac9bf2e7eaf1fbfd1a19ac9cd18d90721" dependencies = [ "base64", "bytes", @@ -5921,7 +6281,7 @@ checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -5966,7 +6326,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.117", ] [[package]] @@ -6007,9 +6367,9 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ - "bit-set", - "bit-vec", - "bitflags", + "bit-set 0.8.0", + "bit-vec 0.8.0", + "bitflags 2.13.0", "num-traits", "rand 0.9.4", "rand_chacha 0.9.0", @@ -6045,7 +6405,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn", + "syn 2.0.117", "tempfile", ] @@ -6059,7 +6419,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -6376,13 +6736,114 @@ dependencies = [ "rustversion", ] +[[package]] +name = "ratatui" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3274ba0a2c5e1bcad2a2005d20f4dc59dad26b2eb0940fb094500dba4099d57d" +dependencies = [ + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-macros", + "ratatui-termina", + "ratatui-termwiz", + "ratatui-widgets", + "serde", +] + +[[package]] +name = "ratatui-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" +dependencies = [ + "bitflags 2.13.0", + "compact_str 0.9.1", + "critical-section", + "hashbrown 0.17.1", + "itertools", + "kasuari", + "lru 0.18.0", + "palette", + "serde", + "strum", + "thiserror 2.0.18", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] + +[[package]] +name = "ratatui-crossterm" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567584a3b0e6a8203c23de40b4861497266725eb5363dbfd18a1edd603cca9f0" +dependencies = [ + "cfg-if 1.0.4", + "crossterm 0.29.0", + "instability", + "ratatui-core", +] + +[[package]] +name = "ratatui-macros" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7dc68daa7498a43e4d68e0eb078427e10c38fbcfbb1e42d955f1fa2140d814" +dependencies = [ + "ratatui-core", + "ratatui-widgets", +] + +[[package]] +name = "ratatui-termina" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0bf912d9e66f057a759d92e386a280ea886b352ab757d6ac4d653c7ed2c43c2" +dependencies = [ + "instability", + "ratatui-core", + "termina", +] + +[[package]] +name = "ratatui-termwiz" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf03e0380b7744054d6cb74224fe3adf062a029754933f575ca1e3b4c2ce977" +dependencies = [ + "ratatui-core", + "termwiz", +] + +[[package]] +name = "ratatui-widgets" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" +dependencies = [ + "bitflags 2.13.0", + "hashbrown 0.17.1", + "indoc", + "instability", + "itertools", + "line-clipping", + "ratatui-core", + "serde", + "strum", + "time", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "raw-cpuid" version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags", + "bitflags 2.13.0", ] [[package]] @@ -6431,7 +6892,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.13.0", ] [[package]] @@ -6462,7 +6923,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -6670,7 +7131,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn", + "syn 2.0.117", ] [[package]] @@ -6749,7 +7210,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -6762,11 +7223,11 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6815,7 +7276,7 @@ checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", - "jni", + "jni 0.22.4", "log", "once_cell", "rustls", @@ -6825,7 +7286,7 @@ dependencies = [ "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6880,7 +7341,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e80413b9a35e9d33217b3dcac04cf95f6559d15944b93887a08be5496c4a4" dependencies = [ - "compact_str", + "compact_str 0.7.1", ] [[package]] @@ -6945,7 +7406,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 2.0.117", ] [[package]] @@ -7037,7 +7498,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.13.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -7050,7 +7511,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -7074,7 +7535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7126,7 +7587,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -7137,7 +7598,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -7172,7 +7633,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -7379,7 +7840,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a75cbde1bf934313596a004973e462f9a82caa814dcf1a5f507bdf51597eeb4" dependencies = [ - "bitflags", + "bitflags 2.13.0", ] [[package]] @@ -7396,8 +7857,8 @@ checksum = "0c6f73aeb92d671e0cc4dca167e59b2deb6387c375391bc99ee743f326994a2b" [[package]] name = "skippy-cache" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "blake3", @@ -7406,29 +7867,29 @@ dependencies = [ [[package]] name = "skippy-coordinator" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "thiserror 2.0.18", ] [[package]] name = "skippy-ffi" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "libloading", ] [[package]] name = "skippy-metrics" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" [[package]] name = "skippy-protocol" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "prost", "prost-build", @@ -7438,8 +7899,8 @@ dependencies = [ [[package]] name = "skippy-runtime" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "libc", @@ -7452,8 +7913,8 @@ dependencies = [ [[package]] name = "skippy-server" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -7480,8 +7941,8 @@ dependencies = [ [[package]] name = "skippy-topology" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "serde", "serde_json", @@ -7520,7 +7981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -7537,7 +7998,7 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -7635,7 +8096,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn", + "syn 2.0.117", ] [[package]] @@ -7658,7 +8119,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn", + "syn 2.0.117", "thiserror 2.0.18", "tokio", "url", @@ -7670,7 +8131,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90b8020fe17c5f2c245bfa2505d7ef59c5604839527c740266ad2214acebea27" dependencies = [ - "bitflags", + "bitflags 2.13.0", "byteorder", "bytes", "chrono", @@ -7700,7 +8161,7 @@ checksum = "87a2bdd6e83f6b3ea525ca9fee568030508b58355a43d0b2c1674d5f79dcd65e" dependencies = [ "atoi", "base64", - "bitflags", + "bitflags 2.13.0", "byteorder", "chrono", "crc", @@ -7825,7 +8286,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -7840,6 +8301,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.117" @@ -7868,7 +8340,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -7905,7 +8377,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags", + "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -7956,7 +8428,83 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.59.0", + "windows-sys 0.61.2", +] + +[[package]] +name = "termina" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" +dependencies = [ + "bitflags 2.13.0", + "parking_lot", + "rustix 1.1.4", + "signal-hook", + "windows-sys 0.61.2", +] + +[[package]] +name = "terminfo" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" +dependencies = [ + "fnv", + "nom", + "phf", + "phf_codegen", +] + +[[package]] +name = "termios" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" +dependencies = [ + "libc", +] + +[[package]] +name = "termwiz" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" +dependencies = [ + "anyhow", + "base64", + "bitflags 2.13.0", + "fancy-regex", + "filedescriptor", + "finl_unicode", + "fixedbitset 0.4.2", + "hex", + "lazy_static", + "libc", + "log", + "memmem", + "nix 0.29.0", + "num-derive", + "num-traits", + "ordered-float", + "pest", + "pest_derive", + "phf", + "sha2 0.10.9", + "signal-hook", + "siphasher", + "terminfo", + "termios", + "thiserror 1.0.69", + "ucd-trie", + "unicode-segmentation", + "vtparse", + "wezterm-bidi", + "wezterm-blob-leases", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-input-types", + "winapi", ] [[package]] @@ -7985,7 +8533,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -7996,7 +8544,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -8101,7 +8649,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -8382,7 +8930,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "async-compression", - "bitflags", + "bitflags 2.13.0", "bytes", "futures-core", "futures-util", @@ -8449,7 +8997,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -8595,7 +9143,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" dependencies = [ "memoffset", "tempfile", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -8643,6 +9191,17 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +[[package]] +name = "unicode-truncate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" +dependencies = [ + "itertools", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "unicode-width" version = "0.2.2" @@ -8720,6 +9279,7 @@ version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ + "atomic", "getrandom 0.4.2", "js-sys", "serde_core", @@ -8781,6 +9341,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vtparse" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" +dependencies = [ + "utf8parse", +] + [[package]] name = "wait-timeout" version = "0.2.1" @@ -8893,7 +9462,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -8960,7 +9529,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags", + "bitflags 2.13.0", "hashbrown 0.15.5", "indexmap", "semver", @@ -8993,7 +9562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc95580916af1e68ff6a7be07446fc5db73ebf71cf092de939bbf5f7e189f72" dependencies = [ "core-foundation 0.10.1", - "jni", + "jni 0.22.4", "log", "ndk-context", "objc2", @@ -9035,6 +9604,78 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" +[[package]] +name = "wezterm-bidi" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0a6e355560527dd2d1cf7890652f4f09bb3433b6aadade4c9b5ed76de5f3ec" +dependencies = [ + "log", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-blob-leases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692daff6d93d94e29e4114544ef6d5c942a7ed998b37abdc19b17136ea428eb7" +dependencies = [ + "getrandom 0.3.4", + "mac_address", + "sha2 0.10.9", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "wezterm-color-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de81ef35c9010270d63772bebef2f2d6d1f2d20a983d27505ac850b8c4b4296" +dependencies = [ + "csscolorparser", + "deltae", + "lazy_static", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-dynamic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac" +dependencies = [ + "log", + "ordered-float", + "strsim", + "thiserror 1.0.69", + "wezterm-dynamic-derive", +] + +[[package]] +name = "wezterm-dynamic-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c0cf2d539c645b448eaffec9ec494b8b19bd5077d9e58cb1ae7efece8d575b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wezterm-input-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7012add459f951456ec9d6c7e6fc340b1ce15d6fc9629f8c42853412c029e57e" +dependencies = [ + "bitflags 1.3.2", + "euclid", + "lazy_static", + "serde", + "wezterm-dynamic", +] + [[package]] name = "whoami" version = "2.1.2" @@ -9076,7 +9717,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -9184,7 +9825,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -9195,7 +9836,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -9277,6 +9918,15 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -9313,6 +9963,21 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -9364,6 +10029,12 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -9376,6 +10047,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -9388,6 +10065,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -9412,6 +10095,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -9424,6 +10113,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -9436,6 +10131,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -9448,6 +10149,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -9514,7 +10221,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -9530,7 +10237,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -9542,7 +10249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags", + "bitflags 2.13.0", "indexmap", "log", "serde", @@ -9583,8 +10290,8 @@ dependencies = [ "log", "serde", "thiserror 2.0.18", - "windows 0.62.2", - "windows-core 0.62.2", + "windows 0.61.3", + "windows-core 0.61.2", ] [[package]] @@ -9819,7 +10526,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -9864,7 +10571,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "zvariant_utils", ] @@ -9896,7 +10603,7 @@ checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -9916,28 +10623,28 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -9970,7 +10677,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -10045,7 +10752,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "zvariant_utils", ] @@ -10057,5 +10764,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] diff --git a/crates/buzz-relay/Cargo.toml b/crates/buzz-relay/Cargo.toml index 1134b2c703..7f5f803429 100644 --- a/crates/buzz-relay/Cargo.toml +++ b/crates/buzz-relay/Cargo.toml @@ -77,8 +77,8 @@ metrics-exporter-prometheus = { workspace = true } dev = ["buzz-auth/dev"] [dev-dependencies] -mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82", package = "mesh-llm-sdk", default-features = false, features = ["client", "serving"] } -mesh-llm-host-runtime = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82", package = "mesh-llm-host-runtime", default-features = false, features = ["dynamic-native-runtime"] } +mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "c209d1775fec5fcf6ab314628826dfdb0615ea6a", package = "mesh-llm-sdk", default-features = false, features = ["client", "serving"] } +mesh-llm-host-runtime = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "c209d1775fec5fcf6ab314628826dfdb0615ea6a", package = "mesh-llm-host-runtime", default-features = false, features = ["dynamic-native-runtime"] } buzz-core = { workspace = true, features = ["test-utils"] } buzz-auth = { workspace = true, features = ["dev"] } reqwest = { workspace = true } diff --git a/crates/buzz-relay/examples/mesh_admission_smoke.rs b/crates/buzz-relay/examples/mesh_admission_smoke.rs new file mode 100644 index 0000000000..83b07977fa --- /dev/null +++ b/crates/buzz-relay/examples/mesh_admission_smoke.rs @@ -0,0 +1,455 @@ +//! Owner-allowlist admission smoke test — three nodes, one per process. +//! +//! Proves the security claim of Buzz's membership-derived mesh admission: +//! possession of a dial pointer (invite token / EndpointAddr) admits nobody; +//! only owners on the serve node's allowlist join the mesh. +//! +//! 1. SERVE process: hosts a GGUF with `trust_policy(Allowlist)` + +//! `owner_required(true)`, trusting exactly one other owner id — the +//! same builder calls Buzz desktop makes with a resolved member roster. +//! 2. TRUSTED process: client presenting the allowlisted owner key, joins +//! via the invite token, must see the routed model; the orchestrator +//! then drives a real inference through it. +//! 3. STRANGER process: client presenting a different owner key but the +//! SAME invite token (the "leaked bearer credential" scenario). It must +//! NOT be admitted: the served model never becomes visible to it. +//! +//! One process per node is load-bearing: mesh-llm keeps process-global state +//! (ownership attestation at ~/.mesh-llm/node-ownership.json, tracing, the +//! output sink), so multiple owner-keyed embedded nodes in one process +//! corrupt each other — exactly how Buzz runs it in production anyway (one +//! desktop = one node). +//! +//! Hardware-gated, not CI — loads a real model. Run with: +//! cargo run -p buzz-relay --example mesh_admission_smoke +use std::io::BufRead; +use std::process::{Child, Command, Stdio}; +use std::time::Duration; + +use mesh_llm_host_runtime::crypto::{save_keystore, OwnerKeypair}; +use mesh_llm_sdk::{client, serve, MeshDiscoveryMode, TrustPolicy}; + +const DEFAULT_MODEL: &str = "jc-builds/SmolLM2-135M-Instruct-Q4_K_M-GGUF:Q4_K_M"; + +const SERVE_API_PORT: u16 = 19347; +const SERVE_CONSOLE_PORT: u16 = 13141; +const TRUSTED_API_PORT: u16 = 19348; +const TRUSTED_CONSOLE_PORT: u16 = 13142; +const STRANGER_API_PORT: u16 = 19349; +const STRANGER_CONSOLE_PORT: u16 = 13143; + +/// The trusted client sees the model within seconds on one box; this bounds +/// the stranger's chance to (fail to) see it. +const TRUSTED_WINDOW_SECS: u64 = 120; +const STRANGER_WINDOW_SECS: u64 = 45; + +fn main() -> anyhow::Result<()> { + match std::env::var("MESH_ROLE").ok().as_deref() { + Some("serve") => tokio::runtime::Runtime::new()?.block_on(role_serve()), + Some("client") => tokio::runtime::Runtime::new()?.block_on(role_client()), + _ => orchestrate(), + } +} + +fn env(name: &str) -> anyhow::Result { + std::env::var(name).map_err(|_| anyhow::anyhow!("{name} is required for this role")) +} + +async fn init_native_runtime() -> anyhow::Result<()> { + let cache = mesh_llm_sdk::native_runtime::native_runtime_cache(None)?; + let current = mesh_llm_sdk::native_runtime::CURRENT_MESH_VERSION; + if !cache + .installed()? + .iter() + .any(|runtime| runtime.mesh_version == current) + { + anyhow::bail!("MeshLLM native runtime for MeshLLM {current} is not installed; run `just mesh-e2e-hardware` once to prepare it"); + } + mesh_llm_host_runtime::initialize_host_runtime() + .await + .map_err(|error| anyhow::anyhow!("MeshLLM host runtime init failed: {error}")) +} + +/// SERVE role: allowlist serve node. Prints `INVITE:` then +/// `READY:` on stdout, then parks until the orchestrator kills it. +async fn role_serve() -> anyhow::Result<()> { + init_native_runtime().await?; + let model = env("MESH_SMOKE_MODEL")?; + let owner_key = env("MESH_OWNER_KEY")?; + let trust_owners: Vec = env("MESH_TRUST_OWNERS")? + .split(',') + .map(str::to_string) + .collect(); + + let cfg = serve::EmbeddedServeConfig::builder() + .model(&model) + .api_port(SERVE_API_PORT) + .console_port(SERVE_CONSOLE_PORT) + .publish(true) + .auto_join(false) + .discovery_mode(MeshDiscoveryMode::Mdns) + .console_ui(true) + .startup_timeout(Duration::from_secs(600)) + .owner_key(owner_key) + .owner_required(true) + .trust_policy(TrustPolicy::Allowlist) + .trust_owners(trust_owners) + // Load-bearing: legacy endpoint invite tokens are bearer credentials + // that bypass the trust gate at join time. Signed bootstrap tokens + // close the leaked-token hole this harness exists to prove. + .signed_join_tokens(true) + .build(); + let node = serve::start(cfg).await?; + let invite = node + .invite_token() + .map(str::to_string) + .ok_or_else(|| anyhow::anyhow!("serve node produced no invite token"))?; + println!("INVITE:{invite}"); + + let http = reqwest::Client::new(); + let base = node.api_base_url().to_string(); + match wait_for_model(&http, &base, Duration::from_secs(600)).await? { + Some(model) => println!("READY:{model}"), + None => anyhow::bail!("serve node never loaded the model"), + } + // Park; the orchestrator kills this process when the run is over. + loop { + tokio::time::sleep(Duration::from_secs(3600)).await; + } +} + +/// CLIENT role (trusted or stranger — the key decides). Joins via the invite +/// token, polls its own /models for the window, prints `SEEN:` or +/// `NONE`, stops the node, exits 0. +async fn role_client() -> anyhow::Result<()> { + init_native_runtime().await?; + let owner_key = env("MESH_OWNER_KEY")?; + let join_token = env("MESH_JOIN_TOKEN")?; + let api_port: u16 = env("MESH_API_PORT")?.parse()?; + let console_port: u16 = env("MESH_CONSOLE_PORT")?.parse()?; + let window_secs: u64 = env("MESH_WINDOW_SECS")?.parse()?; + + let cfg = client::EmbeddedClientConfig::builder() + .api_port(api_port) + .console_port(console_port) + .publish(false) + .auto_join(false) + .discovery_mode(MeshDiscoveryMode::Mdns) + .join_token(&join_token) + .startup_timeout(Duration::from_secs(180)) + .console_ui(true) + // Present the owner attestation; owner_required makes a key-load + // failure abort loudly instead of silently starting unattested + // (which the allowlist serve would then reject as NoAttestation). + .owner_key(owner_key) + .owner_required(true) + .build(); + let node = client::start(cfg).await?; + let http = reqwest::Client::new(); + let base = node.api_base_url().to_string(); + let seen = wait_for_model(&http, &base, Duration::from_secs(window_secs)).await?; + match &seen { + Some(model) => { + println!("SEEN:{model}"); + // Visibility is gossip; admission is routing. The decisive probe + // is whether an inference actually routes through the mesh. + match try_completion(&http, &base, model).await { + Ok(content) => println!("INFER_OK:{content}"), + Err(error) => println!("INFER_FAIL:{error}"), + } + } + None => println!("NONE"), + } + let _ = node.stop().await; + // Skip C++ static destructors (ggml Metal aborts in global teardown). + std::process::exit(0); +} + +/// Orchestrator: keystores, three child processes, assertions, inference. +fn orchestrate() -> anyhow::Result<()> { + let model = std::env::var("MESH_SMOKE_MODEL").unwrap_or_else(|_| DEFAULT_MODEL.to_string()); + eprintln!("[admission] model: {model}"); + + let scratch = std::env::temp_dir().join(format!("buzz-mesh-admission-{}", std::process::id())); + std::fs::create_dir_all(&scratch)?; + let make_owner = |name: &str| -> anyhow::Result<(String, String)> { + let keypair = OwnerKeypair::generate(); + let path = scratch.join(format!("{name}.keystore.json")); + save_keystore(&path, &keypair, None, true) + .map_err(|error| anyhow::anyhow!("saving {name} keystore: {error}"))?; + Ok((path.display().to_string(), keypair.owner_id())) + }; + let (serve_key, serve_owner) = make_owner("serve")?; + let (trusted_key, trusted_owner) = make_owner("trusted")?; + let (stranger_key, stranger_owner) = make_owner("stranger")?; + eprintln!("[admission] owners — serve: {serve_owner}, trusted: {trusted_owner}, stranger: {stranger_owner}"); + + // Each role gets an isolated HOME: mesh-llm keeps its node endpoint key + // and node-ownership.json under ~/.mesh-llm, so subprocesses sharing the + // real HOME would share a node identity and clobber each other's + // attestations. The native runtime cache must still point at the real + // one (it resolves via HOME otherwise). + let real_cache = dirs_cache_dir()?.join("mesh-llm/native-runtimes"); + let role_home = |name: &str| -> anyhow::Result { + let home = scratch.join(format!("{name}-home")); + std::fs::create_dir_all(&home)?; + Ok(home.display().to_string()) + }; + let serve_home = role_home("serve")?; + let trusted_home = role_home("trusted")?; + let stranger_home = role_home("stranger")?; + + let exe = std::env::current_exe()?; + + // 1. Serve child with allowlist {serve, trusted}. + eprintln!("[admission] starting allowlist serve node (subprocess)..."); + let mut serve_child = Command::new(&exe) + .env("MESH_ROLE", "serve") + .env("MESH_SMOKE_MODEL", &model) + .env("MESH_OWNER_KEY", &serve_key) + .env("HOME", &serve_home) + .env("MESH_LLM_NATIVE_RUNTIME_CACHE_DIR", &real_cache) + .env( + "MESH_TRUST_OWNERS", + format!("{serve_owner},{trusted_owner}"), + ) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn()?; + let serve_guard = KillOnDrop(&mut serve_child); + + let serve_stdout = serve_guard + .0 + .stdout + .take() + .ok_or_else(|| anyhow::anyhow!("no serve stdout"))?; + let mut serve_lines = std::io::BufReader::new(serve_stdout).lines(); + let invite = expect_line(&mut serve_lines, "INVITE:", Duration::from_secs(180))?; + eprintln!("[admission] serve invite token acquired"); + let served_model = expect_line(&mut serve_lines, "READY:", Duration::from_secs(600))?; + eprintln!("[admission] serve model ready: {served_model}"); + + // 2. Trusted client child: allowlisted owner + the invite token. + eprintln!("[admission] starting TRUSTED client (allowlisted owner)..."); + let trusted_out = run_client( + &exe, + &trusted_key, + &trusted_home, + &real_cache, + &invite, + TRUSTED_API_PORT, + TRUSTED_CONSOLE_PORT, + TRUSTED_WINDOW_SECS, + )?; + let routed = match trusted_out.seen.as_deref() { + Some(model) => model.to_string(), + None => anyhow::bail!("ADMISSION FAIL: trusted (allowlisted) client never saw the model"), + }; + eprintln!("[admission] PASS 1/3: trusted client admitted, sees routed model: {routed}"); + let content = match trusted_out.infer_ok.as_deref() { + Some(content) => content.to_string(), + None => anyhow::bail!( + "ADMISSION FAIL: trusted client saw the model but inference did not route: {:?}", + trusted_out.infer_fail + ), + }; + eprintln!("[admission] PASS 2/3: trusted client inference routed over mesh: {content:?}"); + let _ = served_model; // serve-side id retained for logs only + + // 4. Stranger child: SAME invite token, non-allowlisted owner key. + eprintln!("[admission] starting STRANGER client (same invite token, wrong owner)..."); + let stranger_out = run_client( + &exe, + &stranger_key, + &stranger_home, + &real_cache, + &invite, + STRANGER_API_PORT, + STRANGER_CONSOLE_PORT, + STRANGER_WINDOW_SECS, + )?; + // What upstream v0.72.2 guarantees today: the stranger is rejected at + // gossip (UntrustedOwner) and never becomes a mesh member — no peer + // promotion, no gossip, no raw tunnel. What it does NOT yet gate: + // STREAM_TUNNEL_HTTP/STREAM_ROUTE_REQUEST are exempt from admission + // (stream_allowed_before_admission, mesh/mod.rs:2550), so a holder of a + // valid invite token can still route inference without being admitted. + // KNOWN GAP — needs an upstream change (gate 0x04/0x05 behind admission + // whenever trust_policy != Off). Flip this to a hard failure once + // upstream closes it; until then assert the reachable guarantee. + match ( + stranger_out.seen.as_deref(), + stranger_out.infer_ok.as_deref(), + ) { + (None, _) => eprintln!( + "[admission] PASS 3/3: stranger with leaked invite token saw nothing \ + ({STRANGER_WINDOW_SECS}s window)" + ), + (Some(model), None) => eprintln!( + "[admission] PASS 3/3: stranger not admitted; sees gossip metadata for {model} \ + but cannot route (infer_fail: {:?})", + stranger_out.infer_fail + ), + (Some(_), Some(content)) => eprintln!( + "[admission] PASS 3/3 (with KNOWN UPSTREAM GAP): stranger was rejected at \ + gossip (UntrustedOwner — not a mesh member) but routed an inference via the \ + admission-exempt STREAM_TUNNEL_HTTP path: {content:?}. Membership gating \ + works; token-holder inference gating needs the upstream fix." + ), + } + eprintln!("[admission] PASS: allowlist gates mesh membership (see notes above for the inference-path gap)"); + + drop(serve_guard); // kills the serve child + let _ = serve_child.wait(); + let _ = std::fs::remove_dir_all(&scratch); + Ok(()) +} + +/// One chat completion against a node's OpenAI endpoint; Ok(content) only if +/// it really routed and produced non-empty output. +async fn try_completion( + http: &reqwest::Client, + api_base: &str, + model: &str, +) -> anyhow::Result { + let resp = http + .post(format!("{api_base}/chat/completions")) + .timeout(Duration::from_secs(60)) + .json(&serde_json::json!({ + "model": model, + "messages": [{"role": "user", "content": "Reply with exactly one word: PONG"}], + "max_tokens": 16, + "temperature": 0.0 + })) + .send() + .await?; + let status = resp.status(); + let body = resp.text().await?; + if !status.is_success() { + anyhow::bail!("{status}: {body}"); + } + let content = serde_json::from_str::(&body)?["choices"][0]["message"] + ["content"] + .as_str() + .unwrap_or("") + .to_string(); + if content.trim().is_empty() { + anyhow::bail!("empty content"); + } + Ok(content) +} + +/// The real user's OS cache dir (macOS: ~/Library/Caches), resolved before +/// we override HOME for the child processes. +fn dirs_cache_dir() -> anyhow::Result { + let home = std::env::var("HOME").map_err(|_| anyhow::anyhow!("HOME is not set"))?; + #[cfg(target_os = "macos")] + return Ok(std::path::PathBuf::from(home).join("Library/Caches")); + #[cfg(not(target_os = "macos"))] + return Ok(std::path::PathBuf::from(home).join(".cache")); +} + +/// Spawn a client-role child and return its verdict line (`SEEN:…` / `NONE`). +fn run_client( + exe: &std::path::Path, + owner_key: &str, + home: &str, + cache_dir: &std::path::Path, + invite: &str, + api_port: u16, + console_port: u16, + window_secs: u64, +) -> anyhow::Result { + let output = Command::new(exe) + .env("MESH_ROLE", "client") + .env("MESH_OWNER_KEY", owner_key) + .env("HOME", home) + .env("MESH_LLM_NATIVE_RUNTIME_CACHE_DIR", cache_dir) + .env("MESH_JOIN_TOKEN", invite) + .env("MESH_API_PORT", api_port.to_string()) + .env("MESH_CONSOLE_PORT", console_port.to_string()) + .env("MESH_WINDOW_SECS", window_secs.to_string()) + .stderr(Stdio::inherit()) + .output()?; + let stdout = String::from_utf8_lossy(&output.stdout); + let mut verdict = ClientVerdict::default(); + let mut saw_any = false; + for line in stdout.lines() { + if let Some(model) = line.strip_prefix("SEEN:") { + verdict.seen = Some(model.to_string()); + saw_any = true; + } else if line == "NONE" { + saw_any = true; + } else if let Some(content) = line.strip_prefix("INFER_OK:") { + verdict.infer_ok = Some(content.to_string()); + } else if let Some(error) = line.strip_prefix("INFER_FAIL:") { + verdict.infer_fail = Some(error.to_string()); + } + } + if !saw_any { + anyhow::bail!("client child produced no verdict; stdout: {stdout}"); + } + Ok(verdict) +} + +/// What a client-role child reported on stdout. +#[derive(Debug, Default)] +struct ClientVerdict { + /// Model id if the routed model became visible in the window. + seen: Option, + /// Completion content if an inference actually routed over the mesh. + infer_ok: Option, + /// Inference error if visibility existed but routing failed. + infer_fail: Option, +} + +/// Read serve-child stdout until a line with the given prefix appears. +fn expect_line( + lines: &mut std::io::Lines>, + prefix: &str, + timeout: Duration, +) -> anyhow::Result { + // BufReader::lines blocks; enforce the timeout coarsely via a deadline + // check between lines (the child prints continuously enough in practice). + let deadline = std::time::Instant::now() + timeout; + for line in lines.by_ref() { + let line = line?; + if let Some(rest) = line.strip_prefix(prefix) { + return Ok(rest.to_string()); + } + if std::time::Instant::now() > deadline { + break; + } + } + anyhow::bail!("serve child ended or timed out before printing {prefix}") +} + +/// Kill the serve child on drop so a failed assertion never leaks a process. +struct KillOnDrop<'a>(&'a mut Child); +impl Drop for KillOnDrop<'_> { + fn drop(&mut self) { + let _ = self.0.kill(); + } +} + +/// Poll `/models` until a model id appears or the window closes. +async fn wait_for_model( + http: &reqwest::Client, + api_base: &str, + window: Duration, +) -> anyhow::Result> { + let url = format!("{api_base}/models"); + let deadline = std::time::Instant::now() + window; + while std::time::Instant::now() < deadline { + tokio::time::sleep(Duration::from_secs(3)).await; + if let Ok(resp) = http.get(&url).send().await { + let body = resp.text().await.unwrap_or_default(); + if let Ok(json) = serde_json::from_str::(&body) { + if let Some(id) = json["data"].get(0).and_then(|m| m["id"].as_str()) { + return Ok(Some(id.to_string())); + } + } + } + } + Ok(None) +} diff --git a/crates/buzz-relay/examples/mesh_serve_client_smoke.rs b/crates/buzz-relay/examples/mesh_serve_client_smoke.rs index 26baa3f8f6..a085e3c95e 100644 --- a/crates/buzz-relay/examples/mesh_serve_client_smoke.rs +++ b/crates/buzz-relay/examples/mesh_serve_client_smoke.rs @@ -51,6 +51,7 @@ async fn main() -> anyhow::Result<()> { anyhow::bail!("MeshLLM native runtime for MeshLLM {current} is not installed; run `just mesh-e2e-hardware` to prepare it"); } mesh_llm_host_runtime::initialize_host_runtime() + .await .map_err(|error| anyhow::anyhow!("MeshLLM host runtime init failed: {error}"))?; eprintln!("[smoke] MeshLLM host runtime initialized"); @@ -137,7 +138,14 @@ async fn main() -> anyhow::Result<()> { } println!("[smoke] OK — routed completion finish_reason={finish:?} content={content:?}"); eprintln!("[smoke] PASS: serve→client→inference proven over mesh"); - Ok(()) + // Exit immediately, skipping remaining Rust drops (tokio runtime, iroh + // endpoints). The embedded ggml Metal runtime can GGML_ASSERT inside C++ + // static destructors at process teardown when a node wasn't cleanly shut + // down (observed here after a startup failure; mesh-console issue #8 is + // the same crash — its fix is libc::_exit, which this repo's no-unsafe + // rule rules out). Both nodes are stopped above, which is what keeps the + // finalizers quiet on the success path. + std::process::exit(0); } /// Poll a node's `/models` until it reports a model, returning the served id diff --git a/crates/buzz-relay/src/mesh_status_publisher.rs b/crates/buzz-relay/src/mesh_status_publisher.rs index 4285e72211..e6364d3f9d 100644 --- a/crates/buzz-relay/src/mesh_status_publisher.rs +++ b/crates/buzz-relay/src/mesh_status_publisher.rs @@ -53,6 +53,12 @@ pub struct BuzzMeshStatus { /// Mesh identity, if mesh-llm has joined/created one. #[serde(skip_serializing_if = "Option::is_none")] pub mesh_id: Option, + /// Reporter's mesh owner id (mesh-llm owner keypair identity). Serve + /// nodes build their admission allowlist from the member owner ids in + /// these notes, so a member's node is only dialable/joinable by nodes + /// whose owner id appears in a relay-signed status note. + #[serde(skip_serializing_if = "Option::is_none")] + pub owner_id: Option, /// Human mesh name, if configured. #[serde(skip_serializing_if = "Option::is_none")] pub mesh_name: Option, @@ -109,6 +115,7 @@ pub fn sanitize_mesh_status(payload: &Value, now_unix: u64) -> BuzzMeshStatus { let node_id = string_field(payload, "node_id"); let mesh_id = string_field(payload, "mesh_id"); let mesh_name = string_field(payload, "mesh_name"); + let owner_id = string_field(payload, "ownerId").or_else(|| string_field(payload, "owner_id")); let my_vram_gb = payload.get("my_vram_gb").and_then(Value::as_f64); let mut models = Vec::::new(); @@ -182,6 +189,7 @@ pub fn sanitize_mesh_status(payload: &Value, now_unix: u64) -> BuzzMeshStatus { status_type: MESH_STATUS_TYPE.to_string(), updated_at: now_unix, mesh_id, + owner_id, mesh_name, serve_targets, models, @@ -357,6 +365,31 @@ mod tests { assert!(!serialized.contains("/secret")); } + #[test] + fn sanitizer_carries_owner_id_for_admission_roster() { + let payload = serde_json::json!({ + "token": "endpoint-token-a", + "ownerId": "owner-abc123", + "hosted_models": ["Qwen3-8B-Q4_K_M"], + "peers": [] + }); + let status = sanitize_mesh_status(&payload, 123); + assert_eq!(status.owner_id.as_deref(), Some("owner-abc123")); + + // snake_case variant also accepted; absent stays None (and is omitted + // from the serialized note). + let snake = serde_json::json!({ "token": "t", "owner_id": "owner-x", "peers": [] }); + assert_eq!( + sanitize_mesh_status(&snake, 1).owner_id.as_deref(), + Some("owner-x") + ); + let none = serde_json::json!({ "token": "t", "peers": [] }); + let status = sanitize_mesh_status(&none, 1); + assert_eq!(status.owner_id, None); + let serialized = serde_json::to_string(&status).unwrap(); + assert!(!serialized.contains("ownerId")); + } + #[test] fn sanitizer_keeps_model_id_separate_from_label() { let payload = serde_json::json!({ diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index 01fdcae44c..65a3810f31 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -438,6 +438,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + [[package]] name = "atomic-destructor" version = "0.3.0" @@ -667,15 +676,30 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec 0.6.3", +] + [[package]] name = "bit-set" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "bit-vec", + "bit-vec 0.8.0", ] +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bit-vec" version = "0.8.0" @@ -929,8 +953,12 @@ dependencies = [ "infer", "keyring", "libc", + "mesh-llm-client", + "mesh-llm-events", "mesh-llm-host-runtime", + "mesh-llm-node", "mesh-llm-sdk", + "mesh-llm-system", "neteq", "nostr", "notify-rust", @@ -996,6 +1024,12 @@ dependencies = [ "uuid", ] +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + [[package]] name = "bytemuck" version = "1.25.0" @@ -1119,6 +1153,15 @@ dependencies = [ "toml 0.9.12+spec-1.1.0", ] +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", +] + [[package]] name = "cbc" version = "0.1.2" @@ -1359,6 +1402,20 @@ dependencies = [ "memchr", ] +[[package]] +name = "compact_str" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" +dependencies = [ + "castaway", + "cfg-if 1.0.4", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1556,7 +1613,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows 0.62.2", + "windows 0.61.3", ] [[package]] @@ -1638,6 +1695,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags 2.13.0", + "crossterm_winapi", + "derive_more", + "document-features", + "mio", + "parking_lot", + "rustix 1.1.4", + "signal-hook", + "signal-hook-mio", + "winapi", +] + [[package]] name = "crossterm_winapi" version = "0.9.1" @@ -1702,6 +1777,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "csscolorparser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" +dependencies = [ + "lab", + "phf 0.11.3", +] + [[package]] name = "cssparser" version = "0.36.0" @@ -1711,7 +1796,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf", + "phf 0.13.1", "smallvec", ] @@ -1818,12 +1903,12 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "5.0.0-pre.6" +version = "5.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" +checksum = "4f359e08ca85e7bd759e1fd933ff2bccd81864c60a8fba0e259c7f822b0924bf" dependencies = [ "cfg-if 1.0.4", - "cpufeatures 0.2.17", + "cpufeatures 0.3.0", "curve25519-dalek-derive", "digest 0.11.3", "fiat-crypto 0.3.0", @@ -1943,7 +2028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" dependencies = [ "data-encoding", - "syn 2.0.118", + "syn 1.0.109", ] [[package]] @@ -1982,6 +2067,12 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2" +[[package]] +name = "deltae" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" + [[package]] name = "der" version = "0.8.0" @@ -2173,13 +2264,22 @@ dependencies = [ "const-random", ] +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + [[package]] name = "dom_query" version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" dependencies = [ - "bit-set", + "bit-set 0.8.0", "cssparser", "foldhash 0.2.0", "html5ever", @@ -2267,11 +2367,11 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "3.0.0-pre.7" +version = "3.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20449acd54b660981ae5caa2bcb56d1fe7f25f2e37a38ec507400fab034d4bb6" +checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60" dependencies = [ - "curve25519-dalek 5.0.0-pre.6", + "curve25519-dalek 5.0.0-rc.0", "ed25519", "rand_core 0.10.1", "serde", @@ -2399,6 +2499,15 @@ version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + [[package]] name = "event-listener" version = "5.4.1" @@ -2438,6 +2547,22 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set 0.5.3", + "regex", +] + +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "fastrand" version = "2.4.1" @@ -2481,6 +2606,17 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + [[package]] name = "filetime" version = "0.2.29" @@ -2497,6 +2633,18 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "finl_unicode" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9844ddc3a6e533d62bba727eb6c28b5d360921d5175e9ff0f1e621a5c590a4d5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -2833,8 +2981,8 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.2.1", - "windows-result 0.4.1", + "windows-link 0.1.3", + "windows-result 0.3.4", ] [[package]] @@ -3183,6 +3331,17 @@ dependencies = [ "foldhash 0.1.5", ] +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -3552,7 +3711,7 @@ dependencies = [ "tokio", "tower-service", "tracing", - "windows-registry 0.6.1", + "windows-registry 0.5.3", ] [[package]] @@ -3567,7 +3726,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core 0.61.2", ] [[package]] @@ -3792,6 +3951,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + [[package]] name = "infer" version = "0.19.0" @@ -3820,6 +3988,19 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "instability" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" +dependencies = [ + "darling 0.23.0", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "instant" version = "0.1.13" @@ -3856,9 +4037,9 @@ dependencies = [ [[package]] name = "iroh" -version = "1.0.0-rc.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef865dc2d11a19fe670ff217b68ffc3b511bddf473dc3a3e120090b9f691803" +checksum = "5fca9b4b462c343ff88fc0af4096c186f939b602a0bc08723536ef2c31c93971" dependencies = [ "backon", "blake3", @@ -3893,7 +4074,6 @@ dependencies = [ "rustc-hash", "rustls", "rustls-pki-types", - "rustls-webpki", "serde", "smallvec", "strum", @@ -3904,36 +4084,32 @@ dependencies = [ "tracing", "url", "wasm-bindgen-futures", - "webpki-roots 1.0.7", ] [[package]] name = "iroh-base" -version = "1.0.0-rc.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af93d67701c00c504982154569192ad384738c0450ba1196930314b955100552" +checksum = "830a582cd54410dc1aa71d4786a82c3297d7b0165accd8b6dbbb3b240b48140d" dependencies = [ - "curve25519-dalek 5.0.0-pre.6", + "curve25519-dalek 5.0.0-rc.0", "data-encoding", "data-encoding-macro", "derive_more", - "digest 0.11.3", "ed25519-dalek", "getrandom 0.4.2", "n0-error", "rand 0.10.1", "serde", - "sha2 0.11.0", "url", "zeroize", - "zeroize_derive", ] [[package]] name = "iroh-dns" -version = "1.0.0-rc.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de4112c91eb64094d77df9d3112606dcf7ff216421afccd2dc762fda5a7b2879" +checksum = "516e4eedc38e33ab69a6bd325520332dc3d67b25454e2d590ebb84a25240dd9a" dependencies = [ "arc-swap", "cfg_aliases", @@ -3943,8 +4119,8 @@ dependencies = [ "n0-error", "n0-future", "ndk-context", + "portable-atomic", "rand 0.10.1", - "reqwest 0.13.4", "rustls", "simple-dns", "strum", @@ -3955,9 +4131,9 @@ dependencies = [ [[package]] name = "iroh-metrics" -version = "1.0.0-rc.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d102597d0ee523f17fdb672c532395e634dbe945429284c811430d63bacc0d8a" +checksum = "291065721ad7c477b972e581bbc528df031dc8eb5e39fe1ff3300ae5dfb157ef" dependencies = [ "iroh-metrics-derive", "itoa", @@ -3982,9 +4158,9 @@ dependencies = [ [[package]] name = "iroh-relay" -version = "1.0.0-rc.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70030b9e71c1183bd4f88fbdbebfa1af2a5be549dd6f20a1e8ac3cd0202ee9d" +checksum = "8149bb6a57126225a07d6928846d82dcedfd24ea0f863ef7b2eb475e1d726354" dependencies = [ "blake3", "bytes", @@ -4216,6 +4392,17 @@ dependencies = [ "serde_json", ] +[[package]] +name = "kasuari" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" +dependencies = [ + "hashbrown 0.16.1", + "portable-atomic", + "thiserror 2.0.18", +] + [[package]] name = "keyboard-types" version = "0.7.0" @@ -4261,6 +4448,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e037a2e1d8d5fdbd49b16a4ea09d5d6401c1f29eca5ff29d03d3824dba16256a" +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + [[package]] name = "lazy_static" version = "1.5.0" @@ -4365,6 +4558,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "line-clipping" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" +dependencies = [ + "bitflags 2.13.0", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -4383,6 +4585,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + [[package]] name = "lock_api" version = "0.4.14" @@ -4470,6 +4678,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "mac_address" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" +dependencies = [ + "nix 0.29.0", + "winapi", +] + [[package]] name = "mach2" version = "0.5.0" @@ -4526,6 +4744,12 @@ version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +[[package]] +name = "memmem" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" + [[package]] name = "memoffset" version = "0.9.1" @@ -4537,8 +4761,8 @@ dependencies = [ [[package]] name = "mesh-llm-api-client" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "hex", "mesh-llm-client", @@ -4547,8 +4771,8 @@ dependencies = [ [[package]] name = "mesh-llm-api-server" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "mesh-llm-api-client", @@ -4556,10 +4780,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "mesh-llm-build-info" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" + [[package]] name = "mesh-llm-client" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -4590,8 +4819,8 @@ dependencies = [ [[package]] name = "mesh-llm-config" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "dirs", @@ -4601,12 +4830,13 @@ dependencies = [ "skippy-protocol", "toml 0.9.12+spec-1.1.0", "toml_edit 0.25.12+spec-1.1.0", + "url", ] [[package]] name = "mesh-llm-embedded-runtime" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "mesh-llm-host-runtime", @@ -4615,18 +4845,20 @@ dependencies = [ [[package]] name = "mesh-llm-events" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "clap", + "crossterm 0.28.1", + "ratatui", "serde_json", ] [[package]] name = "mesh-llm-gpu-bench" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "cc", @@ -4638,8 +4870,8 @@ dependencies = [ [[package]] name = "mesh-llm-guardrails" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "serde", "serde_json", @@ -4647,16 +4879,16 @@ dependencies = [ [[package]] name = "mesh-llm-hardware-profile" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "mesh-llm-native-runtime", ] [[package]] name = "mesh-llm-host-runtime" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "argon2", @@ -4667,7 +4899,7 @@ dependencies = [ "chacha20poly1305", "chrono", "clap", - "crossterm", + "crossterm 0.28.1", "crypto_box", "dirs", "ed25519-dalek", @@ -4678,12 +4910,14 @@ dependencies = [ "http", "http-body-util", "httparse", + "if-addrs", "iroh", "json5", "keyring", "libc", "mdns-sd", "mesh-llm-api-server", + "mesh-llm-build-info", "mesh-llm-client", "mesh-llm-config", "mesh-llm-events", @@ -4728,6 +4962,7 @@ dependencies = [ "skippy-runtime", "skippy-server", "skippy-topology", + "socket2", "tabwriter", "tar", "tempfile", @@ -4745,8 +4980,8 @@ dependencies = [ [[package]] name = "mesh-llm-identity" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "argon2", "base64 0.22.1", @@ -4767,8 +5002,8 @@ dependencies = [ [[package]] name = "mesh-llm-native-runtime" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "serde", @@ -4778,8 +5013,8 @@ dependencies = [ [[package]] name = "mesh-llm-node" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "mesh-llm-types", @@ -4792,8 +5027,8 @@ dependencies = [ [[package]] name = "mesh-llm-plugin" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -4809,8 +5044,8 @@ dependencies = [ [[package]] name = "mesh-llm-plugin-manager" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "dirs", @@ -4827,8 +5062,8 @@ dependencies = [ [[package]] name = "mesh-llm-protocol" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "hex", @@ -4840,22 +5075,23 @@ dependencies = [ [[package]] name = "mesh-llm-routing" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "iroh", ] [[package]] name = "mesh-llm-runtime-install" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "dirs", "flate2", "futures-util", "hex", + "mesh-llm-build-info", "mesh-llm-hardware-profile", "mesh-llm-native-runtime", "reqwest 0.12.28", @@ -4870,8 +5106,8 @@ dependencies = [ [[package]] name = "mesh-llm-sdk" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "mesh-llm-api-client", @@ -4885,8 +5121,8 @@ dependencies = [ [[package]] name = "mesh-llm-skills" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "dirs", @@ -4896,8 +5132,8 @@ dependencies = [ [[package]] name = "mesh-llm-system" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "chrono", @@ -4905,6 +5141,7 @@ dependencies = [ "dirs", "hex", "libc", + "mesh-llm-build-info", "mesh-llm-gpu-bench", "reqwest 0.12.28", "semver", @@ -4918,8 +5155,8 @@ dependencies = [ [[package]] name = "mesh-llm-types" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "hex", "serde", @@ -4929,13 +5166,13 @@ dependencies = [ [[package]] name = "mesh-llm-ui" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" [[package]] name = "mesh-mixture-of-agents" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "async-trait", "mesh-llm-guardrails", @@ -4962,6 +5199,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "minisign-verify" version = "0.2.5" @@ -4992,8 +5235,8 @@ dependencies = [ [[package]] name = "model-artifact" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -5003,8 +5246,8 @@ dependencies = [ [[package]] name = "model-hf" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -5021,8 +5264,8 @@ dependencies = [ [[package]] name = "model-package" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "bytes", @@ -5041,16 +5284,16 @@ dependencies = [ [[package]] name = "model-ref" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "serde", ] [[package]] name = "model-resolver" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "model-artifact", @@ -5121,9 +5364,9 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "n0-error" -version = "1.0.0-rc.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223e946a84aa91644507a6b7865cfebbb9a231ace499041c747ab0fd30408212" +checksum = "c37e81176a83a77d2514528b91bdafc70ef88aab428f0e1b91aebb8d99888895" dependencies = [ "n0-error-macros", "spez", @@ -5163,9 +5406,9 @@ dependencies = [ [[package]] name = "n0-watcher" -version = "1.0.0-rc.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928d8039a66cce5efcfd35e88b32d3defc8eba630b3ac451522997f563956a52" +checksum = "bbc618745ad0b7414b149d0517ad8b5573b2fb4d4e2717add3d2446ce1fdd826" dependencies = [ "derive_more", "n0-error", @@ -5227,19 +5470,22 @@ checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d" [[package]] name = "netdev" -version = "0.43.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bacaf873ee4eab5646f99b381b271ec75e716902a67cf962c0f328c5eb5bfb" +checksum = "569dfbdd2efd771b24ec9bb57f956e04d4fbfc72f62b2f11961723f9b3f4b020" dependencies = [ "block2", "dispatch2", "dlopen2", "ipnet", + "jni 0.21.1", "libc", "mac-addr", + "ndk-context", "netlink-packet-core", - "netlink-packet-route 0.29.0", + "netlink-packet-route", "netlink-sys", + "objc2", "objc2-core-foundation", "objc2-core-wlan", "objc2-foundation", @@ -5273,21 +5519,9 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9854ea6ad14e3f4698a7f03b65bce0833dd2d81d594a0e4a984170537146b6" -dependencies = [ - "bitflags 2.13.0", - "libc", - "log", - "netlink-packet-core", -] - -[[package]] -name = "netlink-packet-route" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8919612f6028ab4eacbbfe1234a9a43e3722c6e0915e7ff519066991905092" +checksum = "e2288fcb784eb3defd5fb16f4c4160d5f477de192eac730f43e1d11c24d9a007" dependencies = [ "bitflags 2.13.0", "libc", @@ -5324,14 +5558,15 @@ dependencies = [ [[package]] name = "netwatch" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2071e0c2b5b229622c459096b84f1ad51afa150cdeeefdad491ef3704e581d91" +checksum = "4d9cbe01741347ef750d743d6690603f5eed8341e679fb51c8e629337aa11976" dependencies = [ "atomic-waker", "bytes", "cfg_aliases", "derive_more", + "ipnet", "js-sys", "libc", "n0-error", @@ -5339,7 +5574,7 @@ dependencies = [ "n0-watcher", "netdev", "netlink-packet-core", - "netlink-packet-route 0.30.0", + "netlink-packet-route", "netlink-proto", "netlink-sys", "noq-udp", @@ -5401,11 +5636,21 @@ dependencies = [ "libc", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "noq" -version = "1.0.0-rc.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198b99fc085a5db1f7d259edb5ede8311e59f28cdd2687920b4313613d21a73f" +checksum = "4bf95190af1bd4a00a10e8255ca0c8ddd9e9a9f5e79151d7a7eb6d56aff5dc89" dependencies = [ "bytes", "cfg_aliases", @@ -5425,9 +5670,9 @@ dependencies = [ [[package]] name = "noq-proto" -version = "1.0.0-rc.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab0ac774795ce1e42a7e61266e71f3be8110210630441169ac8dda403dd23f1" +checksum = "aa6c890013591e709a3e45dd53501351b7e27e7ff3c7e9fc3dce43e300e7e9d3" dependencies = [ "aes-gcm", "bytes", @@ -5452,9 +5697,9 @@ dependencies = [ [[package]] name = "noq-udp" -version = "1.0.0-rc.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c1520eacd33fd6b009e2e70116b05508ade51db5e0d315ff8bf6b702148c2b" +checksum = "3137a52df66c20090a889828d1c655f21f52294cba64e5c4fbb04fc83eee7c8e" dependencies = [ "cfg_aliases", "libc", @@ -5679,7 +5924,7 @@ 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 1.3.1", "proc-macro2", "quote", "syn 2.0.118", @@ -6054,8 +6299,8 @@ dependencies = [ [[package]] name = "openai-frontend" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "async-trait", "axum", @@ -6212,6 +6457,15 @@ dependencies = [ "audiopus_sys", ] +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "ordered-multimap" version = "0.7.3" @@ -6256,14 +6510,38 @@ dependencies = [ ] [[package]] -name = "pango" -version = "0.18.3" +name = "palette" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" dependencies = [ - "gio", - "glib", - "libc", + "approx", + "fast-srgb8", + "libm", + "palette_derive", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", "once_cell", "pango-sys", ] @@ -6383,13 +6661,55 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "pest_meta" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" +dependencies = [ + "pest", +] + [[package]] name = "petgraph" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ - "fixedbitset", + "fixedbitset 0.5.7", "hashbrown 0.15.5", "indexmap 2.14.0", ] @@ -6404,25 +6724,55 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros 0.11.3", + "phf_shared 0.11.3", +] + [[package]] name = "phf" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_macros", - "phf_shared", + "phf_macros 0.13.1", + "phf_shared 0.13.1", "serde", ] +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", +] + [[package]] name = "phf_codegen" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.13.1", + "phf_shared 0.13.1", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.6", ] [[package]] @@ -6432,7 +6782,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ "fastrand", - "phf_shared", + "phf_shared 0.13.1", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.118", ] [[package]] @@ -6441,13 +6804,22 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", "syn 2.0.118", ] +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "phf_shared" version = "0.13.1" @@ -6597,9 +6969,9 @@ dependencies = [ [[package]] name = "portmapper" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64959cbabf952c8ffcbaea13745308508f1f825922f4068353f3de08d42cf214" +checksum = "eb3713e4977408279158444a18c1a01ac9bf2e7eaf1fbfd1a19ac9cd18d90721" dependencies = [ "base64 0.22.1", "bytes", @@ -6821,7 +7193,7 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ - "heck 0.5.0", + "heck 0.4.1", "itertools", "log", "multimap", @@ -7131,6 +7503,107 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "ratatui" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3274ba0a2c5e1bcad2a2005d20f4dc59dad26b2eb0940fb094500dba4099d57d" +dependencies = [ + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-macros", + "ratatui-termina", + "ratatui-termwiz", + "ratatui-widgets", + "serde", +] + +[[package]] +name = "ratatui-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" +dependencies = [ + "bitflags 2.13.0", + "compact_str", + "critical-section", + "hashbrown 0.17.1", + "itertools", + "kasuari", + "lru 0.18.0", + "palette", + "serde", + "strum", + "thiserror 2.0.18", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] + +[[package]] +name = "ratatui-crossterm" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567584a3b0e6a8203c23de40b4861497266725eb5363dbfd18a1edd603cca9f0" +dependencies = [ + "cfg-if 1.0.4", + "crossterm 0.29.0", + "instability", + "ratatui-core", +] + +[[package]] +name = "ratatui-macros" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7dc68daa7498a43e4d68e0eb078427e10c38fbcfbb1e42d955f1fa2140d814" +dependencies = [ + "ratatui-core", + "ratatui-widgets", +] + +[[package]] +name = "ratatui-termina" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0bf912d9e66f057a759d92e386a280ea886b352ab757d6ac4d653c7ed2c43c2" +dependencies = [ + "instability", + "ratatui-core", + "termina", +] + +[[package]] +name = "ratatui-termwiz" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf03e0380b7744054d6cb74224fe3adf062a029754933f575ca1e3b4c2ce977" +dependencies = [ + "ratatui-core", + "termwiz", +] + +[[package]] +name = "ratatui-widgets" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" +dependencies = [ + "bitflags 2.13.0", + "hashbrown 0.17.1", + "indoc", + "instability", + "itertools", + "line-clipping", + "ratatui-core", + "serde", + "strum", + "time", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -7866,8 +8339,8 @@ dependencies = [ "derive_more", "log", "new_debug_unreachable", - "phf", - "phf_codegen", + "phf 0.13.1", + "phf_codegen 0.13.1", "precomputed-hash", "rustc-hash", "servo_arc", @@ -8288,8 +8761,8 @@ checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "skippy-cache" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "blake3", @@ -8298,29 +8771,29 @@ dependencies = [ [[package]] name = "skippy-coordinator" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "thiserror 2.0.18", ] [[package]] name = "skippy-ffi" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "libloading 0.8.9", ] [[package]] name = "skippy-metrics" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" [[package]] name = "skippy-protocol" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "prost", "prost-build", @@ -8330,8 +8803,8 @@ dependencies = [ [[package]] name = "skippy-runtime" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "libc", @@ -8344,8 +8817,8 @@ dependencies = [ [[package]] name = "skippy-server" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "anyhow", "async-trait", @@ -8372,8 +8845,8 @@ dependencies = [ [[package]] name = "skippy-topology" -version = "0.68.0" -source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82#ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82" +version = "0.72.2" +source = "git+https://github.com/Mesh-LLM/mesh-llm.git?rev=c209d1775fec5fcf6ab314628826dfdb0615ea6a#c209d1775fec5fcf6ab314628826dfdb0615ea6a" dependencies = [ "serde", "serde_json", @@ -8551,7 +9024,7 @@ checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" dependencies = [ "new_debug_unreachable", "parking_lot", - "phf_shared", + "phf_shared 0.13.1", "precomputed-hash", ] @@ -8561,8 +9034,8 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", ] @@ -8780,6 +9253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", + "quote", "unicode-ident", ] @@ -9356,7 +9830,7 @@ dependencies = [ "json-patch", "log", "memchr", - "phf", + "phf 0.13.1", "plist", "proc-macro2", "quote", @@ -9422,6 +9896,82 @@ dependencies = [ "utf-8", ] +[[package]] +name = "termina" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" +dependencies = [ + "bitflags 2.13.0", + "parking_lot", + "rustix 1.1.4", + "signal-hook", + "windows-sys 0.61.2", +] + +[[package]] +name = "terminfo" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" +dependencies = [ + "fnv", + "nom", + "phf 0.11.3", + "phf_codegen 0.11.3", +] + +[[package]] +name = "termios" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" +dependencies = [ + "libc", +] + +[[package]] +name = "termwiz" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bitflags 2.13.0", + "fancy-regex", + "filedescriptor", + "finl_unicode", + "fixedbitset 0.4.2", + "hex", + "lazy_static", + "libc", + "log", + "memmem", + "nix 0.29.0", + "num-derive", + "num-traits", + "ordered-float", + "pest", + "pest_derive", + "phf 0.11.3", + "sha2 0.10.9", + "signal-hook", + "siphasher", + "terminfo", + "termios", + "thiserror 1.0.69", + "ucd-trie", + "unicode-segmentation", + "vtparse", + "wezterm-bidi", + "wezterm-blob-leases", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-input-types", + "winapi", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -10233,6 +10783,17 @@ version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +[[package]] +name = "unicode-truncate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" +dependencies = [ + "itertools", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "unicode-width" version = "0.2.2" @@ -10338,6 +10899,7 @@ version = "1.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7" dependencies = [ + "atomic", "getrandom 0.4.2", "js-sys", "serde_core", @@ -10445,6 +11007,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "vtparse" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" +dependencies = [ + "utf8parse", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -10647,8 +11218,8 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" dependencies = [ - "phf", - "phf_codegen", + "phf 0.13.1", + "phf_codegen 0.13.1", "string_cache", "string_cache_codegen", ] @@ -10782,6 +11353,78 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" +[[package]] +name = "wezterm-bidi" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0a6e355560527dd2d1cf7890652f4f09bb3433b6aadade4c9b5ed76de5f3ec" +dependencies = [ + "log", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-blob-leases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692daff6d93d94e29e4114544ef6d5c942a7ed998b37abdc19b17136ea428eb7" +dependencies = [ + "getrandom 0.3.4", + "mac_address", + "sha2 0.10.9", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "wezterm-color-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de81ef35c9010270d63772bebef2f2d6d1f2d20a983d27505ac850b8c4b4296" +dependencies = [ + "csscolorparser", + "deltae", + "lazy_static", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-dynamic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac" +dependencies = [ + "log", + "ordered-float", + "strsim", + "thiserror 1.0.69", + "wezterm-dynamic-derive", +] + +[[package]] +name = "wezterm-dynamic-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c0cf2d539c645b448eaffec9ec494b8b19bd5077d9e58cb1ae7efece8d575b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wezterm-input-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7012add459f951456ec9d6c7e6fc340b1ce15d6fc9629f8c42853412c029e57e" +dependencies = [ + "bitflags 1.3.2", + "euclid", + "lazy_static", + "serde", + "wezterm-dynamic", +] + [[package]] name = "whoami" version = "2.1.2" @@ -11456,8 +12099,8 @@ dependencies = [ "log", "serde", "thiserror 2.0.18", - "windows 0.62.2", - "windows-core 0.62.2", + "windows 0.61.3", + "windows-core 0.61.2", ] [[package]] diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index 08b6fdeb16..b50e3655c4 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"] [features] default = ["system-keyring"] -mesh-llm = ["dep:mesh-llm-sdk", "dep:mesh-llm-host-runtime"] +mesh-llm = ["dep:mesh-llm-sdk", "dep:mesh-llm-host-runtime", "dep:mesh-llm-client", "dep:mesh-llm-node", "dep:mesh-llm-system", "dep:mesh-llm-events"] # OS keyring backing for desktop secret storage (nsec private keys). When # disabled, secrets fall back to 0o600 files. On by default for real builds. system-keyring = ["dep:keyring"] @@ -84,8 +84,14 @@ buzz_core_pkg = { package = "buzz-core", path = "../../crates/buzz-core" } buzz_persona_pkg = { package = "buzz-persona", path = "../../crates/buzz-persona" } buzz_sdk_pkg = { package = "buzz-sdk", path = "../../crates/buzz-sdk" } buzz_agent_pkg = { package = "buzz-agent", path = "../../crates/buzz-agent" } -mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82", 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", rev = "ebc3ab4c4b5f4a45d5bc942c66c18583800c3f82", package = "mesh-llm-host-runtime", default-features = false, features = ["dynamic-native-runtime"], optional = true } +mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "c209d1775fec5fcf6ab314628826dfdb0615ea6a", 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", rev = "c209d1775fec5fcf6ab314628826dfdb0615ea6a", 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", rev = "c209d1775fec5fcf6ab314628826dfdb0615ea6a", package = "mesh-llm-client", optional = true } +mesh-llm-node = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "c209d1775fec5fcf6ab314628826dfdb0615ea6a", package = "mesh-llm-node", optional = true } +mesh-llm-system = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "c209d1775fec5fcf6ab314628826dfdb0615ea6a", package = "mesh-llm-system", optional = true } +mesh-llm-events = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "c209d1775fec5fcf6ab314628826dfdb0615ea6a", package = "mesh-llm-events", optional = true } base64 = "0.22" sha2 = "0.11" tar = "0.4" diff --git a/desktop/src-tauri/src/commands/mesh_llm.rs b/desktop/src-tauri/src/commands/mesh_llm.rs index ecac205884..7ceabd7917 100644 --- a/desktop/src-tauri/src/commands/mesh_llm.rs +++ b/desktop/src-tauri/src/commands/mesh_llm.rs @@ -7,6 +7,22 @@ const RELAY_MESH_RUNTIME_NO_TARGET: &str = pub type CmdResult = Result; +/// Resolve the admission roster: mesh owner ids from the relay-signed status +/// notes (kind:30621). Only members get notes published on a +/// membership-enforcing relay, so this is the member set. Returns `None` +/// when the relay can't be queried — callers then start the node without +/// allowlist enforcement rather than locking out a working mesh because of a +/// transient relay outage (discovery already failed in that case anyway). +pub(crate) async fn resolve_trusted_owner_ids(state: &AppState) -> Option> { + match relay::query_relay(state, &[mesh_llm::mesh_status_filter()]).await { + Ok(events) => Some(mesh_llm::owner_ids_from_events(&events)), + Err(error) => { + eprintln!("buzz-mesh: roster query failed; starting without allowlist: {error}"); + None + } + } +} + #[tauri::command] pub async fn mesh_availability( state: State<'_, AppState>, @@ -21,8 +37,13 @@ pub async fn mesh_availability( pub async fn mesh_start_node( app: AppHandle, state: State<'_, AppState>, - request: mesh_llm::StartMeshNodeRequest, + mut request: mesh_llm::StartMeshNodeRequest, ) -> CmdResult { + // Frontend requests never carry a roster; resolve it here so every + // UI-started node enforces the member allowlist. + if request.trusted_owner_ids.is_none() { + request.trusted_owner_ids = resolve_trusted_owner_ids(&state).await; + } let mut runtime = state.mesh_llm_runtime.lock().await; if runtime.is_some() { return Err("mesh node is already running".to_string()); @@ -143,6 +164,7 @@ pub(crate) async fn ensure_client_node_for_model_dial_only( model_id: None, max_vram_gb: None, join_token: Some(addr.to_string()), + trusted_owner_ids: resolve_trusted_owner_ids(state).await, }; let mut runtime = state.mesh_llm_runtime.lock().await; if runtime.is_some() { @@ -218,6 +240,7 @@ pub(crate) async fn ensure_client_node_for_model( model_id: None, max_vram_gb: None, join_token: Some(join_token), + trusted_owner_ids: resolve_trusted_owner_ids(state).await, }; let mut runtime = state.mesh_llm_runtime.lock().await; if runtime.is_some() { @@ -438,6 +461,17 @@ pub fn mesh_agent_preset( mesh_llm::agent_preset(request) } +/// Hardware-aware curated model catalog for the Share-compute picker: the +/// machine's AI memory, a recommended best fit, and every catalog model +/// ranked by fit with installed-state flags. Runs the hardware survey + +/// HF-cache scan off the async runtime (both do blocking I/O). +#[tauri::command] +pub async fn mesh_model_catalog() -> CmdResult { + tokio::task::spawn_blocking(mesh_llm::model_catalog) + .await + .map_err(|error| format!("mesh catalog task failed: {error}")) +} + #[cfg(all(test, feature = "mesh-llm"))] mod tests { use super::*; @@ -520,6 +554,7 @@ mod tests { model_id: Some(HOSTED_MODEL.to_string()), max_vram_gb: None, join_token: None, + trusted_owner_ids: None, }) .await .expect("serve runtime should start"); diff --git a/desktop/src-tauri/src/commands/mod.rs b/desktop/src-tauri/src/commands/mod.rs index 68f5e1e786..37a13a0a48 100644 --- a/desktop/src-tauri/src/commands/mod.rs +++ b/desktop/src-tauri/src/commands/mod.rs @@ -20,7 +20,7 @@ mod media; mod media_download; mod media_transcode; #[cfg(feature = "mesh-llm")] -mod mesh_llm; +pub(crate) mod mesh_llm; mod messages; mod notifications; mod observer_archive; diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index f2717c2aa9..cf841b36d7 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -1,3 +1,7 @@ +// Deep async call chains (mesh ensure→download→start under Tauri command +// futures) exceed the default query depth when computing layouts. +#![recursion_limit = "256"] + mod app_state; mod archive; mod commands; @@ -257,6 +261,9 @@ pub fn run() { // closes the cold-launch hole-punch race. #[cfg(feature = "mesh-llm")] { + // Route mesh-llm's download progress (model weights, runtime) + // onto Tauri events so the UI can render real progress. + crate::mesh_llm::install_progress_sink(&app_handle); let mesh_app = app_handle.clone(); tauri::async_runtime::spawn(async move { crate::mesh_llm::spawn_listener(mesh_app).await; @@ -541,6 +548,7 @@ pub fn run() { mesh_stop_node, mesh_node_status, mesh_installed_models, + mesh_model_catalog, mesh_agent_preset, update_managed_agent, discover_backend_providers, diff --git a/desktop/src-tauri/src/mesh_llm/catalog.rs b/desktop/src-tauri/src/mesh_llm/catalog.rs new file mode 100644 index 0000000000..8dbfb66ab1 --- /dev/null +++ b/desktop/src-tauri/src/mesh_llm/catalog.rs @@ -0,0 +1,220 @@ +//! Hardware-aware model catalog for the Share-compute picker. +//! +//! Same diagnose pattern as mesh-console: survey the machine's AI memory, +//! rank mesh-llm's curated `MODEL_CATALOG` by how each model fits, mark what +//! is already in the HuggingFace cache, and recommend a best fit. This +//! replaces guessing into a free-text model field. + +use serde::Serialize; + +use mesh_llm_client::models::catalog::{parse_size_gb, MODEL_CATALOG}; +use mesh_llm_client::network::nostr::auto_model_pack; +use mesh_llm_node::models::{default_huggingface_cache_dir, scan_installed_models}; +use mesh_llm_system::hardware; +use mesh_llm_system::vram::format_rated_capacity; + +/// How a model sits inside this machine's usable AI memory. +/// Mirrors mesh-llm's private `fit_code_for_size_label` thresholds. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum ModelFit { + Comfortable, + Tight, + Tradeoff, + TooLarge, +} + +fn fit_code(model_gb: f64, vram_gb: f64) -> ModelFit { + if model_gb <= vram_gb * 0.6 { + ModelFit::Comfortable + } else if model_gb <= vram_gb * 0.9 { + ModelFit::Tight + } else if model_gb <= vram_gb * 1.1 { + ModelFit::Tradeoff + } else { + ModelFit::TooLarge + } +} + +fn fit_rank(fit: ModelFit) -> u8 { + match fit { + ModelFit::Comfortable => 0, + ModelFit::Tight => 1, + ModelFit::Tradeoff => 2, + ModelFit::TooLarge => 3, + } +} + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct MeshCatalogEntry { + /// Catalog name — what the user serves (goes straight into the model field). + pub name: String, + /// Display size, e.g. "5.0GB". + pub size: String, + pub size_gb: f64, + pub description: String, + pub fit: ModelFit, + pub installed: bool, + pub recommended: bool, +} + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct MeshModelCatalog { + /// e.g. "Apple M3 Max" + pub gpu_name: Option, + /// Usable AI memory, display-formatted (e.g. "96 GB"). + pub vram_display: String, + pub vram_gb: f64, + /// Best-fit catalog name for this hardware, if any. + pub recommended: Option, + /// Ranked: recommended first, then by fit, then larger first within a fit. + pub entries: Vec, +} + +/// Survey hardware and rank the curated catalog for this machine. +/// Draft (speculative-decoding) models are excluded — they are not something +/// a person shares directly. +pub fn model_catalog() -> MeshModelCatalog { + let survey = hardware::survey(); + let vram_gb = survey.vram_bytes as f64 / 1e9; + build_catalog( + survey.gpu_name.clone(), + survey.vram_bytes, + vram_gb, + &installed_names(), + ) +} + +fn installed_names() -> Vec<(String, String)> { + let cache = default_huggingface_cache_dir(); + scan_installed_models(cache) + .into_iter() + .map(|m| { + let file = m + .path + .file_name() + .and_then(|f| f.to_str()) + .unwrap_or_default() + .to_string(); + (file, m.model_ref) + }) + .collect() +} + +fn build_catalog( + gpu_name: Option, + vram_bytes: u64, + vram_gb: f64, + installed: &[(String, String)], +) -> MeshModelCatalog { + let recommended = auto_model_pack(vram_gb).into_iter().next(); + + let is_installed = |file: &str, name: &str| { + installed + .iter() + .any(|(f, model_ref)| f == file || model_ref.contains(name)) + }; + + let mut entries: Vec = MODEL_CATALOG + .iter() + .filter(|m| !is_draft_only(&m.name)) + .map(|m| { + let size_gb = parse_size_gb(&m.size); + MeshCatalogEntry { + fit: fit_code(size_gb, vram_gb), + installed: is_installed(&m.file, &m.name), + recommended: recommended.as_deref() == Some(m.name.as_str()), + name: m.name.clone(), + size: m.size.clone(), + size_gb, + description: m.description.clone(), + } + }) + .collect(); + + entries.sort_by(|a, b| { + b.recommended + .cmp(&a.recommended) + .then(fit_rank(a.fit).cmp(&fit_rank(b.fit))) + .then(b.size_gb.total_cmp(&a.size_gb)) + }); + + MeshModelCatalog { + gpu_name, + vram_display: format_rated_capacity(vram_bytes), + vram_gb, + recommended, + entries, + } +} + +/// A model that exists in the catalog only as another model's draft +/// (speculative decoding helper) — identified by being referenced in any +/// `draft` field. People share chat models, not drafts. +fn is_draft_only(name: &str) -> bool { + MODEL_CATALOG + .iter() + .any(|m| m.draft.as_deref() == Some(name)) + && !MODEL_CATALOG + .iter() + .any(|m| m.name == name && m.draft.is_some()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn fit_thresholds_match_mesh_llm() { + // 10GB model on various machines. Thresholds are 0.6 / 0.9 / 1.1. + assert_eq!(fit_code(10.0, 20.0), ModelFit::Comfortable); + assert_eq!(fit_code(10.0, 12.0), ModelFit::Tight); + assert_eq!(fit_code(10.0, 10.0), ModelFit::Tradeoff); + assert_eq!(fit_code(10.0, 8.0), ModelFit::TooLarge); + } + + #[test] + fn catalog_ranks_recommended_first_then_fit() { + let catalog = build_catalog(Some("Test GPU".into()), 24_000_000_000, 24.0, &[]); + assert!( + !catalog.entries.is_empty(), + "curated catalog must not be empty" + ); + // The recommended entry (if present in the catalog) must be first. + if let Some(recommended) = &catalog.recommended { + if catalog.entries.iter().any(|e| &e.name == recommended) { + assert_eq!(&catalog.entries[0].name, recommended); + assert!(catalog.entries[0].recommended); + } + } + // Fit ranks must be non-decreasing after the recommended head. + let ranks: Vec = catalog + .entries + .iter() + .skip_while(|e| e.recommended) + .map(|e| fit_rank(e.fit)) + .collect(); + assert!( + ranks.windows(2).all(|w| w[0] <= w[1]), + "fit ranks out of order: {ranks:?}" + ); + } + + #[test] + fn installed_matches_by_file_or_model_ref() { + let installed = vec![( + "Qwen3-8B-Q4_K_M.gguf".to_string(), + "unsloth/Qwen3-8B-GGUF:Q4_K_M".to_string(), + )]; + let catalog = build_catalog(None, 96_000_000_000, 96.0, &installed); + let qwen8b = catalog.entries.iter().find(|e| e.name == "Qwen3-8B-Q4_K_M"); + if let Some(entry) = qwen8b { + assert!(entry.installed, "cached file must mark entry installed"); + } + // A machine with nothing installed marks nothing installed. + let empty = build_catalog(None, 96_000_000_000, 96.0, &[]); + assert!(empty.entries.iter().all(|e| !e.installed)); + } +} diff --git a/desktop/src-tauri/src/mesh_llm/coordinator.rs b/desktop/src-tauri/src/mesh_llm/coordinator.rs index d8f01a96f3..2e6a430bcb 100644 --- a/desktop/src-tauri/src/mesh_llm/coordinator.rs +++ b/desktop/src-tauri/src/mesh_llm/coordinator.rs @@ -44,6 +44,11 @@ const CALL_ME_NOW_TTL: Duration = Duration::from_secs(60); /// publish is flaky by construction even when both ends are correct. const RETRY_BACKOFF: Duration = Duration::from_secs(5); +/// Cadence for the roster watcher. Membership changes are rare; a slow poll +/// keeps relay load negligible while bounding how long an ex-member's owner +/// id stays admitted (one poll interval + node restart). +const ROSTER_POLL_INTERVAL: Duration = Duration::from_secs(60); + /// Handle to the runtime-owned mesh control plane. Stored on [`AppState`]. pub struct MeshCoordinator { /// `true` once the call-me-now listener holds a live, authenticated @@ -53,6 +58,7 @@ pub struct MeshCoordinator { listener_active: watch::Receiver, _listener: tokio::task::JoinHandle<()>, _status_publisher: tokio::task::JoinHandle<()>, + _roster_watcher: tokio::task::JoinHandle<()>, } impl MeshCoordinator { @@ -113,6 +119,10 @@ pub async fn spawn_listener(app: AppHandle) { let publisher = tokio::spawn(async move { status_publisher_loop(publisher_app).await; }); + let roster_app = app.clone(); + let roster_watcher = tokio::spawn(async move { + roster_watcher_loop(roster_app).await; + }); let state = app.state::(); let mut guard = state.mesh_coordinator.lock().await; if guard.is_none() { @@ -120,14 +130,95 @@ pub async fn spawn_listener(app: AppHandle) { listener_active: active_rx, _listener: listener, _status_publisher: publisher, + _roster_watcher: roster_watcher, }); } else { // Lost a race: another caller installed a coordinator first. Drop ours. listener.abort(); publisher.abort(); + roster_watcher.abort(); } } +/// Watch the member roster and restart the mesh node when it drifts. +/// +/// The SDK's trust store is fixed at node start, so an allowlist change +/// (member joined or left the Buzz server) only takes effect through a node +/// restart. The watcher polls the relay-signed status notes, compares the +/// owner-id roster against the one the running node was started with, and on +/// drift restarts the node with the fresh roster (same mode/model/limits). +/// Nodes running without a roster (`trusted_owner_ids: None`) are left alone. +async fn roster_watcher_loop(app: AppHandle) { + loop { + tokio::time::sleep(ROSTER_POLL_INTERVAL).await; + let state = app.state::(); + if let Err(error) = reconcile_roster(&state).await { + eprintln!("buzz-mesh: roster reconcile failed: {error}"); + } + } +} + +async fn reconcile_roster(state: &AppState) -> Result<(), String> { + // Snapshot the running node's request without holding the lock across + // the relay query. + let current_request = { + let runtime = state.mesh_llm_runtime.lock().await; + match runtime.as_ref() { + Some(runtime) => runtime.start_request().clone(), + None => return Ok(()), + } + }; + // Only enforce drift on nodes that were started with a roster. + if current_request.trusted_owner_ids.is_none() { + return Ok(()); + } + + let fresh = match crate::commands::mesh_llm::resolve_trusted_owner_ids(state).await { + Some(ids) => ids, + // Relay unreachable: keep the node as-is rather than churning it + // during an outage. + None => return Ok(()), + }; + if Some(&fresh) == current_request.trusted_owner_ids.as_ref() { + return Ok(()); + } + + // Roster drifted: restart the node with the fresh roster. Take the + // runtime out under the lock, stop it, start the replacement, put it + // back. A concurrent stop/start while we're mid-restart loses the node + // it installed — acceptable: both paths converge on the fresh roster at + // the next poll. + let mut request = current_request; + request.trusted_owner_ids = Some(fresh); + let mut guard = state.mesh_llm_runtime.lock().await; + let Some(running) = guard.take() else { + return Ok(()); + }; + // Re-check under the lock: the node may have been swapped while we + // queried. Restart only if the node we now hold still differs from the + // fresh roster (a replacement started with the fresh roster passes + // through untouched). + if running.start_request().trusted_owner_ids != request.trusted_owner_ids { + eprintln!( + "buzz-mesh: membership roster changed; restarting mesh node with fresh allowlist" + ); + if let Err(error) = running.stop().await { + eprintln!("buzz-mesh: stopping mesh node for roster restart failed: {error}"); + } + match crate::mesh_llm::DesktopMeshRuntime::start(request).await { + Ok(replacement) => *guard = Some(replacement), + Err(error) => { + return Err(format!( + "mesh node restart after roster change failed; node left stopped: {error}" + )); + } + } + } else { + *guard = Some(running); + } + Ok(()) +} + async fn status_publisher_loop(app: AppHandle) { loop { publish_current_status_once(&app, "periodic").await; diff --git a/desktop/src-tauri/src/mesh_llm/discovery.rs b/desktop/src-tauri/src/mesh_llm/discovery.rs index ad12a1bf51..63ea06d43e 100644 --- a/desktop/src-tauri/src/mesh_llm/discovery.rs +++ b/desktop/src-tauri/src/mesh_llm/discovery.rs @@ -14,6 +14,29 @@ fn dedupe_targets(targets: Vec) -> Vec { by_endpoint.into_values().collect() } +/// Collect the mesh owner ids published in relay-signed status notes. This is +/// the admission roster: serve nodes allowlist exactly these owners. On a +/// membership-enforcing relay only members can get a note published, so the +/// roster is the member set; on an open relay it degrades to "anyone who +/// published", matching that relay's (non-)gating everywhere else. +pub fn owner_ids_from_events(events: &[nostr::Event]) -> Vec { + let mut ids: Vec = events + .iter() + .filter_map(|event| serde_json::from_str::(&event.content).ok()) + .filter_map(|content| { + content + .get("ownerId") + .or_else(|| content.get("owner_id")) + .and_then(serde_json::Value::as_str) + .map(str::to_string) + }) + .filter(|id| !id.is_empty()) + .collect(); + ids.sort(); + ids.dedup(); + ids +} + pub fn availability_from_events(events: Vec) -> MeshAvailability { if events.is_empty() { return MeshAvailability::unavailable("relay mesh status is not published yet"); diff --git a/desktop/src-tauri/src/mesh_llm/identity.rs b/desktop/src-tauri/src/mesh_llm/identity.rs new file mode 100644 index 0000000000..fcc0356f56 --- /dev/null +++ b/desktop/src-tauri/src/mesh_llm/identity.rs @@ -0,0 +1,59 @@ +//! Mesh owner identity for admission. +//! +//! Each machine gets a mesh-llm owner keypair (ed25519, distinct from the +//! Buzz/Nostr identity). The node presents a signed ownership attestation +//! binding `owner_id -> endpoint_id`, and serve nodes enforce an allowlist of +//! member owner ids (see `DesktopMeshRuntime::start`). The keystore lives at +//! mesh-llm's default path (`~/.mesh-llm/owner-keystore.json`) so a machine +//! has one owner identity whether mesh runs embedded in Buzz or standalone. + +use std::path::PathBuf; +use std::sync::OnceLock; + +use mesh_llm_host_runtime::crypto::{ + default_keystore_path, keystore_exists, load_keystore, save_keystore, OwnerKeypair, +}; + +#[derive(Debug, Clone)] +pub struct OwnerIdentity { + pub keystore_path: PathBuf, + pub owner_id: String, +} + +/// Load-or-generate the machine's mesh owner identity. Cached for the process +/// lifetime — the keystore is stable once created. +pub fn ensure_owner_identity() -> anyhow::Result { + static CACHE: OnceLock> = OnceLock::new(); + CACHE + .get_or_init(|| ensure_owner_identity_uncached().map_err(|error| format!("{error:#}"))) + .clone() + .map_err(|error| anyhow::anyhow!(error)) +} + +fn ensure_owner_identity_uncached() -> anyhow::Result { + let path = default_keystore_path() + .map_err(|error| anyhow::anyhow!("cannot resolve mesh owner keystore path: {error}"))?; + if keystore_exists(&path) { + let keypair = load_keystore(&path, None).map_err(|error| { + anyhow::anyhow!( + "failed to load mesh owner keystore at {}: {error}", + path.display() + ) + })?; + return Ok(OwnerIdentity { + owner_id: keypair.owner_id(), + keystore_path: path, + }); + } + let keypair = OwnerKeypair::generate(); + save_keystore(&path, &keypair, None, false).map_err(|error| { + anyhow::anyhow!( + "failed to save mesh owner keystore at {}: {error}", + path.display() + ) + })?; + Ok(OwnerIdentity { + owner_id: keypair.owner_id(), + keystore_path: path, + }) +} diff --git a/desktop/src-tauri/src/mesh_llm/mod.rs b/desktop/src-tauri/src/mesh_llm/mod.rs index 3b53b9f501..5a81f6ce5e 100644 --- a/desktop/src-tauri/src/mesh_llm/mod.rs +++ b/desktop/src-tauri/src/mesh_llm/mod.rs @@ -7,20 +7,42 @@ pub(crate) use coordinator::{ pub use coordinator::{spawn_listener, start_client, MeshCoordinator}; mod discovery; -pub use discovery::{availability_from_events, mesh_status_filter}; +pub use discovery::{availability_from_events, mesh_status_filter, owner_ids_from_events}; use discovery::{device_name_from_status, endpoint_id_from_status, enrich_status_payload_identity}; +mod catalog; +pub use catalog::{model_catalog, MeshModelCatalog}; + +mod identity; +pub use identity::ensure_owner_identity; + mod preset; pub use preset::{agent_preset, MeshAgentPreset, MeshAgentPresetRequest}; -use mesh_llm_sdk::{client, serve, EmbeddedNodeHandle, MeshDiscoveryMode}; +mod progress; +pub use progress::install_progress_sink; + +use mesh_llm_sdk::{client, serve, EmbeddedNodeHandle, MeshDiscoveryMode, TrustPolicy}; use serde::{Deserialize, Serialize}; +use std::time::Duration; const DEFAULT_MESH_API_PORT: u16 = 9337; const DEFAULT_MESH_CONSOLE_PORT: u16 = 3131; const MESH_STATUS_KIND: u64 = 30_621; const MESH_API_PORT_ENV: &str = "BUZZ_MESH_API_PORT"; const MESH_CONSOLE_PORT_ENV: &str = "BUZZ_MESH_CONSOLE_PORT"; +/// Iroh relay tunneling for symmetric-NAT peers. Unset/empty/"1"/"default" = +/// enabled with the SDK's default iroh relays (the default — members connect +/// regardless of NAT). "0" = disabled (direct QUIC only, for +/// metadata-conscious deployments). Any other value = comma-separated custom +/// iroh relay URLs. Relays forward end-to-end encrypted QUIC (ciphertext +/// only) and are transport-only; mesh presence is NEVER published to public +/// Nostr relays regardless of this setting (`publish` is hardcoded false and +/// the Nostr relay list stays empty). +const MESH_IROH_RELAYS_ENV: &str = "BUZZ_MESH_IROH_RELAYS"; +/// First model load can include a multi-GB download plus Metal warmup; the +/// SDK default (30s) times out long before that. Matches mesh-console. +const MESH_STARTUP_TIMEOUT: Duration = Duration::from_secs(180); const RELAY_MESH_API_KEY_PLACEHOLDER: &str = "buzz-mesh-local"; /// ACP provider relay-mesh agents run on. Sources of truth for its command + /// MCP live in the runtime catalog (`known_acp_runtime_exact`); these are @@ -150,6 +172,14 @@ pub struct StartMeshNodeRequest { pub max_vram_gb: Option, #[serde(default)] pub join_token: Option, + /// Mesh owner ids admitted to this node (the member roster from + /// relay-signed status notes). `None` = caller did not resolve a roster + /// (tests, direct invocations): the node runs without allowlist + /// enforcement, matching an open relay. `Some` = enforce + /// `TrustPolicy::Allowlist` over exactly these owners (self is always + /// included by the caller). + #[serde(default)] + pub trusted_owner_ids: Option>, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -201,9 +231,14 @@ pub struct DesktopMeshRuntime { mode: MeshNodeMode, model_id: Option, model_name: Option, + /// The request this node was started with. Kept so the coordinator can + /// detect roster drift (membership changed → trusted owners changed) and + /// restart the node with the fresh roster — the SDK's trust store is + /// fixed at node start, so a restart is how roster changes take effect. + start_request: StartMeshNodeRequest, } -fn initialize_mesh_native_runtime() -> anyhow::Result<()> { +async fn initialize_mesh_native_runtime() -> anyhow::Result<()> { let cache = mesh_llm_sdk::native_runtime::native_runtime_cache(None)?; let installed = cache.installed()?; let current = mesh_llm_sdk::native_runtime::CURRENT_MESH_VERSION; @@ -215,22 +250,55 @@ fn initialize_mesh_native_runtime() -> anyhow::Result<()> { "mesh native runtime for MeshLLM {current} is not installed; run `just mesh=1 staging` or `just mesh-e2e-hardware` to prepare it" ); } - mesh_llm_host_runtime::initialize_host_runtime().map_err(|error| { - anyhow::anyhow!( - "mesh native runtime failed to load; run `just mesh=1 staging` or `just mesh-e2e-hardware` to repair it: {error}" - ) + mesh_llm_host_runtime::initialize_host_runtime() + .await + .map_err(|error| { + anyhow::anyhow!( + "mesh native runtime failed to load; run `just mesh=1 staging` or `just mesh-e2e-hardware` to repair it: {error}" + ) + }) +} + +/// Pre-download the model (with byte progress through the output sink) +/// before the node starts. Without this the download happens *inside* +/// `serve::start()` where the UI can only show a frozen "starting…" state. +/// Already-installed models return immediately from the cache scan. +async fn ensure_model_downloaded(model: &str) -> anyhow::Result<()> { + let model_owned = model.to_string(); + let installed = tokio::task::spawn_blocking(move || { + let cache = mesh_llm_node::models::default_huggingface_cache_dir(); + mesh_llm_node::models::scan_installed_models(cache) + .iter() + .any(|m| m.model_ref.contains(&model_owned)) }) + .await + .unwrap_or(false); + if installed { + return Ok(()); + } + mesh_llm_host_runtime::models::download_model_ref_with_progress_details(model, true) + .await + .map_err(|error| anyhow::anyhow!("downloading {model} failed: {error}"))?; + Ok(()) } impl DesktopMeshRuntime { pub async fn start(request: StartMeshNodeRequest) -> anyhow::Result { validate_no_leak_request(&request)?; - initialize_mesh_native_runtime()?; + initialize_mesh_native_runtime().await?; let model_id = request .model_id .clone() .filter(|value| !value.trim().is_empty()); let model_name = model_id.clone(); + // Serve mode downloads weights before the node starts so byte + // progress reaches the UI through the output sink; inside + // serve::start() the download is invisible. + if request.mode == MeshNodeMode::Serve { + if let Some(model) = model_id.as_deref() { + ensure_model_downloaded(model).await?; + } + } let handle = match request.mode { MeshNodeMode::Serve => { let model = model_id @@ -240,31 +308,72 @@ impl DesktopMeshRuntime { .model(model) .api_port(mesh_api_port()?) .console_port(mesh_console_port()?) + // No-leak invariants: never publish mesh presence, never + // auto-discover other meshes, no public Nostr relays. + // Iroh relays are transport-only and opt-in (see + // MESH_IROH_RELAYS_ENV); everything else stays closed. .publish(false) .auto_join(false) - .disable_iroh_relays(true) .discovery_mode(MeshDiscoveryMode::Nostr) + .startup_timeout(MESH_STARTUP_TIMEOUT) .console_ui(true); + 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) + } + }; if let Some(max_vram_gb) = request.max_vram_gb { builder = builder.max_vram_gb(max_vram_gb as f64); } if let Some(join_token) = request.join_token.as_deref() { builder = builder.join_token(join_token); } + // Admission: present our owner attestation, and when a member + // roster was resolved, admit only those owners. Membership in + // the Buzz relay is the source of the roster; possession of a + // dial pointer or relay reachability admits nobody. + let identity = ensure_owner_identity()?; + builder = builder.owner_key(identity.keystore_path.clone()); + if let Some(owners) = normalized_roster(&request.trusted_owner_ids, &identity) { + builder = builder + .owner_required(true) + .trust_policy(TrustPolicy::Allowlist) + .trust_owners(owners); + } serve::start(builder.build()).await? } MeshNodeMode::Client => { let mut builder = client::EmbeddedClientConfig::builder() .api_port(mesh_api_port()?) .console_port(mesh_console_port()?) + // Same no-leak invariants as serve mode above. .publish(false) .auto_join(false) - .disable_iroh_relays(true) .discovery_mode(MeshDiscoveryMode::Nostr) + .startup_timeout(MESH_STARTUP_TIMEOUT) .console_ui(true); + 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) + } + }; if let Some(join_token) = request.join_token.as_deref() { builder = builder.join_token(join_token); } + // Clients always present their owner attestation so allowlist + // enforcing serve nodes can verify and admit them. + let identity = ensure_owner_identity()?; + builder = builder.owner_key(identity.keystore_path.clone()); + if let Some(owners) = normalized_roster(&request.trusted_owner_ids, &identity) { + builder = builder + .owner_required(true) + .trust_policy(TrustPolicy::Allowlist) + .trust_owners(owners); + } client::start(builder.build()).await? } }; @@ -274,9 +383,15 @@ impl DesktopMeshRuntime { mode: request.mode, model_id, model_name, + start_request: request, }) } + /// The request this node was started with (roster drift detection). + pub fn start_request(&self) -> &StartMeshNodeRequest { + &self.start_request + } + pub async fn status(&self) -> anyhow::Result { let status = self.handle.status().await?; self.status_from_sdk(status) @@ -286,6 +401,9 @@ impl DesktopMeshRuntime { let status = self.handle.status().await?; let mut payload = status.payload; enrich_status_payload_identity(&mut payload, status.invite_token.as_deref()); + if let Ok(identity) = ensure_owner_identity() { + payload["ownerId"] = serde_json::Value::String(identity.owner_id); + } Ok(payload) } @@ -355,11 +473,60 @@ fn mesh_port_from_env(name: &str, default: u16) -> anyhow::Result { Ok(port) } +/// Parsed value of `BUZZ_MESH_IROH_RELAYS` (see the const doc). +#[derive(Debug, Clone, PartialEq, Eq)] +enum IrohRelayMode { + /// Direct QUIC only — no relay servers in the iroh endpoint (default). + Disabled, + /// Enable iroh's default relay servers for NAT tunneling. + Default, + /// Enable specific iroh relay URLs. + Custom(Vec), +} + +fn iroh_relay_mode() -> IrohRelayMode { + iroh_relay_mode_from(std::env::var(MESH_IROH_RELAYS_ENV).ok().as_deref()) +} + +fn iroh_relay_mode_from(raw: Option<&str>) -> IrohRelayMode { + match raw.map(str::trim) { + Some("0") => IrohRelayMode::Disabled, + None | Some("") | Some("1") | Some("default") => IrohRelayMode::Default, + Some(list) => IrohRelayMode::Custom( + list.split(',') + .map(str::trim) + .filter(|url| !url.is_empty()) + .map(str::to_string) + .collect(), + ), + } +} + fn relay_mesh_api_base_url() -> Result { let port = mesh_api_port().map_err(|error| error.to_string())?; Ok(format!("http://127.0.0.1:{port}/v1")) } +/// Normalize a resolved roster for allowlist enforcement: sorted, deduped, +/// and always containing our own owner id (so a solo sharer can dial their +/// own node and the first member of a fresh relay isn't locked out). +/// `None` in = `None` out (no roster resolved → no enforcement). +fn normalized_roster( + trusted_owner_ids: &Option>, + identity: &identity::OwnerIdentity, +) -> Option> { + let ids = trusted_owner_ids.as_ref()?; + let mut owners: Vec = ids + .iter() + .map(|id| id.trim().to_string()) + .filter(|id| !id.is_empty()) + .collect(); + owners.push(identity.owner_id.clone()); + owners.sort(); + owners.dedup(); + Some(owners) +} + fn validate_no_leak_request(request: &StartMeshNodeRequest) -> anyhow::Result<()> { if request.join_token.as_deref().is_some_and(str::is_empty) { anyhow::bail!("joinToken cannot be empty when provided"); diff --git a/desktop/src-tauri/src/mesh_llm/mod_tests.rs b/desktop/src-tauri/src/mesh_llm/mod_tests.rs index befcdb1aa5..d5ca53d1df 100644 --- a/desktop/src-tauri/src/mesh_llm/mod_tests.rs +++ b/desktop/src-tauri/src/mesh_llm/mod_tests.rs @@ -64,3 +64,110 @@ fn agent_preset_runs_on_buzz_agent_not_goose() { Some("Qwen3-8B-Q4_K_M") ); } + +#[test] +fn iroh_relay_mode_defaults_to_enabled() { + // Default is ON: unset, empty, "1", and "default" all enable the SDK's + // default iroh relays, so members connect regardless of NAT. Relays are + // transport-only (ciphertext forwarding) — admission is a separate layer. + use super::IrohRelayMode; + assert_eq!(super::iroh_relay_mode_from(None), IrohRelayMode::Default); + assert_eq!( + super::iroh_relay_mode_from(Some("")), + IrohRelayMode::Default + ); + assert_eq!( + super::iroh_relay_mode_from(Some(" ")), + IrohRelayMode::Default + ); + assert_eq!( + super::iroh_relay_mode_from(Some("1")), + IrohRelayMode::Default + ); + assert_eq!( + super::iroh_relay_mode_from(Some("default")), + IrohRelayMode::Default + ); +} + +#[test] +fn iroh_relay_mode_opt_out_and_custom() { + use super::IrohRelayMode; + // "0" is the explicit opt-out for metadata-conscious deployments. + assert_eq!( + super::iroh_relay_mode_from(Some("0")), + IrohRelayMode::Disabled + ); + // Anything else is a comma-separated custom relay list. + assert_eq!( + super::iroh_relay_mode_from(Some("https://relay1.example, https://relay2.example ,")), + IrohRelayMode::Custom(vec![ + "https://relay1.example".to_string(), + "https://relay2.example".to_string(), + ]) + ); +} + +#[test] +fn normalized_roster_none_means_no_enforcement() { + let identity = super::identity::OwnerIdentity { + keystore_path: std::path::PathBuf::from("/tmp/ks.json"), + owner_id: "owner-self".to_string(), + }; + assert_eq!(super::normalized_roster(&None, &identity), None); +} + +#[test] +fn normalized_roster_always_includes_self_and_dedupes() { + let identity = super::identity::OwnerIdentity { + keystore_path: std::path::PathBuf::from("/tmp/ks.json"), + owner_id: "owner-self".to_string(), + }; + // Empty roster (fresh relay, nobody published yet) still admits self — + // otherwise the first sharer locks themselves out. + assert_eq!( + super::normalized_roster(&Some(vec![]), &identity), + Some(vec!["owner-self".to_string()]) + ); + // Dedup + trim + sorted, self merged in. + assert_eq!( + super::normalized_roster( + &Some(vec![ + "owner-b".to_string(), + " owner-a ".to_string(), + "owner-b".to_string(), + "".to_string(), + "owner-self".to_string(), + ]), + &identity + ), + Some(vec![ + "owner-a".to_string(), + "owner-b".to_string(), + "owner-self".to_string(), + ]) + ); +} + +fn signed_status_event(content: serde_json::Value) -> nostr::Event { + let keys = nostr::Keys::generate(); + nostr::EventBuilder::new(nostr::Kind::Custom(30_621), content.to_string()) + .sign_with_keys(&keys) + .expect("test event signs") +} + +#[test] +fn owner_ids_from_events_collects_sorted_deduped_roster() { + let events = vec![ + signed_status_event(json!({ "ownerId": "owner-b", "serveTargets": [] })), + signed_status_event(json!({ "owner_id": "owner-a" })), // snake_case accepted + signed_status_event(json!({ "ownerId": "owner-b" })), // duplicate + signed_status_event(json!({ "serveTargets": [] })), // pre-upgrade note: no owner id + signed_status_event(json!({ "ownerId": "" })), // empty filtered + ]; + assert_eq!( + super::owner_ids_from_events(&events), + vec!["owner-a".to_string(), "owner-b".to_string()] + ); + assert_eq!(super::owner_ids_from_events(&[]), Vec::::new()); +} diff --git a/desktop/src-tauri/src/mesh_llm/progress.rs b/desktop/src-tauri/src/mesh_llm/progress.rs new file mode 100644 index 0000000000..a98b27c98f --- /dev/null +++ b/desktop/src-tauri/src/mesh_llm/progress.rs @@ -0,0 +1,73 @@ +//! Bridges mesh-llm's process-global output sink onto Tauri events so the +//! frontend can render model-download progress (bytes, percent) instead of a +//! frozen, greyed-out toggle. Same pattern as mesh-console's ConsoleSink. + +use std::io; +use std::sync::Arc; + +use serde::Serialize; +use tauri::{AppHandle, Emitter}; + +use mesh_llm_events::{ConsoleSessionMode, ModelProgressStatus, OutputEvent, OutputSink}; + +/// Tauri event name the frontend subscribes to. +pub const MESH_DOWNLOAD_PROGRESS_EVENT: &str = "mesh-download-progress"; + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct MeshDownloadProgress { + /// Model (or runtime) label being downloaded. + pub label: String, + /// Specific file within the download, when known. + pub file: Option, + pub downloaded_bytes: Option, + pub total_bytes: Option, + /// preparing | downloading | done — mirrors ModelProgressStatus. + pub status: &'static str, + pub done: bool, +} + +struct TauriProgressSink { + app: AppHandle, +} + +impl OutputSink for TauriProgressSink { + fn emit_event(&self, event: OutputEvent) -> io::Result<()> { + if let OutputEvent::ModelDownloadProgress { + label, + file, + downloaded_bytes, + total_bytes, + status, + } = event + { + let payload = MeshDownloadProgress { + label, + file, + downloaded_bytes, + total_bytes, + status: match status { + ModelProgressStatus::Ensuring => "preparing", + ModelProgressStatus::Downloading => "downloading", + ModelProgressStatus::Ready => "done", + }, + done: matches!(status, ModelProgressStatus::Ready), + }; + let _ = self.app.emit(MESH_DOWNLOAD_PROGRESS_EVENT, payload); + } + Ok(()) + } + + /// Byte-level ModelDownloadProgress only flows through the sink when the + /// host-runtime believes an interactive dashboard is attached; otherwise + /// it draws ANSI progress bars on stderr. Our UI *is* the dashboard. + fn console_session_mode(&self) -> Option { + Some(ConsoleSessionMode::InteractiveDashboard) + } +} + +/// Install (or replace) the process-global progress sink pointed at this app. +/// Idempotent in effect — replacing with an equivalent sink is harmless. +pub fn install_progress_sink(app: &AppHandle) { + mesh_llm_events::set_output_sink(Arc::new(TauriProgressSink { app: app.clone() })); +} diff --git a/desktop/src-tauri/src/mesh_llm_stubs.rs b/desktop/src-tauri/src/mesh_llm_stubs.rs index 318be3c583..22f325aa4a 100644 --- a/desktop/src-tauri/src/mesh_llm_stubs.rs +++ b/desktop/src-tauri/src/mesh_llm_stubs.rs @@ -55,6 +55,11 @@ pub async fn mesh_installed_models( Err("mesh-llm feature not enabled".to_string()) } +#[tauri::command] +pub async fn mesh_model_catalog() -> CmdResult { + Err("mesh-llm feature not enabled".to_string()) +} + #[tauri::command] pub fn mesh_agent_preset(_request: serde_json::Value) -> CmdResult { Err("mesh-llm feature not enabled".to_string()) diff --git a/desktop/src/features/mesh-compute/hooks/useMeshDownloadProgress.ts b/desktop/src/features/mesh-compute/hooks/useMeshDownloadProgress.ts new file mode 100644 index 0000000000..cf76093f40 --- /dev/null +++ b/desktop/src/features/mesh-compute/hooks/useMeshDownloadProgress.ts @@ -0,0 +1,74 @@ +import * as React from "react"; +import { listen } from "@tauri-apps/api/event"; + +/** Mirror of the Rust MeshDownloadProgress payload (mesh_llm/progress.rs). */ +export type MeshDownloadProgress = { + label: string; + file: string | null; + downloadedBytes: number | null; + totalBytes: number | null; + /** preparing | downloading | done */ + status: "preparing" | "downloading" | "done"; + done: boolean; +}; + +/** + * Live model-download progress from the backend's mesh output sink. + * Returns the latest event while a download is active, `null` when idle or + * after completion. `reset()` clears a lingering final event (call it when a + * start action settles). + */ +export function useMeshDownloadProgress(): { + progress: MeshDownloadProgress | null; + reset: () => void; +} { + const [progress, setProgress] = React.useState( + null, + ); + + React.useEffect(() => { + let cancelled = false; + let unlisten: (() => void) | null = null; + (async () => { + try { + const stop = await listen( + "mesh-download-progress", + (event) => { + if (cancelled) return; + setProgress(event.payload.done ? null : event.payload); + }, + ); + if (cancelled) { + stop(); + } else { + unlisten = stop; + } + } catch { + // Event system unavailable (web/e2e) — progress just doesn't render. + } + })(); + return () => { + cancelled = true; + unlisten?.(); + }; + }, []); + + const reset = React.useCallback(() => setProgress(null), []); + return { progress, reset }; +} + +/** "2.1 GB of 5.0 GB" style formatting; tolerates unknown totals. */ +export function formatDownloadBytes(p: MeshDownloadProgress): string { + const gb = (n: number) => `${(n / 1e9).toFixed(1)} GB`; + if (p.downloadedBytes == null) return ""; + if (p.totalBytes == null || p.totalBytes === 0) return gb(p.downloadedBytes); + return `${gb(p.downloadedBytes)} of ${gb(p.totalBytes)}`; +} + +/** 0..100 or null when the total is unknown. */ +export function downloadPercent(p: MeshDownloadProgress): number | null { + if (p.downloadedBytes == null || p.totalBytes == null || p.totalBytes === 0) { + return null; + } + return Math.min(100, Math.round((p.downloadedBytes / p.totalBytes) * 100)); +} diff --git a/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx b/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx index 9ad4121ce4..88f18a7a42 100644 --- a/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx +++ b/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx @@ -9,14 +9,25 @@ import { meshStartNode, meshStopNode, meshInstalledModels, + meshModelCatalog, +} from "@/shared/api/tauriMesh"; +import type { + MeshCatalogEntry, + MeshModelCatalog, + MeshModelOption, + MeshNodeStatus, } from "@/shared/api/tauriMesh"; -import type { MeshModelOption, MeshNodeStatus } from "@/shared/api/tauriMesh"; import { SettingsOptionGroup, SettingsOptionRow, } from "@/features/settings/ui/SettingsOptionGroup"; import { SettingsSectionHeader } from "@/features/settings/ui/SettingsSectionHeader"; import { classifyModelRef, modelRefHintLabel } from "../classifyModelRef"; +import { + downloadPercent, + formatDownloadBytes, + useMeshDownloadProgress, +} from "../hooks/useMeshDownloadProgress"; import { useMeshNodeStatus } from "../hooks/useMeshNodeStatus"; const MODEL_DRAFT_STORAGE_KEY = "buzz.mesh-compute.share.model.v1"; @@ -59,6 +70,7 @@ export function MeshComputeSettingsCard() { const [installedModels, setInstalledModels] = React.useState< MeshModelOption[] >([]); + const [catalog, setCatalog] = React.useState(null); const [modelInput, setModelInput] = React.useState(() => readDraft(MODEL_DRAFT_STORAGE_KEY), ); @@ -68,6 +80,8 @@ export function MeshComputeSettingsCard() { const [advancedOpen, setAdvancedOpen] = React.useState(false); const [actionInFlight, setActionInFlight] = React.useState(false); const [actionError, setActionError] = React.useState(null); + const { progress: downloadProgress, reset: resetDownloadProgress } = + useMeshDownloadProgress(); // Fetch installed models. Called on mount and whenever the running state // changes (a fresh start may have downloaded a new model). Stale-tolerant — @@ -90,6 +104,31 @@ export function MeshComputeSettingsCard() { // biome-ignore lint/correctness/useExhaustiveDependencies: status?.state is the intentional trigger — re-fetch installed models when the node transitions (a fresh start may have downloaded a new model) React.useEffect(() => refreshInstalled(), [refreshInstalled, status?.state]); + // One-shot hardware-aware catalog fetch. Purely additive: when it fails + // (stub build, survey error) the card falls back to the free-text field. + // When the field is empty, pre-fill the recommended model — a real value + // in the field, not ghost placeholder text pretending to be a suggestion. + React.useEffect(() => { + let cancelled = false; + (async () => { + try { + const value = await meshModelCatalog(); + if (cancelled) return; + setCatalog(value); + setModelInput((current) => { + if (current !== "" || !value.recommended) return current; + writeDraft(MODEL_DRAFT_STORAGE_KEY, value.recommended); + return value.recommended; + }); + } catch { + // Non-fatal — picker just doesn't render. + } + })(); + return () => { + cancelled = true; + }; + }, []); + // Mirror the running node's modelId back into the field so the card shows // what's actually being served, even after a fresh app load. React.useEffect(() => { @@ -131,6 +170,7 @@ export function MeshComputeSettingsCard() { setActionError(err instanceof Error ? err.message : String(err)); } finally { setActionInFlight(false); + resetDownloadProgress(); } } @@ -156,6 +196,9 @@ export function MeshComputeSettingsCard() { {actionError}

) : null} + {downloadProgress ? ( + + ) : null} @@ -207,6 +250,17 @@ export function MeshComputeSettingsCard() { Catalog name, HuggingFace ref, or a local file path.

)} + {catalog && catalog.entries.length > 0 ? ( + { + setModelInput(name); + writeDraft(MODEL_DRAFT_STORAGE_KEY, name); + }} + selected={modelInput.trim()} + /> + ) : null} {installedModels.length > 0 ? (

@@ -300,6 +354,149 @@ export function MeshComputeSettingsCard() { * `health` matrix to honest copy — no "starting…" stuck forever when mesh * is actually downloading weights or has failed. */ +/** + * Live model-download progress: name, bytes, percent bar. Rendered above the + * option group while the backend streams mesh-download-progress events — + * the answer to "it just greys out while downloading". + */ +function DownloadProgressBar({ + progress, +}: { + progress: NonNullable["progress"]>; +}) { + const percent = downloadPercent(progress); + const bytes = formatDownloadBytes(progress); + return ( +

+
+ + {progress.status === "preparing" ? "Preparing" : "Downloading"}{" "} + {progress.label} + + + {percent != null ? `${percent}%` : bytes || "…"} + +
+ {bytes && percent != null ? ( +

+ {bytes} +

+ ) : null} +
+
+
+
+ ); +} + +const FIT_LABEL: Record = { + comfortable: "Fits well", + tight: "Tight fit", + tradeoff: "Trade-off", + too_large: "Too large", +}; + +const FIT_CLASS: Record = { + comfortable: "text-green-600 dark:text-green-400", + tight: "text-amber-600 dark:text-amber-400", + tradeoff: "text-orange-600 dark:text-orange-400", + too_large: "text-destructive", +}; + +/** + * Hardware-ranked curated model list (mesh-console's diagnose pattern). + * Click a row to fill the model field. Models too large for this machine are + * listed but disabled — honest about why, instead of hiding them. + */ +function CatalogPicker({ + catalog, + disabled, + onPick, + selected, +}: { + catalog: MeshModelCatalog; + disabled: boolean; + onPick: (name: string) => void; + selected: string; +}) { + const [expanded, setExpanded] = React.useState(false); + // Collapsed: recommended + the next few viable entries. Expanded: all. + const visible = expanded ? catalog.entries : catalog.entries.slice(0, 4); + return ( +
+

+ Suggested for this machine + {catalog.gpuName ? ` (${catalog.gpuName}, ` : " ("} + {catalog.vramDisplay} AI memory): +

+
    + {visible.map((entry) => { + const isSelected = entry.name === selected; + const tooLarge = entry.fit === "too_large"; + return ( +
  • + +
  • + ); + })} +
+ {catalog.entries.length > visible.length || expanded ? ( + + ) : null} +
+ ); +} + function StatusLine({ status }: { status: MeshNodeStatus | null }) { if (!status) { return

Loading…

; diff --git a/desktop/src/shared/api/tauriMesh.ts b/desktop/src/shared/api/tauriMesh.ts index 8f22d563c5..e7c91d6e1c 100644 --- a/desktop/src/shared/api/tauriMesh.ts +++ b/desktop/src/shared/api/tauriMesh.ts @@ -141,6 +141,37 @@ export async function meshInstalledModels(): Promise { return await invokeTauri("mesh_installed_models"); } +export type MeshModelFit = "comfortable" | "tight" | "tradeoff" | "too_large"; + +export type MeshCatalogEntry = { + /** Catalog name — valid as-is in the model field. */ + name: string; + /** Display size, e.g. "5.0GB". */ + size: string; + sizeGb: number; + description: string; + fit: MeshModelFit; + installed: boolean; + recommended: boolean; +}; + +export type MeshModelCatalog = { + gpuName: string | null; + vramDisplay: string; + vramGb: number; + recommended: string | null; + /** Ranked: recommended first, then by fit, then larger first within a fit. */ + entries: MeshCatalogEntry[]; +}; + +/** + * Hardware-aware curated model catalog for the Share-compute picker. + * Works without a running mesh node (hardware survey + HF cache scan). + */ +export async function meshModelCatalog(): Promise { + return await invokeTauri("mesh_model_catalog"); +} + export async function meshAgentPreset( modelId: string, ): Promise { diff --git a/desktop/src/testing/e2eBridge.ts b/desktop/src/testing/e2eBridge.ts index 37443a0dc4..47922816c8 100644 --- a/desktop/src/testing/e2eBridge.ts +++ b/desktop/src/testing/e2eBridge.ts @@ -7945,6 +7945,33 @@ export function maybeInstallE2eTauriMocks() { }; case "mesh_installed_models": return mockMeshState.models; + case "mesh_model_catalog": + return { + gpuName: "Mock GPU", + vramDisplay: "96 GB", + vramGb: 96, + recommended: "Qwen3-8B-Q4_K_M", + entries: [ + { + name: "Qwen3-8B-Q4_K_M", + size: "5.0GB", + sizeGb: 5.0, + description: "Mock recommended model", + fit: "comfortable", + installed: true, + recommended: true, + }, + { + name: "Qwen3-4B-Q4_K_M", + size: "2.5GB", + sizeGb: 2.5, + description: "Mock small model", + fit: "comfortable", + installed: false, + recommended: false, + }, + ], + }; case "mesh_node_status": return meshNodeStatus(mockMeshState.nodeState, mockMeshState.nodeMode); case "mesh_start_node": { diff --git a/docs/mesh-llm-local-build.md b/docs/mesh-llm-local-build.md index 4c466d68e6..a5fe27b604 100644 --- a/docs/mesh-llm-local-build.md +++ b/docs/mesh-llm-local-build.md @@ -58,26 +58,30 @@ Do not use dynamic-link locally unless you already have compatible `llama`, `llama-common`, and `mtmd` dynamic libraries. The default static build is the supported local path for M1. -## Connectivity model: public iroh relays off, raw STUN on (WAN) - -Buzz Desktop starts the embedded mesh node with `disable_iroh_relays(true)` -(mesh-llm fork rev `bc2f1106`, `RelayPolicy::ExplicitlyDisabled`): **no public -iroh relays** (no `*.iroh.link` traffic, no relay transport), so there is no -empty-relay fallback to public infrastructure. - -Raw STUN **remains on** under this policy: the node discovers its public address -(via `stun.l.google.com` / `stun.cloudflare.com`) and injects it into the invite -token / `EndpointAddr`. That address rides the relay-signed `24621`/`24622` -call-me-now exchange, and peers hole-punch directly over UDP — so this works over -**WAN**, not just LAN. STUN is a "what's my public IP" lookup, not a relay or a -data path; the Buzz relay performs the address-exchange coordination. - -Residual limit (intentional v1): with iroh relays off there is **no relay -transport fallback**, so two peers both behind **symmetric NATs** may fail to -hole-punch. Works for the common cases (≥1 side cone-NAT / port-forwarded / -server). A hosted private-iroh-relay fallback (relay advertises an -`iroh_relay_url` + NIP-98 auth) is the planned follow-up once the relay side is -wired end-to-end. +## Connectivity model: iroh relay tunneling on by default, raw STUN on (WAN) + +Buzz Desktop starts the embedded mesh node with iroh's **default relay +servers enabled** (`BUZZ_MESH_IROH_RELAYS`, default on). Peers first attempt +a direct connection — the node discovers its public address via raw STUN +(`stun.l.google.com` / `stun.cloudflare.com`), injects it into the invite +token / `EndpointAddr`, and both sides hole-punch over UDP after the +relay-signed `24621`/`24622` call-me-now exchange. When hole-punching fails +(e.g. both peers behind symmetric NATs), traffic falls back to an iroh relay +tunnel; iroh keeps probing and upgrades to a direct path when one appears. + +Iroh relays are **transport-only**: they forward end-to-end encrypted QUIC +(ciphertext), perform no admission, and are unrelated to the Buzz relay +(which does identity, membership, and matchmaking). Mesh presence is never +published to public Nostr relays — `publish(false)` is hardcoded and the +node's Nostr relay list stays empty regardless of this setting. + +`BUZZ_MESH_IROH_RELAYS=0` disables relay transport entirely (direct QUIC +only) for metadata-conscious deployments; a comma-separated URL list selects +custom (e.g. self-hosted) iroh relays instead of the defaults. + +Because reachability is no longer a de-facto gate, membership enforcement is +the mesh admission layer's job (owner allowlist derived from relay +membership) — see the admission section / roadmap. ## Mesh-compute e2e acceptance matrix