captchakraken 2.9.0 → 3.0.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 (77) hide show
  1. package/AGENTS.md +112 -0
  2. package/NOTICE +36 -0
  3. package/dist/cli-invocation.d.ts +7 -36
  4. package/dist/cli-invocation.js +8 -49
  5. package/dist/errors.d.ts +7 -27
  6. package/dist/errors.js +6 -25
  7. package/dist/humanize.d.ts +56 -240
  8. package/dist/humanize.js +159 -415
  9. package/dist/index.d.ts +5 -129
  10. package/dist/index.js +4 -98
  11. package/dist/kinds.d.ts +135 -0
  12. package/dist/kinds.js +70 -0
  13. package/dist/limits.d.ts +0 -48
  14. package/dist/limits.js +2 -48
  15. package/dist/model-name.d.ts +4 -19
  16. package/dist/model-name.js +32 -40
  17. package/dist/playwright-types.d.ts +25 -95
  18. package/dist/playwright-types.js +0 -23
  19. package/dist/puppeteer-adapter.d.ts +4 -43
  20. package/dist/puppeteer-adapter.js +22 -58
  21. package/dist/python-command.d.ts +0 -41
  22. package/dist/python-command.js +0 -37
  23. package/dist/selectors.d.ts +54 -0
  24. package/dist/selectors.js +117 -0
  25. package/dist/slide-geometry.d.ts +2 -29
  26. package/dist/slide-geometry.js +18 -44
  27. package/dist/solver.d.ts +94 -712
  28. package/dist/solver.js +923 -3362
  29. package/dist/timing.d.ts +7 -40
  30. package/dist/timing.js +4 -36
  31. package/dist/token-usage.d.ts +1 -7
  32. package/dist/token-usage.js +10 -95
  33. package/dist/types.d.ts +75 -493
  34. package/dist/watcher.d.ts +5 -78
  35. package/dist/watcher.js +0 -56
  36. package/package.json +11 -4
  37. package/python/AGENTS.md +122 -0
  38. package/python/NOTICE +36 -0
  39. package/python/README.md +1 -2
  40. package/python/examples/README.md +10 -0
  41. package/python/examples/_harness.py +4 -73
  42. package/python/examples/demoHcaptcha.py +0 -13
  43. package/python/examples/demoRecaptcha.py +0 -10
  44. package/python/examples/watch_playwright.py +1 -26
  45. package/python/examples/with_local_gguf.py +28 -0
  46. package/python/examples/with_playwright.py +0 -19
  47. package/python/pyproject.toml +68 -19
  48. package/python/src/captchakraken/__init__.py +37 -45
  49. package/python/src/captchakraken/action_types.py +14 -36
  50. package/python/src/captchakraken/cli.py +262 -883
  51. package/python/src/captchakraken/config.py +60 -146
  52. package/python/src/captchakraken/errors.py +17 -95
  53. package/python/src/captchakraken/humanize.py +174 -597
  54. package/python/src/captchakraken/image_processor.py +16 -235
  55. package/python/src/captchakraken/keyframes.py +46 -484
  56. package/python/src/captchakraken/kinds.py +152 -0
  57. package/python/src/captchakraken/models.json +36 -4
  58. package/python/src/captchakraken/overlay.py +65 -498
  59. package/python/src/captchakraken/page_solver.py +1052 -3098
  60. package/python/src/captchakraken/planner.py +50 -487
  61. package/python/src/captchakraken/prompts.py +45 -261
  62. package/python/src/captchakraken/selectors.py +184 -0
  63. package/python/src/captchakraken/server_manager.py +7 -58
  64. package/python/src/captchakraken/solver.py +128 -522
  65. package/python/src/captchakraken/timing.py +20 -74
  66. package/python/src/captchakraken/tool_calls/board_painted.py +47 -0
  67. package/python/src/captchakraken/tool_calls/find_checkbox.py +20 -30
  68. package/python/src/captchakraken/tool_calls/find_grid.py +186 -1339
  69. package/python/src/captchakraken/tool_calls/track_piece.py +81 -57
  70. package/python/src/captchakraken/updater.py +7 -76
  71. package/python/src/captchakraken/watcher.py +12 -101
  72. package/scripts/copy-python.mjs +10 -10
  73. package/scripts/setup-python.js +1 -21
  74. package/dist/trajectory.d.ts +0 -58
  75. package/dist/trajectory.js +0 -266
  76. package/python/src/captchakraken/tool_calls/move_indicator.py +0 -431
  77. package/python/src/captchakraken/trajectory.py +0 -284
