captchakraken 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +47 -7
  2. package/README.md +24 -4
  3. package/dist/cli-invocation.d.ts +46 -0
  4. package/dist/cli-invocation.js +68 -0
  5. package/dist/index.d.ts +27 -0
  6. package/dist/index.js +29 -1
  7. package/dist/limits.d.ts +51 -0
  8. package/dist/limits.js +54 -0
  9. package/dist/model-name.d.ts +23 -0
  10. package/dist/model-name.js +70 -0
  11. package/dist/playwright-types.d.ts +28 -0
  12. package/dist/puppeteer-adapter.d.ts +11 -0
  13. package/dist/puppeteer-adapter.js +23 -0
  14. package/dist/python-command.d.ts +50 -0
  15. package/dist/python-command.js +60 -0
  16. package/dist/slide-geometry.d.ts +33 -0
  17. package/dist/slide-geometry.js +64 -0
  18. package/dist/solver.d.ts +214 -12
  19. package/dist/solver.js +1285 -165
  20. package/dist/trajectory.d.ts +31 -0
  21. package/dist/trajectory.js +162 -0
  22. package/dist/types.d.ts +128 -11
  23. package/dist/watcher.d.ts +99 -0
  24. package/dist/watcher.js +129 -0
  25. package/package.json +2 -5
  26. package/python/LICENSE +47 -7
  27. package/python/README.md +25 -8
  28. package/python/examples/README.md +36 -0
  29. package/python/examples/_harness.py +182 -94
  30. package/python/examples/demoHcaptcha.py +2 -1
  31. package/python/examples/demoRecaptcha.py +2 -1
  32. package/python/examples/watch_playwright.py +56 -0
  33. package/python/examples/with_playwright.py +43 -0
  34. package/python/pyproject.toml +4 -3
  35. package/python/src/captchakraken/__init__.py +5 -3
  36. package/python/src/captchakraken/action_types.py +24 -3
  37. package/python/src/captchakraken/cli.py +212 -2
  38. package/python/src/captchakraken/config.py +39 -5
  39. package/python/src/captchakraken/keyframes.py +690 -0
  40. package/python/src/captchakraken/models.json +120 -0
  41. package/python/src/captchakraken/page_solver.py +1465 -102
  42. package/python/src/captchakraken/pinned_model.json +5 -7
  43. package/python/src/captchakraken/planner.py +253 -59
  44. package/python/src/captchakraken/prompts.py +485 -0
  45. package/python/src/captchakraken/solver.py +182 -11
  46. package/python/src/captchakraken/timing.py +70 -0
  47. package/python/src/captchakraken/tool_calls/find_grid.py +367 -52
  48. package/python/src/captchakraken/tool_calls/track_piece.py +96 -0
  49. package/python/src/captchakraken/trajectory.py +2 -7
  50. package/python/src/captchakraken/watcher.py +193 -0
  51. package/python/src/captchakraken/planner_types.py +0 -74
