captchakraken 3.1.0 → 3.2.1

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 (44) hide show
  1. package/AGENTS.md +4 -4
  2. package/LICENSE +1 -1
  3. package/README.md +10 -13
  4. package/dist/index.d.ts +1 -0
  5. package/dist/kinds.d.ts +8 -0
  6. package/dist/kinds.js +3 -1
  7. package/dist/model-name.d.ts +6 -0
  8. package/dist/model-name.js +28 -0
  9. package/dist/playwright-types.d.ts +18 -0
  10. package/dist/png.d.ts +16 -0
  11. package/dist/png.js +119 -0
  12. package/dist/puppeteer-adapter.d.ts +7 -1
  13. package/dist/puppeteer-adapter.js +6 -0
  14. package/dist/selectors.d.ts +9 -0
  15. package/dist/selectors.js +11 -3
  16. package/dist/solver.d.ts +76 -4
  17. package/dist/solver.js +509 -176
  18. package/dist/types.d.ts +10 -5
  19. package/dist/verdicts.d.ts +45 -0
  20. package/dist/verdicts.js +125 -0
  21. package/package.json +7 -7
  22. package/python/AGENTS.md +13 -8
  23. package/python/LICENSE +1 -1
  24. package/python/README.md +10 -13
  25. package/python/pyproject.toml +6 -6
  26. package/python/src/captchakraken/__init__.py +5 -1
  27. package/python/src/captchakraken/cli.py +7 -1
  28. package/python/src/captchakraken/kinds.py +9 -0
  29. package/python/src/captchakraken/page_solver.py +472 -167
  30. package/python/src/captchakraken/planner.py +52 -11
  31. package/python/src/captchakraken/prompts.py +24 -0
  32. package/python/src/captchakraken/selectors.py +19 -2
  33. package/python/src/captchakraken/tool_calls/find_checkbox.py +4 -0
  34. package/python/src/captchakraken/tool_calls/find_grid.py +22 -0
  35. package/python/src/captchakraken/verdicts.py +154 -0
  36. package/python/Dockerfile +0 -41
  37. package/python/examples/README.md +0 -114
  38. package/python/examples/_harness.py +0 -177
  39. package/python/examples/demoHcaptcha.py +0 -8
  40. package/python/examples/demoRecaptcha.py +0 -8
  41. package/python/examples/watch_playwright.py +0 -31
  42. package/python/examples/with_local_gguf.py +0 -28
  43. package/python/examples/with_playwright.py +0 -24
  44. package/scripts/copy-python.mjs +0 -29
package/dist/solver.d.ts CHANGED
@@ -20,9 +20,13 @@ export declare function answerNeedsElementBox(actions: ReadonlyArray<{
20
20
  }>): boolean;
21
21
  /** The widget moved on under us (hCaptcha swapped rounds, GeeTest closed on accept): re-detect, do not fail. */
22
22
  export declare function isStaleHandleError(message: string): boolean;
23
+ /** A closed target is not a stale handle: retried as one, a dead page was re-detected until the loops ran out. */
24
+ export declare function isClosedTargetError(message: string): boolean;
25
+ export declare const INPUT_SETTLE_MS = 400;
23
26
  export declare const SOLVE_DEFAULTS: {
24
27
  readonly maxSolveLoops: 6;
25
28
  readonly overallSolveTimeoutMs: 45000;
29
+ readonly detectionTimeoutMs: 15000;
26
30
  readonly keyframeWaitTimeoutMs: 9000;
27
31
  };
28
32
  /** A hang detector for a burst whose screenshot never returns, sized off the ceiling. */