@@ -1,92 +1,28 @@
1
1
  /**
2
- * How the driver MOVES. One pluggable object per input device.
2
+ * How the driver moves: one pluggable object per input device. Mirrors python/humanize.py.
3
3
  *
4
- * The TypeScript side of `python/src/captchakraken/humanize.py`; the two are one
5
- * design in two languages, and `the training repo's humanizer parity tests` in
6
- * the training repo pins that the mode names and the pause vocabulary have
7
- * not drifted.
4
+ * The pointer position lives here, not in the solver, because a touch mode that dispatches no
5
+ * motion between taps still has to say where the next gesture starts.
8
6
  *
9
- * Humanisation used to be wired straight into `solver.ts`: every gesture was a
10
- * `page.mouse.*` call with a Bezier trajectory in front of it and a `Math.
11
- * random()` sleep behind it, and there was no way to ask for anything else. That
12
- * is wrong in three directions at once —
13
- *
14
- * - a caller driving a MOBILE page has no cursor. Dispatching mousemove at a
15
- * touch-only widget is not weak humanisation, it is the wrong event type:
16
- * the page's touch handlers never fire, and a vendor that scores pointer
17
- * telemetry sees a desktop mouse on a phone.
18
- * - a caller who has their OWN humanisation (a hardware pointer, a proxied
19
- * device farm, a model of their own users) was composing two of them. That
20
- * is not hypothetical — camoufox's `humanize` juggler re-humanises every
21
- * `mouse.move()` it is handed, and running both measured 82.1s against
22
- * 13.4s on one a GeeTest v4 slider solve, because each of the 60 trajectory
23
- * points became its own humanised sub-trajectory.
24
- * - a caller on their own infrastructure, against their own fixtures, is
25
- * paying for texture nobody is measuring.
26
- *
27
- * So the vocabulary of gestures is an INTERFACE and the humanisation is an
28
- * implementation of it. The solver says "tap here", "drag this there", "type
29
- * that"; a `Humanizer` decides what events that is and how long it takes.
30
- *
31
- * Four modes, selected by `CaptchaKrakenConfig.humanization`:
32
- *
33
- * 'mouse' MouseHumanizer — the default, and byte-for-byte what the
34
- * driver did before this module existed.
35
- * 'mobile' MobileHumanizer — touch events, finger kinematics. Dispatches
36
- * through a `TouchBackend`, so it drives either
37
- * a Chromium-family page (CDP) or an
38
- * Appium/WebdriverIO driver on a real device.
39
- * 'none' NullHumanizer — the shortest legal path to the same DOM
40
- * effect.
41
- * custom anything satisfying `Humanizer`, passed as
42
- * `CaptchaKrakenConfig.humanizer`.
43
- *
44
- * THE POINTER POSITION LIVES HERE, not in the solver. A humanizer that
45
- * dispatches no motion at all (mobile, between taps) still has to answer "where
46
- * is the pointer", because that is what the next gesture starts from and what
47
- * `SolveResult.finalMousePosition` reports.
7
+ * Pluggable because camoufox's juggler re-humanises every mouse.move() it is handed, and running
8
+ * both measured 82s against 13s on one GeeTest slider; and a touch widget needs touch events, not
9
+ * mousemove. See TRIBAL_KNOWLEDGE.md. The 2026-09 cut removed our drag-overshoot redraw and swipe
10
+ * wobble in favour of Cursory's raw recordings; the one-pixel tap wobble stayed because a
11
+ * motionless tap is a synthetic one.
48
12
  */
