diff --git a/Cargo.lock b/Cargo.lock index 7afc9869f..893358f54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,24 +332,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "async-io" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" -dependencies = [ - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix 1.1.4", - "slab", - "windows-sys 0.61.2", -] - [[package]] name = "async-lock" version = "3.4.2" @@ -514,7 +496,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.37.3", + "object", "rustc-demangle", "windows-link", ] @@ -537,26 +519,6 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" -[[package]] -name = "bincode" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" -dependencies = [ - "bincode_derive", - "serde", - "unty", -] - -[[package]] -name = "bincode_derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" -dependencies = [ - "virtue", -] - [[package]] name = "bindgen" version = "0.72.1" @@ -577,26 +539,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "bitfield" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ba6517c6b0f2bf08be60e187ab64b038438f22dd755614d8fe4d4098c46419" -dependencies = [ - "bitfield-macros", -] - -[[package]] -name = "bitfield-macros" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -618,18 +560,6 @@ version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "blake2" version = "0.10.6" @@ -730,20 +660,6 @@ name = "bytemuck" version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] [[package]] name = "byteorder" @@ -989,16 +905,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0758edba32d61d1fd9f4d69491b47604b91ee2f7e6b33de7e54ca4ebe55dc3" -[[package]] -name = "cobs" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd93fd2c1b27acd030440c9dbd9d14c1122aad622374fe05a670b67a4bc034be" -dependencies = [ - "heapless", - "thiserror 2.0.18", -] - [[package]] name = "cocoa" version = "0.22.0" @@ -1080,7 +986,7 @@ dependencies = [ "encode_unicode", "libc", "once_cell", - "unicode-width 0.2.2", + "unicode-width", "windows-sys 0.59.0", ] @@ -1092,7 +998,7 @@ checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" dependencies = [ "encode_unicode", "libc", - "unicode-width 0.2.2", + "unicode-width", "windows-sys 0.61.2", ] @@ -1294,7 +1200,7 @@ dependencies = [ "jni", "js-sys", "libc", - "mach2 0.4.3", + "mach2", "ndk", "ndk-context", "oboe", @@ -1402,27 +1308,6 @@ dependencies = [ "hybrid-array", ] -[[package]] -name = "csv" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde_core", -] - -[[package]] -name = "csv-core" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" -dependencies = [ - "memchr", -] - [[package]] name = "ctr" version = "0.9.2" @@ -1595,31 +1480,6 @@ dependencies = [ "regex", ] -[[package]] -name = "deku" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9711031e209dc1306d66985363b4397d4c7b911597580340b93c9729b55f6eb" -dependencies = [ - "bitvec", - "deku_derive", - "no_std_io2", - "rustversion", -] - -[[package]] -name = "deku_derive" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cb0719583cbe4e81fb40434ace2f0d22ccc3e39a74bb3796c22b451b4f139d" -dependencies = [ - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "delegate-display" version = "3.0.0" @@ -1845,26 +1705,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "docsplay" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8547ea80db62c5bb9d7796fcce5e6e07d1136bdc1a02269095061e806758fab4" -dependencies = [ - "docsplay-macros", -] - -[[package]] -name = "docsplay-macros" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11772ed3eb3db124d826f3abeadf5a791a557f62c19b123e3f07288158a71fdd" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "document-features" version = "0.2.12" @@ -2081,48 +1921,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6" -[[package]] -name = "esp-idf-part" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5ebc2381d030e4e89183554c3fcd4ad44dc5ab34961ab09e09b4adbe4f94b61" -dependencies = [ - "bitflags 2.11.0", - "csv", - "deku", - "md-5 0.10.6", - "parse_int", - "regex", - "serde", - "serde_plain", - "strum", - "thiserror 2.0.18", -] - -[[package]] -name = "espflash" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f05d15cb2479a3cbbbe684b9f0831b2ae036d9faefd1eb08f21267275862f9" -dependencies = [ - "base64 0.22.1", - "bitflags 2.11.0", - "bytemuck", - "esp-idf-part", - "flate2", - "gimli", - "libc", - "log", - "md-5 0.10.6", - "miette", - "nix 0.30.1", - "object 0.38.1", - "serde", - "sha2 0.10.9", - "strum", - "thiserror 2.0.18", -] - [[package]] name = "euclid" version = "0.20.14" @@ -2392,12 +2190,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futf" version = "0.1.5" @@ -2456,16 +2248,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "futures-core", - "pin-project-lite", -] - [[package]] name = "futures-macro" version = "0.3.32" @@ -2531,7 +2313,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "rustix 1.1.4", + "rustix", "windows-link", ] @@ -2591,11 +2373,6 @@ name = "gimli" version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" -dependencies = [ - "fallible-iterator 0.3.0", - "indexmap", - "stable_deref_trait", -] [[package]] name = "glob" @@ -2670,15 +2447,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -2751,28 +2519,12 @@ dependencies = [ "http 1.4.0", ] -[[package]] -name = "heapless" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" -dependencies = [ - "hash32", - "stable_deref_trait", -] - [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.5.2" @@ -2806,21 +2558,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "hidapi" -version = "2.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1b71e1f4791fb9e93b9d7ee03d70b501ab48f6151432fbcadeabc30fe15396e" -dependencies = [ - "cc", - "cfg-if", - "libc", - "nix 0.30.1", - "pkg-config", - "udev", - "windows-sys 0.61.2", -] - [[package]] name = "hkdf" version = "0.12.4" @@ -3245,12 +2982,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "ihex" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2" - [[package]] name = "image" version = "0.25.10" @@ -3351,7 +3082,7 @@ dependencies = [ "console 0.15.11", "number_prefix", "portable-atomic", - "unicode-width 0.2.2", + "unicode-width", "web-time", ] @@ -3365,37 +3096,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "io-kit-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" -dependencies = [ - "core-foundation-sys 0.8.7", - "mach2 0.4.3", -] - -[[package]] -name = "io-kit-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06d3a048d09fbb6597dbf7c69f40d14df4a49487db1487191618c893fc3b1c26" -dependencies = [ - "core-foundation-sys 0.8.7", - "mach2 0.5.0", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" version = "2.12.0" @@ -3442,15 +3142,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jep106" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1354c92c91fd5595fd4cc46694b6914749cc90ea437246549c26b6ff0ec6d1" -dependencies = [ - "serde", -] - [[package]] name = "jiff" version = "0.2.23" @@ -3683,22 +3374,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "libudev-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -3787,15 +3462,6 @@ dependencies = [ "libc", ] -[[package]] -name = "mach2" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" -dependencies = [ - "libc", -] - [[package]] name = "macro_rules_attribute" version = "0.2.2" @@ -4264,28 +3930,6 @@ dependencies = [ "libc", ] -[[package]] -name = "miette" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" -dependencies = [ - "cfg-if", - "miette-derive", - "unicode-width 0.1.14", -] - -[[package]] -name = "miette-derive" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "mime" version = "0.3.17" @@ -4331,24 +3975,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", - "log", "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] -[[package]] -name = "mio-serial" -version = "5.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029e1f407e261176a983a6599c084efd322d9301028055c87174beac71397ba3" -dependencies = [ - "log", - "mio", - "nix 0.29.0", - "serialport", - "winapi", -] - [[package]] name = "moka" version = "0.12.15" @@ -4474,29 +4104,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.11.0", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nix" version = "0.30.1" @@ -4509,15 +4116,6 @@ dependencies = [ "libc", ] -[[package]] -name = "no_std_io2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3564ce7035b1e4778d8cb6cacebb5d766b5e8fe5a75b9e441e33fb61a872c6" -dependencies = [ - "memchr", -] - [[package]] name = "nom" version = "7.1.3" @@ -4626,7 +4224,7 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.5.2", + "hermit-abi", "libc", ] @@ -4658,43 +4256,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" -[[package]] -name = "nusb" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f861541f15de120eae5982923d073bfc0c1a65466561988c82d6e197734c19e" -dependencies = [ - "atomic-waker", - "core-foundation 0.9.4", - "core-foundation-sys 0.8.7", - "futures-core", - "io-kit-sys 0.4.1", - "libc", - "log", - "once_cell", - "rustix 0.38.44", - "slab", - "windows-sys 0.48.0", -] - -[[package]] -name = "nusb" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a330b3bc7f8b4fc729a4c63164b3927eeeaced198222a3ce6b8b6e034851b7a" -dependencies = [ - "core-foundation 0.10.1", - "core-foundation-sys 0.8.7", - "futures-core", - "io-kit-sys 0.5.0", - "linux-raw-sys 0.12.1", - "log", - "once_cell", - "rustix 1.1.4", - "slab", - "windows-sys 0.61.2", -] - [[package]] name = "oauth2" version = "5.0.0" @@ -5006,17 +4567,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "object" -version = "0.38.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc" -dependencies = [ - "flate2", - "memchr", - "ruzstd", -] - [[package]] name = "oboe" version = "0.6.1" @@ -5082,7 +4632,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openhuman" -version = "0.52.3" +version = "0.52.4" dependencies = [ "aes-gcm", "anyhow", @@ -5121,7 +4671,6 @@ dependencies = [ "mail-parser", "matrix-sdk", "nu-ansi-term 0.46.0", - "nusb 0.2.3", "once_cell", "opentelemetry", "opentelemetry-otlp", @@ -5130,7 +4679,6 @@ dependencies = [ "parking_lot", "pdf-extract", "postgres", - "probe-rs", "prometheus", "prost 0.14.3", "rand 0.9.2", @@ -5156,7 +4704,6 @@ dependencies = [ "thiserror 2.0.18", "tokio", "tokio-rustls", - "tokio-serial", "tokio-stream", "tokio-tungstenite 0.24.0", "tokio-util", @@ -5325,7 +4872,7 @@ checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" dependencies = [ "android_system_properties", "log", - "nix 0.30.1", + "nix", "objc2 0.6.4", "objc2-foundation 0.3.2", "objc2-ui-kit", @@ -5368,15 +4915,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "parse_int" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c464266693329dd5a8715098c7f86e6c5fd5d985018b8318f53d9c6c2b21a31" -dependencies = [ - "num-traits", -] - [[package]] name = "password-hash" version = "0.5.0" @@ -5594,20 +5132,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "polling" -version = "3.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.5.2", - "pin-project-lite", - "rustix 1.1.4", - "windows-sys 0.61.2", -] - [[package]] name = "poly1305" version = "0.8.0" @@ -5742,56 +5266,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "probe-rs" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee27329ac37fa02b194c62a4e3c1aa053739884ea7bcf861249866d3bf7de00" -dependencies = [ - "anyhow", - "async-io", - "bincode", - "bitfield", - "bitvec", - "cobs", - "docsplay", - "dunce", - "espflash", - "flate2", - "futures-lite", - "hidapi", - "ihex", - "itertools 0.14.0", - "jep106", - "nusb 0.1.14", - "object 0.37.3", - "parking_lot", - "probe-rs-target", - "rmp-serde", - "scroll", - "serde", - "serde_yaml", - "serialport", - "thiserror 2.0.18", - "tracing", - "uf2-decode", - "zerocopy", -] - -[[package]] -name = "probe-rs-target" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2239aca5dc62c68ca6d8ff0051fe617cb8363b803380fbc60567e67c82b474df" -dependencies = [ - "base64 0.22.1", - "indexmap", - "jep106", - "serde", - "serde_with", - "url", -] - [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -6050,12 +5524,6 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "rand" version = "0.8.5" @@ -6665,19 +6133,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.11.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.1.4" @@ -6687,7 +6142,7 @@ dependencies = [ "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.12.1", + "linux-raw-sys", "windows-sys 0.61.2", ] @@ -6774,15 +6229,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ruzstd" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ff0cc5e135c8870a775d3320910cd9b564ec036b4dc0b8741629020be63f01" -dependencies = [ - "twox-hash", -] - [[package]] name = "ryu" version = "1.0.23" @@ -6849,12 +6295,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "scroll" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add" - [[package]] name = "sealed" version = "0.6.0" @@ -7106,15 +6546,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_plain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50" -dependencies = [ - "serde", -] - [[package]] name = "serde_spanned" version = "1.1.0" @@ -7136,52 +6567,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_with" -version = "3.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap", - "serde_core", - "serde_json", - "time", -] - -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "serialport" -version = "4.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d91116f97173694f1642263b2ff837f80d933aa837e2314969f6728f661df3" -dependencies = [ - "bitflags 2.11.0", - "cfg-if", - "core-foundation 0.10.1", - "core-foundation-sys 0.8.7", - "io-kit-sys 0.4.1", - "mach2 0.4.3", - "nix 0.26.4", - "scopeguard", - "unescaper", - "windows-sys 0.52.0", -] - [[package]] name = "sha1" version = "0.10.6" @@ -7456,27 +6841,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "subtle" version = "2.6.1" @@ -7565,12 +6929,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "tempfile" version = "3.27.0" @@ -7580,7 +6938,7 @@ dependencies = [ "fastrand", "getrandom 0.4.2", "once_cell", - "rustix 1.1.4", + "rustix", "windows-sys 0.61.2", ] @@ -7830,20 +7188,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-serial" -version = "5.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa1d5427f11ba7c5e6384521cfd76f2d64572ff29f3f4f7aa0f496282923fdc8" -dependencies = [ - "cfg-if", - "futures", - "log", - "mio-serial", - "serialport", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.18" @@ -8184,12 +7528,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "twox-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" - [[package]] name = "type1-encoding-parser" version = "0.1.1" @@ -8240,24 +7578,6 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e36a83ea2b3c704935a01b4642946aadd445cea40b10935e3f8bd8052b8193d6" -[[package]] -name = "udev" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e37e9ea4401fc841ff54b9ddfc9be1079b1e89434c1a6a865dd68980f7e9f" -dependencies = [ - "io-lifetimes", - "libc", - "libudev-sys", - "pkg-config", -] - -[[package]] -name = "uf2-decode" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca77d41ab27e3fa45df42043f96c79b80c6d8632eed906b54681d8d47ab00623" - [[package]] name = "ulid" version = "1.2.1" @@ -8277,15 +7597,6 @@ dependencies = [ "libc", ] -[[package]] -name = "unescaper" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4064ed685c487dbc25bd3f0e9548f2e34bab9d18cefc700f9ec2dba74ba1138e" -dependencies = [ - "thiserror 2.0.18", -] - [[package]] name = "unicase" version = "2.9.0" @@ -8334,12 +7645,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "unicode-width" version = "0.2.2" @@ -8368,24 +7673,12 @@ dependencies = [ "subtle", ] -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "unty" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" - [[package]] name = "ureq" version = "2.12.1" @@ -8510,12 +7803,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "virtue" -version = "0.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" - [[package]] name = "vodozemac" version = "0.9.0" @@ -9720,15 +9007,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "x11" version = "2.21.0" @@ -9746,7 +9024,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ "gethostname", - "rustix 1.1.4", + "rustix", "x11rb-protocol", ] diff --git a/Cargo.toml b/Cargo.toml index 9e55db6e2..8833a3fc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,9 +95,6 @@ rdev = "0.5" matrix-sdk = { version = "0.16", optional = true, default-features = false, features = ["e2e-encryption", "rustls-tls", "markdown"] } fantoccini = { version = "0.22.0", optional = true, default-features = false, features = ["rustls-tls"] } serde-big-array = { version = "0.5", optional = true } -nusb = { version = "0.2", default-features = false, optional = true } -tokio-serial = { version = "5", default-features = false, optional = true } -probe-rs = { version = "0.30", optional = true } pdf-extract = { version = "0.10", optional = true } wa-rs = { version = "0.2", optional = true, default-features = false } wa-rs-core = { version = "0.2", optional = true, default-features = false } @@ -115,13 +112,11 @@ rppal = { version = "0.22", optional = true } [features] sandbox-landlock = ["dep:landlock"] sandbox-bubblewrap = [] -hardware = ["dep:nusb", "dep:tokio-serial"] channel-matrix = ["dep:matrix-sdk"] peripheral-rpi = ["dep:rppal"] browser-native = ["dep:fantoccini"] fantoccini = ["browser-native"] landlock = ["sandbox-landlock"] -probe = ["dep:probe-rs"] rag-pdf = ["dep:pdf-extract"] whatsapp-web = ["dep:wa-rs", "dep:wa-rs-core", "dep:wa-rs-binary", "dep:wa-rs-proto", "dep:wa-rs-ureq-http", "dep:wa-rs-tokio-transport", "serde-big-array"] diff --git a/app/src-tauri/Cargo.lock b/app/src-tauri/Cargo.lock index d5068dc92..b91fb37eb 100644 --- a/app/src-tauri/Cargo.lock +++ b/app/src-tauri/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "OpenHuman" -version = "0.52.3" +version = "0.52.4" dependencies = [ "env_logger", "log", diff --git a/app/src/lib/coreState/store.ts b/app/src/lib/coreState/store.ts index f861d6b7a..e4d181091 100644 --- a/app/src/lib/coreState/store.ts +++ b/app/src/lib/coreState/store.ts @@ -2,8 +2,8 @@ import type { User } from '../../types/api'; import type { TeamInvite, TeamMember, TeamWithRole } from '../../types/team'; import type { AccessibilityStatus } from '../../utils/tauriCommands/accessibility'; import type { AutocompleteStatus } from '../../utils/tauriCommands/autocomplete'; -import type { ServiceStatus } from '../../utils/tauriCommands/hardware'; import type { LocalAiStatus } from '../../utils/tauriCommands/localAi'; +import type { ServiceStatus } from '../../utils/tauriCommands/service'; export interface CoreOnboardingTasks { accessibilityPermissionGranted: boolean; diff --git a/app/src/services/coreStateApi.ts b/app/src/services/coreStateApi.ts index e60155489..b6aeba2a0 100644 --- a/app/src/services/coreStateApi.ts +++ b/app/src/services/coreStateApi.ts @@ -2,8 +2,8 @@ import type { User } from '../types/api'; import type { TeamInvite, TeamMember, TeamWithRole } from '../types/team'; import type { AccessibilityStatus } from '../utils/tauriCommands/accessibility'; import type { AutocompleteStatus } from '../utils/tauriCommands/autocomplete'; -import type { ServiceStatus } from '../utils/tauriCommands/hardware'; import type { LocalAiStatus } from '../utils/tauriCommands/localAi'; +import type { ServiceStatus } from '../utils/tauriCommands/service'; import { callCoreRpc } from './coreRpcClient'; export interface OnboardingTasks { diff --git a/app/src/utils/tauriCommands/index.ts b/app/src/utils/tauriCommands/index.ts index fab83b57b..3bcc6bf6a 100644 --- a/app/src/utils/tauriCommands/index.ts +++ b/app/src/utils/tauriCommands/index.ts @@ -12,7 +12,7 @@ export * from './subconscious'; export * from './localAi'; export * from './config'; export * from './cron'; -export * from './hardware'; +export * from './service'; export * from './accessibility'; export * from './autocomplete'; export * from './skills'; diff --git a/app/src/utils/tauriCommands/hardware.ts b/app/src/utils/tauriCommands/service.ts similarity index 78% rename from app/src/utils/tauriCommands/hardware.ts rename to app/src/utils/tauriCommands/service.ts index ca705d71b..27b264a71 100644 --- a/app/src/utils/tauriCommands/hardware.ts +++ b/app/src/utils/tauriCommands/service.ts @@ -1,30 +1,13 @@ /** - * Hardware and service management commands. + * Service and daemon management commands. */ import { invoke } from '@tauri-apps/api/core'; import { callCoreRpc } from '../../services/coreRpcClient'; import { CommandResponse, isTauri, parseServiceCliOutput } from './common'; -export type HardwareTransport = 'Native' | 'Serial' | 'Probe' | 'None'; export type ServiceState = 'Running' | 'Stopped' | 'NotInstalled' | { Unknown: string }; -export interface DiscoveredDevice { - name: string; - detail?: string | null; - device_path?: string | null; - transport: HardwareTransport; -} - -export interface HardwareIntrospect { - path: string; - vid?: number | null; - pid?: number | null; - board_name?: string | null; - architecture?: string | null; - memory_map_note: string; -} - export interface ServiceStatus { state: ServiceState; unit_path?: string | null; @@ -47,27 +30,6 @@ export interface RestartStatus { reason: string; } -export async function openhumanHardwareDiscover(): Promise> { - if (!isTauri()) { - throw new Error('Not running in Tauri'); - } - return await callCoreRpc>({ - method: 'openhuman.hardware_discover', - }); -} - -export async function openhumanHardwareIntrospect( - path: string -): Promise> { - if (!isTauri()) { - throw new Error('Not running in Tauri'); - } - return await callCoreRpc>({ - method: 'openhuman.hardware_introspect', - params: { path }, - }); -} - export async function openhumanServiceInstall(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); diff --git a/src/openhuman/channels/prompt.rs b/src/openhuman/channels/prompt.rs index fca1c337e..45783dfc6 100644 --- a/src/openhuman/channels/prompt.rs +++ b/src/openhuman/channels/prompt.rs @@ -71,28 +71,7 @@ pub fn build_system_prompt( .push_str("Continue reasoning with the results until you can give a final answer.\n\n"); } - // ── 1b. Hardware (when gpio/arduino tools present) ─────────── - let has_hardware = tools.iter().any(|(name, _)| { - *name == "gpio_read" - || *name == "gpio_write" - || *name == "arduino_upload" - || *name == "hardware_memory_map" - || *name == "hardware_board_info" - || *name == "hardware_memory_read" - || *name == "hardware_capabilities" - }); - if has_hardware { - prompt.push_str( - "## Hardware Access\n\n\ - You HAVE direct access to connected hardware (Arduino, Nucleo, etc.). The user owns this system and has configured it.\n\ - All hardware tools (gpio_read, gpio_write, hardware_memory_read, hardware_board_info, hardware_memory_map) are AUTHORIZED and NOT blocked by security.\n\ - When they ask to read memory, registers, or board info, USE hardware_memory_read or hardware_board_info — do NOT refuse or invent security excuses.\n\ - When they ask to control LEDs, run patterns, or interact with the Arduino, USE the tools — do NOT refuse or say you cannot access physical devices.\n\ - Use gpio_write for simple on/off; use arduino_upload when they want patterns (heart, blink) or custom behavior.\n\n", - ); - } - - // ── 1c. Action instruction (avoid meta-summary) ─────────────── + // ── 1b. Action instruction (avoid meta-summary) ─────────────── prompt.push_str( "## Your Task\n\n\ When the user sends a message, ACT on it. Use the tools to fulfill their request.\n\ diff --git a/src/openhuman/config/mod.rs b/src/openhuman/config/mod.rs index 9de3c4617..3c3d2b13a 100644 --- a/src/openhuman/config/mod.rs +++ b/src/openhuman/config/mod.rs @@ -27,20 +27,19 @@ pub use schema::{ AgentConfig, AuditConfig, AutocompleteConfig, AutonomyConfig, BrowserComputerUseConfig, BrowserConfig, ChannelsConfig, ClassificationRule, ComposioConfig, Config, CostConfig, CronConfig, DelegateAgentConfig, DictationActivationMode, DictationConfig, DiscordConfig, - DockerRuntimeConfig, EmbeddingRouteConfig, HardwareConfig, HardwareTransport, HeartbeatConfig, - HttpRequestConfig, IMessageConfig, IntegrationToggle, IntegrationsConfig, LarkConfig, - LearningConfig, LocalAiConfig, MatrixConfig, MemoryConfig, ModelRouteConfig, MultimodalConfig, - ObservabilityConfig, OrchestratorConfig, PeripheralBoardConfig, PeripheralsConfig, ProxyConfig, - ProxyScope, QueryClassificationConfig, ReflectionSource, ReliabilityConfig, - ResourceLimitsConfig, RuntimeConfig, SandboxBackend, SandboxConfig, SchedulerConfig, - ScreenIntelligenceConfig, SecretsConfig, SecurityConfig, SlackConfig, StorageConfig, - StorageProviderConfig, StorageProviderSection, StreamMode, TelegramConfig, UpdateConfig, - VoiceActivationMode, VoiceServerConfig, WebSearchConfig, WebhookConfig, DEFAULT_MODEL, - MODEL_AGENTIC_V1, MODEL_CODING_V1, MODEL_REASONING_V1, + DockerRuntimeConfig, EmbeddingRouteConfig, HeartbeatConfig, HttpRequestConfig, IMessageConfig, + IntegrationToggle, IntegrationsConfig, LarkConfig, LearningConfig, LocalAiConfig, MatrixConfig, + MemoryConfig, ModelRouteConfig, MultimodalConfig, ObservabilityConfig, OrchestratorConfig, + PeripheralBoardConfig, PeripheralsConfig, ProxyConfig, ProxyScope, QueryClassificationConfig, + ReflectionSource, ReliabilityConfig, ResourceLimitsConfig, RuntimeConfig, SandboxBackend, + SandboxConfig, SchedulerConfig, ScreenIntelligenceConfig, SecretsConfig, SecurityConfig, + SlackConfig, StorageConfig, StorageProviderConfig, StorageProviderSection, StreamMode, + TelegramConfig, UpdateConfig, VoiceActivationMode, VoiceServerConfig, WebSearchConfig, + WebhookConfig, DEFAULT_MODEL, MODEL_AGENTIC_V1, MODEL_CODING_V1, MODEL_REASONING_V1, }; pub use schema::{ - clear_active_user, default_root_openhuman_dir, read_active_user_id, user_openhuman_dir, - write_active_user_id, + clear_active_user, default_root_openhuman_dir, pre_login_user_dir, read_active_user_id, + user_openhuman_dir, write_active_user_id, PRE_LOGIN_USER_ID, }; pub use schemas::{ all_controller_schemas as all_config_controller_schemas, diff --git a/src/openhuman/config/schema/hardware.rs b/src/openhuman/config/schema/hardware.rs deleted file mode 100644 index 89673647c..000000000 --- a/src/openhuman/config/schema/hardware.rs +++ /dev/null @@ -1,72 +0,0 @@ -//! Hardware (wizard-driven) configuration. - -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -/// Hardware transport mode. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, JsonSchema)] -pub enum HardwareTransport { - #[default] - None, - Native, - Serial, - Probe, -} - -impl std::fmt::Display for HardwareTransport { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::None => write!(f, "none"), - Self::Native => write!(f, "native"), - Self::Serial => write!(f, "serial"), - Self::Probe => write!(f, "probe"), - } - } -} - -fn default_baud_rate() -> u32 { - 115_200 -} - -/// Wizard-driven hardware configuration for physical world interaction. -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] -pub struct HardwareConfig { - /// Whether hardware access is enabled - #[serde(default)] - pub enabled: bool, - /// Transport mode - #[serde(default)] - pub transport: HardwareTransport, - /// Serial port path (e.g. "/dev/ttyACM0") - #[serde(default)] - pub serial_port: Option, - /// Serial baud rate - #[serde(default = "default_baud_rate")] - pub baud_rate: u32, - /// Probe target chip (e.g. "STM32F401RE") - #[serde(default)] - pub probe_target: Option, - /// Enable workspace datasheet RAG (index PDF schematics for AI pin lookups) - #[serde(default)] - pub workspace_datasheets: bool, -} - -impl HardwareConfig { - /// Return the active transport mode. - pub fn transport_mode(&self) -> HardwareTransport { - self.transport.clone() - } -} - -impl Default for HardwareConfig { - fn default() -> Self { - Self { - enabled: false, - transport: HardwareTransport::None, - serial_port: None, - baud_rate: default_baud_rate(), - probe_target: None, - workspace_datasheets: false, - } - } -} diff --git a/src/openhuman/config/schema/load.rs b/src/openhuman/config/schema/load.rs index 73d66e513..195b83f9f 100644 --- a/src/openhuman/config/schema/load.rs +++ b/src/openhuman/config/schema/load.rs @@ -240,10 +240,21 @@ async fn resolve_runtime_config_dirs( )); } - // 4. Default. + // 4. Default: no login yet. Encapsulate config/memory/state under the + // pre-login user directory so everything is user-scoped from the very + // first init. On first real login, this directory is migrated to the + // authenticated user id (see `credentials::ops::store_session`). + let user_dir = pre_login_user_dir(default_openhuman_dir); + let user_workspace = user_dir.join("workspace"); + tracing::debug!( + user_id = %PRE_LOGIN_USER_ID, + user_dir = %user_dir.display(), + default_workspace_dir = %default_workspace_dir.display(), + "Config dirs resolved to pre-login user directory (no active user, no workspace marker)" + ); Ok(( - default_openhuman_dir.to_path_buf(), - default_workspace_dir.to_path_buf(), + user_dir, + user_workspace, ConfigResolutionSource::DefaultConfigDir, )) } @@ -334,6 +345,21 @@ pub fn user_openhuman_dir(default_openhuman_dir: &Path, user_id: &str) -> PathBu default_openhuman_dir.join("users").join(user_id) } +/// Stable id used to scope the openhuman directory before any user has +/// logged in. All memory, state, config, sessions and workspace files +/// created on first init land under `{root}/users/{PRE_LOGIN_USER_ID}` +/// so nothing is ever written directly at the root `.openhuman` path. +/// +/// On first successful login, this directory is migrated into the real +/// user-scoped directory (see `credentials::ops::store_session`). +pub const PRE_LOGIN_USER_ID: &str = "local"; + +/// Returns the pre-login (unauthenticated) user directory: +/// `{default_openhuman_dir}/users/local`. +pub fn pre_login_user_dir(default_openhuman_dir: &Path) -> PathBuf { + user_openhuman_dir(default_openhuman_dir, PRE_LOGIN_USER_ID) +} + fn migrate_legacy_autocomplete_disabled_apps(config: &mut Config) { // Legacy defaults blocked both terminal and code, which prevented Codex/CLI usage. // Migrate only the exact legacy default so custom user preferences remain untouched. @@ -377,6 +403,29 @@ impl Config { let config_path = openhuman_dir.join("config.toml"); + // Pre-login path: no active user, no workspace marker, no env override, + // and no existing config.toml on disk. Return an in-memory default + // config without creating any directories or writing any files — disk + // state is deferred until the first successful login in + // `credentials::ops::store_session`, which writes `active_user.toml` + // and triggers a reload that materializes the user-scoped directory. + if resolution_source == ConfigResolutionSource::DefaultConfigDir && !config_path.exists() { + let mut config = Config::default(); + config.config_path = config_path.clone(); + config.workspace_dir = workspace_dir.clone(); + config.apply_env_overrides(); + + tracing::debug!( + path = %config.config_path.display(), + workspace = %config.workspace_dir.display(), + source = resolution_source.as_str(), + initialized = false, + persisted = false, + "Config loaded (pre-login, in-memory only — no dirs or files written)" + ); + return Ok(config); + } + fs::create_dir_all(&openhuman_dir) .await .context("Failed to create config directory")?; @@ -1014,12 +1063,14 @@ mod tests { let root = tmp.path(); let default_workspace = root.join("workspace"); - // No active user → uses default. + // No active user → falls back to the pre-login user directory so + // memory/state/config are still encapsulated under users/. let (oh_dir, ws_dir, source) = resolve_runtime_config_dirs(root, &default_workspace) .await .unwrap(); - assert_eq!(oh_dir, root); - assert_eq!(ws_dir, default_workspace); + let expected_pre_login_dir = root.join("users").join(PRE_LOGIN_USER_ID); + assert_eq!(oh_dir, expected_pre_login_dir); + assert_eq!(ws_dir, expected_pre_login_dir.join("workspace")); assert_eq!(source, ConfigResolutionSource::DefaultConfigDir); // With active user → scopes to user dir. @@ -1032,4 +1083,14 @@ mod tests { assert_eq!(ws_dir, expected_user_dir.join("workspace")); assert_eq!(source, ConfigResolutionSource::ActiveUser); } + + #[test] + fn pre_login_user_dir_is_under_users_tree() { + let root = PathBuf::from("/home/test/.openhuman"); + let dir = pre_login_user_dir(&root); + assert_eq!( + dir, + PathBuf::from("/home/test/.openhuman/users").join(PRE_LOGIN_USER_ID) + ); + } } diff --git a/src/openhuman/config/schema/mod.rs b/src/openhuman/config/schema/mod.rs index b1c80fd44..585947abc 100644 --- a/src/openhuman/config/schema/mod.rs +++ b/src/openhuman/config/schema/mod.rs @@ -9,14 +9,13 @@ mod autonomy; mod channels; mod defaults; mod dictation; -mod hardware; mod heartbeat_cron; mod identity_cost; mod learning; mod load; pub use load::{ - clear_active_user, default_root_openhuman_dir, read_active_user_id, user_openhuman_dir, - write_active_user_id, + clear_active_user, default_root_openhuman_dir, pre_login_user_dir, read_active_user_id, + user_openhuman_dir, write_active_user_id, PRE_LOGIN_USER_ID, }; mod local_ai; mod observability; @@ -39,7 +38,6 @@ pub use channels::{ TelegramConfig, WebhookConfig, WhatsAppConfig, }; pub use dictation::{DictationActivationMode, DictationConfig}; -pub use hardware::{HardwareConfig, HardwareTransport}; pub use heartbeat_cron::{CronConfig, HeartbeatConfig}; pub use identity_cost::{CostConfig, ModelPricing, PeripheralBoardConfig, PeripheralsConfig}; pub use learning::{LearningConfig, ReflectionSource}; diff --git a/src/openhuman/config/schema/types.rs b/src/openhuman/config/schema/types.rs index 4ae630919..e8f198473 100644 --- a/src/openhuman/config/schema/types.rs +++ b/src/openhuman/config/schema/types.rs @@ -111,9 +111,6 @@ pub struct Config { #[serde(default)] pub agents: HashMap, - #[serde(default)] - pub hardware: HardwareConfig, - #[serde(default)] pub local_ai: LocalAiConfig, @@ -178,7 +175,6 @@ impl Default for Config { cost: CostConfig::default(), peripherals: PeripheralsConfig::default(), agents: HashMap::new(), - hardware: HardwareConfig::default(), local_ai: LocalAiConfig::default(), voice_server: VoiceServerConfig::default(), query_classification: QueryClassificationConfig::default(), diff --git a/src/openhuman/tools/impl/hardware/board_info.rs b/src/openhuman/tools/impl/hardware/board_info.rs deleted file mode 100644 index 237071cb9..000000000 --- a/src/openhuman/tools/impl/hardware/board_info.rs +++ /dev/null @@ -1,195 +0,0 @@ -//! Hardware board info tool — returns chip name, architecture, memory map for Telegram/agent. -//! -//! Use when user asks "what board do I have?", "board info", "connected hardware", etc. -//! Uses probe-rs for Nucleo when available; otherwise static datasheet info. - -use crate::openhuman::tools::traits::{Tool, ToolResult}; -use async_trait::async_trait; -use serde_json::json; - -/// Static board info (datasheets). Used when probe-rs is unavailable. -const BOARD_INFO: &[(&str, &str, &str)] = &[ - ( - "nucleo-f401re", - "STM32F401RET6", - "ARM Cortex-M4, 84 MHz. Flash: 512 KB, RAM: 128 KB. User LED on PA5 (pin 13).", - ), - ( - "nucleo-f411re", - "STM32F411RET6", - "ARM Cortex-M4, 100 MHz. Flash: 512 KB, RAM: 128 KB. User LED on PA5 (pin 13).", - ), - ( - "arduino-uno", - "ATmega328P", - "8-bit AVR, 16 MHz. Flash: 16 KB, SRAM: 2 KB. Built-in LED on pin 13.", - ), - ( - "arduino-uno-q", - "STM32U585 + Qualcomm", - "Dual-core: STM32 (MCU) + Linux (aarch64). GPIO via Bridge app on port 9999.", - ), - ( - "esp32", - "ESP32", - "Dual-core Xtensa LX6, 240 MHz. Flash: 4 MB typical. Built-in LED on GPIO 2.", - ), - ( - "rpi-gpio", - "Raspberry Pi", - "ARM Linux. Native GPIO via sysfs/rppal. No fixed LED pin.", - ), -]; - -/// Tool: return full board info (chip, architecture, memory map) for agent/Telegram. -pub struct HardwareBoardInfoTool { - boards: Vec, -} - -impl HardwareBoardInfoTool { - pub fn new(boards: Vec) -> Self { - Self { boards } - } - - fn static_info_for_board(&self, board: &str) -> Option { - BOARD_INFO - .iter() - .find(|(b, _, _)| *b == board) - .map(|(_, chip, desc)| { - format!( - "**Board:** {}\n**Chip:** {}\n**Description:** {}", - board, chip, desc - ) - }) - } -} - -#[async_trait] -impl Tool for HardwareBoardInfoTool { - fn name(&self) -> &str { - "hardware_board_info" - } - - fn description(&self) -> &str { - "Return full board info (chip, architecture, memory map) for connected hardware. Use when: user asks for 'board info', 'what board do I have', 'connected hardware', 'chip info', 'what hardware', or 'memory map'." - } - - fn parameters_schema(&self) -> serde_json::Value { - json!({ - "type": "object", - "properties": { - "board": { - "type": "string", - "description": "Optional board name (e.g. nucleo-f401re). If omitted, returns info for first configured board." - } - } - }) - } - - async fn execute(&self, args: serde_json::Value) -> anyhow::Result { - let board = args - .get("board") - .and_then(|v| v.as_str()) - .map(String::from) - .or_else(|| self.boards.first().cloned()); - - let board = board.as_deref().unwrap_or("unknown"); - - if self.boards.is_empty() { - return Ok(ToolResult::error( - "No peripherals configured. Add boards to config.toml [peripherals.boards].", - )); - } - - let mut output = String::new(); - - #[cfg(feature = "probe")] - if board == "nucleo-f401re" || board == "nucleo-f411re" { - let chip = if board == "nucleo-f411re" { - "STM32F411RETx" - } else { - "STM32F401RETx" - }; - match probe_board_info(chip) { - Ok(info) => { - return Ok(ToolResult::success(info)); - } - Err(e) => { - use std::fmt::Write; - let _ = write!( - output, - "probe-rs attach failed: {e}. Using static info.\n\n" - ); - } - } - } - - if let Some(info) = self.static_info_for_board(board) { - output.push_str(&info); - if let Some(mem) = memory_map_static(board) { - use std::fmt::Write; - let _ = write!(output, "\n\n**Memory map:**\n{mem}"); - } - } else { - use std::fmt::Write; - let _ = write!( - output, - "Board '{board}' configured. No static info available." - ); - } - - Ok(ToolResult::success(output)) - } -} - -#[cfg(feature = "probe")] -fn probe_board_info(chip: &str) -> anyhow::Result { - use probe_rs::config::MemoryRegion; - use probe_rs::{Session, SessionConfig}; - - let session = Session::auto_attach(chip, SessionConfig::default()) - .map_err(|e| anyhow::anyhow!("{}", e))?; - let target = session.target(); - let arch = session.architecture(); - - let mut out = format!( - "**Board:** {}\n**Chip:** {}\n**Architecture:** {:?}\n\n**Memory map:**\n", - chip, target.name, arch - ); - for region in target.memory_map.iter() { - match region { - MemoryRegion::Ram(ram) => { - let (start, end) = (ram.range.start, ram.range.end); - out.push_str(&format!( - "RAM: 0x{:08X} - 0x{:08X} ({} KB)\n", - start, - end, - (end - start) / 1024 - )); - } - MemoryRegion::Nvm(flash) => { - let (start, end) = (flash.range.start, flash.range.end); - out.push_str(&format!( - "Flash: 0x{:08X} - 0x{:08X} ({} KB)\n", - start, - end, - (end - start) / 1024 - )); - } - _ => {} - } - } - out.push_str("\n(Info read via USB/SWD — no firmware on target needed.)"); - Ok(out) -} - -fn memory_map_static(board: &str) -> Option<&'static str> { - match board { - "nucleo-f401re" | "nucleo-f411re" => Some( - "Flash: 0x0800_0000 - 0x0807_FFFF (512 KB)\nRAM: 0x2000_0000 - 0x2001_FFFF (128 KB)", - ), - "arduino-uno" => Some("Flash: 16 KB, SRAM: 2 KB, EEPROM: 1 KB"), - "esp32" => Some("Flash: 4 MB, IRAM/DRAM per ESP-IDF layout"), - _ => None, - } -} diff --git a/src/openhuman/tools/impl/hardware/memory_map.rs b/src/openhuman/tools/impl/hardware/memory_map.rs deleted file mode 100644 index 9fddd33b4..000000000 --- a/src/openhuman/tools/impl/hardware/memory_map.rs +++ /dev/null @@ -1,198 +0,0 @@ -//! Hardware memory map tool — returns flash/RAM address ranges for connected boards. -//! -//! Phase B: When user asks "what are the upper and lower memory addresses?", this tool -//! returns the memory map. Uses probe-rs for Nucleo/STM32 when available; otherwise -//! returns static maps from datasheets. - -use crate::openhuman::tools::traits::{Tool, ToolResult}; -use async_trait::async_trait; -use serde_json::json; - -/// Known memory maps (from datasheets). Used when probe-rs is unavailable. -const MEMORY_MAPS: &[(&str, &str)] = &[ - ( - "nucleo-f401re", - "Flash: 0x0800_0000 - 0x0807_FFFF (512 KB)\nRAM: 0x2000_0000 - 0x2001_FFFF (128 KB)\nSTM32F401RET6, ARM Cortex-M4", - ), - ( - "nucleo-f411re", - "Flash: 0x0800_0000 - 0x0807_FFFF (512 KB)\nRAM: 0x2000_0000 - 0x2001_FFFF (128 KB)\nSTM32F411RET6, ARM Cortex-M4", - ), - ( - "arduino-uno", - "Flash: 0x0000 - 0x3FFF (16 KB, ATmega328P)\nSRAM: 0x0100 - 0x08FF (2 KB)\nEEPROM: 0x0000 - 0x03FF (1 KB)", - ), - ( - "arduino-mega", - "Flash: 0x0000 - 0x3FFFF (256 KB, ATmega2560)\nSRAM: 0x0200 - 0x21FF (8 KB)\nEEPROM: 0x0000 - 0x0FFF (4 KB)", - ), - ( - "esp32", - "Flash: 0x3F40_0000 - 0x3F7F_FFFF (4 MB typical)\nIRAM: 0x4000_0000 - 0x4005_FFFF\nDRAM: 0x3FFB_0000 - 0x3FFF_FFFF", - ), -]; - -/// Tool: report hardware memory map for connected boards. -pub struct HardwareMemoryMapTool { - boards: Vec, -} - -impl HardwareMemoryMapTool { - pub fn new(boards: Vec) -> Self { - Self { boards } - } - - fn static_map_for_board(&self, board: &str) -> Option<&'static str> { - MEMORY_MAPS - .iter() - .find(|(b, _)| *b == board) - .map(|(_, m)| *m) - } -} - -#[async_trait] -impl Tool for HardwareMemoryMapTool { - fn name(&self) -> &str { - "hardware_memory_map" - } - - fn description(&self) -> &str { - "Return the memory map (flash and RAM address ranges) for connected hardware. Use when: user asks for 'upper and lower memory addresses', 'memory map', 'address space', or 'readable addresses'. Returns flash/RAM ranges from datasheets." - } - - fn parameters_schema(&self) -> serde_json::Value { - json!({ - "type": "object", - "properties": { - "board": { - "type": "string", - "description": "Optional board name (e.g. nucleo-f401re, arduino-uno). If omitted, returns map for first configured board." - } - } - }) - } - - async fn execute(&self, args: serde_json::Value) -> anyhow::Result { - let board = args - .get("board") - .and_then(|v| v.as_str()) - .map(String::from) - .or_else(|| self.boards.first().cloned()); - - let board = board.as_deref().unwrap_or("unknown"); - - if self.boards.is_empty() { - return Ok(ToolResult::error( - "No peripherals configured. Add boards to config.toml [peripherals.boards].", - )); - } - - let mut output = String::new(); - - #[cfg(feature = "probe")] - let probe_ok = { - if board == "nucleo-f401re" || board == "nucleo-f411re" { - let chip = if board == "nucleo-f411re" { - "STM32F411RETx" - } else { - "STM32F401RETx" - }; - match probe_rs_memory_map(chip) { - Ok(probe_msg) => { - output.push_str(&format!("**{}** (via probe-rs):\n{}\n", board, probe_msg)); - true - } - Err(e) => { - output.push_str(&format!("Probe-rs failed: {}. ", e)); - false - } - } - } else { - false - } - }; - - #[cfg(not(feature = "probe"))] - let probe_ok = false; - - if !probe_ok { - if let Some(map) = self.static_map_for_board(board) { - use std::fmt::Write; - let _ = write!(output, "**{board}** (from datasheet):\n{map}"); - } else { - use std::fmt::Write; - let known: Vec<&str> = MEMORY_MAPS.iter().map(|(b, _)| *b).collect(); - let _ = write!( - output, - "No memory map for board '{board}'. Known boards: {}", - known.join(", ") - ); - } - } - - Ok(ToolResult::success(output)) - } -} - -#[cfg(feature = "probe")] -fn probe_rs_memory_map(chip: &str) -> anyhow::Result { - use probe_rs::config::MemoryRegion; - use probe_rs::{Session, SessionConfig}; - - let session = Session::auto_attach(chip, SessionConfig::default()) - .map_err(|e| anyhow::anyhow!("probe-rs attach failed: {}", e))?; - - let target = session.target(); - let mut out = String::new(); - - for region in target.memory_map.iter() { - match region { - MemoryRegion::Ram(ram) => { - let start = ram.range.start; - let end = ram.range.end; - let size_kb = (end - start) / 1024; - out.push_str(&format!( - "RAM: 0x{:08X} - 0x{:08X} ({} KB)\n", - start, end, size_kb - )); - } - MemoryRegion::Nvm(flash) => { - let start = flash.range.start; - let end = flash.range.end; - let size_kb = (end - start) / 1024; - out.push_str(&format!( - "Flash: 0x{:08X} - 0x{:08X} ({} KB)\n", - start, end, size_kb - )); - } - _ => {} - } - } - - if out.is_empty() { - out = "Could not read memory regions from probe.".to_string(); - } - - Ok(out) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn static_map_nucleo() { - let tool = HardwareMemoryMapTool::new(vec!["nucleo-f401re".into()]); - assert!(tool.static_map_for_board("nucleo-f401re").is_some()); - assert!(tool - .static_map_for_board("nucleo-f401re") - .unwrap() - .contains("Flash")); - } - - #[test] - fn static_map_arduino() { - let tool = HardwareMemoryMapTool::new(vec!["arduino-uno".into()]); - assert!(tool.static_map_for_board("arduino-uno").is_some()); - } -} diff --git a/src/openhuman/tools/impl/hardware/memory_read.rs b/src/openhuman/tools/impl/hardware/memory_read.rs deleted file mode 100644 index b4680df81..000000000 --- a/src/openhuman/tools/impl/hardware/memory_read.rs +++ /dev/null @@ -1,161 +0,0 @@ -//! Hardware memory read tool — read actual memory/register values from Nucleo via probe-rs. -//! -//! Use when user asks to "read register values", "read memory at address", "dump lower memory", etc. -//! Requires probe feature and Nucleo connected via USB. - -use crate::openhuman::tools::traits::{Tool, ToolResult}; -use async_trait::async_trait; -use serde_json::json; - -/// RAM base for Nucleo-F401RE (STM32F401) -const NUCLEO_RAM_BASE: u64 = 0x2000_0000; - -/// Tool: read memory at address from connected Nucleo via probe-rs. -pub struct HardwareMemoryReadTool { - boards: Vec, -} - -impl HardwareMemoryReadTool { - pub fn new(boards: Vec) -> Self { - Self { boards } - } - - fn chip_for_board(board: &str) -> Option<&'static str> { - match board { - "nucleo-f401re" => Some("STM32F401RETx"), - "nucleo-f411re" => Some("STM32F411RETx"), - _ => None, - } - } -} - -#[async_trait] -impl Tool for HardwareMemoryReadTool { - fn name(&self) -> &str { - "hardware_memory_read" - } - - fn description(&self) -> &str { - "Read actual memory/register values from Nucleo via USB. Use when: user asks to 'read register values', 'read memory at address', 'dump memory', 'lower memory 0-126', or 'give address and value'. Returns hex dump. Requires Nucleo connected via USB and probe feature. Params: address (hex, e.g. 0x20000000 for RAM start), length (bytes, default 128)." - } - - fn parameters_schema(&self) -> serde_json::Value { - json!({ - "type": "object", - "properties": { - "address": { - "type": "string", - "description": "Memory address in hex (e.g. 0x20000000 for RAM start). Default: 0x20000000 (RAM base)." - }, - "length": { - "type": "integer", - "description": "Number of bytes to read (default 128, max 256)." - }, - "board": { - "type": "string", - "description": "Board name (nucleo-f401re). Optional if only one configured." - } - } - }) - } - - async fn execute(&self, args: serde_json::Value) -> anyhow::Result { - if self.boards.is_empty() { - return Ok(ToolResult::error( - "No peripherals configured. Add nucleo-f401re to config.toml [peripherals.boards].", - )); - } - - let board = args - .get("board") - .and_then(|v| v.as_str()) - .map(String::from) - .or_else(|| self.boards.first().cloned()) - .unwrap_or_else(|| "nucleo-f401re".into()); - - let chip = Self::chip_for_board(&board); - if chip.is_none() { - return Ok(ToolResult::error(format!( - "Memory read only supports nucleo-f401re, nucleo-f411re. Got: {}", - board - ))); - } - - let address_str = args - .get("address") - .and_then(|v| v.as_str()) - .unwrap_or("0x20000000"); - let _address = parse_hex_address(address_str).unwrap_or(NUCLEO_RAM_BASE); - - let requested_length = args.get("length").and_then(|v| v.as_u64()).unwrap_or(128); - let _length = usize::try_from(requested_length) - .unwrap_or(256) - .clamp(1, 256); - - #[cfg(feature = "probe")] - { - match probe_read_memory(chip.unwrap(), _address, _length) { - Ok(output) => { - return Ok(ToolResult::success(output)); - } - Err(e) => { - return Ok(ToolResult::error(format!( - "probe-rs read failed: {}. Ensure Nucleo is connected via USB and built with --features probe.", - e - ))); - } - } - } - - #[cfg(not(feature = "probe"))] - { - Ok(ToolResult::error( - "Memory read requires probe feature. Build with: cargo build --features hardware,probe", - )) - } - } -} - -fn parse_hex_address(s: &str) -> Option { - let s = s.trim().trim_start_matches("0x").trim_start_matches("0X"); - u64::from_str_radix(s, 16).ok() -} - -#[cfg(feature = "probe")] -fn probe_read_memory(chip: &str, address: u64, length: usize) -> anyhow::Result { - use probe_rs::MemoryInterface; - use probe_rs::Session; - use probe_rs::SessionConfig; - - let mut session = Session::auto_attach(chip, SessionConfig::default()) - .map_err(|e| anyhow::anyhow!("{}", e))?; - - let mut core = session.core(0)?; - let mut buf = vec![0u8; length]; - core.read_8(address, &mut buf) - .map_err(|e| anyhow::anyhow!("{}", e))?; - - // Format as hex dump: address | bytes (16 per line) - let mut out = format!("Memory read from 0x{:08X} ({} bytes):\n\n", address, length); - const COLS: usize = 16; - for (i, chunk) in buf.chunks(COLS).enumerate() { - let addr = address + (i * COLS) as u64; - let hex: String = chunk - .iter() - .map(|b| format!("{:02X}", b)) - .collect::>() - .join(" "); - let ascii: String = chunk - .iter() - .map(|&b| { - if b.is_ascii_graphic() || b == b' ' { - b as char - } else { - '.' - } - }) - .collect(); - out.push_str(&format!("0x{:08X} {:48} {}\n", addr, hex, ascii)); - } - Ok(out) -} diff --git a/src/openhuman/tools/impl/hardware/mod.rs b/src/openhuman/tools/impl/hardware/mod.rs deleted file mode 100644 index 2575fdf46..000000000 --- a/src/openhuman/tools/impl/hardware/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod board_info; -mod memory_map; -mod memory_read; - -pub use board_info::HardwareBoardInfoTool; -pub use memory_map::HardwareMemoryMapTool; -pub use memory_read::HardwareMemoryReadTool; diff --git a/src/openhuman/tools/impl/mod.rs b/src/openhuman/tools/impl/mod.rs index 352e202a0..003275b84 100644 --- a/src/openhuman/tools/impl/mod.rs +++ b/src/openhuman/tools/impl/mod.rs @@ -2,7 +2,6 @@ pub mod agent; pub mod browser; pub mod cron; pub mod filesystem; -pub mod hardware; pub mod memory; pub mod network; pub mod system; @@ -11,7 +10,6 @@ pub use agent::*; pub use browser::*; pub use cron::*; pub use filesystem::*; -pub use hardware::*; pub use memory::*; pub use network::*; pub use system::*; diff --git a/tests/json_rpc_e2e.rs b/tests/json_rpc_e2e.rs index 68e47aba2..ee0b76740 100644 --- a/tests/json_rpc_e2e.rs +++ b/tests/json_rpc_e2e.rs @@ -542,9 +542,24 @@ default_temperature = 0.7 encrypt = false "# ); - std::fs::create_dir_all(openhuman_dir).expect("mkdir openhuman"); - let path = openhuman_dir.join("config.toml"); - std::fs::write(&path, &cfg).expect("write config"); + fn write_config_file(config_dir: &Path, cfg: &str) { + std::fs::create_dir_all(config_dir).expect("mkdir openhuman"); + let path = config_dir.join("config.toml"); + std::fs::write(&path, cfg).expect("write config"); + } + + write_config_file(openhuman_dir, &cfg); + + // Runtime config resolution is user-scoped before login, so tests that seed + // the root `~/.openhuman` directory also need the equivalent pre-login + // config under `~/.openhuman/users/local`. + if openhuman_dir + .file_name() + .is_some_and(|name| name == std::ffi::OsStr::new(".openhuman")) + { + write_config_file(&openhuman_dir.join("users").join("local"), &cfg); + } + let _: openhuman_core::openhuman::config::Config = toml::from_str(&cfg).expect("config toml must match Config schema"); } @@ -563,9 +578,21 @@ encrypt = false enabled = false "# ); - std::fs::create_dir_all(openhuman_dir).expect("mkdir openhuman"); - let path = openhuman_dir.join("config.toml"); - std::fs::write(&path, &cfg).expect("write config"); + fn write_config_file(config_dir: &Path, cfg: &str) { + std::fs::create_dir_all(config_dir).expect("mkdir openhuman"); + let path = config_dir.join("config.toml"); + std::fs::write(&path, cfg).expect("write config"); + } + + write_config_file(openhuman_dir, &cfg); + + if openhuman_dir + .file_name() + .is_some_and(|name| name == std::ffi::OsStr::new(".openhuman")) + { + write_config_file(&openhuman_dir.join("users").join("local"), &cfg); + } + let _: openhuman_core::openhuman::config::Config = toml::from_str(&cfg).expect("config toml must match Config schema"); }