@@ -0,0 +1,120 @@
1
+ {
2
+ "_comment": [
3
+ "The models this client knows how to talk to, and WHICH GENERATION OF",
4
+ "PROMPTS each one was trained on.",
5
+ "",
6
+ "Why a map and not a constant: a model answers in whatever schema its prompt",
7
+ "asks for. Send a version-1 model the version-2 prompt and nothing errors —",
8
+ "it just answers worse, on every puzzle, silently. That is exactly the",
9
+ "2026-07-18 regression (failure-mode 3 in the finetune repo's",
10
+ "scripts/check_prompt_parity.py), where the shipped prompt kept asking for",
11
+ "the legacy output/simulate_drag/PascalCase schema long after the LoRA had",
12
+ "been retrained on action: drag / drags[].",
13
+ "",
14
+ "Hardcoding one generation makes that inevitable the moment a new model",
15
+ "trains on different prompts: updating the constants breaks every already-",
16
+ "published model, and not updating them breaks the new one. So each model",
17
+ "declares its generation here, captchakraken.prompts serves the matching",
18
+ "built-ins, and both keep working.",
19
+ "",
20
+ "`latest` is what you get by default. Pin a specific model with",
21
+ "CAPTCHA_LORA_ADAPTER (or CAPTCHA_LORA_NAME for a served alias) — pinning is",
22
+ "opt-in, so the default download and the default prompt always move forward",
23
+ "together. That coupling is why moving `latest` to a generation-2 model is",
24
+ "safe here and would not have been before: a client that ships this file",
25
+ "reads prompt_version 2 from the same entry that named the weights. Clients",
26
+ "old enough to predate this file resolve from pinned_model.json instead and",
27
+ "never see `latest`, so they are not silently moved onto prompts they cannot",
28
+ "produce.",
29
+ "",
30
+ "Adding a model: add its entry here IN THE SAME COMMIT as publishing it. The",
31
+ "finetune repo's check_prompt_parity.py fails if any registered model names a",
32
+ "prompt_version this client ships no built-ins for, so an unmapped model",
33
+ "cannot reach a release.",
34
+ "",
35
+ "`pixel_budget` is the same idea for RESOLUTION. Qwen reads MIN_PIXELS /",
36
+ "MAX_PIXELS from the environment and clamps each image's AREA into that band,",
37
+ "so it decides how many visual tokens the model reads a puzzle from. One",
38
+ "visual token is a 32x32 px square (patch_size 16, then spatial_merge_size 2).",
39
+ "It lives here, per model, for exactly the reason prompt_version does — one",
40
+ "client constant cannot be right for two adapters with different budgets.",
41
+ "",
42
+ "SERVE-AT, not trained-at. Seed it from the training run, then tune it by",
43
+ "measurement: these adapters generalize UPWARD, so the best serving band is",
44
+ "usually larger than the training floor. Serving under a band nobody checked",
45
+ "is the prompt bug in a different costume — nothing errors, the model just",
46
+ "answers on a picture at a scale it was not tuned for.",
47
+ "",
48
+ "Omit it and the client keeps its historical behaviour (floor at 448 squared,",
49
+ "no ceiling). Absent means UNKNOWN, not zero — set it only where it has been",
50
+ "measured or the training run is known."
51
+ ],
52
+ "latest": "CaptchaKraken/CaptchaKraken-Lora-v1.2",
53
+ "models": {
54
+ "CaptchaKraken/CaptchaKraken-Lora-v1.2": {
55
+ "prompt_version": "2",
56
+ "kind": "lora",
57
+ "base_model": "RedHatAI/Qwen3.5-9B-FP8-dynamic",
58
+ "lora_revision": "main",
59
+ "lora_name": "captcha-v12",
60
+ "pixel_budget": {
61
+ "min": 518400,
62
+ "max": 518400
63
+ },
64
+ "note": "Run 20260812-005302 (ready-to-deploy). PUBLIC on the Hub under Source-Available License v1.1, and the first published generation-2 model. TRAINED with floor 448^2 / ceiling 720^2, but MEASURED best served at a flat 720^2 — floor == ceiling, so every image arrives at exactly one size. Tier 2 overall 0.6115 -> 0.6412 across the full 1458-sample real eval and reCAPTCHA 3x3 exact 0.648 -> 0.715, against run-to-run noise of +/-0.001. Swept 2026-08-18 over 448/576/640/704/720/736/768/896/1024^2: the plateau is 704-736^2 and it falls off above 768^2, where a 400x580 portrait capture runs more than 40% past the ViT's 48x48 position grid. Note 640^2 is where that grid is exactly saturated and it scores WORSE (0.6357) — mild extrapolation plus real pixels beats staying inside the grid. Was served as `captcha-v12` while absent from this file, which resolved it to generation 1 prompts against generation-2 weights — the failure this file exists to prevent."
65
+ },
66
+ "CaptchaKraken/Twilight-v1.2-FP8": {
67
+ "prompt_version": "2",
68
+ "kind": "merged",
69
+ "lora_name": "CaptchaKraken/Twilight-v1.2-FP8",
70
+ "pixel_budget": {
71
+ "min": 518400,
72
+ "max": 518400
73
+ },
74
+ "note": "CaptchaKraken-Lora-v1.2 merged into Qwen/Qwen3.5-9B at FP8-dynamic. The weights the hosted API answers with. Generation 2, same band as the adapter it is made from: a merge that resolved to a different prompt generation or a different pixel budget than its own LoRA would be the 2026-07-18 regression with extra steps."
75
+ },
76
+ "CaptchaKraken/Sunlight-v1.2-AWQ-4bit": {
77
+ "prompt_version": "2",
78
+ "kind": "merged",
79
+ "lora_name": "CaptchaKraken/Sunlight-v1.2-AWQ-4bit",
80
+ "pixel_budget": {
81
+ "min": 518400,
82
+ "max": 518400
83
+ },
84
+ "note": "CaptchaKraken-Lora-v1.2 merged into Qwen/Qwen3.5-9B at AWQ 4-bit. Generation 2. Quantization changes the weights, not the schema they answer in, so the prompt generation and the pixel budget are the adapter's."
85
+ },
86
+ "CaptchaKraken/CaptchaKraken_v1.1": {
87
+ "prompt_version": "1",
88
+ "kind": "lora",
89
+ "base_model": "RedHatAI/Qwen3.5-9B-FP8-dynamic",
90
+ "lora_revision": "main",
91
+ "lora_name": "captcha",
92
+ "note": "Currently served in production. PRIVATE on the Hub, so prompts.json can never be fetched for it — this entry is the only thing that maps it to a prompt generation."
93
+ },
94
+ "CaptchaKraken/CaptchaKrakenV1_Lora": {
95
+ "prompt_version": "1",
96
+ "kind": "lora",
97
+ "base_model": "RedHatAI/Qwen3.5-9B-FP8-dynamic",
98
+ "lora_revision": "main",
99
+ "lora_name": "captcha",
100
+ "note": "Published before prompts.json existed — no such file in the repo, so it resolves from here."
101
+ },
102
+ "CaptchaKraken/Sunlight-AWQ-4bit": {
103
+ "prompt_version": "1",
104
+ "kind": "merged",
105
+ "lora_name": "captcha",
106
+ "note": "Ships its own prompts.json; this entry keeps it resolvable offline."
107
+ },
108
+ "CaptchaKraken/Twilight-FP8": {
109
+ "prompt_version": "1",
110
+ "kind": "merged",
111
+ "lora_name": "captcha",
112
+ "note": "Ships its own prompts.json; this entry keeps it resolvable offline."
113
+ }
114
+ },
115
+ "served_aliases": {
116
+ "_comment": "A hosted endpoint serves a bare name, not a repo id. Map it back so prompt resolution works for callers who only ever see the alias.",
117
+ "captcha": "CaptchaKraken/CaptchaKraken_v1.1",
118
+ "captcha-v12": "CaptchaKraken/CaptchaKraken-Lora-v1.2"
119
+ }
120
+ }