1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
//! captchaforge — automatic CAPTCHA detection and solving for
//! `chromiumoxide`-driven headless browsers.
//!
//! Extracted from [golemn-browser](https://github.com/santhsecurity/golemn)
//! (originally GPL-3.0) and re-licensed MIT OR Apache-2.0 by the
//! original author so it can stand alone and be embedded by other
//! Santh-ecosystem tools (wafrift, gossan, sear, …).
//!
//! # Module map
//!
//! - [`detect`] — heuristic + DOM-based CAPTCHA identification.
//! - [`solver`] — multi-strategy solving chain (behavioural, VLM,
//! audio, third-party, pattern-cached, human fallback).
//! - [`stealth`] / [`stealth_profiles`] — pre-navigation
//! fingerprint hardening + named browser-vendor profiles.
//! - [`warmup`] — natural pre-captcha activity (mouse / scroll
//! entropy) so passive challenges score the visitor as human.
//! - [`behavior`] — primitive realistic gestures (Bézier mouse,
//! variable-cadence typing, hover dwell, touch swipe, jitter).
//! - [`cookies`] — capture / replay session cookies, vendor-filter.
//! - [`frame`] — same-origin iframe + cross-origin CDP frame walk.
//! - [`provider`] — pluggable vendor-rule registry.
//! - [`config`] — Tier-A `.captchaforge.toml` discovery.
//! - [`backends`] — local backend probe (Ollama / Whisper / Tesseract).
//! - [`stt`] — speech-to-text endpoint ladder.
//! - [`sdk`] — one-call orchestration ([`solve_url`], [`prepare_page`],
//! [`auto_solve_with_retries`], [`dismiss_cookie_consent`],
//! [`dismiss_chat_widget`], [`wait_for_no_captcha`]).
//! - [`prelude`] — glob-import target for the most-used types.
//!
//! Three layered consumption modes:
//!
//! 1. **One-call** — `captchaforge::solve_url(&page, url, None).await?`
//! when you want the whole chain wired for you.
//! 2. **Building blocks** — call [`detect::detect`] then drive a
//! custom [`solver::CaptchaSolverChain`] when you need
//! telemetry, custom solvers, or non-default cache semantics.
//! 3. **Primitives** — embed individual modules ([`stealth`],
//! [`behavior`], [`frame`], [`cookies`]) inside an existing
//! chromiumoxide flow without touching the solver chain.
//!
//! Originally extracted from
//! [golemn-browser](https://github.com/santhsecurity/golemn) and
//! re-licensed MIT OR Apache-2.0 by the original author so it can
//! stand alone and be embedded by other Santh-ecosystem tools
//! (wafrift, gossan, sear, …).
//!
//! # Example — one-call solve
//!
//! ```rust,no_run
//! use captchaforge::prelude::*;
//! # async fn run(page: &chromiumoxide::Page) -> anyhow::Result<()> {
//! match solve_url(page, "https://example.com", Some(StealthProfile::ChromeMacStable)).await? {
//! None => println!("no captcha detected"),
//! Some(r) if r.success => println!("solved via {:?} in {}ms", r.method, r.time_ms),
//! Some(r) => println!("failed: {:?}", r.method),
//! }
//! # Ok(()) }
//! ```
//!
//! # Example — detect + custom chain
//!
//! ```rust,no_run
//! use captchaforge::{detect, solver::CaptchaSolverChain};
//! # async fn run(page: &chromiumoxide::Page) -> anyhow::Result<()> {
//! let info = detect::detect(page).await?;
//! if detect::is_captcha(&info) {
//! let chain = CaptchaSolverChain::default_chain();
//! // chain.solve(page, &info).await?;
//! }
//! # Ok(()) }
//! ```
//!
//! # Example — pattern store
//!
//! ```rust
//! use captchaforge::solver::{CaptchaType, PatternStore, SolveMethod};
//!
//! let store = PatternStore::default();
//! store.record("example.com", &CaptchaType::CloudflareTurnstile, true, 1200, SolveMethod::BehavioralBypass);
//! assert_eq!(store.best_method("example.com", &CaptchaType::CloudflareTurnstile), Some(SolveMethod::BehavioralBypass));
//! ```
//!
//! # Example — primitives only (no chain)
//!
//! ```rust,no_run
//! use captchaforge::behavior::{mouse_move_bezier, click_realistic};
//! use captchaforge::frame::evaluate_in_all_frames;
//! # async fn run(page: &chromiumoxide::Page) -> anyhow::Result<()> {
//! mouse_move_bezier(page, 0.0, 0.0, 400.0, 300.0).await?;
//! click_realistic(page, 400.0, 300.0).await?;
//! let titles: Vec<String> = evaluate_in_all_frames(page, "document.title").await?;
//! # let _ = titles;
//! # Ok(()) }
//! ```
pub use Config;
pub use CapturedCookie;
pub use StealthProfile;
// Back-compat re-export so code that used `golemn_browser::captcha_detect`
// can `use captchaforge::captcha_detect` instead.
pub use detect as captcha_detect;
pub use ;
// Top-level re-exports for the most common SDK surface so users can
// `use captchaforge::{Capabilities, AudioCaptchaSolver, ...}` without
// remembering which submodule each name lives in.
pub use ;
pub use ;
// One-call SDK helpers. Their definitions live in [`sdk`] — these
// re-exports give SDK consumers a flat `captchaforge::solve_url(…)`
// import path matching the established `captchaforge::auto_solve(…)`
// shape, without forcing a `captchaforge::sdk::` prefix.
pub use ;
/// One-call convenience: detect + solve in a single API.
///
/// Equivalent to:
///
/// ```ignore
/// let info = captchaforge::detect::detect(page).await?;
/// if !captchaforge::detect::is_captcha(&info) {
/// return Ok(None);
/// }
/// let chain = captchaforge::solver::CaptchaSolverChain::default_chain();
/// Ok(Some(chain.solve(page, &info).await))
/// ```
///
/// Returns:
/// * `Ok(None)` — no captcha was detected on the page.
/// * `Ok(Some(result))` — captcha detected; `result.success` indicates
/// whether the chain solved it. Failed solves still return Some
/// so the caller can inspect the screenshot for human fallback.
/// * `Err(_)` — the detection step itself failed (page eval error,
/// CDP transport error). Solver errors are swallowed into a
/// no-op `CaptchaSolveResult` and don't surface here.
///
/// Power users that need a custom chain (telemetry, token cache,
/// pattern store, custom solvers) construct their own
/// [`solver::CaptchaSolverChain`] and call `chain.solve()` directly.
///
/// For a "navigate + solve in one call" entry point, see
/// [`solve_url`] (re-exported from [`sdk`]).
pub async