diff --git a/.cargo/audit.toml b/.cargo/audit.toml index 967c3f7149..3a297867fa 100644 --- a/.cargo/audit.toml +++ b/.cargo/audit.toml @@ -31,4 +31,5 @@ ignore = [ "RUSTSEC-2025-0100", # gio-sys unmaintained "RUSTSEC-2026-0002", # serde_cbor unmaintained "RUSTSEC-2023-0086", # lexopt unmaintained (if present) + "RUSTSEC-2026-0049", # rustls-webpki CRL matching — rumqttc 0.25.1 depends on vulnerable version, awaiting upstream fix ] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f20467766f..eed9ab24f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,32 @@ env: RUSTFLAGS: "-D warnings" jobs: + # ── Build verification (all 3 platforms) ─────────────────────────────────── + build: + name: Build / ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + key: build-${{ matrix.os }} + - name: Install Tauri system deps (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y \ + libwebkit2gtk-4.1-dev \ + libgtk-3-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + patchelf + - run: cargo build --workspace --lib + # ── Rust library crates (all 3 platforms) ────────────────────────────────── check: name: Check / ${{ matrix.os }} diff --git a/Cargo.lock b/Cargo.lock index 55e1647fe9..aa68d79da2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addr2line" -version = "0.25.1" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +checksum = "59317f77929f0e679d39364702289274de2f0f0b22cbf50b2b8cff2169a0b27a" dependencies = [ "gimli", ] @@ -969,16 +969,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -1002,7 +992,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ "bitflags 2.11.0", - "core-foundation 0.10.1", + "core-foundation", "core-graphics-types", "foreign-types 0.5.0", "libc", @@ -1015,7 +1005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ "bitflags 2.11.0", - "core-foundation 0.10.1", + "core-foundation", "libc", ] @@ -1039,46 +1029,48 @@ dependencies = [ [[package]] name = "cranelift-assembler-x64" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50a04121a197fde2fe896f8e7cac9812fc41ed6ee9c63e1906090f9f497845f6" +checksum = "046d4b584c3bb9b5eb500c8f29549bec36be11000f1ba2a927cef3d1a9875691" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a09e699a94f477303820fb2167024f091543d6240783a2d3b01a3f21c42bc744" +checksum = "b9b194a7870becb1490366fc0ae392ccd188065ff35f8391e77ac659db6fb977" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07732c662a9755529e332d86f8c5842171f6e98ba4d5976a178043dad838654" +checksum = "bb6a4ab44c6b371e661846b97dab687387a60ac4e2f864e2d4257284aad9e889" dependencies = [ "cranelift-entity", + "wasmtime-internal-core", ] [[package]] name = "cranelift-bitset" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18391da761cf362a06def7a7cf11474d79e55801dd34c2e9ba105b33dc0aef88" +checksum = "b8b7a44150c2f471a94023482bda1902710746e4bed9f9973d60c5a94319b06d" dependencies = [ "serde", "serde_derive", + "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b3a09b3042c69810d255aef59ddc3b3e4c0644d1d90ecfd6e3837798cc88a3c" +checksum = "01b06598133b1dd76758b8b95f8d6747c124124aade50cea96a3d88b962da9fa" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -1090,7 +1082,8 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.15.5", + "hashbrown 0.16.1", + "libm", "log", "pulley-interpreter", "regalloc2", @@ -1098,14 +1091,14 @@ dependencies = [ "serde", "smallvec", "target-lexicon 0.13.5", - "wasmtime-internal-math", + "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen-meta" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75817926ec812241889208d1b190cadb7fedded4592a4bb01b8524babb9e4849" +checksum = "6190e2e7bcf0a678da2f715363d34ed530fedf7a2f0ab75edaefef72a70465ff" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -1116,35 +1109,36 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859158f87a59476476eda3884d883c32e08a143cf3d315095533b362a3250a63" +checksum = "f583cf203d1aa8b79560e3b01f929bdacf9070b015eec4ea9c46e22a3f83e4a0" [[package]] name = "cranelift-control" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b65a9aec442d715cbf54d14548b8f395476c09cef7abe03e104a378291ab88" +checksum = "803159df35cc398ae54473c150b16d6c77e92ab2948be638488de126a3328fbc" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334c99a7e86060c24028732efd23bac84585770dcb752329c69f135d64f2fc1" +checksum = "3109e417257082d88087f5bcce677525bdaa8322b88dd7f175ed1a1fd41d546c" dependencies = [ "cranelift-bitset", "serde", "serde_derive", + "wasmtime-internal-core", ] [[package]] name = "cranelift-frontend" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ac6c095aa5b3e845d7ca3461e67e2b65249eb5401477a5ff9100369b745111" +checksum = "14db6b0e0e4994c581092df78d837be2072578f7cb2528f96a6cf895e56dee63" dependencies = [ "cranelift-codegen", "log", @@ -1154,15 +1148,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3d992870ed4f0f2e82e2175275cb3a123a46e9660c6558c46417b822c91fa" +checksum = "ec66ea5025c7317383699778282ac98741d68444f956e3b1d7b62f12b7216e67" [[package]] name = "cranelift-native" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee32e36beaf80f309edb535274cfe0349e1c5cf5799ba2d9f42e828285c6b52e" +checksum = "373ade56438e6232619d85678477d0a88a31b3581936e0503e61e96b546b0800" dependencies = [ "cranelift-codegen", "libc", @@ -1171,9 +1165,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.128.4" +version = "0.130.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903adeaf4938e60209a97b53a2e4326cd2d356aab9764a1934630204bae381c9" +checksum = "ef53619d3cd5c78fd998c6d9420547af26b72e6456f94c2a8a2334cb76b42baa" [[package]] name = "crc32fast" @@ -1901,6 +1895,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.1.9" @@ -2320,11 +2320,12 @@ dependencies = [ [[package]] name = "gimli" -version = "0.32.3" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +checksum = "19e16c5073773ccf057c282be832a59ee53ef5ff98db3aeff7f8314f52ffc196" dependencies = [ - "fallible-iterator", + "fnv", + "hashbrown 0.16.1", "indexmap 2.13.0", "stable_deref_trait", ] @@ -2542,7 +2543,6 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash 0.1.5", - "serde", ] [[package]] @@ -2554,6 +2554,8 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash 0.2.0", + "serde", + "serde_core", ] [[package]] @@ -2716,10 +2718,10 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.37", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower-service", "webpki-roots", ] @@ -3271,10 +3273,10 @@ dependencies = [ "nom 8.0.0", "percent-encoding", "quoted_printable", - "rustls 0.23.37", + "rustls", "socket2 0.6.3", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "url", "webpki-roots", ] @@ -3629,10 +3631,10 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe 0.2.1", + "openssl-probe", "openssl-sys", "schannel", - "security-framework 3.7.0", + "security-framework", "security-framework-sys", "tempfile", ] @@ -3915,12 +3917,12 @@ dependencies = [ [[package]] name = "object" -version = "0.37.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc" dependencies = [ "crc32fast", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "indexmap 2.13.0", "memchr", ] @@ -4160,7 +4162,7 @@ dependencies = [ "openfang-wire", "rand 0.8.5", "reqwest 0.12.28", - "rustls 0.23.37", + "rustls", "serde", "serde_json", "subtle", @@ -4340,12 +4342,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - [[package]] name = "openssl-probe" version = "0.2.1" @@ -4546,7 +4542,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ - "fixedbitset", + "fixedbitset 0.4.2", "indexmap 2.13.0", ] @@ -5030,21 +5026,21 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9812652c1feb63cf39f8780cecac154a32b22b3665806c733cd4072547233a4" +checksum = "010dec3755eb61b2f1051ecb3611b718460b7a74c131e474de2af20a845938af" dependencies = [ "cranelift-bitset", "log", "pulley-macros", - "wasmtime-internal-math", + "wasmtime-internal-core", ] [[package]] name = "pulley-macros" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56000349b6896e3d44286eb9c330891237f40b27fd43c1ccc84547d0b463cb40" +checksum = "ad360c32e85ca4b083ac0e2b6856e8f11c3d5060dafa7d5dc57b370857fa3018" dependencies = [ "proc-macro2", "quote", @@ -5102,7 +5098,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.37", + "rustls", "socket2 0.6.3", "thiserror 2.0.18", "tokio", @@ -5123,7 +5119,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.37", + "rustls", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -5410,9 +5406,9 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.13.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08effbc1fa53aaebff69521a5c05640523fab037b34a4a2c109506bc938246fa" +checksum = "952ddbfc6f9f64d006c3efd8c9851a6ba2f2b944ba94730db255d55006e0ffda" dependencies = [ "allocator-api2", "bumpalo", @@ -5480,14 +5476,14 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.37", + "rustls", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -5521,14 +5517,14 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.37", + "rustls", "rustls-pki-types", "rustls-platform-verifier", "serde", "serde_json", "sync_wrapper", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -5631,20 +5627,23 @@ dependencies = [ [[package]] name = "rumqttc" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1568e15fab2d546f940ed3a21f48bbbd1c494c90c99c4481339364a497f94a9" +checksum = "0feff8d882bff0b2fddaf99355a10336d43dd3ed44204f85ece28cf9626ab519" dependencies = [ "bytes", + "fixedbitset 0.5.7", "flume", "futures-util", "log", - "rustls-native-certs 0.7.3", + "rustls-native-certs", "rustls-pemfile", "rustls-webpki 0.102.8", - "thiserror 1.0.69", + "thiserror 2.0.18", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", + "tokio-stream", + "tokio-util", ] [[package]] @@ -5709,20 +5708,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "rustls" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.8", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.37" @@ -5739,29 +5724,16 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe 0.1.6", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework 2.11.1", -] - [[package]] name = "rustls-native-certs" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe 0.2.1", + "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.7.0", + "security-framework", ] [[package]] @@ -5789,16 +5761,16 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" dependencies = [ - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "jni", "log", "once_cell", - "rustls 0.23.37", - "rustls-native-certs 0.8.3", + "rustls", + "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki 0.103.10", - "security-framework 3.7.0", + "security-framework", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -5920,19 +5892,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.11.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.7.0" @@ -5940,7 +5899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.11.0", - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -6632,7 +6591,7 @@ checksum = "9103edf55f2da3c82aea4c7fab7c4241032bfeea0e71fa557d98e00e7ce7cc20" dependencies = [ "bitflags 2.11.0", "block2", - "core-foundation 0.10.1", + "core-foundation", "core-graphics", "crossbeam-channel", "dispatch2", @@ -6969,7 +6928,7 @@ dependencies = [ "osakit", "percent-encoding", "reqwest 0.13.2", - "rustls 0.23.37", + "rustls", "semver", "serde", "serde_json", @@ -7273,24 +7232,13 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.37", + "rustls", "tokio", ] @@ -7324,11 +7272,11 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls 0.23.37", - "rustls-native-certs 0.8.3", + "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tungstenite 0.24.0", ] @@ -7630,7 +7578,7 @@ dependencies = [ "httparse", "log", "rand 0.8.5", - "rustls 0.23.37", + "rustls", "rustls-pki-types", "sha1", "thiserror 1.0.69", @@ -8009,9 +7957,9 @@ dependencies = [ [[package]] name = "wasm-compose" -version = "0.243.0" +version = "0.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af801b6f36459023eaec63fdbaedad2fd5a4ab7dc74ecc110a8b5d375c5775e4" +checksum = "5fd23d12cc95c451c1306db5bc63075fbebb612bb70c53b4237b1ce5bc178343" dependencies = [ "anyhow", "heck 0.5.0", @@ -8023,21 +7971,11 @@ dependencies = [ "serde_derive", "serde_yaml", "smallvec", - "wasm-encoder 0.243.0", - "wasmparser 0.243.0", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", "wat", ] -[[package]] -name = "wasm-encoder" -version = "0.243.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55db9c896d70bd9fa535ce83cd4e1f2ec3726b0edd2142079f594fc3be1cb35" -dependencies = [ - "leb128fmt", - "wasmparser 0.243.0", -] - [[package]] name = "wasm-encoder" version = "0.244.0" @@ -8096,19 +8034,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.243.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d8db401b0528ec316dfbe579e6ab4152d61739cfe076706d2009127970159d" -dependencies = [ - "bitflags 2.11.0", - "hashbrown 0.15.5", - "indexmap 2.13.0", - "semver", - "serde", -] - [[package]] name = "wasmparser" version = "0.244.0" @@ -8128,29 +8053,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e" dependencies = [ "bitflags 2.11.0", + "hashbrown 0.16.1", "indexmap 2.13.0", "semver", + "serde", ] [[package]] name = "wasmprinter" -version = "0.243.0" +version = "0.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2b6035559e146114c29a909a3232928ee488d6507a1504d8934e8607b36d7b" +checksum = "5f41517a3716fbb8ccf46daa9c1325f760fcbff5168e75c7392288e410b91ac8" dependencies = [ "anyhow", "termcolor", - "wasmparser 0.243.0", + "wasmparser 0.245.1", ] [[package]] name = "wasmtime" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a83182bf04af87571b4c642300479501684f26bab5597f68f68cded5b098fd" +checksum = "ce205cd643d661b5ba5ba4717e13730262e8cdbc8f2eacbc7b906d45c1a74026" dependencies = [ "addr2line", - "anyhow", "async-trait", "bitflags 2.11.0", "bumpalo", @@ -8160,8 +8086,6 @@ dependencies = [ "futures", "fxprof-processed-profile", "gimli", - "hashbrown 0.15.5", - "indexmap 2.13.0", "ittapi", "libc", "log", @@ -8181,18 +8105,17 @@ dependencies = [ "target-lexicon 0.13.5", "tempfile", "wasm-compose", - "wasm-encoder 0.243.0", - "wasmparser 0.243.0", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", "wasmtime-environ", "wasmtime-internal-cache", "wasmtime-internal-component-macro", "wasmtime-internal-component-util", + "wasmtime-internal-core", "wasmtime-internal-cranelift", "wasmtime-internal-fiber", "wasmtime-internal-jit-debug", "wasmtime-internal-jit-icache-coherence", - "wasmtime-internal-math", - "wasmtime-internal-slab", "wasmtime-internal-unwinder", "wasmtime-internal-versioned-export-macros", "wasmtime-internal-winch", @@ -8202,15 +8125,17 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb201c41aa23a3642365cfb2e4a183573d85127a3c9d528f56b9997c984541ab" +checksum = "0b8b78abf3677d4a0a5db82e5015b4d085ff3a1b8b472cbb8c70d4b769f019ce" dependencies = [ "anyhow", "cpp_demangle", + "cranelift-bforest", "cranelift-bitset", "cranelift-entity", "gimli", + "hashbrown 0.16.1", "indexmap 2.13.0", "log", "object", @@ -8219,19 +8144,21 @@ dependencies = [ "semver", "serde", "serde_derive", + "sha2", "smallvec", "target-lexicon 0.13.5", - "wasm-encoder 0.243.0", - "wasmparser 0.243.0", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", "wasmprinter", "wasmtime-internal-component-util", + "wasmtime-internal-core", ] [[package]] name = "wasmtime-internal-cache" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5b3069d1a67ba5969d0eb1ccd7e141367d4e713f4649aa90356c98e8f19bea" +checksum = "8e4fd4103ba413c0da2e636f73490c6c8e446d708cbde7573703941bc3d6a448" dependencies = [ "base64 0.22.1", "directories-next", @@ -8249,9 +8176,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-macro" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c924400db7b6ca996fef1b23beb0f41d5c809836b1ec60fc25b4057e2d25d9b" +checksum = "0d3d6914f34be2f9d78d8ee9f422e834dfc204e71ccce697205fae95fed87892" dependencies = [ "anyhow", "proc-macro2", @@ -8259,20 +8186,32 @@ dependencies = [ "syn 2.0.117", "wasmtime-internal-component-util", "wasmtime-internal-wit-bindgen", - "wit-parser 0.243.0", + "wit-parser 0.245.1", ] [[package]] name = "wasmtime-internal-component-util" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3f65daf4bf3d74ca2fbbe20af0589c42e2b398a073486451425d94fd4afef4" +checksum = "3751b0616b914fdd87fe1bf804694a078f321b000338e6476bc48a4d6e454f21" + +[[package]] +name = "wasmtime-internal-core" +version = "43.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22632b187e1b0716f1b9ac57ad29013bed33175fcb19e10bb6896126f82fac67" +dependencies = [ + "anyhow", + "hashbrown 0.16.1", + "libm", + "serde", +] [[package]] name = "wasmtime-internal-cranelift" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633e889cdae76829738db0114ab3b02fce51ea4a1cd9675a67a65fce92e8b418" +checksum = "8b3ca07b3e0bb3429674b173b5800577719d600774dd81bff58f775c0aaa64ee" dependencies = [ "cfg-if", "cranelift-codegen", @@ -8288,18 +8227,18 @@ dependencies = [ "smallvec", "target-lexicon 0.13.5", "thiserror 2.0.18", - "wasmparser 0.243.0", + "wasmparser 0.245.1", "wasmtime-environ", - "wasmtime-internal-math", + "wasmtime-internal-core", "wasmtime-internal-unwinder", "wasmtime-internal-versioned-export-macros", ] [[package]] name = "wasmtime-internal-fiber" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb126adc5d0c72695cfb77260b357f1b81705a0f8fa30b3944e7c2219c17341" +checksum = "20c8b2c9704eb1f33ead025ec16038277ccb63d0a14c31e99d5b765d7c36da55" dependencies = [ "cc", "cfg-if", @@ -8312,9 +8251,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-debug" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e66ff7f90a8002187691ff6237ffd09f954a0ebb9de8b2ff7f5c62632134120" +checksum = "d950310d07391d34369f62c48336ebb14eacbd4d6f772bb5f349c24e838e0664" dependencies = [ "cc", "object", @@ -8324,36 +8263,21 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b96df23179ae16d54fb3a420f84ffe4383ec9dd06fad3e5bc782f85f66e8e08" +checksum = "3606662c156962d096be3127b8b8ae8ee2f8be3f896dad29259ff01ddb64abfd" dependencies = [ - "anyhow", "cfg-if", "libc", + "wasmtime-internal-core", "windows-sys 0.61.2", ] -[[package]] -name = "wasmtime-internal-math" -version = "41.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d1380926682b44c383e9a67f47e7a95e60c6d3fa8c072294dab2c7de6168a0" -dependencies = [ - "libm", -] - -[[package]] -name = "wasmtime-internal-slab" -version = "41.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b63cbea1c0192c7feb7c0dfb35f47166988a3742f29f46b585ef57246c65764" - [[package]] name = "wasmtime-internal-unwinder" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c392c7e5fb891a7416e3c34cfbd148849271e8c58744fda875dde4bec4d6a" +checksum = "75eef0747e52dc545b075f64fd0e0cc237ae738e641266b1970e07e2d744bc32" dependencies = [ "cfg-if", "cranelift-codegen", @@ -8364,9 +8288,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-versioned-export-macros" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f8b9796a3f0451a7b702508b303d654de640271ac80287176de222f187a237" +checksum = "d8b0a5dab02a8fb527f547855ecc0e05f9fdc3d5bd57b8b080349408f9a6cece" dependencies = [ "proc-macro2", "quote", @@ -8375,16 +8299,16 @@ dependencies = [ [[package]] name = "wasmtime-internal-winch" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0063e61f1d0b2c20e9cfc58361a6513d074a23c80b417aac3033724f51648a0" +checksum = "8007342bd12ff400293a817973f7ecd6f1d9a8549a53369a9c1af357166f1f1e" dependencies = [ "cranelift-codegen", "gimli", "log", "object", "target-lexicon 0.13.5", - "wasmparser 0.243.0", + "wasmparser 0.245.1", "wasmtime-environ", "wasmtime-internal-cranelift", "winch-codegen", @@ -8392,15 +8316,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-wit-bindgen" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "587699ca7cae16b4a234ffcc834f37e75675933d533809919b52975f5609e2ef" +checksum = "7900c3e3c1d6e475bc225d73b02d6d5484815f260022e6964dca9558e50dd01a" dependencies = [ "anyhow", "bitflags 2.11.0", "heck 0.5.0", "indexmap 2.13.0", - "wit-parser 0.243.0", + "wit-parser 0.245.1", ] [[package]] @@ -8588,11 +8512,10 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "41.0.4" +version = "43.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55de3ac5b8bd71e5f6c87a9e511dd3ceb194bdb58183c6a7bf21cd8c0e46fbc" +checksum = "eb9f45f7172a2628c8317766e427babc0a400f9d10b1c0f0b0617c5ed5b79de6" dependencies = [ - "anyhow", "cranelift-assembler-x64", "cranelift-codegen", "gimli", @@ -8600,10 +8523,10 @@ dependencies = [ "smallvec", "target-lexicon 0.13.5", "thiserror 2.0.18", - "wasmparser 0.243.0", + "wasmparser 0.245.1", "wasmtime-environ", + "wasmtime-internal-core", "wasmtime-internal-cranelift", - "wasmtime-internal-math", ] [[package]] @@ -9178,9 +9101,9 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.243.0" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df983a8608e513d8997f435bb74207bf0933d0e49ca97aa9d8a6157164b9b7fc" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", @@ -9191,16 +9114,17 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.243.0", + "wasmparser 0.244.0", ] [[package]] name = "wit-parser" -version = "0.244.0" +version = "0.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929" dependencies = [ "anyhow", + "hashbrown 0.16.1", "id-arena", "indexmap 2.13.0", "log", @@ -9209,7 +9133,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.244.0", + "wasmparser 0.245.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2c41a14138..48ec4d8be4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,7 +83,7 @@ tokio-tungstenite = { version = "0.24", default-features = false, features = ["c url = "2" # WASM sandbox -wasmtime = "41" +wasmtime = "43" # HTTP server (for API daemon) axum = { version = "0.8", features = ["ws", "multipart"] } @@ -147,7 +147,7 @@ native-tls = { version = "0.2", features = ["vendored"] } mailparse = "0.16" # MQTT client -rumqttc = "0.24" +rumqttc = "0.25" # OpenSSL (vendored = statically compiled, no runtime libssl dependency on Linux) openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/openfang-api/src/lib.rs b/crates/openfang-api/src/lib.rs index a4653917aa..243da788b2 100644 --- a/crates/openfang-api/src/lib.rs +++ b/crates/openfang-api/src/lib.rs @@ -11,10 +11,7 @@ pub(crate) fn percent_decode(input: &str) -> String { let mut i = 0; while i < bytes.len() { if bytes[i] == b'%' && i + 2 < bytes.len() { - if let (Some(hi), Some(lo)) = ( - hex_val(bytes[i + 1]), - hex_val(bytes[i + 2]), - ) { + if let (Some(hi), Some(lo)) = (hex_val(bytes[i + 1]), hex_val(bytes[i + 2])) { out.push(hi << 4 | lo); i += 3; continue; diff --git a/crates/openfang-api/src/ws.rs b/crates/openfang-api/src/ws.rs index 9f776ba839..193c689fba 100644 --- a/crates/openfang-api/src/ws.rs +++ b/crates/openfang-api/src/ws.rs @@ -169,7 +169,7 @@ pub async fn agent_ws( let query_auth = uri .query() .and_then(|q| q.split('&').find_map(|pair| pair.strip_prefix("token="))) - .map(|raw| crate::percent_decode(raw)) + .map(crate::percent_decode) .map(|token| ct_eq(&token, api_key)) .unwrap_or(false); diff --git a/crates/openfang-cli/src/main.rs b/crates/openfang-cli/src/main.rs index 5817017c07..8aa4b7f0b2 100644 --- a/crates/openfang-cli/src/main.rs +++ b/crates/openfang-cli/src/main.rs @@ -2466,7 +2466,9 @@ decay_rate = 0.05 if !json { ui::check_ok("GitHub Copilot (authenticated via device flow)"); } - checks.push(serde_json::json!({"check": "provider", "name": "GitHub Copilot", "status": "ok"})); + checks.push( + serde_json::json!({"check": "provider", "name": "GitHub Copilot", "status": "ok"}), + ); } } @@ -4992,7 +4994,9 @@ fn cmd_config_set_key(provider: &str) { ui::error(&format!("Failed to create async runtime: {e}")); std::process::exit(1); }); - match rt.block_on(openfang_runtime::drivers::copilot::run_interactive_setup(&openfang_dir)) { + match rt.block_on(openfang_runtime::drivers::copilot::run_interactive_setup( + &openfang_dir, + )) { Ok(_) => { ui::success("GitHub Copilot configured successfully"); ui::hint("Restart the daemon: openfang stop && openfang start"); diff --git a/crates/openfang-cli/src/tui/screens/init_wizard.rs b/crates/openfang-cli/src/tui/screens/init_wizard.rs index 54071b28e4..7f256082ec 100644 --- a/crates/openfang-cli/src/tui/screens/init_wizard.rs +++ b/crates/openfang-cli/src/tui/screens/init_wizard.rs @@ -312,7 +312,10 @@ enum CopilotAuthStatus { } enum CopilotAuthEvent { - DeviceCode { user_code: String, verification_uri: String }, + DeviceCode { + user_code: String, + verification_uri: String, + }, Authenticated, Models(Vec), } @@ -648,8 +651,7 @@ pub fn run() -> InitResult { let (test_tx, test_rx) = std::sync::mpsc::channel::(); let (migrate_tx, migrate_rx) = std::sync::mpsc::channel::>(); - let (copilot_tx, copilot_rx) = - std::sync::mpsc::channel::>(); + let (copilot_tx, copilot_rx) = std::sync::mpsc::channel::>(); let result = loop { terminal @@ -660,7 +662,10 @@ pub fn run() -> InitResult { if state.step == Step::CopilotAuth { while let Ok(event) = copilot_rx.try_recv() { match event { - Ok(CopilotAuthEvent::DeviceCode { user_code, verification_uri }) => { + Ok(CopilotAuthEvent::DeviceCode { + user_code, + verification_uri, + }) => { state.copilot_user_code = user_code; state.copilot_verification_uri = verification_uri; state.copilot_auth_status = CopilotAuthStatus::WaitingForUser; @@ -839,7 +844,8 @@ pub fn run() -> InitResult { let rt = match tokio::runtime::Runtime::new() { Ok(rt) => rt, Err(e) => { - let _ = copilot_tx.send(Err(format!("Runtime error: {e}"))); + let _ = copilot_tx + .send(Err(format!("Runtime error: {e}"))); return; } }; @@ -851,21 +857,31 @@ pub fn run() -> InitResult { .map_err(|e| format!("HTTP error: {e}")); let http = match http { Ok(h) => h, - Err(e) => { let _ = copilot_tx.send(Err(e)); return; } + Err(e) => { + let _ = copilot_tx.send(Err(e)); + return; + } }; // Step 1: request device code use openfang_runtime::drivers::copilot; - let device = match copilot::request_device_code(&http).await { - Ok(d) => d, - Err(e) => { let _ = copilot_tx.send(Err(e)); return; } - }; + let device = + match copilot::request_device_code(&http).await { + Ok(d) => d, + Err(e) => { + let _ = copilot_tx.send(Err(e)); + return; + } + }; // Send device code to TUI for display - let _ = copilot_tx.send(Ok(CopilotAuthEvent::DeviceCode { - user_code: device.user_code.clone(), - verification_uri: device.verification_uri.clone(), - })); + let _ = + copilot_tx.send(Ok(CopilotAuthEvent::DeviceCode { + user_code: device.user_code.clone(), + verification_uri: device + .verification_uri + .clone(), + })); // Browser will be opened by user pressing Enter in TUI @@ -874,9 +890,14 @@ pub fn run() -> InitResult { &http, &device.device_code, device.interval, - ).await { + ) + .await + { Ok(t) => t, - Err(e) => { let _ = copilot_tx.send(Err(e)); return; } + Err(e) => { + let _ = copilot_tx.send(Err(e)); + return; + } }; // Save tokens @@ -885,16 +906,38 @@ pub fn run() -> InitResult { return; } - let _ = copilot_tx.send(Ok(CopilotAuthEvent::Authenticated)); + let _ = copilot_tx + .send(Ok(CopilotAuthEvent::Authenticated)); // Step 3: fetch models - let ct = match copilot::exchange_copilot_token(&http, &tokens.access_token).await { + let ct = match copilot::exchange_copilot_token( + &http, + &tokens.access_token, + ) + .await + { Ok(ct) => ct, - Err(e) => { let _ = copilot_tx.send(Err(format!("Token exchange: {e}"))); return; } + Err(e) => { + let _ = copilot_tx + .send(Err(format!("Token exchange: {e}"))); + return; + } }; - match copilot::fetch_models(&http, &ct.base_url, &ct.token).await { - Ok(models) => { let _ = copilot_tx.send(Ok(CopilotAuthEvent::Models(models))); } - Err(e) => { let _ = copilot_tx.send(Err(format!("Model fetch: {e}"))); } + match copilot::fetch_models( + &http, + &ct.base_url, + &ct.token, + ) + .await + { + Ok(models) => { + let _ = copilot_tx + .send(Ok(CopilotAuthEvent::Models(models))); + } + Err(e) => { + let _ = copilot_tx + .send(Err(format!("Model fetch: {e}"))); + } } }); }); @@ -924,12 +967,14 @@ pub fn run() -> InitResult { } } KeyCode::Enter => { - if matches!(state.copilot_auth_status, CopilotAuthStatus::WaitingForUser) { - if !state.copilot_verification_uri.is_empty() { - let _ = openfang_runtime::drivers::copilot::open_verification_url( - &state.copilot_verification_uri, - ); - } + if matches!( + state.copilot_auth_status, + CopilotAuthStatus::WaitingForUser + ) && !state.copilot_verification_uri.is_empty() + { + let _ = openfang_runtime::drivers::copilot::open_verification_url( + &state.copilot_verification_uri, + ); } } _ => {} @@ -1956,14 +2001,15 @@ fn draw_copilot_auth(f: &mut Frame, area: Rect, state: &mut State) { Constraint::Length(1), // code value Constraint::Length(1), // blank Constraint::Length(1), // url - Constraint::Min(0), // spacer + Constraint::Min(0), // spacer Constraint::Length(1), // hint ]) .split(area); - let title = Paragraph::new(Line::from(vec![ - Span::styled(" GitHub Copilot Authentication", Style::default().fg(theme::ACCENT)), - ])); + let title = Paragraph::new(Line::from(vec![Span::styled( + " GitHub Copilot Authentication", + Style::default().fg(theme::ACCENT), + )])); f.render_widget(title, chunks[0]); let spinner = theme::SPINNER_FRAMES[state.tick % theme::SPINNER_FRAMES.len()]; @@ -1985,9 +2031,7 @@ fn draw_copilot_auth(f: &mut Frame, area: Rect, state: &mut State) { ])); f.render_widget(line1, chunks[2]); - let code_label = Paragraph::new(Line::from(vec![ - Span::raw(" Enter this code:"), - ])); + let code_label = Paragraph::new(Line::from(vec![Span::raw(" Enter this code:")])); f.render_widget(code_label, chunks[5]); let code_value = Paragraph::new(Line::from(vec![ @@ -2007,9 +2051,10 @@ fn draw_copilot_auth(f: &mut Frame, area: Rect, state: &mut State) { ])); f.render_widget(url, chunks[8]); - let hint = Paragraph::new(Line::from(vec![ - Span::styled(" [Enter] Open browser", theme::dim_style()), - ])); + let hint = Paragraph::new(Line::from(vec![Span::styled( + " [Enter] Open browser", + theme::dim_style(), + )])); f.render_widget(hint, chunks[10]); } CopilotAuthStatus::FetchingModels => { @@ -2040,9 +2085,10 @@ fn draw_copilot_auth(f: &mut Frame, area: Rect, state: &mut State) { ])); f.render_widget(line, chunks[2]); - let hint = Paragraph::new(Line::from(vec![ - Span::styled(" Esc to go back", theme::dim_style()), - ])); + let hint = Paragraph::new(Line::from(vec![Span::styled( + " Esc to go back", + theme::dim_style(), + )])); f.render_widget(hint, chunks[10]); } } diff --git a/crates/openfang-kernel/src/kernel.rs b/crates/openfang-kernel/src/kernel.rs index 599541ee9f..e126104003 100644 --- a/crates/openfang-kernel/src/kernel.rs +++ b/crates/openfang-kernel/src/kernel.rs @@ -514,7 +514,7 @@ impl OpenFangKernel { fn fetch_copilot_models(openfang_dir: &Path) -> Result, String> { use openfang_runtime::drivers::copilot; - let tokens = copilot::PersistedTokens::load(&openfang_dir.to_path_buf()) + let tokens = copilot::PersistedTokens::load(openfang_dir) .ok_or("No persisted Copilot tokens found")?; let fetch = async { @@ -531,9 +531,9 @@ impl OpenFangKernel { // Otherwise (CLI commands), create a new one. if let Ok(handle) = tokio::runtime::Handle::try_current() { std::thread::scope(|s| { - s.spawn(|| { - handle.block_on(fetch) - }).join().unwrap_or(Err("Thread panicked".to_string())) + s.spawn(|| handle.block_on(fetch)) + .join() + .unwrap_or(Err("Thread panicked".to_string())) }) } else { let rt = tokio::runtime::Runtime::new() diff --git a/crates/openfang-runtime/src/compactor.rs b/crates/openfang-runtime/src/compactor.rs index de120f21d9..fef90c8154 100644 --- a/crates/openfang-runtime/src/compactor.rs +++ b/crates/openfang-runtime/src/compactor.rs @@ -435,10 +435,10 @@ async fn summarize_messages( let safe_start = if conversation_text.is_char_boundary(start) { start } else { - // Find the nearest valid character boundary moving upward - (start..conversation_text.len()) - .find(|&i| conversation_text.is_char_boundary(i)) - .unwrap_or(conversation_text.len()) + // Find the nearest valid character boundary moving upward + (start..conversation_text.len()) + .find(|&i| conversation_text.is_char_boundary(i)) + .unwrap_or(conversation_text.len()) }; conversation_text = conversation_text[safe_start..].to_string(); } diff --git a/crates/openfang-runtime/src/drivers/copilot.rs b/crates/openfang-runtime/src/drivers/copilot.rs index 8df53c64e4..f042360517 100644 --- a/crates/openfang-runtime/src/drivers/copilot.rs +++ b/crates/openfang-runtime/src/drivers/copilot.rs @@ -10,7 +10,7 @@ //! `config.toml`. The driver handles the rest — device flow, token persistence, //! refresh, and Copilot API token exchange — automatically. -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::Mutex; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; @@ -55,6 +55,8 @@ const OAUTH_SCOPES: &str = "copilot"; const TOKEN_FILE_NAME: &str = ".copilot-tokens.json"; /// Device flow polling interval (seconds) — GitHub default is 5. +// NOTE: not fixing unused warning — expected to be wired up in a future commit +#[allow(dead_code)] const DEVICE_FLOW_POLL_INTERVAL: Duration = Duration::from_secs(5); /// Maximum time to wait for user to authorize the device flow. @@ -83,14 +85,14 @@ impl PersistedTokens { } /// Load from the OpenFang data directory. - pub fn load(openfang_dir: &PathBuf) -> Option { + pub fn load(openfang_dir: &Path) -> Option { let path = openfang_dir.join(TOKEN_FILE_NAME); let data = std::fs::read_to_string(&path).ok()?; serde_json::from_str(&data).ok() } /// Persist to the OpenFang data directory with restricted permissions. - pub fn save(&self, openfang_dir: &PathBuf) -> Result<(), String> { + pub fn save(&self, openfang_dir: &Path) -> Result<(), String> { let path = openfang_dir.join(TOKEN_FILE_NAME); let json = serde_json::to_string_pretty(self) .map_err(|e| format!("Failed to serialize tokens: {e}"))?; @@ -138,6 +140,8 @@ impl CachedCopilotToken { #[derive(Clone)] struct CachedModels { models: Vec, + // NOTE: not fixing unused warning — expected to be read in a future commit + #[allow(dead_code)] fetched_at: Instant, } @@ -168,6 +172,8 @@ struct OAuthTokenResponse { refresh_token: Option, #[serde(default)] expires_in: Option, + // NOTE: not fixing unused warning — expected to be read in a future commit + #[allow(dead_code)] #[serde(default)] refresh_token_expires_in: Option, #[serde(default)] @@ -177,9 +183,7 @@ struct OAuthTokenResponse { } /// Request a device code from GitHub using the Copilot client ID. -pub async fn request_device_code( - client: &reqwest::Client, -) -> Result { +pub async fn request_device_code(client: &reqwest::Client) -> Result { let resp = client .post(GITHUB_DEVICE_CODE_URL) .header("Accept", "application/json") @@ -259,9 +263,7 @@ pub async fn poll_for_token( let access_token = token_resp .access_token .ok_or("Missing access_token in response")?; - let refresh_token = token_resp - .refresh_token - .unwrap_or_default(); // Empty if token expiration is disabled on the OAuth App + let refresh_token = token_resp.refresh_token.unwrap_or_default(); // Empty if token expiration is disabled on the OAuth App let expires_in = token_resp.expires_in.unwrap_or(0); // 0 = non-expiring return Ok(PersistedTokens { @@ -361,7 +363,7 @@ pub async fn exchange_copilot_token( .ok_or("Missing 'token' field in Copilot response")?; let expires_at_unix = body.get("expires_at").and_then(|v| v.as_i64()).unwrap_or(0); - let ttl_secs = (expires_at_unix - unix_now() as i64).max(60) as u64; + let ttl_secs = (expires_at_unix - unix_now()).max(60) as u64; // Extract base URL from endpoints.api or proxy-ep in the token. let base_url = body @@ -444,7 +446,11 @@ pub async fn fetch_models( .and_then(|v| v.as_array()) .map(|arr| { arr.iter() - .filter_map(|m| m.get("id").and_then(|id| id.as_str()).map(|s| s.to_string())) + .filter_map(|m| { + m.get("id") + .and_then(|id| id.as_str()) + .map(|s| s.to_string()) + }) .collect() }) .unwrap_or_default(); @@ -514,12 +520,7 @@ impl CopilotDriver { }; if let Some(ref rt) = refresh_token { - match refresh_access_token( - &self.http_client, - rt, - ) - .await - { + match refresh_access_token(&self.http_client, rt).await { Ok(new_tokens) => { info!("Copilot access token refreshed successfully"); if let Err(e) = new_tokens.save(&self.openfang_dir) { @@ -547,8 +548,9 @@ impl CopilotDriver { } /// Ensure we have a valid Copilot API token (tid=…). - async fn ensure_copilot_token(&self) -> Result - { + async fn ensure_copilot_token( + &self, + ) -> Result { // Check cache. { let lock = self.copilot_token.lock().unwrap_or_else(|e| e.into_inner()); @@ -595,13 +597,16 @@ impl CopilotDriver { &self, copilot_token: &CachedCopilotToken, ) -> Result, crate::llm_driver::LlmError> { - let models = - fetch_models(&self.http_client, &copilot_token.base_url, &copilot_token.token) - .await - .map_err(|e| crate::llm_driver::LlmError::Api { - status: 500, - message: format!("Failed to fetch model list: {e}"), - })?; + let models = fetch_models( + &self.http_client, + &copilot_token.base_url, + &copilot_token.token, + ) + .await + .map_err(|e| crate::llm_driver::LlmError::Api { + status: 500, + message: format!("Failed to fetch model list: {e}"), + })?; let mut lock = self.models.lock().unwrap_or_else(|e| e.into_inner()); *lock = Some(CachedModels { @@ -638,10 +643,7 @@ impl CopilotDriver { execute: F, ) -> Result where - F: Fn( - super::openai::OpenAIDriver, - crate::llm_driver::CompletionRequest, - ) -> Fut, + F: Fn(super::openai::OpenAIDriver, crate::llm_driver::CompletionRequest) -> Fut, Fut: std::future::Future< Output = Result, >, @@ -652,9 +654,10 @@ impl CopilotDriver { match execute(driver, request.clone()).await { Ok(resp) => Ok(resp), - Err(crate::llm_driver::LlmError::Api { status, ref message }) - if status == 400 && message.contains("model_not_supported") => - { + Err(crate::llm_driver::LlmError::Api { + status, + ref message, + }) if status == 400 && message.contains("model_not_supported") => { // Refresh model list so subsequent calls have updated info. warn!( model = %request.model, @@ -683,9 +686,10 @@ impl crate::llm_driver::LlmDriver for CopilotDriver { &self, request: crate::llm_driver::CompletionRequest, ) -> Result { - self.execute_with_model_retry(request, |driver, req| async move { - driver.complete(req).await - }) + self.execute_with_model_retry( + request, + |driver, req| async move { driver.complete(req).await }, + ) .await } @@ -700,9 +704,10 @@ impl crate::llm_driver::LlmDriver for CopilotDriver { match driver.stream(request.clone(), tx.clone()).await { Ok(resp) => Ok(resp), - Err(crate::llm_driver::LlmError::Api { status, ref message }) - if status == 400 && message.contains("model_not_supported") => - { + Err(crate::llm_driver::LlmError::Api { + status, + ref message, + }) if status == 400 && message.contains("model_not_supported") => { warn!( model = %request.model, "Model not supported — refreshing model catalog" @@ -732,9 +737,7 @@ impl crate::llm_driver::LlmDriver for CopilotDriver { /// /// Called from `openfang config set-key github-copilot`, `openfang init`, /// `openfang onboard`, and `openfang configure`. -pub async fn run_interactive_setup( - openfang_dir: &PathBuf, -) -> Result { +pub async fn run_interactive_setup(openfang_dir: &Path) -> Result { run_device_flow(openfang_dir).await } @@ -742,9 +745,7 @@ pub async fn run_interactive_setup( /// /// Prints the user code and verification URL, attempts to open the browser, /// then polls until the user authorizes. -pub async fn run_device_flow( - openfang_dir: &PathBuf, -) -> Result { +pub async fn run_device_flow(openfang_dir: &Path) -> Result { let client = reqwest::Client::builder() .timeout(Duration::from_secs(30)) .build() @@ -767,12 +768,7 @@ pub async fn run_device_flow( println!(" Waiting for authorization..."); // Step 3: Poll for authorization. - let tokens = poll_for_token( - &client, - &device.device_code, - device.interval, - ) - .await?; + let tokens = poll_for_token(&client, &device.device_code, device.interval).await?; // Step 4: Persist. tokens.save(openfang_dir)?; @@ -782,6 +778,8 @@ pub async fn run_device_flow( } /// Read a line from stdin with a prompt. Used during interactive setup. +// NOTE: not fixing unused warning — expected to be called in a future commit +#[allow(dead_code)] fn prompt_line(prompt: &str) -> Result { use std::io::{self, BufRead, Write}; print!("{prompt}"); @@ -825,7 +823,7 @@ pub fn open_verification_url(url: &str) -> bool { } /// Check if Copilot OAuth tokens exist on disk. -pub fn copilot_auth_available(openfang_dir: &PathBuf) -> bool { +pub fn copilot_auth_available(openfang_dir: &Path) -> bool { openfang_dir.join(TOKEN_FILE_NAME).exists() } diff --git a/crates/openfang-runtime/src/drivers/mod.rs b/crates/openfang-runtime/src/drivers/mod.rs index b69ca82b0b..50359216f8 100644 --- a/crates/openfang-runtime/src/drivers/mod.rs +++ b/crates/openfang-runtime/src/drivers/mod.rs @@ -19,7 +19,7 @@ use openfang_types::model_catalog::{ AI21_BASE_URL, ANTHROPIC_BASE_URL, AZURE_OPENAI_BASE_URL, CEREBRAS_BASE_URL, CHUTES_BASE_URL, COHERE_BASE_URL, DEEPSEEK_BASE_URL, FIREWORKS_BASE_URL, GEMINI_BASE_URL, GROQ_BASE_URL, HUGGINGFACE_BASE_URL, KIMI_CODING_BASE_URL, LEMONADE_BASE_URL, LMSTUDIO_BASE_URL, - MINIMAX_BASE_URL, MISTRAL_BASE_URL, MOONSHOT_BASE_URL, NVIDIA_NIM_BASE_URL, NOVITA_BASE_URL, + MINIMAX_BASE_URL, MISTRAL_BASE_URL, MOONSHOT_BASE_URL, NOVITA_BASE_URL, NVIDIA_NIM_BASE_URL, OLLAMA_BASE_URL, OPENAI_BASE_URL, OPENROUTER_BASE_URL, PERPLEXITY_BASE_URL, QIANFAN_BASE_URL, QWEN_BASE_URL, REPLICATE_BASE_URL, SAMBANOVA_BASE_URL, TOGETHER_BASE_URL, VENICE_BASE_URL, VLLM_BASE_URL, VOLCENGINE_BASE_URL, VOLCENGINE_CODING_BASE_URL, XAI_BASE_URL, ZAI_BASE_URL, diff --git a/crates/openfang-runtime/src/drivers/openai.rs b/crates/openfang-runtime/src/drivers/openai.rs index 2d9f63a256..2c3edc8cd2 100644 --- a/crates/openfang-runtime/src/drivers/openai.rs +++ b/crates/openfang-runtime/src/drivers/openai.rs @@ -276,7 +276,7 @@ struct OaiUsage { /// Strip trailing empty assistant messages without tool calls. /// Some API proxies reject empty assistant messages as "prefill". fn strip_trailing_empty_assistant(messages: &mut Vec) { - while messages.last().map_or(false, |m| { + while messages.last().is_some_and(|m| { m.role == "assistant" && m.tool_calls.is_none() && match &m.content { diff --git a/crates/openfang-runtime/src/sandbox.rs b/crates/openfang-runtime/src/sandbox.rs index b20afac612..1694a0157b 100644 --- a/crates/openfang-runtime/src/sandbox.rs +++ b/crates/openfang-runtime/src/sandbox.rs @@ -286,18 +286,18 @@ impl WasmSandbox { |mut caller: Caller<'_, GuestState>, request_ptr: i32, request_len: i32| - -> Result { + -> Result { // Read request from guest memory let memory = caller .get_export("memory") .and_then(|e| e.into_memory()) - .ok_or_else(|| anyhow::anyhow!("no memory export"))?; + .ok_or_else(|| format_err!("no memory export"))?; let data = memory.data(&caller); let start = request_ptr as usize; let end = start + request_len as usize; if end > data.len() { - anyhow::bail!("host_call: request out of bounds"); + bail!("host_call: request out of bounds"); } let request_bytes = data[start..end].to_vec(); @@ -324,7 +324,7 @@ impl WasmSandbox { let alloc_fn = caller .get_export("alloc") .and_then(|e| e.into_func()) - .ok_or_else(|| anyhow::anyhow!("no alloc export"))?; + .ok_or_else(|| format_err!("no alloc export"))?; let alloc_typed = alloc_fn.typed::(&caller)?; let ptr = alloc_typed.call(&mut caller, len)?; @@ -332,12 +332,12 @@ impl WasmSandbox { let memory = caller .get_export("memory") .and_then(|e| e.into_memory()) - .ok_or_else(|| anyhow::anyhow!("no memory export"))?; + .ok_or_else(|| format_err!("no memory export"))?; let mem_data = memory.data_mut(&mut caller); let dest_start = ptr as usize; let dest_end = dest_start + response_bytes.len(); if dest_end > mem_data.len() { - anyhow::bail!("host_call: response exceeds memory bounds"); + bail!("host_call: response exceeds memory bounds"); } mem_data[dest_start..dest_end].copy_from_slice(&response_bytes); @@ -356,17 +356,17 @@ impl WasmSandbox { level: i32, msg_ptr: i32, msg_len: i32| - -> Result<(), anyhow::Error> { + -> Result<()> { let memory = caller .get_export("memory") .and_then(|e| e.into_memory()) - .ok_or_else(|| anyhow::anyhow!("no memory export"))?; + .ok_or_else(|| format_err!("no memory export"))?; let data = memory.data(&caller); let start = msg_ptr as usize; let end = start + msg_len as usize; if end > data.len() { - anyhow::bail!("host_log: pointer out of bounds"); + bail!("host_log: pointer out of bounds"); } let msg = std::str::from_utf8(&data[start..end]).unwrap_or(""); let agent_id = &caller.data().agent_id; diff --git a/crates/openfang-runtime/src/subprocess_sandbox.rs b/crates/openfang-runtime/src/subprocess_sandbox.rs index 54b754304f..7d6fd249fe 100644 --- a/crates/openfang-runtime/src/subprocess_sandbox.rs +++ b/crates/openfang-runtime/src/subprocess_sandbox.rs @@ -192,13 +192,13 @@ fn extract_shell_wrapper_commands(command: &str) -> Vec { let base_lower = base.to_lowercase(); // Also strip .exe suffix for Windows let base_normalized = base_lower.strip_suffix(".exe").unwrap_or(&base_lower); - if !SHELL_WRAPPERS.iter().any(|w| *w == base_normalized) { + if !SHELL_WRAPPERS.contains(&base_normalized) { return Vec::new(); } // Find the inline flag and extract everything after it for (wrappers, flag) in SHELL_INLINE_FLAGS { - if !wrappers.iter().any(|w| *w == base_normalized) { + if !wrappers.contains(&base_normalized) { continue; } // Search for the flag in the command args (case-insensitive for PowerShell) @@ -1089,10 +1089,7 @@ mod tests { allowed_commands: vec!["powershell".to_string(), "Get-Process".to_string()], ..ExecPolicy::default() }; - let result = validate_command_allowlist( - r#"powershell -Command "Get-Process""#, - &policy, - ); + let result = validate_command_allowlist(r#"powershell -Command "Get-Process""#, &policy); assert!( result.is_ok(), "Get-Process should be allowed when in allowed_commands" @@ -1106,10 +1103,8 @@ mod tests { allowed_commands: vec!["cmd".to_string()], ..ExecPolicy::default() }; - let result = validate_command_allowlist( - r#"cmd /C "del /F /Q C:\temp\secret.txt""#, - &policy, - ); + let result = + validate_command_allowlist(r#"cmd /C "del /F /Q C:\temp\secret.txt""#, &policy); assert!( result.is_err(), "del inside cmd /C must be blocked when not in allowlist" @@ -1123,10 +1118,7 @@ mod tests { allowed_commands: vec!["bash".to_string()], ..ExecPolicy::default() }; - let result = validate_command_allowlist( - r#"bash -c "curl https://evil.com""#, - &policy, - ); + let result = validate_command_allowlist(r#"bash -c "curl https://evil.com""#, &policy); assert!( result.is_err(), "curl inside bash -c must be blocked when not in allowlist" @@ -1141,10 +1133,7 @@ mod tests { ..ExecPolicy::default() }; // "echo" is in safe_bins by default - let result = validate_command_allowlist( - r#"bash -c "echo hello""#, - &policy, - ); + let result = validate_command_allowlist(r#"bash -c "echo hello""#, &policy); assert!( result.is_ok(), "echo inside bash -c should be allowed (echo is in safe_bins)" diff --git a/crates/openfang-types/src/tool.rs b/crates/openfang-types/src/tool.rs index 200d6b3ddd..9943a106be 100644 --- a/crates/openfang-types/src/tool.rs +++ b/crates/openfang-types/src/tool.rs @@ -173,13 +173,9 @@ fn normalize_schema_recursive(schema: &serde_json::Value) -> serde_json::Value { // JSON Schema allows arrays without `items`, but the Gemini API rejects // such schemas with INVALID_ARGUMENT. Inject a default string items schema // so MCP tools (and any other source) don't break Gemini requests. - if result.get("type").and_then(|t| t.as_str()) == Some("array") - && !result.contains_key("items") + if result.get("type").and_then(|t| t.as_str()) == Some("array") && !result.contains_key("items") { - result.insert( - "items".to_string(), - serde_json::json!({"type": "string"}), - ); + result.insert("items".to_string(), serde_json::json!({"type": "string"})); } serde_json::Value::Object(result)