49
13
  import type { Page, PlaywrightElementHandle } from './playwright-types.js';
14
+ import { HumanizationMode, PauseKind } from './kinds.js';
15
+ export type { HumanizationMode, PauseKind } from './kinds.js';
50
16
  export type Point = [number, number];
51
- /**
52
- * Every inter-gesture wait the driver takes, named.
53
- *
54
- * A vocabulary rather than a number at each call site, because the whole point
55
- * of the mode switch is that these differ per device — a finger dwells on a tap
56
- * about four times as long as a mouse button is held, and neither number means
57
- * anything to the caller who turned humanisation off. Each mode supplies its own
58
- * table below; an unknown name yields no wait rather than throwing, so adding a
59
- * pause site cannot break a custom humanizer written against an older release.
60
- *
61
- * tap inside a click/tap, between press and release
62
- * between between two taps of one batch (grid tiles)
63
- * grab after pressing, before a drag starts moving
64
- * drop after a drag arrives, before releasing
65
- * probe between the slider's measurement nudges
66
- * settle before releasing a slider — the release IS the submit, and some
67
- * vendors sample the final milliseconds of the gesture
68
- * key between two typed characters
69
- */
70
- export type PauseKind = 'tap' | 'between' | 'grab' | 'drop' | 'probe' | 'settle' | 'key';
17
+ /** A recorded human movement morphed onto the endpoints; timings are cumulative ms. */
18
+ export declare function trajectory(start: Point, end: Point, frequency: number): [Point[], number[]];
19
+ /** Every inter-gesture wait the driver takes, named, so each device supplies its own table. */
71
20
  export declare const PAUSE_KINDS: readonly PauseKind[];
