From 1a2a04b96b77d9f2e7c30eb436051937adce8ada Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 23 Mar 2026 08:13:50 -0400 Subject: [PATCH] Fix test timeouts caused by reqwest system proxy detection on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reqwest::Client::new() queries macOS SCDynamicStore for system proxy settings, which calls CFBundleGetMainBundle() → readdir() on target/debug/deps/. With 576K stale build artifacts accumulated in that directory, each readdir() took 1.3s, causing 15s+ delays when multiple test processes ran concurrently. - Disable jsonschema default features to remove unnecessary reqwest@0.13 and rustls-platform-verifier dependencies - Make reqwest::Client lazy in web_search tool (OnceLock) to avoid constructing it during profile tests - Mark validate_api_key_rejects_invalid_key as #[ignore] since it hits the live Anthropic API (3.2s per invocation) Co-Authored-By: Claude Opus 4.6 (1M context) --- Cargo.lock | 165 +++------------------- Cargo.toml | 2 +- lib/crates/fabro-agent/src/tools.rs | 6 +- lib/crates/fabro-cli/src/provider_auth.rs | 1 + 4 files changed, 25 insertions(+), 149 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9da580085..d6a1a340b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -483,12 +483,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.4" @@ -589,16 +583,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - [[package]] name = "concurrent-queue" version = "2.5.0" @@ -916,7 +900,7 @@ name = "daytona-api-client" version = "0.1.0" source = "git+https://github.com/brynary/daytona-sdk-rust?rev=06033ca#06033caaf5d9e12918ae68396048c5c0a98822c6" dependencies = [ - "reqwest 0.12.28", + "reqwest", "reqwest-middleware", "serde", "serde_json", @@ -933,7 +917,7 @@ dependencies = [ "daytona-api-client", "daytona-toolbox-client", "futures-util", - "reqwest 0.12.28", + "reqwest", "reqwest-middleware", "serde", "serde_json", @@ -949,7 +933,7 @@ name = "daytona-toolbox-client" version = "0.1.0" source = "git+https://github.com/brynary/daytona-sdk-rust?rev=06033ca#06033caaf5d9e12918ae68396048c5c0a98822c6" dependencies = [ - "reqwest 0.12.28", + "reqwest", "reqwest-middleware", "serde", "serde_json", @@ -1257,7 +1241,7 @@ dependencies = [ "jsonschema", "libc", "paste", - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "shell-escape", @@ -1302,7 +1286,7 @@ dependencies = [ "hyper-util", "jsonwebtoken", "openapiv3", - "reqwest 0.12.28", + "reqwest", "rustls", "rustls-pemfile", "rustls-pki-types", @@ -1382,7 +1366,7 @@ dependencies = [ "predicates", "rand 0.8.5", "regex", - "reqwest 0.12.28", + "reqwest", "rustls", "rustls-pemfile", "scopeguard", @@ -1436,7 +1420,7 @@ version = "0.176.2" dependencies = [ "fabro-util", "insta", - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "serde_yaml", @@ -1465,7 +1449,7 @@ dependencies = [ "chrono", "jsonwebtoken", "mockito", - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "tokio", @@ -1494,7 +1478,7 @@ dependencies = [ "fabro-util", "mockito", "regex", - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "tokio", @@ -1537,7 +1521,7 @@ dependencies = [ "indicatif", "insta", "rand 0.8.5", - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "thiserror 2.0.18", @@ -1555,7 +1539,7 @@ dependencies = [ "anyhow", "fabro-config", "futures", - "reqwest 0.12.28", + "reqwest", "rmcp", "serde", "serde_json", @@ -1582,7 +1566,7 @@ dependencies = [ "mockito", "open", "rand 0.8.5", - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "sha2", @@ -1642,7 +1626,7 @@ dependencies = [ "fabro-interview", "fabro-workflows", "futures-util", - "reqwest 0.12.28", + "reqwest", "rustls", "serde", "serde_json", @@ -1669,7 +1653,7 @@ dependencies = [ "mac_address", "md5", "regex", - "reqwest 0.12.28", + "reqwest", "sentry", "serde", "serde_json", @@ -1685,7 +1669,7 @@ dependencies = [ "async-trait", "fabro-github", "mockito", - "reqwest 0.12.28", + "reqwest", "serde_json", "tokio", "tracing", @@ -1769,7 +1753,7 @@ dependencies = [ "predicates", "rand 0.8.5", "regex", - "reqwest 0.12.28", + "reqwest", "scopeguard", "serde", "serde_json", @@ -2699,28 +2683,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - [[package]] name = "jobserver" version = "0.1.34" @@ -2762,8 +2724,6 @@ dependencies = [ "referencing", "regex", "regex-syntax", - "reqwest 0.13.2", - "rustls", "serde", "serde_json", "unicode-general-category", @@ -4190,45 +4150,6 @@ dependencies = [ "webpki-roots 1.0.6", ] -[[package]] -name = "reqwest" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", - "serde", - "serde_json", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "reqwest-middleware" version = "0.4.2" @@ -4238,7 +4159,7 @@ dependencies = [ "anyhow", "async-trait", "http", - "reqwest 0.12.28", + "reqwest", "serde", "thiserror 1.0.69", "tower-service", @@ -4271,7 +4192,7 @@ dependencies = [ "pastey", "pin-project-lite", "process-wrap", - "reqwest 0.12.28", + "reqwest", "rmcp-macros", "schemars 1.2.1", "serde", @@ -4376,18 +4297,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pemfile" version = "2.2.0" @@ -4407,33 +4316,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-platform-verifier" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" -dependencies = [ - "core-foundation 0.10.1", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" - [[package]] name = "rustls-webpki" version = "0.103.9" @@ -4580,7 +4462,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "016958f51b96861dead7c1e02290f138411d05e94fad175c8636a835dee6e51e" dependencies = [ "httpdate", - "reqwest 0.12.28", + "reqwest", "rustls", "sentry-backtrace", "sentry-contexts", @@ -6272,15 +6154,6 @@ dependencies = [ "string_cache_codegen", ] -[[package]] -name = "webpki-root-certs" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "webpki-roots" version = "0.26.11" diff --git a/Cargo.toml b/Cargo.toml index d772c4596..c1710113e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ base64 = "0.22" bytes = "1" tokio-util = "0.7" clap = { version = "4", features = ["derive"] } -jsonschema = "0.42" +jsonschema = { version = "0.42", default-features = false } chrono = { version = "0.4", features = ["clock"] } bollard = "0.18" tar = "0.4" diff --git a/lib/crates/fabro-agent/src/tools.rs b/lib/crates/fabro-agent/src/tools.rs index dc7ed3822..14d5898e4 100644 --- a/lib/crates/fabro-agent/src/tools.rs +++ b/lib/crates/fabro-agent/src/tools.rs @@ -460,7 +460,9 @@ pub(crate) fn make_web_search_tool() -> RegisteredTool { } fn make_web_search_tool_with_api_key(api_key: Option) -> RegisteredTool { - let client = reqwest::Client::new(); + use std::sync::OnceLock; + static CLIENT: OnceLock = OnceLock::new(); + RegisteredTool { definition: ToolDefinition { name: "web_search".into(), @@ -475,7 +477,7 @@ fn make_web_search_tool_with_api_key(api_key: Option) -> RegisteredTool }), }, executor: Arc::new(move |args, _ctx| { - let client = client.clone(); + let client = CLIENT.get_or_init(reqwest::Client::new).clone(); let api_key = api_key.clone(); Box::pin(async move { let api_key = api_key.ok_or_else(|| { diff --git a/lib/crates/fabro-cli/src/provider_auth.rs b/lib/crates/fabro-cli/src/provider_auth.rs index 83b691f5e..3f0fc7bd9 100644 --- a/lib/crates/fabro-cli/src/provider_auth.rs +++ b/lib/crates/fabro-cli/src/provider_auth.rs @@ -262,6 +262,7 @@ mod tests { // -- API key validation -- #[tokio::test] + #[ignore] // hits live Anthropic API async fn validate_api_key_rejects_invalid_key() { let result = validate_api_key(Provider::Anthropic, "sk-invalid-key-12345").await; assert!(result.is_err(), "expected invalid key to be rejected");