diff --git a/Cargo.lock b/Cargo.lock index c08d0d1282..8d592125b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,9 +284,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.16.3" +version = "1.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" dependencies = [ "aws-lc-sys", "untrusted 0.7.1", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.40.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" dependencies = [ "cc", "cmake", @@ -920,7 +920,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -953,9 +953,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.4" +version = "4.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e962dae2b1e5007fe9e3db363ddc43a8bf25546d279f7a8a4401204690e80c" +checksum = "660c0520455b1013b9bcb0393d5f643d7e4454fb69c915b8d6d2aa0e9a45acc3" dependencies = [ "clap", ] @@ -1023,7 +1023,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -1776,7 +1776,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1949,7 +1949,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2217,7 +2217,7 @@ dependencies = [ "merge", "pretty_assertions", "regex", - "reqwest 0.12.28", + "reqwest 0.13.3", "schemars 1.2.1", "serde", "serde_json", @@ -2350,7 +2350,7 @@ dependencies = [ "nom", "pin-project-lite", "pin-utils", - "reqwest 0.12.28", + "reqwest 0.13.3", "rocket", "thiserror 2.0.18", "tokio", @@ -2410,6 +2410,7 @@ dependencies = [ "forge_domain", "forge_eventsource", "forge_fs", + "forge_reqwest", "forge_select", "forge_services", "forge_snaps", @@ -2422,7 +2423,7 @@ dependencies = [ "oauth2", "open", "pretty_assertions", - "reqwest 0.12.28", + "reqwest 0.13.3", "rmcp", "schemars 1.2.1", "serde", @@ -2583,7 +2584,7 @@ dependencies = [ "prost", "prost-types", "regex", - "reqwest 0.12.28", + "reqwest 0.13.3", "schemars 1.2.1", "serde", "serde_json", @@ -2600,6 +2601,14 @@ dependencies = [ "url", ] +[[package]] +name = "forge_reqwest" +version = "0.1.0" +dependencies = [ + "reqwest 0.13.3", + "webpki-root-certs", +] + [[package]] name = "forge_select" version = "0.1.0" @@ -2639,6 +2648,7 @@ dependencies = [ "forge_domain", "forge_eventsource", "forge_fs", + "forge_reqwest", "forge_snaps", "forge_stream", "forge_test_kit", @@ -2658,7 +2668,7 @@ dependencies = [ "oauth2", "pretty_assertions", "regex", - "reqwest 0.12.28", + "reqwest 0.13.3", "serde", "serde_json", "serde_urlencoded", @@ -2753,13 +2763,14 @@ dependencies = [ "derive_more", "dirs", "forge_domain", + "forge_reqwest", "http 1.4.0", "lazy_static", "machineid-rs", "posthog-rs", "pretty_assertions", "regex", - "reqwest 0.12.28", + "reqwest 0.13.3", "serde", "serde_json", "sysinfo 0.38.4", @@ -2944,7 +2955,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix 1.1.4", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -3971,9 +3982,9 @@ dependencies = [ [[package]] name = "google-cloud-auth" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd4f8c914f230834828771125168eaa39bc6602e32cb0316ceeff2add10d449" +checksum = "54a26c047222f874ea87177368ad07c65a9f66534ad3a3f9401f1322c802ccac" dependencies = [ "async-trait", "aws-lc-rs", @@ -4000,9 +4011,9 @@ dependencies = [ [[package]] name = "google-cloud-gax" -version = "1.10.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d597e9e4758fc778a60d8c28a8677629675ae40d8652ec000ae5f53f5ae7ec" +checksum = "7dc387965cc2efc28d73896d6707125815c16792c23c33a0c67794f3d6e31cc8" dependencies = [ "base64 0.22.1", "bytes", @@ -4020,9 +4031,9 @@ dependencies = [ [[package]] name = "google-cloud-rpc" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b177796075b7bfc02bf2e405db665ee850a924fa44cedfc5282b473c5ab203" +checksum = "7e3b123ea17ff20539fbdf145e6213e0464cc0a30b0d078a68bf90405ef17fb7" dependencies = [ "bytes", "google-cloud-wkt", @@ -4033,9 +4044,9 @@ dependencies = [ [[package]] name = "google-cloud-wkt" -version = "1.4.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5daa3084991800bcc5333d7e77bb19259a02b34ee35f35c27b49d602732306e" +checksum = "0b30ccefdb9276269bb0336afe207c5e0ba1a544a5eb0034763af051f2b9eb63" dependencies = [ "base64 0.22.1", "bytes", @@ -4562,7 +4573,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.3", "tokio", "tower-service", "tracing", @@ -4580,7 +4591,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core", ] [[package]] @@ -4839,7 +4850,7 @@ dependencies = [ "socket2 0.6.3", "widestring", "windows-registry", - "windows-result 0.4.1", + "windows-result", "windows-sys 0.61.2", ] @@ -4876,7 +4887,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4910,6 +4921,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -4928,7 +4948,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5548,18 +5568,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.11.0", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nix" version = "0.31.2" @@ -5602,7 +5610,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5710,7 +5718,6 @@ dependencies = [ "getrandom 0.2.17", "http 1.4.0", "rand 0.8.5", - "reqwest 0.12.28", "serde", "serde_json", "serde_path_to_error", @@ -5946,7 +5953,7 @@ dependencies = [ "libc", "redox_syscall 0.5.18", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -6288,16 +6295,16 @@ dependencies = [ [[package]] name = "process-wrap" -version = "8.2.1" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ef4f2f0422f23a82ec9f628ea2acd12871c81a9362b02c43c1aa86acfc3ba1" +checksum = "2e842efad9119158434d193c6682e2ebee4b44d6ad801d7b349623b3f57cdf55" dependencies = [ "futures", "indexmap 2.14.0", - "nix 0.30.1", + "nix", "tokio", "tracing", - "windows 0.61.3", + "windows 0.62.2", ] [[package]] @@ -6328,7 +6335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" dependencies = [ "heck", - "itertools", + "itertools 0.14.0", "log", "multimap", "petgraph", @@ -6349,7 +6356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", - "itertools", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -6418,7 +6425,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls 0.23.40", - "socket2 0.5.10", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -6456,7 +6463,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.3", "tracing", "windows-sys 0.59.0", ] @@ -6648,7 +6655,7 @@ dependencies = [ "chrono", "crossterm 0.29.0", "fd-lock", - "itertools", + "itertools 0.13.0", "nu-ansi-term", "serde", "strip-ansi-escapes", @@ -6763,7 +6770,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", "winreg 0.50.0", ] @@ -6779,8 +6786,6 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.13", - "hickory-resolver", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -6789,7 +6794,6 @@ dependencies = [ "hyper-util", "js-sys", "log", - "once_cell", "percent-encoding", "pin-project-lite", "quinn", @@ -6801,14 +6805,12 @@ dependencies = [ "sync_wrapper 1.0.2", "tokio", "tokio-rustls 0.26.4", - "tokio-util", "tower", "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", "web-sys", "webpki-roots", ] @@ -6824,6 +6826,8 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2 0.4.13", + "hickory-resolver", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -6832,6 +6836,7 @@ dependencies = [ "hyper-util", "js-sys", "log", + "once_cell", "percent-encoding", "pin-project-lite", "quinn", @@ -6844,12 +6849,14 @@ dependencies = [ "sync_wrapper 1.0.2", "tokio", "tokio-rustls 0.26.4", + "tokio-util", "tower", "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams 0.5.0", "web-sys", ] @@ -6875,9 +6882,9 @@ dependencies = [ [[package]] name = "rmcp" -version = "0.10.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b18323edc657390a6ed4d7a9110b0dec2dc3ed128eb2a123edfbafabdbddc5" +checksum = "67d69668de0b0ccd9cc435f700f3b39a7861863cf37a15e1f304ea78688a4826" dependencies = [ "async-trait", "base64 0.22.1", @@ -6888,7 +6895,7 @@ dependencies = [ "pastey", "pin-project-lite", "process-wrap", - "reqwest 0.12.28", + "reqwest 0.13.3", "rmcp-macros", "schemars 1.2.1", "serde", @@ -6904,11 +6911,11 @@ dependencies = [ [[package]] name = "rmcp-macros" -version = "0.10.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75d0a62676bf8c8003c4e3c348e2ceb6a7b3e48323681aaf177fdccdac2ce50" +checksum = "48fdc01c81097b0aed18633e676e269fefa3a78ec1df56b4fe597c1241b92025" dependencies = [ - "darling 0.21.3", + "darling 0.23.0", "proc-macro2", "quote", "serde_json", @@ -7068,7 +7075,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -7148,7 +7155,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -7198,7 +7205,7 @@ dependencies = [ "libc", "log", "memchr", - "nix 0.31.2", + "nix", "radix_trie", "unicode-segmentation", "unicode-width 0.2.2", @@ -8101,7 +8108,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -8164,7 +8171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix 1.1.4", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -8309,9 +8316,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.3" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -8506,9 +8513,9 @@ checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" -version = "0.14.6" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" dependencies = [ "async-trait", "axum", @@ -8537,9 +8544,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.6" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" +checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" dependencies = [ "prettyplease", "proc-macro2", @@ -8549,9 +8556,9 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.6" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" dependencies = [ "bytes", "prost", @@ -8560,9 +8567,9 @@ dependencies = [ [[package]] name = "tonic-prost-build" -version = "0.14.6" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" +checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" dependencies = [ "prettyplease", "proc-macro2", @@ -9145,6 +9152,19 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasmparser" version = "0.244.0" @@ -9253,7 +9273,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -9273,38 +9293,16 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections 0.2.0", - "windows-core 0.61.2", - "windows-future 0.2.1", - "windows-link 0.1.3", - "windows-numerics 0.2.0", -] - [[package]] name = "windows" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-collections 0.3.2", - "windows-core 0.62.2", - "windows-future 0.3.2", - "windows-numerics 0.3.1", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", ] [[package]] @@ -9313,20 +9311,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-core 0.62.2", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement 0.60.2", - "windows-interface 0.59.3", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-core", ] [[package]] @@ -9337,20 +9322,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement 0.60.2", "windows-interface 0.59.3", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading 0.1.0", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -9359,9 +9333,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", - "windows-threading 0.2.1", + "windows-core", + "windows-link", + "windows-threading", ] [[package]] @@ -9408,36 +9382,20 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] - [[package]] name = "windows-numerics" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", + "windows-core", + "windows-link", ] [[package]] @@ -9446,18 +9404,9 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -9466,16 +9415,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -9484,7 +9424,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -9529,7 +9469,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -9578,22 +9518,13 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-threading" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 208aa18735..574a7a5c6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,13 +66,14 @@ quote = "1.0" reedline = "0.47.0" rustyline = "18.0.0" regex = "1.12.3" -reqwest = { version = "0.12.23", features = [ +reqwest = { version = "0.13.3", features = [ "json", - "rustls-tls", + "rustls", "hickory-dns", "http2", ], default-features = false } rustls = { version = "0.23", features = ["ring"], default-features = false } +webpki-root-certs = "1.0" include_dir = "0.7.4" schemars = "1.2" serde = { version = "1.0.217", features = ["derive"] } @@ -121,9 +122,8 @@ whoami = "2.1.0" fnv_rs = "0.4.3" merge = { version = "0.2", features = ["derive"] } hex = "0.4.3" -rmcp = { version = "0.10.0", features = [ +rmcp = { version = "1.5", features = [ "client", - "transport-sse-client-reqwest", "transport-child-process", "transport-streamable-http-client-reqwest", "auth", @@ -166,3 +166,4 @@ forge_markdown_stream = { path = "crates/forge_markdown_stream" } forge_config = { path = "crates/forge_config" } forge_eventsource = { path = "crates/forge_eventsource" } forge_eventsource_stream = { path = "crates/forge_eventsource_stream" } +forge_reqwest = { path = "crates/forge_reqwest" } diff --git a/crates/forge_eventsource/Cargo.toml b/crates/forge_eventsource/Cargo.toml index 4f1aad9d8f..efef78ebba 100644 --- a/crates/forge_eventsource/Cargo.toml +++ b/crates/forge_eventsource/Cargo.toml @@ -6,7 +6,7 @@ rust-version.workspace = true [dependencies] forge_eventsource_stream.workspace = true -reqwest = { version = "0.12.0", default-features = false, features = ["stream"] } +reqwest = { workspace = true, features = ["stream"] } futures-core = "0.3.5" pin-project-lite = "0.2.8" nom = "8.0.0" diff --git a/crates/forge_infra/Cargo.toml b/crates/forge_infra/Cargo.toml index f907fa33db..c87b31ff8a 100644 --- a/crates/forge_infra/Cargo.toml +++ b/crates/forge_infra/Cargo.toml @@ -33,6 +33,7 @@ forge_walker.workspace = true forge_eventsource.workspace = true +forge_reqwest.workspace = true glob.workspace = true futures.workspace = true diesel = { version= "2.3.7", features = ["sqlite", "r2d2", "chrono"] } @@ -41,7 +42,7 @@ diesel_migrations = "2.2.0" chrono = { version = "0.4", features = ["serde"] } cacache = { version = "13.1.0", features = ["tokio-runtime"], default-features = false } serde.workspace = true -oauth2 = { version = "5.0", features = ["reqwest"] } +oauth2 = { version = "5.0", default-features = false } serde_urlencoded = "0.7.1" base64.workspace = true http.workspace = true diff --git a/crates/forge_infra/src/auth/mcp_token_storage.rs b/crates/forge_infra/src/auth/mcp_token_storage.rs index 544833fe40..8fbb44904d 100644 --- a/crates/forge_infra/src/auth/mcp_token_storage.rs +++ b/crates/forge_infra/src/auth/mcp_token_storage.rs @@ -98,11 +98,11 @@ impl CredentialStore for McpTokenStorage { if let Some(entry) = store.get(&self.server_url) { use oauth2::basic::BasicTokenType; use oauth2::{AccessToken, RefreshToken}; - use rmcp::transport::auth::OAuthTokenResponse; + use rmcp::transport::auth::{OAuthTokenResponse, VendorExtraTokenFields}; let access_token = AccessToken::new(entry.tokens.access_token.clone()); let token_type = BasicTokenType::Bearer; - let extra_fields = oauth2::EmptyExtraTokenFields {}; + let extra_fields = VendorExtraTokenFields::default(); let mut token_response = OAuthTokenResponse::new(access_token, token_type, extra_fields); @@ -127,14 +127,23 @@ impl CredentialStore for McpTokenStorage { } } - Ok(Some(StoredCredentials { - client_id: entry + let granted_scopes = entry + .tokens + .scope + .as_deref() + .map(|s| s.split_whitespace().map(str::to_string).collect()) + .unwrap_or_default(); + + Ok(Some(StoredCredentials::new( + entry .client_registration .as_ref() .map(|r| r.client_id.clone()) .unwrap_or_default(), - token_response: Some(token_response), - })) + Some(token_response), + granted_scopes, + None, + ))) } else { Ok(None) } diff --git a/crates/forge_infra/src/http.rs b/crates/forge_infra/src/http.rs index 228cc902ef..fe8c7595fe 100644 --- a/crates/forge_infra/src/http.rs +++ b/crates/forge_infra/src/http.rs @@ -55,7 +55,7 @@ impl ForgeHttpInfra { root_cert_paths: None, }); - let mut client = reqwest::Client::builder() + let mut client = forge_reqwest::builder() .connect_timeout(Duration::from_secs(http.connect_timeout_secs)) .read_timeout(Duration::from_secs(http.read_timeout_secs)) .pool_idle_timeout(Duration::from_secs(http.pool_idle_timeout_secs)) diff --git a/crates/forge_infra/src/mcp_client.rs b/crates/forge_infra/src/mcp_client.rs index 23e246a1f3..1dcde47b42 100644 --- a/crates/forge_infra/src/mcp_client.rs +++ b/crates/forge_infra/src/mcp_client.rs @@ -1,4 +1,3 @@ -use std::borrow::Cow; use std::collections::BTreeMap; use std::future::Future; use std::str::FromStr; @@ -12,11 +11,12 @@ use forge_domain::{ }; use reqwest::Client; use reqwest::header::{HeaderName, HeaderValue}; -use rmcp::model::{CallToolRequestParam, ClientInfo, Implementation, InitializeRequestParam}; +use rmcp::model::{CallToolRequestParams, ClientInfo, Implementation, InitializeRequestParams}; use rmcp::service::RunningService; -use rmcp::transport::sse_client::SseClientConfig; -use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig; -use rmcp::transport::{SseClientTransport, StreamableHttpClientTransport, TokioChildProcess}; +use rmcp::transport::TokioChildProcess; +use rmcp::transport::streamable_http_client::{ + StreamableHttpClientTransport, StreamableHttpClientTransportConfig, +}; use rmcp::{RoleClient, ServiceExt}; use schemars::Schema; use serde_json::Value; @@ -30,7 +30,7 @@ const VERSION: &str = match option_env!("APP_VERSION") { None => env!("CARGO_PKG_VERSION"), }; -type RmcpClient = RunningService; +type RmcpClient = RunningService; #[derive(Clone)] pub struct ForgeMcpClient { @@ -107,17 +107,7 @@ impl ForgeMcpClient { } fn client_info(&self) -> ClientInfo { - ClientInfo { - protocol_version: Default::default(), - capabilities: Default::default(), - client_info: Implementation { - name: "Forge".to_string(), - version: VERSION.to_string(), - icons: None, - title: None, - website_url: None, - }, - } + ClientInfo::new(Default::default(), Implementation::new("Forge", VERSION)) } /// Connects to the MCP server. If `force` is true, it will reconnect even @@ -219,23 +209,12 @@ impl ForgeMcpClient { &self, http: &McpHttpServer, ) -> anyhow::Result { - // Try HTTP first, fall back to SSE if it fails let client = self.reqwest_client(); let transport = StreamableHttpClientTransport::with_client( client.as_ref().clone(), StreamableHttpClientTransportConfig::with_uri(http.url.clone()), ); - match self.client_info().serve(transport).await { - Ok(client) => Ok(client), - Err(_e) => { - let transport = SseClientTransport::start_with_client( - client.as_ref().clone(), - SseClientConfig { sse_endpoint: http.url.clone().into(), ..Default::default() }, - ) - .await?; - Ok(self.client_info().serve(transport).await?) - } - } + Ok(self.client_info().serve(transport).await?) } /// Create an OAuth-enabled connection using rmcp's OAuth support. @@ -366,12 +345,23 @@ impl ForgeMcpClient { .map_err(|e| anyhow::anyhow!("Failed to get credentials: {}", e))?; { + use oauth2::TokenResponse; use rmcp::transport::auth::CredentialStore; let save_store = McpTokenStorage::new(http.url.clone(), self.environment.clone()); - let stored = rmcp::transport::auth::StoredCredentials { - client_id: credentials.0, - token_response: credentials.1, - }; + // Prefer scopes granted by the server (from the token response); fall + // back to the scopes we requested if the server didn't echo them back. + let granted_scopes = credentials + .1 + .as_ref() + .and_then(|t| t.scopes()) + .map(|s| s.iter().map(|s| s.to_string()).collect::>()) + .unwrap_or_else(|| oauth_config.scopes.clone()); + let stored = rmcp::transport::auth::StoredCredentials::new( + credentials.0, + credentials.1, + granted_scopes, + None, + ); save_store .save(stored) .await @@ -526,16 +516,11 @@ impl ForgeMcpClient { async fn call(&self, tool_name: &ToolName, input: &Value) -> anyhow::Result { let client = self.connect().await?; - let result = client - .call_tool(CallToolRequestParam { - name: Cow::Owned(tool_name.to_string()), - arguments: if let Value::Object(args) = input { - Some(args.clone()) - } else { - None - }, - }) - .await?; + let mut params = CallToolRequestParams::new(tool_name.to_string()); + if let Value::Object(args) = input { + params = params.with_arguments(args.clone()); + } + let result = client.call_tool(params).await?; let tool_contents: Vec = result .content @@ -734,10 +719,21 @@ pub async fn mcp_auth(server_url: &str, env: &Environment) -> anyhow::Result<()> .map_err(|e| anyhow::anyhow!("Failed to get credentials: {}", e))?; let save_store = McpTokenStorage::new(server_url.to_string(), env.clone()); - let stored = rmcp::transport::auth::StoredCredentials { - client_id: credentials.0, - token_response: credentials.1, + let granted_scopes = { + use oauth2::TokenResponse; + credentials + .1 + .as_ref() + .and_then(|t| t.scopes()) + .map(|s| s.iter().map(|s| s.to_string()).collect::>()) + .unwrap_or_default() }; + let stored = rmcp::transport::auth::StoredCredentials::new( + credentials.0, + credentials.1, + granted_scopes, + None, + ); save_store .save(stored) .await diff --git a/crates/forge_reqwest/Cargo.toml b/crates/forge_reqwest/Cargo.toml new file mode 100644 index 0000000000..d235fcadf9 --- /dev/null +++ b/crates/forge_reqwest/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "forge_reqwest" +version = "0.1.0" +edition.workspace = true +rust-version.workspace = true + +[dependencies] +reqwest.workspace = true +webpki-root-certs.workspace = true diff --git a/crates/forge_reqwest/src/lib.rs b/crates/forge_reqwest/src/lib.rs new file mode 100644 index 0000000000..ea494841c2 --- /dev/null +++ b/crates/forge_reqwest/src/lib.rs @@ -0,0 +1,26 @@ +//! Centralized [`reqwest::Client`] construction for the workspace. +//! +//! `reqwest 0.13` removed the compiled-in `rustls-tls-webpki-roots` feature +//! and switched its default trust source to `rustls-platform-verifier`, which +//! synchronously parses the OS trust store on every `Client::build()` +//! (~38 ms on Linux). Per the upstream `0.13.0` changelog, the recommended +//! replacement is to call `ClientBuilder::tls_certs_only(your_roots)`. +//! +//! All `reqwest::Client`s in the codebase should be built from +//! [`builder`] so the trust-source decision lives in one place and the +//! platform-verifier cost is avoided on cold-start paths. + +use reqwest::ClientBuilder; +use reqwest::tls::Certificate; + +/// Returns a [`reqwest::ClientBuilder`] preconfigured with the bundled +/// Mozilla webpki root CAs. +pub fn builder() -> ClientBuilder { + reqwest::Client::builder().tls_certs_only(webpki_root_certs()) +} + +fn webpki_root_certs() -> impl IntoIterator { + webpki_root_certs::TLS_SERVER_ROOT_CERTS + .iter() + .filter_map(|der| Certificate::from_der(der.as_ref()).ok()) +} diff --git a/crates/forge_services/Cargo.toml b/crates/forge_services/Cargo.toml index 5e3be29337..d38ba80197 100644 --- a/crates/forge_services/Cargo.toml +++ b/crates/forge_services/Cargo.toml @@ -23,6 +23,7 @@ dashmap.workspace = true anyhow.workspace = true futures.workspace = true reqwest.workspace = true +forge_reqwest.workspace = true derive_more.workspace = true regex.workspace = true backon.workspace = true @@ -48,7 +49,7 @@ forge_eventsource.workspace = true lazy_static = "1.5.0" forge_domain.workspace = true forge_config.workspace = true -oauth2 = { version = "5.0", features = ["reqwest"] } +oauth2 = { version = "5.0", default-features = false } serde_urlencoded = "0.7.1" http.workspace = true infer.workspace = true diff --git a/crates/forge_services/src/tool_services/fetch.rs b/crates/forge_services/src/tool_services/fetch.rs index 273f614df2..8c7ebf9b3f 100644 --- a/crates/forge_services/src/tool_services/fetch.rs +++ b/crates/forge_services/src/tool_services/fetch.rs @@ -23,7 +23,7 @@ impl Default for ForgeFetch { impl ForgeFetch { pub fn new() -> Self { - Self { client: Client::new() } + Self { client: forge_reqwest::builder().build().unwrap_or_default() } } } diff --git a/crates/forge_tracker/Cargo.toml b/crates/forge_tracker/Cargo.toml index 3e83449f6a..751f0913ce 100644 --- a/crates/forge_tracker/Cargo.toml +++ b/crates/forge_tracker/Cargo.toml @@ -6,6 +6,7 @@ rust-version.workspace = true [dependencies] reqwest.workspace = true +forge_reqwest.workspace = true derive_more.workspace = true url.workspace = true serde.workspace = true diff --git a/crates/forge_tracker/src/collect/posthog.rs b/crates/forge_tracker/src/collect/posthog.rs index d7c3213a29..545bfd7381 100644 --- a/crates/forge_tracker/src/collect/posthog.rs +++ b/crates/forge_tracker/src/collect/posthog.rs @@ -19,7 +19,7 @@ pub struct Tracker { impl Tracker { pub fn new(api_secret: &'static str) -> Self { // Configure HTTP client with connection pooling similar to forge_provider - let client = Client::builder() + let client = forge_reqwest::builder() .connect_timeout(Duration::from_secs(10)) .read_timeout(Duration::from_secs(30)) .pool_idle_timeout(Duration::from_secs(90))