72
- /**
73
- * The gesture vocabulary the solver drives. Implement this to supply your own
74
- * humanisation; only `move`, `press`, `release`, `typeText` and `pause` are
75
- * required, and `BaseHumanizer` composes `click`/`drag` from them.
76
- */
77
21
  export interface Humanizer {
78
- /** Mode name, for logs. */
79
22
  readonly name: string;
80
- /**
81
- * Whether this device has a cursor that can rest somewhere without touching.
82
- * False switches off every hover-for-realism behaviour — the reCAPTCHA tile
83
- * hover and the idle drift during inference — because on a touchscreen those
84
- * are not weak mimicry, they are impossible.
85
- */
23
+ /** False on a device with no resting cursor; switches off every hover-for-realism behaviour. */
86
24
  readonly hovers: boolean;
87
- /** Where the pointer is now. */
88
25
  at: Point;
89
- /** Called once at the top of each `solve()`. Drop per-page caches. */
90
26
  reset(page: Page): Promise<void>;
91
27
  move(page: Page, to: Point): Promise<void>;
92
28
  press(page: Page): Promise<void>;
@@ -96,7 +32,7 @@ export interface Humanizer {
96
32
  typeText(page: Page, field: PlaywrightElementHandle, text: string): Promise<boolean>;
97
33
  pause(kind: PauseKind): Promise<void>;
98
34
  }
99
- type PauseTable = Record<string, [number, number]>;
35
+ type PauseTable = Partial<Record<PauseKind, [number, number]>>;
100
36
  export declare abstract class BaseHumanizer implements Humanizer {
101
37
  abstract readonly name: string;
102
38
  abstract readonly hovers: boolean;
@@ -108,190 +44,99 @@ export declare abstract class BaseHumanizer implements Humanizer {
108
44
  abstract press(page: Page): Promise<void>;
109
45
  abstract release(page: Page): Promise<void>;
110
46
  abstract typeText(page: Page, field: PlaywrightElementHandle, text: string): Promise<boolean>;
47
+ /** An unknown kind waits nothing, so adding a pause site cannot break a custom humanizer written against an older release. */
111
48
  protected pauseMs(kind: PauseKind): number;
112
49
  pause(kind: PauseKind): Promise<void>;
113
50
  click(page: Page, to: Point): Promise<void>;
114
51
  drag(page: Page, src: Point, dst: Point): Promise<void>;
115
52
  }
116
- /**
117
- * A hand on a mouse. Bezier arcs, Fitts's-law durations, overshoot.
118
- *
119
- * Everything in here was `solver.performSmoothMove` / `tracePath` before this
120
- * module existed, and is unchanged: the constants were measured and a refactor
121
- * is not the place to revisit them.
122
- */
123
53
  export declare class MouseHumanizer extends BaseHumanizer {
124
- readonly name = "mouse";
54
+ readonly name: HumanizationMode;
125
55
  readonly hovers = true;
126
- /** Inclusive ranges, in ms. See PauseKind. */
127
56
  protected readonly pauses: PauseTable;
128
57
  private frequency;
58
+ private viewportCache;
129
59
  constructor(start?: Point, frequency?: number);
60
+ reset(_page: Page): Promise<void>;
61
+ /** The window to keep the cursor inside; null under camoufox, which reports no viewport and whose window we ask instead. */
62
+ private viewport;
130
63
  move(page: Page, to: Point): Promise<void>;
131
64
  press(page: Page): Promise<void>;
132
65
  release(page: Page): Promise<void>;
66
+ /** Per character with a humanised pause, not type(text, {delay}): a constant inter-key delay is itself a signal these vendors score. */
133
67
  typeText(page: Page, _field: PlaywrightElementHandle, text: string): Promise<boolean>;
134
- private trace;
135
68
  }
136
- /** `[x, y, dtMs]` — dt is the wait BEFORE that sample. */
69
+ /** `[x, y, dtMs]`: dt is the wait before that sample. */
137
70
  export type TouchSample = [number, number, number];
138
- /**
139
- * Where touch events actually go.
140
- *
141
- * Three methods rather than one per sample, because the two backends want
142
- * opposite things: CDP dispatches one event per call and we pace it locally,
143
- * while a W3C/Appium driver takes a whole timed action chain in one round trip
144
- * and paces it on the device. Handing `move` the entire leg lets each do what it
145
- * is good at — and on a real device, pacing over the wire is not pacing at all.
146
- */
71
+ /** Where touch events go. `move` takes a whole leg so a device driver can pace it itself. */
147
72
  export interface TouchBackend {
148
73
  readonly name: string;
149
74
  down(x: number, y: number): Promise<void>;
150
75
  move(path: TouchSample[]): Promise<void>;
151
76
  up(x: number, y: number): Promise<void>;
152
77
  }
153
- /**
154
- * `Input.dispatchTouchEvent` over a CDP session on a Playwright page.
155
- *
156
- * Chromium-family only, and that is checked at construction rather than
157
- * discovered per gesture: WebKit and Firefox (camoufox included) expose no touch
158
- * dispatch through Playwright at all, so the alternatives there are to fail
159
- * loudly or to quietly emit MOUSE events at a touch-only widget. The second is
160
- * worse than not running — the page's touch handlers never fire, the solve fails
161
- * for a reason nothing reports, and the report reads as a model that cannot
162
- * solve mobile puzzles.
163
- *
164
- * The context must also have been created with `hasTouch: true`, or the page
165
- * advertises no touch support to feature detection and a mobile widget renders
166
- * its desktop branch.
167
- */
78
+ /** `Input.dispatchTouchEvent` over CDP; Chromium-family pages launched with `hasTouch: true`. */
168
79
  export declare class CdpTouchBackend implements TouchBackend {
169
- readonly name = "cdp";
170
80
  private session;
81
+ readonly name = "cdp";
171
82
  private constructor();
83
+ /**
84
+ * Checked at construction, not per gesture. WebKit and Firefox expose no touch dispatch, and emitting
85
+ * mouse events instead is worse than not running: the page's touch handlers never fire and the report
86
+ * reads as a model that cannot solve mobile puzzles.
87
+ */
172
88
  static open(page: Page): Promise<CdpTouchBackend>;
173
89
  private send;
174
90
  down(x: number, y: number): Promise<void>;
175
91
  move(path: TouchSample[]): Promise<void>;
176
92
  up(_x: number, _y: number): Promise<void>;
177
93
  }
178
- /** CSS-pixel → device-pixel transform for a real handset. See AppiumTouchBackend. */
94
+ /** CSS-pixel to device-pixel transform for a real handset. */
179
95
  export interface TouchTransform {
180
96
  scale?: number;
181
97
  origin?: Point;
182
98
  }
183
99
  /**
184
- * W3C pointer actions with `pointerType: 'touch'`, for Appium and WebdriverIO.
185
- *
186
- * Batches a whole leg into ONE action chain with per-sample durations, so the
187
- * kinematics are reproduced BY THE DEVICE rather than by a JS loop round-tripping
188
- * over the wire — over which a 90Hz path is not 90Hz at all.
189
- *
190
- * Press and release are separate `performActions()` calls on purpose. W3C input
191
- * state is per SESSION, so a pointer put down in one chain stays down across
192
- * later chains until it is lifted; that is what lets the puzzle-slider driver
193
- * press, screenshot, steer, screenshot and only then release. (It is also why
194
- * the spec has a "release actions" endpoint at all.)
195
- *
196
- * COORDINATES. Everything upstream of here is CSS pixels in the page's viewport,
197
- * because that is what `boundingBox()` returns. A real device wants screen
198
- * pixels, and the two differ by the device pixel ratio and by whatever chrome
199
- * sits above the webview. Neither is guessable from here, so both are options:
200
- *
201
- * new AppiumTouchBackend(driver, { scale: 3, origin: [0, 132] })
202
- *
203
- * `scale` is usually `window.devicePixelRatio`; `origin` is the top-left of the
204
- * webview in screen coordinates. Defaults are the identity transform, which is
205
- * correct for browser mobile emulation and for any caller who has already mapped
206
- * the coordinates themselves.
100
+ * W3C touch pointer actions for Appium and WebdriverIO, paced by the device from one chain per leg.
101
+ * Raw protocol payloads so this imports no client. Press and release are separate performs because W3C
102
+ * input state is per session: that is what lets the slider driver press, screenshot, steer, then release.
207
103
  */
208
104
  export declare class AppiumTouchBackend implements TouchBackend {
209
- readonly name = "appium";
210
105
  private driver;
106
+ private page?;
107
+ readonly name = "appium";
211
108
  private scale;
212
109
  private origin;
213
- /**
214
- * UNSET is not the same fact as an explicit 1. The first is a caller who has
215
- * not thought about the transform; the second is one who has, and says the
216
- * coordinates are already mapped. Only the first is checked.
217
- */
218
110
  private scaleGiven;
219
- private page;
220
111
  private checked;
221
- constructor(driver: any, transform?: TouchTransform, page?: Page);
112
+ constructor(driver: any, transform?: TouchTransform, page?: Page | undefined);
222
113
  /**
223
- * Refuse an unset scale on a session that reports it is not 1.
224
- *
225
- * A wrong transform fails SILENTLY on both sides of the wire: the chain is
226
- * valid W3C, the device performs it, and the finger lands somewhere else. The
227
- * solve then fails looking exactly like a model that cannot read the puzzle.
228
- *
229
- * Read once, not per gesture — it is a round trip into the page and a solve
230
- * makes hundreds of these. An unreadable ratio is absent evidence, not
231
- * evidence of a mismatch, so it falls through to the identity. `origin`
232
- * cannot be measured from here at all, so it is named in the refusal rather
233
- * than guessed at.
114
+ * Refuse an unset scale on a device whose pixel ratio is not 1: the finger would land elsewhere. An
115
+ * explicit scale of 1 is the caller's word and is not re-checked; the ratio is read once, since a solve
116
+ * makes hundreds of these, and an unreadable ratio is taken as 1.
234
117
  */
235
118
  private checkScale;
236
119
  private map;
237
- /**
238
- * One W3C action chain on a single touch pointer.
239
- *
240
- * Sent as the raw protocol payload rather than through a client's action
241
- * builder, so this imports nothing and works against any client that speaks
242
- * WebDriver — WebdriverIO (`performActions`), selenium-webdriver, or a thin
243
- * HTTP wrapper of someone's own.
244
- */
245
120
  private perform;
246
121
  down(x: number, y: number): Promise<void>;
122
+ /** The per-sample gap becomes the move's `duration`, so the device interpolates the leg itself. */
247
123
  move(path: TouchSample[]): Promise<void>;
248
124
  up(_x: number, _y: number): Promise<void>;
249
125
  }
250
- /**
251
- * Playwright's `page.touchscreen.tap()` — taps only, no travel.
252
- *
253
- * The fallback for a browser with touch support but no CDP (WebKit). A tap still
254
- * lands correctly; a DRAG cannot be expressed at all, so it throws rather than
255
- * approximating one with a mouse, for the reason in `CdpTouchBackend`.
256
- */
126
+ /** Playwright's tap-only touchscreen, for browsers with touch but no CDP. A drag cannot be expressed. */
257
127
  export declare class TouchscreenTouchBackend implements TouchBackend {
258
- readonly name = "touchscreen";
259
128
  private page;
129
+ readonly name = "touchscreen";
260
130
  private pending;
261
- constructor(page: Page);
131
+ constructor(page: any);
262
132
  down(x: number, y: number): Promise<void>;
263
133
  move(_path: TouchSample[]): Promise<void>;
264
134
  up(x: number, y: number): Promise<void>;
265
135
  }
266
- /**
267
- * Pick a backend. An explicit `driver` always wins.
268
- *
269
- * `driver` is what a caller passes when the thing under automation is not the
270
- * thing being touched — an Appium session driving a real handset while the page
271
- * object is a webview bridge over it.
272
- */
273
136
  export declare function touchBackendFor(page: Page, driver?: any, transform?: TouchTransform): Promise<TouchBackend>;
274
- /**
275
- * A finger on glass.
276
- *
277
- * What differs from `MouseHumanizer`, and none of it is cosmetic:
278
- *
279
- * - **A move that is not touching dispatches nothing.** There is no hover on a
280
- * touchscreen. The position is still RECORDED, because the next gesture
281
- * starts from it, but no event is emitted — emitting one would be the
282
- * desktop tell this mode exists to remove.
283
- * - **Taps carry a contact wobble.** A finger held on glass for 90ms does not
284
- * report one unchanging coordinate; the centroid of the contact patch rolls
285
- * a pixel or two under pressure. A tap with zero movement between touchstart
286
- * and touchend is a synthetic tap.
287
- * - **Touch kinematics**, via `generate_swipe` — see its docstring for why that
288
- * is a different model rather than the mouse one retuned.
289
- * - **Longer, more variable pauses.** Every measured touch interaction is
290
- * slower than its mouse equivalent, and a phone's are more variable because
291
- * the hand holding the device is also moving.
292
- */
137
+ /** A finger on glass: no hover, touch events only, slower and more variable pauses. */
293
138
  export declare class MobileHumanizer extends BaseHumanizer {
294
- readonly name = "mobile";
139
+ readonly name: HumanizationMode;
295
140
  readonly hovers = false;
296
141
  protected readonly pauses: PauseTable;
297
142
  private backend;
@@ -305,37 +150,23 @@ export declare class MobileHumanizer extends BaseHumanizer {
305
150
  transform?: TouchTransform;
306
151
  frequency?: number;
307
152
  });
153
+ /** A solve that ended mid-gesture leaves a pointer down in the session's input state; lift it before the next one. */
308
154
  reset(page: Page): Promise<void>;
309
155
  private touch;
310
156
  move(page: Page, to: Point): Promise<void>;
311
157
  press(page: Page): Promise<void>;
312
158
  release(page: Page): Promise<void>;
313
- /** Tap. The wobble is the point — see the class docstring. */
159
+ /** A tap whose contact patch wobbles a pixel while held; a motionless tap is a synthetic one. */
314
160
  click(page: Page, to: Point): Promise<void>;
315
- /**
316
- * Into the field, at soft-keyboard pace.
317
- *
318
- * The mouse path clears with Control+A. There is no Control on a phone
319
- * keyboard, so the box is cleared through the element instead — which also
320
- * works on an Appium element, where `page.keyboard` does not exist.
321
- */
161
+ /** Clears through the element: there is no Control key on a phone and no `page.keyboard` on Appium. */
322
162
  typeText(page: Page, field: PlaywrightElementHandle, text: string): Promise<boolean>;
323
163
  }
324
164
  /**
325
- * No humanisation: the shortest legal path to the same DOM effect.
326
- *
327
- * One mousemove per gesture instead of sixty, no dwell, no jitter, and text goes
328
- * in with a single `fill()`. Roughly an order of magnitude faster on a slider
329
- * puzzle, and it will be detected by anything that scores pointer telemetry —
330
- * which is the whole trade, stated plainly. For fixtures, for self-hosted
331
- * targets, and for callers whose stack humanises somewhere else.
332
- *
333
- * Still moves the mouse and still presses and releases: the events are what make
334
- * the widget respond at all, and a click dispatched with no preceding move fails
335
- * on the vendors that require a hover state first.
165
+ * No humanisation: one move per gesture and a single fill. Fast, and detectable. It still moves before
166
+ * it presses, because a click with no preceding move fails on the vendors that require a hover state first.
336
167
  */
337
168
  export declare class NullHumanizer extends BaseHumanizer {
338
- readonly name = "none";
169
+ readonly name: HumanizationMode;
339
170
  readonly hovers = false;
340
171
  protected readonly pauses: PauseTable;
341
172
  move(page: Page, to: Point): Promise<void>;
@@ -343,9 +174,7 @@ export declare class NullHumanizer extends BaseHumanizer {
343
174
  release(page: Page): Promise<void>;
344
175
  typeText(page: Page, field: PlaywrightElementHandle, text: string): Promise<boolean>;
345
176
  }
346
- export type HumanizationMode = 'mouse' | 'mobile' | 'none';
347
177
  export declare const MODES: readonly HumanizationMode[];
348
- /** The subset of `CaptchaKrakenConfig` this module reads. */
349
178
  export interface HumanizerOptions {
350
179
  humanization?: HumanizationMode;
351
180
  humanizer?: Humanizer;
@@ -357,21 +186,8 @@ export interface HumanizerOptions {
357
186
  };
358
187
  }
359
188
  /**
360
- * The humanizer one solver will use, from its config.
361
- *
362
- * Precedence, and the reasoning for it:
363
- *
364
- * 1. `config.humanizer` — a caller who handed us an OBJECT has already
365
- * decided; there is nothing left to select.
366
- * 2. `config.humanization` — an explicit mode set in code.
367
- * 3. `CAPTCHA_HUMANIZATION` — for a caller who cannot edit the code.
368
- * 4. 'mouse'.
369
- *
370
- * Note that the env var loses to code, which is the opposite of this package's
371
- * model-identity settings. Deliberate: which mode is right is a property of the
372
- * PAGE the caller is driving, and an env var flipping a desktop solve to touch
373
- * dispatch would break every one of them silently. Pinning a model is a
374
- * deployment decision; picking an input device is not.
189
+ * `config.humanizer`, else `config.humanization`, else CAPTCHA_HUMANIZATION, else mouse. The env var loses
190
+ * to code, the opposite of the model settings, on purpose: an env var flipping a desktop solve to touch
191
+ * dispatch would break every one of them silently.
375
192
  */
376
193
  export declare function resolveHumanizer(config?: HumanizerOptions): Humanizer;
377
- export {};