@@ -44,7 +48,6 @@ export declare class CaptchaKrakenSolver {
44
48
  /** Answers keyed by screenshot hash; a hit means the answer already ran and changed nothing. */
45
49
  private solutionCache;
46
50
  private repeatedAnswerSeen;
47
- private retriedUnusableAnswer;
48
51
  private knownAnimated;
49
52
  private animatedProbeDone;
50
53
  /** The one recording for the animated board on screen, and its answer until the widget refuses it. */
@@ -69,24 +72,91 @@ export declare class CaptchaKrakenSolver {
69
72
  private actedOnBoard;
70
73
  private lastSubmitFrameHash;
71
74
  private solveSessionId;
75
+ /** Which vendor and site this solve is for, sent to the hosted API; the site is a hostname only. */
76
+ private solveVendor;
77
+ private solveSite;
78
+ /** The host the widget itself was served from (its iframe's); null for an inline widget. */
79
+ private solveWidgetHost;
80
+ private legacyModelWarned;
81
+ private verdicts;
82
+ /** False once a self-hosted endpoint has answered 404: it has no outcome route to report to. */
83
+ private outcomeSupported;
72
84
  private cliCache;
73
85
  private loraNameCache;
74
86
  budget: PhaseBudget | null;
87
+ /** The page being solved: every capture is taken of its viewport. Set by `solve`. */
88
+ private page;
89
+ /** When our last gesture ended; the board's reaction to it is never read as the board's own motion. */
90
+ private lastInputAt;
75
91
  private ph;
92
+ /** A pointer gesture, timed as MOUSE and remembered: see `INPUT_SETTLE_MS`. */
93
+ private gesture;
76
94
  constructor(config?: CaptchaKrakenConfig);
77
95
  private get lastMousePosition();
78
96
  private set lastMousePosition(value);
79
- /** `disabled` freezes CSS animation, which once sliced GeeTest svg to a static clip; callers filming motion pass `allow`. */
97
+ /**
98
+ * Every capture the driver takes: the whole viewport, cropped here to the element.
99
+ *
100
+ * Never a clipped capture. An element screenshot, or any `clip`, makes a headed Chromium repaint the page at the
101
+ * clip's size for that frame, which the user watches as the page flashing and jumping; a viewport capture
102
+ * repaints nothing, and measured twice as fast. `disabled` freezes CSS animation, which once sliced GeeTest svg to
103
+ * a static clip; callers filming motion pass `allow`.
104
+ */
80
105
  private shot;
106
+ private rectOf;
107
+ /** Where the element sits in the viewport, scrolled in when it is merely off screen; null when it cannot fit. */
108
+ private rectInView;
109
+ /**
110
+ * Take the pointer off the board and let our own feedback fade before the board is judged still or animated.
111
+ *
112
+ * A hovered or pressed control repaints, and a board wearing our highlight read as motion: a still board was
113
+ * filmed as animated because of the Verify button under the cursor.
114
+ */
115
+ private stepOffTheBoard;
81
116
  solve(page: Page): Promise<SolveResult | void>;
82
- /** Tell the hosted API whether the widget accepted, through the CLI, detached, never awaited. */
117
+ /** Tell the hosted API whether the widget accepted, through the CLI. The solve never awaits it; the promise is for callers that must know it finished. */
83
118
  private reportOutcome;
84
119
  /** Solve captchas on `page` as they appear, until `stop()`. Injects nothing into the page. */
85
120
  watch(page: Page, options?: WatchOptions): CaptchaWatcher;
121
+ /**
122
+ * Give up only when the vendor refuses to serve us, or when every one of `maxSolveLoops` has been spent. Any other
123
+ * failed round — a stale handle, an unusable or repeated answer, a board that would not film — counts one loop,
124
+ * pauses, and goes again.
125
+ */
86
126
  private solveImpl;
127
+ /** What the vendor's server said since the last look: BLOCKED outranks everything, else the latest answer. */
128
+ private vendorVerdict;
129
+ /**
130
+ * A page that has not drawn its widget yet is looked at again until `detectionTimeoutMs`. Solving straight after
131
+ * `domcontentloaded` failed 3/3 on a demo page whose frames arrived a moment later.
132
+ */
133
+ private awaitWidget;
134
+ /** The vendor showing its refusal screen: rate-limited or flagged, with no board to answer. */
135
+ private isBlocked;
136
+ /** The env the engine reads its routing headers from: session, and the vendor and site once they are known. */
137
+ private routingEnv;
87
138
  /** Fire the optional onStep observer with a fresh screenshot; best-effort, never fails the solve. */
88
139
  private emitStep;
89
140
  private solveSingle;
141
+ /**
142
+ * Tick the box and wait for what it opens. A checkbox is not a board: it is never polled, filmed or asked about.
143
+ *
144
+ * Treated as a board it cost 70 screenshots and three model calls in one measured solve, two of them answering the
145
+ * checkbox picture with a drag.
146
+ */
147
+ private clickCheckbox;
148
+ /**
149
+ * The box in a checkbox frame once the frame has drawn it; null when the DOM cannot reach it. Turnstile's box is in
150
+ * a closed shadow root, and a frame can refuse access; both are found on screen instead.
151
+ */
152
+ private checkboxBox;
153
+ /** One capture and OpenCV: a point inside the tick box, in page coordinates. No model is asked. */
154
+ private findCheckboxOnScreen;
155
+ /**
156
+ * A clicked checkbox passes or opens a challenge, and both show in the DOM.
157
+ * Without this wait the next round found the same checkbox still up and clicked it again.
158
+ */
159
+ private awaitWhatTheCheckboxOpened;
90
160
  private getVerifyButton;
91
161
  /** Any element at `selector` carrying a non-blank value; response fields are hidden, so no visibility filter. */
92
162
  private hasValue;
@@ -107,6 +177,8 @@ export declare class CaptchaKrakenSolver {
107
177
  private waitForBoardImages;
108
178
  /** Which vendors' code the page loaded, from resource timing and linked URLs. A tripwire, not a detector. */
109
179
  vendorsOnTheWire(page: Page): Promise<Vendor[]>;
180
+ /** Vendors showing a frame no selector names. Only asked once detection has found nothing, and a passive frame (an invisible badge, an enclave) is not a widget, so what is left is markup the table no longer matches. */
181
+ private unmatchedVendorFrames;
110
182
  private noWidgetMessage;
111
183
  /**
112
184
  * Is a widget in the DOM at all, rendered or not? Invisible reCAPTCHA is excluded by its selector. The inline vendors
@@ -180,7 +252,7 @@ export declare class CaptchaKrakenSolver {
180
252
  private startKeyframeBurst;
181
253
  /** Slice a burst into keyframes and solve them in one model request. The frame number is the guard. */
182
254
  private getAnimatedSolution;
183
- /** The session id and the credential travel in the environment, never in argv. */
255
+ /** The routing values and the credential travel in the environment, never in argv. */
184
256
  private solveEnvironment;
185
257
  /** Exit 2 is an unsupported puzzle, exit 3 the hosted API's own refusal; both are relayed, not reworded. */
186
258
  private cliError;