captchaforge 0.2.38

[DO NOT USE — UNDER ACTIVE DEVELOPMENT, NOT PRODUCTION-READY] Captcha solver scaffolding for Firefox + BiDi-driven browsers. The architecture is in place (vendor solvers, retry-loop iframe walking, VLM provider abstraction, real-WAF bench harness) but the live-vendor success rate is still 0% — Cloudflare Turnstile / hCaptcha / reCAPTCHA detect us at a TLS / BiDi fingerprint layer that no flag-based stealth has cleared. Watch the repo; do not depend on this for any real workload.
Documentation
//! One source for captchaforge's plain (non-impersonating) HTTP clients.
//!
//! The CAPTCHA backends/solvers each talk to a *local* service (Ollama,
//! Whisper, Tesseract sidecar) or a vendor solver API — not to the target
//! site — so they want a plain timed client, not the browser-impersonating
//! [`guise`] client. The same `reqwest::Client::builder().timeout(d).build()`
//! block was copy-pasted across `backends`, `solver::{audio,third_party,
//! vlm}`, `stt`, and the CLI. Centralizing it here gives one place to evolve
//! connection policy (connect-timeout, pooling, a default UA) for all of them.

use std::time::Duration;

/// A plain reqwest client with a total-request `timeout` and no browser
/// impersonation. Callers own their own error handling (`?`, `match`,
/// `.ok()`, `.unwrap_or_else(|_| reqwest::Client::new())`).
pub(crate) fn timed_client(timeout: Duration) -> reqwest::Result<reqwest::Client> {
    reqwest::Client::builder()
        .timeout(timeout)
        .no_gzip()
        .no_brotli()
        .build()
}