captchakraken 2.9.0 → 3.1.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.
- package/AGENTS.md +112 -0
- package/NOTICE +36 -0
- package/dist/cli-invocation.d.ts +7 -36
- package/dist/cli-invocation.js +8 -49
- package/dist/errors.d.ts +7 -27
- package/dist/errors.js +6 -25
- package/dist/humanize.d.ts +56 -240
- package/dist/humanize.js +159 -415
- package/dist/index.d.ts +5 -129
- package/dist/index.js +4 -98
- package/dist/kinds.d.ts +135 -0
- package/dist/kinds.js +70 -0
- package/dist/limits.d.ts +0 -48
- package/dist/limits.js +2 -48
- package/dist/model-name.d.ts +4 -19
- package/dist/model-name.js +32 -40
- package/dist/playwright-types.d.ts +25 -95
- package/dist/playwright-types.js +0 -23
- package/dist/puppeteer-adapter.d.ts +4 -43
- package/dist/puppeteer-adapter.js +22 -58
- package/dist/python-command.d.ts +0 -41
- package/dist/python-command.js +0 -37
- package/dist/selectors.d.ts +54 -0
- package/dist/selectors.js +117 -0
- package/dist/slide-geometry.d.ts +2 -29
- package/dist/slide-geometry.js +18 -44
- package/dist/solver.d.ts +131 -708
- package/dist/solver.js +1319 -3382
- package/dist/timing.d.ts +7 -40
- package/dist/timing.js +4 -36
- package/dist/token-usage.d.ts +1 -7
- package/dist/token-usage.js +10 -95
- package/dist/types.d.ts +77 -493
- package/dist/watcher.d.ts +5 -78
- package/dist/watcher.js +0 -56
- package/package.json +11 -4
- package/python/AGENTS.md +122 -0
- package/python/NOTICE +36 -0
- package/python/README.md +1 -2
- package/python/examples/README.md +10 -0
- package/python/examples/_harness.py +4 -73
- package/python/examples/demoHcaptcha.py +0 -13
- package/python/examples/demoRecaptcha.py +0 -10
- package/python/examples/watch_playwright.py +1 -26
- package/python/examples/with_local_gguf.py +28 -0
- package/python/examples/with_playwright.py +0 -19
- package/python/pyproject.toml +68 -19
- package/python/src/captchakraken/__init__.py +37 -45
- package/python/src/captchakraken/action_types.py +14 -36
- package/python/src/captchakraken/cli.py +262 -883
- package/python/src/captchakraken/config.py +60 -146
- package/python/src/captchakraken/errors.py +17 -95
- package/python/src/captchakraken/humanize.py +174 -597
- package/python/src/captchakraken/image_processor.py +16 -235
- package/python/src/captchakraken/keyframes.py +46 -484
- package/python/src/captchakraken/kinds.py +152 -0
- package/python/src/captchakraken/models.json +36 -4
- package/python/src/captchakraken/overlay.py +65 -498
- package/python/src/captchakraken/page_solver.py +1282 -3101
- package/python/src/captchakraken/planner.py +65 -487
- package/python/src/captchakraken/prompts.py +45 -261
- package/python/src/captchakraken/selectors.py +184 -0
- package/python/src/captchakraken/server_manager.py +7 -58
- package/python/src/captchakraken/solver.py +128 -522
- package/python/src/captchakraken/timing.py +20 -74
- package/python/src/captchakraken/tool_calls/board_painted.py +47 -0
- package/python/src/captchakraken/tool_calls/find_checkbox.py +20 -30
- package/python/src/captchakraken/tool_calls/find_grid.py +186 -1339
- package/python/src/captchakraken/tool_calls/track_piece.py +81 -57
- package/python/src/captchakraken/updater.py +7 -76
- package/python/src/captchakraken/watcher.py +12 -101
- package/scripts/copy-python.mjs +10 -10
- package/scripts/setup-python.js +1 -21
- package/dist/trajectory.d.ts +0 -58
- package/dist/trajectory.js +0 -266
- package/python/src/captchakraken/tool_calls/move_indicator.py +0 -431
- package/python/src/captchakraken/trajectory.py +0 -284
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""Every closed set of names the two ports agree on. Mirrored in js/src/kinds.ts; keep both in the same order."""
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Vendor(StrEnum):
|
|
6
|
+
"""`puzzle_source` everywhere. UNKNOWN must stay permissive: GeeTest and Prosopo report it, and so does the offline grader."""
|
|
7
|
+
|
|
8
|
+
HCAPTCHA = "hcaptcha"
|
|
9
|
+
RECAPTCHA = "recaptcha"
|
|
10
|
+
TURNSTILE = "turnstile"
|
|
11
|
+
GEETEST = "geetest"
|
|
12
|
+
TENCENT = "tencent"
|
|
13
|
+
YIDUN = "yidun"
|
|
14
|
+
YANDEX = "yandex"
|
|
15
|
+
LEMIN = "lemin"
|
|
16
|
+
PROSOPO = "prosopo"
|
|
17
|
+
MTCAPTCHA = "mtcaptcha"
|
|
18
|
+
BOTDETECT = "botdetect"
|
|
19
|
+
UNKNOWN = "unknown"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ActionKind(StrEnum):
|
|
23
|
+
CLICK = "click"
|
|
24
|
+
DRAG = "drag"
|
|
25
|
+
TYPE = "type"
|
|
26
|
+
WAIT = "wait"
|
|
27
|
+
DONE = "done"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class PixelAnswerKind(StrEnum):
|
|
31
|
+
"""What the pixel parser reads off the model's text before it becomes an action."""
|
|
32
|
+
|
|
33
|
+
CLICK = "click"
|
|
34
|
+
DRAG = "drag"
|
|
35
|
+
SLIDE = "slide"
|
|
36
|
+
TYPE = "type"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class RetryMode(StrEnum):
|
|
40
|
+
MISSED_TILES = "missed-tiles"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SettleVerdict(StrEnum):
|
|
44
|
+
SETTLED = "settled"
|
|
45
|
+
ANIMATED = "animated"
|
|
46
|
+
TIMEOUT = "timeout"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class PaintVerdict(StrEnum):
|
|
50
|
+
PAINTED = "painted"
|
|
51
|
+
BLANK = "blank"
|
|
52
|
+
UNKNOWN = "unknown"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class KeyframeMode(StrEnum):
|
|
56
|
+
"""EVEN means the slicer could not prove recurrence, not that the board is still."""
|
|
57
|
+
|
|
58
|
+
STATIC = "static"
|
|
59
|
+
CYCLE = "cycle"
|
|
60
|
+
EVEN = "even"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class RecaptchaBanner(StrEnum):
|
|
64
|
+
SELECT_MORE = "select-more"
|
|
65
|
+
DYNAMIC_MORE = "dynamic-more"
|
|
66
|
+
REJECTED = "rejected"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class PromptFamily(StrEnum):
|
|
70
|
+
"""One expert per family; `pixel` is spelled to match ckgate's prompt markers."""
|
|
71
|
+
|
|
72
|
+
PIXEL = "pixel"
|
|
73
|
+
GRID = "grid"
|
|
74
|
+
VIDEO = "video"
|
|
75
|
+
TEXT = "text"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class Availability(StrEnum):
|
|
79
|
+
"""PRIVATE is not a softer LICENSED: refusing a private model early would stop an authorised token from fetching weights."""
|
|
80
|
+
|
|
81
|
+
PUBLIC = "public"
|
|
82
|
+
PRIVATE = "private"
|
|
83
|
+
LICENSED = "licensed"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class HumanizationMode(StrEnum):
|
|
87
|
+
MOUSE = "mouse"
|
|
88
|
+
MOBILE = "mobile"
|
|
89
|
+
NONE = "none"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class PauseKind(StrEnum):
|
|
93
|
+
TAP = "tap"
|
|
94
|
+
BETWEEN = "between"
|
|
95
|
+
GRAB = "grab"
|
|
96
|
+
DROP = "drop"
|
|
97
|
+
PROBE = "probe"
|
|
98
|
+
SETTLE = "settle"
|
|
99
|
+
KEY = "key"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class Outcome(StrEnum):
|
|
103
|
+
SOLVED = "solved"
|
|
104
|
+
FAILED = "failed"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class Phase(StrEnum):
|
|
108
|
+
"""Timing phases. Only INFERENCE and MOUSE are productive; everything else is waiting."""
|
|
109
|
+
|
|
110
|
+
INFERENCE = "inference"
|
|
111
|
+
MOUSE = "mouse"
|
|
112
|
+
SCREENSHOT = "screenshot"
|
|
113
|
+
DETECT = "detect"
|
|
114
|
+
SETTLE = "settle"
|
|
115
|
+
BURST = "burst"
|
|
116
|
+
GRID = "grid"
|
|
117
|
+
GRID_LOAD = "grid-load"
|
|
118
|
+
FADE_WAIT = "fade-wait"
|
|
119
|
+
BOARD_PAINT = "board-paint"
|
|
120
|
+
HCAPTCHA_IMAGES = "hcaptcha-images"
|
|
121
|
+
AWAIT_NEXT_ROUND = "await-next-round"
|
|
122
|
+
AWAIT_VERDICT = "await-verdict"
|
|
123
|
+
POST_SUBMIT_DELAY = "post-submit-delay"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class FrameRole(StrEnum):
|
|
127
|
+
CHECKBOX = "checkbox"
|
|
128
|
+
CHALLENGE = "challenge"
|
|
129
|
+
UNKNOWN = "unknown"
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class LabelPosition(StrEnum):
|
|
133
|
+
TOP_LEFT = "top-left"
|
|
134
|
+
CENTER = "center"
|
|
135
|
+
TOP_RIGHT = "top-right"
|
|
136
|
+
BOTTOM_LEFT = "bottom-left"
|
|
137
|
+
BOTTOM_RIGHT = "bottom-right"
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class ErrorCode(StrEnum):
|
|
141
|
+
"""The hosted API's machine-readable codes. Unknown codes still carry the server's message through; this is not a filter."""
|
|
142
|
+
|
|
143
|
+
MISSING_API_KEY = "missing_api_key"
|
|
144
|
+
INVALID_API_KEY = "invalid_api_key"
|
|
145
|
+
ACCOUNT_SUSPENDED = "account_suspended"
|
|
146
|
+
INSUFFICIENT_CREDITS = "insufficient_credits"
|
|
147
|
+
RATE_LIMITED = "rate_limited"
|
|
148
|
+
SOLVE_ABANDONED = "solve_abandoned"
|
|
149
|
+
UNRECOGNIZED_PROMPT = "unrecognized_prompt"
|
|
150
|
+
INVALID_REQUEST = "invalid_request"
|
|
151
|
+
REQUEST_TOO_LARGE = "request_too_large"
|
|
152
|
+
UPSTREAM_UNAVAILABLE = "upstream_unavailable"
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
" never be private either — an unpinned self-hoster would get",
|
|
65
65
|
" a 401 instead of a model — and the release parity gate says so.",
|
|
66
66
|
"",
|
|
67
|
-
" \"licensed\" — NOT downloadable
|
|
68
|
-
" api.captchakraken.com
|
|
67
|
+
" \"licensed\" — NOT downloadable without a licence we issue. Served to",
|
|
68
|
+
" every account through api.captchakraken.com.",
|
|
69
69
|
" There is no Hub repo to point CAPTCHA_LORA_ADAPTER at, and",
|
|
70
70
|
" `captchakraken fetch` refuses rather than 404ing at the Hub.",
|
|
71
71
|
"",
|
|
@@ -121,6 +121,28 @@
|
|
|
121
121
|
"routed model in the first place."
|
|
122
122
|
],
|
|
123
123
|
"latest": "CaptchaKraken/CaptchaKraken-Lora-v1.2",
|
|
124
|
+
"_comment_hosted_default": [
|
|
125
|
+
"WHAT THE HOSTED ENDPOINT IS ASKED FOR, which is not what gets DOWNLOADED.",
|
|
126
|
+
"",
|
|
127
|
+
"`latest` is the download default: the repo a self-hoster pulls and serves.",
|
|
128
|
+
"`hosted_default` is the served NAME a client sends when it is talking to",
|
|
129
|
+
"our API. They were one field until Abyss, and one field cannot express",
|
|
130
|
+
"this: Abyss is hosted-only, so naming it as `latest` would point every",
|
|
131
|
+
"self-hoster at weights they are not licensed to download, while leaving it",
|
|
132
|
+
"out would mean the hosted endpoint never serves the better model.",
|
|
133
|
+
"",
|
|
134
|
+
"This is also what makes the rollout version-gated without a version",
|
|
135
|
+
"header. A client that ships this file asks for `abyss`; one that predates",
|
|
136
|
+
"it asks for whatever its own registry says and keeps getting v1.2. Nothing",
|
|
137
|
+
"server-side has to know which is which.",
|
|
138
|
+
"",
|
|
139
|
+
"Only consulted for an endpoint that is OURS \u2014 see config.is_hosted_endpoint.",
|
|
140
|
+
"A self-hosted vLLM, local or remote, resolves from `latest` exactly as",
|
|
141
|
+
"before, because it serves whatever its operator loaded and asking it for",
|
|
142
|
+
"`abyss` would 404."
|
|
143
|
+
],
|
|
144
|
+
"hosted_default": "CaptchaKraken/Abyss",
|
|
145
|
+
|
|
124
146
|
"models": {
|
|
125
147
|
"CaptchaKraken/CaptchaKraken-Lora-v1.2": {
|
|
126
148
|
"prompt_version": "2",
|
|
@@ -154,6 +176,16 @@
|
|
|
154
176
|
},
|
|
155
177
|
"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."
|
|
156
178
|
},
|
|
179
|
+
"CaptchaKraken/CaptchaKraken-v1.2-GGUF": {
|
|
180
|
+
"prompt_version": "2",
|
|
181
|
+
"kind": "merged",
|
|
182
|
+
"lora_name": "CaptchaKraken/CaptchaKraken-v1.2-GGUF",
|
|
183
|
+
"pixel_budget": {
|
|
184
|
+
"min": 518400,
|
|
185
|
+
"max": 518400
|
|
186
|
+
},
|
|
187
|
+
"note": "CaptchaKraken-Lora-v1.2 merged into Qwen/Qwen3.5-9B and converted to GGUF, for llama.cpp and Ollama. ONE entry covers every quantisation in that repo: Q4_K_M, Q8_0 and F16 differ in weight precision, not in the schema they answer or the resolution they read at, so all three share this generation and this band. The vision tower ships beside them as a separate F16 projector and is never quantised — a runtime that loads the weights without it is text-only and cannot see a puzzle at all. Ollama names a model after whatever it was pulled or created as, and that name is what reaches us as `model`; an unrecognised one resolves through CAPTCHA_LORA_ADAPTER instead, which is why the self-hosting guide sets it."
|
|
188
|
+
},
|
|
157
189
|
"CaptchaKraken/CaptchaKraken_v1.1": {
|
|
158
190
|
"prompt_version": "1",
|
|
159
191
|
"kind": "lora",
|
|
@@ -198,7 +230,7 @@
|
|
|
198
230
|
"video": "abyss-video",
|
|
199
231
|
"text": "abyss-text"
|
|
200
232
|
},
|
|
201
|
-
"note": "A routed mixture of four expert LoRAs on Qwen3.5-9B — grid, pixel, video and text — selected by prompt family. Hosted only: `availability` refuses the weights, and being nameable is not being downloadable.
|
|
233
|
+
"note": "A routed mixture of four expert LoRAs on Qwen3.5-9B — grid, pixel, video and text — selected by prompt family. Hosted only: `availability` refuses the weights, and being nameable is not being downloadable. The current client names this model against our endpoint, which is why it and each of its arms has a served_aliases entry. `lora_name` is `abyss-general` rather than a fifth name because the generalist IS the fallback for any family `experts` does not map, so the two point at one adapter and the mixture needs one fewer resident LoRA slot."
|
|
202
234
|
},
|
|
203
235
|
"CaptchaKraken/Abyss-27B": {
|
|
204
236
|
"availability": "private",
|
|
@@ -270,7 +302,7 @@
|
|
|
270
302
|
"_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. The hosted API serves one model behind the permanent public name `captcha`, whatever the caller sends, so `captcha` means whichever adapter is current there. Self-hosters resolve by repo id via CAPTCHA_LORA_ADAPTER and are unaffected. Move this in the same change as the gateway's upstream model, or the hosted model answers a prompt generation it was not trained on.",
|
|
271
303
|
"captcha": "CaptchaKraken/CaptchaKraken-Lora-v1.2",
|
|
272
304
|
"captcha-v12": "CaptchaKraken/CaptchaKraken-Lora-v1.2",
|
|
273
|
-
"_comment_abyss": "An alias says which model a served NAME means; `availability` says whether its weights can be downloaded. The two are independent.
|
|
305
|
+
"_comment_abyss": "An alias says which model a served NAME means; `availability` says whether its weights can be downloaded. The two are independent. The current client names this model against our endpoint — the hosted API serves it to every account and lists it on /v1/models — and without this line prompt resolution falls through to the `latest` fallback, which is the model/generation mispairing this file exists to prevent. It does not make the weights fetchable.",
|
|
274
306
|
"abyss": "CaptchaKraken/Abyss",
|
|
275
307
|
"_comment_abyss_experts": "The four expert arms. These are the names that go on the wire — a routed request for a grid names `abyss-grid`, never `abyss` — so without these lines prompt resolution falls through to `latest` on every routed solve. Aliasing the arms onto one entry is deliberate and checked: they share a base, a prompt generation and a pixel band, and the parity gate requires every expert name to resolve to a registered entry declaring the SAME prompt_version and pixel_budget as the router — so the day an arm trains at another generation or band, the gate refuses the alias and that arm has to graduate to an entry of its own.",
|
|
276
308
|
"abyss-grid": "CaptchaKraken/Abyss-grid",
|