From bfbb78383d1f243ad748c3e0ea3209a61e7bb841 Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Sun, 7 Jun 2026 14:35:05 +0100 Subject: [PATCH] docs: README updates for gemini, stealth coherence, headed mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reflect the previously-deferred items as done: gemini provider is fully wired to native generateContent (vision + audio), unit-tested, with a note that live use needs a real Google key. Document that get_stealth_script now takes os/browser/locale/seed and returns a fingerprint, and that the evasion script is templated to match it (coherent) — inject both together or share a seed. Note reasoning-model blocks are stripped before json parse. Record the CAPTCHA_E2E_HEADED toggle, drop the done roadmap items, keep the honest note that headless reCAPTCHA v2 usually won't mint a token, and call out the single package-lock.json lockfile. --- README.md | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 292fb90..a6f75f6 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Copy `.env.example` as a starting point. | Variable | Required | Default | Notes | |----------|----------|---------|-------| -| `CAPTCHA_LLM_PROVIDER` | yes | — | `anthropic` \| `openai` \| `openai-compatible` \| `gemini` | +| `CAPTCHA_LLM_PROVIDER` | yes | — | `anthropic` \| `openai` \| `openai-compatible` \| `gemini` (all four fully implemented) | | `CAPTCHA_LLM_BASE_URL` | for `openai-compatible` | provider default | Endpoint override (local / Ollama / OpenRouter / gateway) | | `CAPTCHA_LLM_API_KEY` | yes\* | — | \*May be **empty** for a keyless local/gateway endpoint **when `BASE_URL` is set** | | `CAPTCHA_LLM_MODEL` | yes | — | Vision-capable model id (see compatibility notes) | @@ -66,6 +66,12 @@ Copy `.env.example` as a starting point. > **Keyless gateways:** if you point `CAPTCHA_LLM_BASE_URL` at an OpenAI-compatible gateway > that does not require auth, leave `CAPTCHA_LLM_API_KEY` empty — startup will accept it. +> **Gemini:** the `gemini` provider is **fully implemented** against Google's native +> `generateContent` wire format (vision *and* audio) and is unit-tested. Live use needs a +> real Google Gemini API key (`generativelanguage.googleapis.com`) — the project's +> OpenAI-compatible test gateway can't exercise the native Gemini path, so it is covered by +> unit tests against a mock endpoint rather than the live e2e suite. + ## Tools All nine tools are registered in `internal/mcp/server.go`. Every image/audio input accepts @@ -78,7 +84,7 @@ All nine tools are registered in `internal/mcp/server.go`. Every image/audio inp | `solve_audio_captcha` | `audio`, `language?` | `{text,confidence}`; errors clearly if provider has no transcription | | `solve_grid_captcha` | `screenshot`, `instruction`, `rows`, `cols`, `image_width?`, `image_height?`, `captcha_type?` | `{tiles,centroids?,confidence,recheck_recommended}` (reCAPTCHA v2 / hCaptcha) | | `solve_rotation_captcha` | `screenshot`, `instruction?` | `{choice,rotations,confidence}` (FunCaptcha, best-effort) | -| `get_stealth_script` | `engine?` = `playwright`\|`cdp`\|`generic` | `{script,apply,included_evasions}` — JS init script + how to inject it | +| `get_stealth_script` | `engine?` = `playwright`\|`cdp`\|`generic`, `os?`, `browser?`, `locale?`, `seed?` | `{script,apply,fingerprint,included_evasions}` — JS init script (templated to match `fingerprint`) + how to inject it | | `generate_fingerprint` | `os?`, `browser?`, `locale?`, `seed?` | `{fingerprint,header_set}` — coherent identity + matching headers (seeded = stable) | | `plan_interaction` | `actions`, `seed?` | humanized mouse/keyboard timeline (Bézier paths, jitter, cadence) | | `solver_info` | — | configured provider/model + per-type capability flags | @@ -91,6 +97,12 @@ All nine tools are registered in `internal/mcp/server.go`. Every image/audio inp (set `CAPTCHA_LLM_AUDIO_MODEL`). - `plan_interaction` is designed to pair with grid centroids: feed it `click` actions at the tile centroids to produce human-looking pointer motion. +- `get_stealth_script` accepts `os` / `browser` / `locale` / `seed` and returns a + `fingerprint` field. The injected evasion script's WebGL vendor/renderer, + `navigator.platform`, and `navigator.languages` are **templated to match that + fingerprint** (coherent), so the script and the identity tell the same story. Inject the + `script` and apply the returned `fingerprint` together — or call `get_stealth_script` and + `generate_fingerprint` with the **same `seed`** to get an identical, coherent pair. ## Captcha-type matrix @@ -190,6 +202,9 @@ npx playwright install chromium make e2e-browser ``` +> Node deps are pinned by a single lockfile, **`package-lock.json`** (npm). Use `npm` to +> install so the lockfile stays canonical. + Two paths (`test/e2e/playwright/*.mjs`, wrapped by `test/e2e/browser_test.go`): - **Text captcha (`solve-text.mjs`) — verified end-to-end.** Screenshots the demo's @@ -201,7 +216,10 @@ Two paths (`test/e2e/playwright/*.mjs`, wrapped by `test/e2e/browser_test.go`): `plan_interaction` → humanized clicks over the tile grid, and reads `g-recaptcha-response`. Real Google reCAPTCHA commonly resists headless automation, so this path **logs the outcome and exits 0 even with no token** — it fails only on a real - script/transport error. + script/transport error. Set **`CAPTCHA_E2E_HEADED=1`** to launch a visible, slow-mo + browser for a real-profile attempt that improves the odds of Google minting a token. + Headless reCAPTCHA v2 usually **won't** mint a token — that is inherent to Google's + defenses, not a bug in this harness. ## Compatibility notes @@ -209,15 +227,20 @@ Two paths (`test/e2e/playwright/*.mjs`, wrapped by `test/e2e/browser_test.go`): with `max_completion_tokens` when a model (e.g. GPT-5.x) rejects `max_tokens`. This works transparently across old and new OpenAI-style backends — you don't configure anything. - **Prefer a vision-capable model** for the image/grid tools (e.g. `openai/gpt-5.4`, - `zai/GLM-4.6V-FlashX`). Reasoning models that emit `…` still work - (responses are JSON-extracted), but non-reasoning vision models give cleaner output. + `zai/GLM-4.6V-FlashX`). Reasoning models that emit `…` (or + `…`) are now **handled** — the scratchpad block is stripped *before* + JSON extraction, so a JSON-looking object inside the reasoning never gets mistaken for the + answer. Non-reasoning vision models still give the lowest latency. - **TLS/JA3 + HTTP/2 fingerprints are browser/proxy-level.** The stealth tools only *advise* on these — they cannot change them. To control them, terminate through a fingerprint-aware proxy or a browser build that emits the JA3/H2 profile you want. ## Roadmap / not yet built -Two pieces are **designed but deferred** (see +The **Gemini provider** and **WebGL/fingerprint coherence** are now **done** (see the +Provider and Tools sections above); they are no longer on this list. + +One piece remains **designed but deferred** (see [`docs/superpowers/specs/`](./docs/superpowers/specs) and [`docs/superpowers/plans/`](./docs/superpowers/plans)): @@ -226,8 +249,9 @@ Two pieces are **designed but deferred** (see CI without hitting real sites. A **live** browser harness already exists (`make e2e-browser`, see [Testing](#testing)): it targets the 2captcha demo, is network/browser-gated, verifies the text path end-to-end against the demo's success - indicator, and runs the reCAPTCHA v2 path best-effort. The remaining work is the - offline, deterministic local-page variant for CI. -- **Gemini provider** — a stub exists (`internal/llm/gemini.go`); the `generateContent` - wire format still needs verification against current Google docs before it ships. Use - `openai` / `openai-compatible` / `anthropic` in the meantime. + indicator, and runs the reCAPTCHA v2 path best-effort (with an optional + `CAPTCHA_E2E_HEADED=1` real-profile attempt). The remaining work is the offline, + deterministic local-page variant for CI. + +> Note: headless reCAPTCHA v2 usually won't mint a token regardless of harness quality — +> that is Google's anti-automation defense working as intended, not a defect here.