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.
- 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 +94 -712
- package/dist/solver.js +923 -3362
- 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 +75 -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 +1052 -3098
- package/python/src/captchakraken/planner.py +50 -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
package/dist/index.d.ts
CHANGED
|
@@ -1,139 +1,15 @@
|
|
|
1
1
|
export * from './types';
|
|
2
|
+
export * from './kinds';
|
|
2
3
|
export { CaptchaKrakenSolver } from './solver';
|
|
3
|
-
|
|
4
|
-
* The served LoRA name this client will ask for when `model` is left unset —
|
|
5
|
-
* `CAPTCHA_LORA_NAME`, else `models.json`'s `latest`, else the shipped pin.
|
|
6
|
-
*
|
|
7
|
-
* Exported so anything that REPORTS which adapter was driven can ask the client
|
|
8
|
-
* instead of re-deriving the answer. That distinction is not cosmetic: the name
|
|
9
|
-
* selects the prompt generation, so a reporter that guesses it can disagree with
|
|
10
|
-
* the solver and describe a run that never happened.
|
|
11
|
-
*/
|
|
4
|
+
export type { Widget } from './solver';
|
|
12
5
|
export { resolveLoraName } from './model-name';
|
|
13
|
-
/**
|
|
14
|
-
* Errors raised when the **hosted** CaptchaKraken API refuses a solve — out of
|
|
15
|
-
* credits, rate limited, key rejected, attempt abandoned.
|
|
16
|
-
*
|
|
17
|
-
* `message` is already a complete sentence naming the product and, where one
|
|
18
|
-
* exists, the URL that fixes it, so printing it is enough. `code` is the stable
|
|
19
|
-
* contract to branch on; the prose is not.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* import { CaptchaKrakenSolver, CaptchaKrakenAPIError } from 'captchakraken';
|
|
24
|
-
*
|
|
25
|
-
* try {
|
|
26
|
-
* await solver.solve(page);
|
|
27
|
-
* } catch (e) {
|
|
28
|
-
* if (e instanceof CaptchaKrakenAPIError && e.code === 'insufficient_credits') {
|
|
29
|
-
* console.error(`Top up: ${e.resolutionUrl}`);
|
|
30
|
-
* } else throw e;
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
6
|
export { CaptchaKrakenAPIError } from './errors';
|
|
35
7
|
export type { CaptchaKrakenErrorCode } from './errors';
|
|
36
|
-
/**
|
|
37
|
-
* Adapter for driving the solver with **Puppeteer** instead of a Playwright
|
|
38
|
-
* launcher. Puppeteer's `Page` is API-compatible with Playwright's except for a
|
|
39
|
-
* few method names/options; `fromPuppeteer(page)` wraps it so `solve()` accepts
|
|
40
|
-
* it. Playwright-family launchers (vanilla `playwright`, `patchright`,
|
|
41
|
-
* `camoufox-js`) need no adapter — pass their `Page` directly.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```typescript
|
|
45
|
-
* import puppeteer from 'puppeteer';
|
|
46
|
-
* import { CaptchaKrakenSolver, fromPuppeteer } from 'captchakraken';
|
|
47
|
-
*
|
|
48
|
-
* const browser = await puppeteer.launch({ headless: false });
|
|
49
|
-
* const page = await browser.newPage();
|
|
50
|
-
* await page.goto('https://www.google.com/recaptcha/api2/demo');
|
|
51
|
-
*
|
|
52
|
-
* const solver = new CaptchaKrakenSolver();
|
|
53
|
-
* await solver.solve(fromPuppeteer(page));
|
|
54
|
-
* await browser.close();
|
|
55
|
-
* ```
|
|
56
|
-
*/
|
|
57
8
|
export { fromPuppeteer } from './puppeteer-adapter';
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
* This is an implementation-neutral, structurally-typed Playwright `Page` — a
|
|
62
|
-
* duck-typed surface defined by this package, NOT imported from any browser
|
|
63
|
-
* library. The package depends on no concrete browser implementation, so you
|
|
64
|
-
* can drive the solver with ANY Playwright-compatible launcher: vanilla
|
|
65
|
-
* `playwright`, `patchright`, `camoufox-js`, or anything else that hands back a
|
|
66
|
-
* standard Playwright `Page`. They all structurally satisfy this type — pass
|
|
67
|
-
* yours directly, no cast needed.
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```typescript
|
|
71
|
-
* // Pick whichever Playwright-compatible launcher you want — install it
|
|
72
|
-
* // yourself; this package does not bundle a browser:
|
|
73
|
-
* import { chromium } from 'playwright'; // vanilla
|
|
74
|
-
* // import { chromium } from 'patchright'; // stealth-patched
|
|
75
|
-
* // import { Camoufox } from 'camoufox-js'; // Firefox stealth
|
|
76
|
-
* import { CaptchaKrakenSolver } from 'captchakraken';
|
|
77
|
-
*
|
|
78
|
-
* const browser = await chromium.launch({ headless: false });
|
|
79
|
-
* const page = await (await browser.newContext()).newPage();
|
|
80
|
-
* await page.goto('https://www.google.com/recaptcha/api2/demo');
|
|
81
|
-
*
|
|
82
|
-
* // Reads VLLM_BASE_URL + CAPTCHA_KRAKEN_API_KEY from the environment.
|
|
83
|
-
* const solver = new CaptchaKrakenSolver();
|
|
84
|
-
* await solver.solve(page); // detect → solve grid → click → verify
|
|
85
|
-
*
|
|
86
|
-
* await browser.close();
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
export type { Page, PlaywrightPage, PlaywrightFrame, PlaywrightElementHandle } from './playwright-types';
|
|
90
|
-
/**
|
|
91
|
-
* Auto-solve watcher: `solver.watch(page)` installs a background poller that
|
|
92
|
-
* solves captchas as they appear, and returns a handle with `stop()`.
|
|
93
|
-
*
|
|
94
|
-
* Injects nothing into the page, on any platform — see watcher.ts. On Camoufox
|
|
95
|
-
* its DOM reads run in the isolated Juggler world by default.
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```typescript
|
|
99
|
-
* const solver = new CaptchaKrakenSolver();
|
|
100
|
-
* const watcher = solver.watch(page, { onSolved: r => console.log(r.isSolved) });
|
|
101
|
-
* // ... your automation ...
|
|
102
|
-
* await watcher.stop();
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
9
|
+
export type { Page, PlaywrightPage, PlaywrightFrame, PlaywrightElementHandle, PlaywrightLocator, PlaywrightScope } from './playwright-types';
|
|
10
|
+
export { SELECTORS } from './selectors';
|
|
11
|
+
export type { VendorSelectors } from './selectors';
|
|
105
12
|
export { watchPage } from './watcher';
|
|
106
13
|
export type { CaptchaWatcher, WatchOptions, WatchableSolver } from './watcher';
|
|
107
|
-
/**
|
|
108
|
-
* Humanisation: how the driver moves. `humanization: 'mouse' | 'mobile' |
|
|
109
|
-
* 'none'` picks a built-in; `humanizer` takes one of your own.
|
|
110
|
-
*
|
|
111
|
-
* `MobileHumanizer` emits real touch events with finger kinematics, through a
|
|
112
|
-
* `TouchBackend` — CDP against a Chromium-family page, or W3C pointer actions
|
|
113
|
-
* against an Appium / WebdriverIO driver on a real handset.
|
|
114
|
-
*
|
|
115
|
-
* @example Mobile emulation in the browser
|
|
116
|
-
* ```typescript
|
|
117
|
-
* import { chromium, devices } from 'playwright';
|
|
118
|
-
* import { CaptchaKrakenSolver } from 'captchakraken';
|
|
119
|
-
*
|
|
120
|
-
* const browser = await chromium.launch();
|
|
121
|
-
* const context = await browser.newContext({ ...devices['Pixel 7'], hasTouch: true });
|
|
122
|
-
* const page = await context.newPage();
|
|
123
|
-
* await page.goto('https://example.com/signup');
|
|
124
|
-
*
|
|
125
|
-
* await new CaptchaKrakenSolver({ humanization: 'mobile' }).solve(page);
|
|
126
|
-
* ```
|
|
127
|
-
*
|
|
128
|
-
* @example A real device over Appium
|
|
129
|
-
* ```typescript
|
|
130
|
-
* const solver = new CaptchaKrakenSolver({
|
|
131
|
-
* humanization: 'mobile',
|
|
132
|
-
* touchDriver: driver, // the WebdriverIO browser
|
|
133
|
-
* touchTransform: { scale: 3, origin: [0, 132] }, // CSS px -> screen px
|
|
134
|
-
* });
|
|
135
|
-
* await solver.solve(page);
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
14
|
export { MouseHumanizer, MobileHumanizer, NullHumanizer, BaseHumanizer, resolveHumanizer, touchBackendFor, CdpTouchBackend, AppiumTouchBackend, TouchscreenTouchBackend, PAUSE_KINDS, MODES as HUMANIZATION_MODES, } from './humanize';
|
|
139
15
|
export type { Humanizer, HumanizationMode, HumanizerOptions, TouchBackend, TouchSample, TouchTransform, PauseKind, } from './humanize';
|
package/dist/index.js
CHANGED
|
@@ -14,115 +14,21 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.HUMANIZATION_MODES = exports.PAUSE_KINDS = exports.TouchscreenTouchBackend = exports.AppiumTouchBackend = exports.CdpTouchBackend = exports.touchBackendFor = exports.resolveHumanizer = exports.BaseHumanizer = exports.NullHumanizer = exports.MobileHumanizer = exports.MouseHumanizer = exports.watchPage = exports.fromPuppeteer = exports.CaptchaKrakenAPIError = exports.resolveLoraName = exports.CaptchaKrakenSolver = void 0;
|
|
17
|
+
exports.HUMANIZATION_MODES = exports.PAUSE_KINDS = exports.TouchscreenTouchBackend = exports.AppiumTouchBackend = exports.CdpTouchBackend = exports.touchBackendFor = exports.resolveHumanizer = exports.BaseHumanizer = exports.NullHumanizer = exports.MobileHumanizer = exports.MouseHumanizer = exports.watchPage = exports.SELECTORS = exports.fromPuppeteer = exports.CaptchaKrakenAPIError = exports.resolveLoraName = exports.CaptchaKrakenSolver = void 0;
|
|
18
18
|
__exportStar(require("./types"), exports);
|
|
19
|
+
__exportStar(require("./kinds"), exports);
|
|
19
20
|
var solver_1 = require("./solver");
|
|
20
21
|
Object.defineProperty(exports, "CaptchaKrakenSolver", { enumerable: true, get: function () { return solver_1.CaptchaKrakenSolver; } });
|
|
21
|
-
/**
|
|
22
|
-
* The served LoRA name this client will ask for when `model` is left unset —
|
|
23
|
-
* `CAPTCHA_LORA_NAME`, else `models.json`'s `latest`, else the shipped pin.
|
|
24
|
-
*
|
|
25
|
-
* Exported so anything that REPORTS which adapter was driven can ask the client
|
|
26
|
-
* instead of re-deriving the answer. That distinction is not cosmetic: the name
|
|
27
|
-
* selects the prompt generation, so a reporter that guesses it can disagree with
|
|
28
|
-
* the solver and describe a run that never happened.
|
|
29
|
-
*/
|
|
30
22
|
var model_name_1 = require("./model-name");
|
|
31
23
|
Object.defineProperty(exports, "resolveLoraName", { enumerable: true, get: function () { return model_name_1.resolveLoraName; } });
|
|
32
|
-
/**
|
|
33
|
-
* Errors raised when the **hosted** CaptchaKraken API refuses a solve — out of
|
|
34
|
-
* credits, rate limited, key rejected, attempt abandoned.
|
|
35
|
-
*
|
|
36
|
-
* `message` is already a complete sentence naming the product and, where one
|
|
37
|
-
* exists, the URL that fixes it, so printing it is enough. `code` is the stable
|
|
38
|
-
* contract to branch on; the prose is not.
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```typescript
|
|
42
|
-
* import { CaptchaKrakenSolver, CaptchaKrakenAPIError } from 'captchakraken';
|
|
43
|
-
*
|
|
44
|
-
* try {
|
|
45
|
-
* await solver.solve(page);
|
|
46
|
-
* } catch (e) {
|
|
47
|
-
* if (e instanceof CaptchaKrakenAPIError && e.code === 'insufficient_credits') {
|
|
48
|
-
* console.error(`Top up: ${e.resolutionUrl}`);
|
|
49
|
-
* } else throw e;
|
|
50
|
-
* }
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
24
|
var errors_1 = require("./errors");
|
|
54
25
|
Object.defineProperty(exports, "CaptchaKrakenAPIError", { enumerable: true, get: function () { return errors_1.CaptchaKrakenAPIError; } });
|
|
55
|
-
/**
|
|
56
|
-
* Adapter for driving the solver with **Puppeteer** instead of a Playwright
|
|
57
|
-
* launcher. Puppeteer's `Page` is API-compatible with Playwright's except for a
|
|
58
|
-
* few method names/options; `fromPuppeteer(page)` wraps it so `solve()` accepts
|
|
59
|
-
* it. Playwright-family launchers (vanilla `playwright`, `patchright`,
|
|
60
|
-
* `camoufox-js`) need no adapter — pass their `Page` directly.
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```typescript
|
|
64
|
-
* import puppeteer from 'puppeteer';
|
|
65
|
-
* import { CaptchaKrakenSolver, fromPuppeteer } from 'captchakraken';
|
|
66
|
-
*
|
|
67
|
-
* const browser = await puppeteer.launch({ headless: false });
|
|
68
|
-
* const page = await browser.newPage();
|
|
69
|
-
* await page.goto('https://www.google.com/recaptcha/api2/demo');
|
|
70
|
-
*
|
|
71
|
-
* const solver = new CaptchaKrakenSolver();
|
|
72
|
-
* await solver.solve(fromPuppeteer(page));
|
|
73
|
-
* await browser.close();
|
|
74
|
-
* ```
|
|
75
|
-
*/
|
|
76
26
|
var puppeteer_adapter_1 = require("./puppeteer-adapter");
|
|
77
27
|
Object.defineProperty(exports, "fromPuppeteer", { enumerable: true, get: function () { return puppeteer_adapter_1.fromPuppeteer; } });
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
* solves captchas as they appear, and returns a handle with `stop()`.
|
|
81
|
-
*
|
|
82
|
-
* Injects nothing into the page, on any platform — see watcher.ts. On Camoufox
|
|
83
|
-
* its DOM reads run in the isolated Juggler world by default.
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```typescript
|
|
87
|
-
* const solver = new CaptchaKrakenSolver();
|
|
88
|
-
* const watcher = solver.watch(page, { onSolved: r => console.log(r.isSolved) });
|
|
89
|
-
* // ... your automation ...
|
|
90
|
-
* await watcher.stop();
|
|
91
|
-
* ```
|
|
92
|
-
*/
|
|
28
|
+
var selectors_1 = require("./selectors");
|
|
29
|
+
Object.defineProperty(exports, "SELECTORS", { enumerable: true, get: function () { return selectors_1.SELECTORS; } });
|
|
93
30
|
var watcher_1 = require("./watcher");
|
|
94
31
|
Object.defineProperty(exports, "watchPage", { enumerable: true, get: function () { return watcher_1.watchPage; } });
|
|
95
|
-
/**
|
|
96
|
-
* Humanisation: how the driver moves. `humanization: 'mouse' | 'mobile' |
|
|
97
|
-
* 'none'` picks a built-in; `humanizer` takes one of your own.
|
|
98
|
-
*
|
|
99
|
-
* `MobileHumanizer` emits real touch events with finger kinematics, through a
|
|
100
|
-
* `TouchBackend` — CDP against a Chromium-family page, or W3C pointer actions
|
|
101
|
-
* against an Appium / WebdriverIO driver on a real handset.
|
|
102
|
-
*
|
|
103
|
-
* @example Mobile emulation in the browser
|
|
104
|
-
* ```typescript
|
|
105
|
-
* import { chromium, devices } from 'playwright';
|
|
106
|
-
* import { CaptchaKrakenSolver } from 'captchakraken';
|
|
107
|
-
*
|
|
108
|
-
* const browser = await chromium.launch();
|
|
109
|
-
* const context = await browser.newContext({ ...devices['Pixel 7'], hasTouch: true });
|
|
110
|
-
* const page = await context.newPage();
|
|
111
|
-
* await page.goto('https://example.com/signup');
|
|
112
|
-
*
|
|
113
|
-
* await new CaptchaKrakenSolver({ humanization: 'mobile' }).solve(page);
|
|
114
|
-
* ```
|
|
115
|
-
*
|
|
116
|
-
* @example A real device over Appium
|
|
117
|
-
* ```typescript
|
|
118
|
-
* const solver = new CaptchaKrakenSolver({
|
|
119
|
-
* humanization: 'mobile',
|
|
120
|
-
* touchDriver: driver, // the WebdriverIO browser
|
|
121
|
-
* touchTransform: { scale: 3, origin: [0, 132] }, // CSS px -> screen px
|
|
122
|
-
* });
|
|
123
|
-
* await solver.solve(page);
|
|
124
|
-
* ```
|
|
125
|
-
*/
|
|
126
32
|
var humanize_1 = require("./humanize");
|
|
127
33
|
Object.defineProperty(exports, "MouseHumanizer", { enumerable: true, get: function () { return humanize_1.MouseHumanizer; } });
|
|
128
34
|
Object.defineProperty(exports, "MobileHumanizer", { enumerable: true, get: function () { return humanize_1.MobileHumanizer; } });
|
package/dist/kinds.d.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every closed set of names the two ports agree on. Mirrored in python/src/captchakraken/kinds.py; keep both in the same order.
|
|
3
|
+
* `as const` objects rather than `enum`: a literal off the wire (`'click'`) type-checks against them, an `enum` would not.
|
|
4
|
+
*/
|
|
5
|
+
/** `puzzleSource` everywhere. UNKNOWN must stay permissive: GeeTest and Prosopo report it, and so does the offline grader. */
|
|
6
|
+
export declare const Vendor: {
|
|
7
|
+
readonly HCAPTCHA: "hcaptcha";
|
|
8
|
+
readonly RECAPTCHA: "recaptcha";
|
|
9
|
+
readonly TURNSTILE: "turnstile";
|
|
10
|
+
readonly GEETEST: "geetest";
|
|
11
|
+
readonly TENCENT: "tencent";
|
|
12
|
+
readonly YIDUN: "yidun";
|
|
13
|
+
readonly YANDEX: "yandex";
|
|
14
|
+
readonly LEMIN: "lemin";
|
|
15
|
+
readonly PROSOPO: "prosopo";
|
|
16
|
+
readonly MTCAPTCHA: "mtcaptcha";
|
|
17
|
+
readonly BOTDETECT: "botdetect";
|
|
18
|
+
readonly UNKNOWN: "unknown";
|
|
19
|
+
};
|
|
20
|
+
export type Vendor = (typeof Vendor)[keyof typeof Vendor];
|
|
21
|
+
export declare const ActionKind: {
|
|
22
|
+
readonly CLICK: "click";
|
|
23
|
+
readonly DRAG: "drag";
|
|
24
|
+
readonly TYPE: "type";
|
|
25
|
+
readonly WAIT: "wait";
|
|
26
|
+
readonly DONE: "done";
|
|
27
|
+
};
|
|
28
|
+
export type ActionKind = (typeof ActionKind)[keyof typeof ActionKind];
|
|
29
|
+
export declare const RetryMode: {
|
|
30
|
+
readonly MISSED_TILES: "missed-tiles";
|
|
31
|
+
};
|
|
32
|
+
export type RetryMode = (typeof RetryMode)[keyof typeof RetryMode];
|
|
33
|
+
export declare const SettleVerdict: {
|
|
34
|
+
readonly SETTLED: "settled";
|
|
35
|
+
readonly ANIMATED: "animated";
|
|
36
|
+
readonly TIMEOUT: "timeout";
|
|
37
|
+
};
|
|
38
|
+
export type SettleVerdict = (typeof SettleVerdict)[keyof typeof SettleVerdict];
|
|
39
|
+
export declare const PaintVerdict: {
|
|
40
|
+
readonly PAINTED: "painted";
|
|
41
|
+
readonly BLANK: "blank";
|
|
42
|
+
readonly UNKNOWN: "unknown";
|
|
43
|
+
};
|
|
44
|
+
export type PaintVerdict = (typeof PaintVerdict)[keyof typeof PaintVerdict];
|
|
45
|
+
/** EVEN means the slicer could not prove recurrence, not that the board is still. */
|
|
46
|
+
export declare const KeyframeMode: {
|
|
47
|
+
readonly STATIC: "static";
|
|
48
|
+
readonly CYCLE: "cycle";
|
|
49
|
+
readonly EVEN: "even";
|
|
50
|
+
};
|
|
51
|
+
export type KeyframeMode = (typeof KeyframeMode)[keyof typeof KeyframeMode];
|
|
52
|
+
export declare const RecaptchaBanner: {
|
|
53
|
+
readonly SELECT_MORE: "select-more";
|
|
54
|
+
readonly DYNAMIC_MORE: "dynamic-more";
|
|
55
|
+
readonly REJECTED: "rejected";
|
|
56
|
+
};
|
|
57
|
+
export type RecaptchaBanner = (typeof RecaptchaBanner)[keyof typeof RecaptchaBanner];
|
|
58
|
+
/** One expert per family; `pixel` is spelled to match ckgate's prompt markers. */
|
|
59
|
+
export declare const PromptFamily: {
|
|
60
|
+
readonly PIXEL: "pixel";
|
|
61
|
+
readonly GRID: "grid";
|
|
62
|
+
readonly VIDEO: "video";
|
|
63
|
+
readonly TEXT: "text";
|
|
64
|
+
};
|
|
65
|
+
export type PromptFamily = (typeof PromptFamily)[keyof typeof PromptFamily];
|
|
66
|
+
export declare const HumanizationMode: {
|
|
67
|
+
readonly MOUSE: "mouse";
|
|
68
|
+
readonly MOBILE: "mobile";
|
|
69
|
+
readonly NONE: "none";
|
|
70
|
+
};
|
|
71
|
+
export type HumanizationMode = (typeof HumanizationMode)[keyof typeof HumanizationMode];
|
|
72
|
+
export declare const PauseKind: {
|
|
73
|
+
readonly TAP: "tap";
|
|
74
|
+
readonly BETWEEN: "between";
|
|
75
|
+
readonly GRAB: "grab";
|
|
76
|
+
readonly DROP: "drop";
|
|
77
|
+
readonly PROBE: "probe";
|
|
78
|
+
readonly SETTLE: "settle";
|
|
79
|
+
readonly KEY: "key";
|
|
80
|
+
};
|
|
81
|
+
export type PauseKind = (typeof PauseKind)[keyof typeof PauseKind];
|
|
82
|
+
export declare const Outcome: {
|
|
83
|
+
readonly SOLVED: "solved";
|
|
84
|
+
readonly FAILED: "failed";
|
|
85
|
+
};
|
|
86
|
+
export type Outcome = (typeof Outcome)[keyof typeof Outcome];
|
|
87
|
+
/** Timing phases. Only INFERENCE and MOUSE are productive; everything else is waiting. */
|
|
88
|
+
export declare const Phase: {
|
|
89
|
+
readonly INFERENCE: "inference";
|
|
90
|
+
readonly MOUSE: "mouse";
|
|
91
|
+
readonly SCREENSHOT: "screenshot";
|
|
92
|
+
readonly DETECT: "detect";
|
|
93
|
+
readonly SETTLE: "settle";
|
|
94
|
+
readonly BURST: "burst";
|
|
95
|
+
readonly GRID: "grid";
|
|
96
|
+
readonly GRID_LOAD: "grid-load";
|
|
97
|
+
readonly FADE_WAIT: "fade-wait";
|
|
98
|
+
readonly BOARD_PAINT: "board-paint";
|
|
99
|
+
readonly HCAPTCHA_IMAGES: "hcaptcha-images";
|
|
100
|
+
readonly AWAIT_NEXT_ROUND: "await-next-round";
|
|
101
|
+
readonly AWAIT_VERDICT: "await-verdict";
|
|
102
|
+
readonly POST_SUBMIT_DELAY: "post-submit-delay";
|
|
103
|
+
};
|
|
104
|
+
export type Phase = (typeof Phase)[keyof typeof Phase];
|
|
105
|
+
export declare const SolveStage: {
|
|
106
|
+
readonly INITIAL: "initial";
|
|
107
|
+
readonly CLICK: "click";
|
|
108
|
+
readonly DRAG: "drag";
|
|
109
|
+
readonly TYPE: "type";
|
|
110
|
+
readonly WAIT: "wait";
|
|
111
|
+
readonly SUBMIT: "submit";
|
|
112
|
+
readonly ROUND: "round";
|
|
113
|
+
};
|
|
114
|
+
export type SolveStage = (typeof SolveStage)[keyof typeof SolveStage];
|
|
115
|
+
export declare const FrameRole: {
|
|
116
|
+
readonly CHECKBOX: "checkbox";
|
|
117
|
+
readonly CHALLENGE: "challenge";
|
|
118
|
+
readonly UNKNOWN: "unknown";
|
|
119
|
+
};
|
|
120
|
+
export type FrameRole = (typeof FrameRole)[keyof typeof FrameRole];
|
|
121
|
+
/** The hosted API's machine-readable codes. Unknown codes still carry the server's message through; this is not a filter. */
|
|
122
|
+
export declare const ErrorCode: {
|
|
123
|
+
readonly MISSING_API_KEY: "missing_api_key";
|
|
124
|
+
readonly INVALID_API_KEY: "invalid_api_key";
|
|
125
|
+
readonly ACCOUNT_SUSPENDED: "account_suspended";
|
|
126
|
+
readonly INSUFFICIENT_CREDITS: "insufficient_credits";
|
|
127
|
+
readonly RATE_LIMITED: "rate_limited";
|
|
128
|
+
readonly SOLVE_ABANDONED: "solve_abandoned";
|
|
129
|
+
readonly UNRECOGNIZED_PROMPT: "unrecognized_prompt";
|
|
130
|
+
readonly INVALID_REQUEST: "invalid_request";
|
|
131
|
+
readonly REQUEST_TOO_LARGE: "request_too_large";
|
|
132
|
+
readonly UPSTREAM_UNAVAILABLE: "upstream_unavailable";
|
|
133
|
+
};
|
|
134
|
+
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
135
|
+
export declare function isOneOf<T extends Record<string, string>>(set: T, value: unknown): value is T[keyof T];
|
package/dist/kinds.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Every closed set of names the two ports agree on. Mirrored in python/src/captchakraken/kinds.py; keep both in the same order.
|
|
4
|
+
* `as const` objects rather than `enum`: a literal off the wire (`'click'`) type-checks against them, an `enum` would not.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ErrorCode = exports.FrameRole = exports.SolveStage = exports.Phase = exports.Outcome = exports.PauseKind = exports.HumanizationMode = exports.PromptFamily = exports.RecaptchaBanner = exports.KeyframeMode = exports.PaintVerdict = exports.SettleVerdict = exports.RetryMode = exports.ActionKind = exports.Vendor = void 0;
|
|
8
|
+
exports.isOneOf = isOneOf;
|
|
9
|
+
/** `puzzleSource` everywhere. UNKNOWN must stay permissive: GeeTest and Prosopo report it, and so does the offline grader. */
|
|
10
|
+
exports.Vendor = {
|
|
11
|
+
HCAPTCHA: 'hcaptcha',
|
|
12
|
+
RECAPTCHA: 'recaptcha',
|
|
13
|
+
TURNSTILE: 'turnstile',
|
|
14
|
+
GEETEST: 'geetest',
|
|
15
|
+
TENCENT: 'tencent',
|
|
16
|
+
YIDUN: 'yidun',
|
|
17
|
+
YANDEX: 'yandex',
|
|
18
|
+
LEMIN: 'lemin',
|
|
19
|
+
PROSOPO: 'prosopo',
|
|
20
|
+
MTCAPTCHA: 'mtcaptcha',
|
|
21
|
+
BOTDETECT: 'botdetect',
|
|
22
|
+
UNKNOWN: 'unknown',
|
|
23
|
+
};
|
|
24
|
+
exports.ActionKind = { CLICK: 'click', DRAG: 'drag', TYPE: 'type', WAIT: 'wait', DONE: 'done' };
|
|
25
|
+
exports.RetryMode = { MISSED_TILES: 'missed-tiles' };
|
|
26
|
+
exports.SettleVerdict = { SETTLED: 'settled', ANIMATED: 'animated', TIMEOUT: 'timeout' };
|
|
27
|
+
exports.PaintVerdict = { PAINTED: 'painted', BLANK: 'blank', UNKNOWN: 'unknown' };
|
|
28
|
+
/** EVEN means the slicer could not prove recurrence, not that the board is still. */
|
|
29
|
+
exports.KeyframeMode = { STATIC: 'static', CYCLE: 'cycle', EVEN: 'even' };
|
|
30
|
+
exports.RecaptchaBanner = { SELECT_MORE: 'select-more', DYNAMIC_MORE: 'dynamic-more', REJECTED: 'rejected' };
|
|
31
|
+
/** One expert per family; `pixel` is spelled to match ckgate's prompt markers. */
|
|
32
|
+
exports.PromptFamily = { PIXEL: 'pixel', GRID: 'grid', VIDEO: 'video', TEXT: 'text' };
|
|
33
|
+
exports.HumanizationMode = { MOUSE: 'mouse', MOBILE: 'mobile', NONE: 'none' };
|
|
34
|
+
exports.PauseKind = { TAP: 'tap', BETWEEN: 'between', GRAB: 'grab', DROP: 'drop', PROBE: 'probe', SETTLE: 'settle', KEY: 'key' };
|
|
35
|
+
exports.Outcome = { SOLVED: 'solved', FAILED: 'failed' };
|
|
36
|
+
/** Timing phases. Only INFERENCE and MOUSE are productive; everything else is waiting. */
|
|
37
|
+
exports.Phase = {
|
|
38
|
+
INFERENCE: 'inference',
|
|
39
|
+
MOUSE: 'mouse',
|
|
40
|
+
SCREENSHOT: 'screenshot',
|
|
41
|
+
DETECT: 'detect',
|
|
42
|
+
SETTLE: 'settle',
|
|
43
|
+
BURST: 'burst',
|
|
44
|
+
GRID: 'grid',
|
|
45
|
+
GRID_LOAD: 'grid-load',
|
|
46
|
+
FADE_WAIT: 'fade-wait',
|
|
47
|
+
BOARD_PAINT: 'board-paint',
|
|
48
|
+
HCAPTCHA_IMAGES: 'hcaptcha-images',
|
|
49
|
+
AWAIT_NEXT_ROUND: 'await-next-round',
|
|
50
|
+
AWAIT_VERDICT: 'await-verdict',
|
|
51
|
+
POST_SUBMIT_DELAY: 'post-submit-delay',
|
|
52
|
+
};
|
|
53
|
+
exports.SolveStage = { INITIAL: 'initial', CLICK: 'click', DRAG: 'drag', TYPE: 'type', WAIT: 'wait', SUBMIT: 'submit', ROUND: 'round' };
|
|
54
|
+
exports.FrameRole = { CHECKBOX: 'checkbox', CHALLENGE: 'challenge', UNKNOWN: 'unknown' };
|
|
55
|
+
/** The hosted API's machine-readable codes. Unknown codes still carry the server's message through; this is not a filter. */
|
|
56
|
+
exports.ErrorCode = {
|
|
57
|
+
MISSING_API_KEY: 'missing_api_key',
|
|
58
|
+
INVALID_API_KEY: 'invalid_api_key',
|
|
59
|
+
ACCOUNT_SUSPENDED: 'account_suspended',
|
|
60
|
+
INSUFFICIENT_CREDITS: 'insufficient_credits',
|
|
61
|
+
RATE_LIMITED: 'rate_limited',
|
|
62
|
+
SOLVE_ABANDONED: 'solve_abandoned',
|
|
63
|
+
UNRECOGNIZED_PROMPT: 'unrecognized_prompt',
|
|
64
|
+
INVALID_REQUEST: 'invalid_request',
|
|
65
|
+
REQUEST_TOO_LARGE: 'request_too_large',
|
|
66
|
+
UPSTREAM_UNAVAILABLE: 'upstream_unavailable',
|
|
67
|
+
};
|
|
68
|
+
function isOneOf(set, value) {
|
|
69
|
+
return typeof value === 'string' && Object.values(set).includes(value);
|
|
70
|
+
}
|
package/dist/limits.d.ts
CHANGED
|
@@ -1,51 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Numbers that must agree with the hosted gateway, stated once.
|
|
3
|
-
*
|
|
4
|
-
* These are not arbitrary defaults. They sit inside an ordering the server
|
|
5
|
-
* enforces, and the ordering — not any individual value — is the property worth
|
|
6
|
-
* protecting. `limits.test.ts` pins it.
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* The server bills at most this many responses per captcha attempt.
|
|
10
|
-
*
|
|
11
|
-
* Mirrors `MAX_BILLABLE_ROUNDS_PER_SESSION` in captchakraken-gateway's
|
|
12
|
-
* `src/pricing.ts`. Declared here so the ordering below can be asserted; the
|
|
13
|
-
* gateway is what actually enforces it.
|
|
14
|
-
*/
|
|
15
1
|
export declare const SERVER_MAX_BILLABLE_ROUNDS = 5;
|
|
16
|
-
/**
|
|
17
|
-
* The server answers at most this many responses per attempt, then refuses the
|
|
18
|
-
* eleventh with 409 `solve_abandoned`.
|
|
19
|
-
*
|
|
20
|
-
* Mirrors `MAX_ROUNDS_PER_SESSION` in the gateway.
|
|
21
|
-
*/
|
|
22
2
|
export declare const SERVER_MAX_SERVED_ROUNDS = 10;
|
|
23
|
-
/**
|
|
24
|
-
* How many click → refresh → re-solve rounds the client will attempt on one
|
|
25
|
-
* reCAPTCHA 3x3 dynamic puzzle.
|
|
26
|
-
*
|
|
27
|
-
* ── WHY 8, AND WHY IT MUST STAY STRICTLY BETWEEN 5 AND 10 ───────────────────
|
|
28
|
-
*
|
|
29
|
-
* The three numbers describe one attempt in three stages:
|
|
30
|
-
*
|
|
31
|
-
* rounds 1–5 billed
|
|
32
|
-
* rounds 6–10 served, and comped
|
|
33
|
-
* round 11 refused — 409, the attempt is over
|
|
34
|
-
*
|
|
35
|
-
* 8 sits strictly inside that, with room on both sides, and both margins do a
|
|
36
|
-
* job:
|
|
37
|
-
*
|
|
38
|
-
* Above 5 — rounds 6, 7 and 8 are free. A puzzle that needs a couple of extra
|
|
39
|
-
* passes still gets them, and the customer is not charged for our model
|
|
40
|
-
* needing another look. Dropping to 5 would abandon winnable puzzles at
|
|
41
|
-
* exactly the point where continuing costs the customer nothing.
|
|
42
|
-
*
|
|
43
|
-
* Below 10 — a well-behaved client gives up BEFORE the server refuses it.
|
|
44
|
-
* Raising this to 10 or beyond means the normal end of a hard puzzle is a
|
|
45
|
-
* 409 rather than a clean local stop, which turns an ordinary outcome into an
|
|
46
|
-
* error the caller has to interpret.
|
|
47
|
-
*
|
|
48
|
-
* So: if the billable cap moves, re-derive this and move the test in the same
|
|
49
|
-
* commit. Changing one number alone silently breaks one of the two margins.
|
|
50
|
-
*/
|
|
51
3
|
export declare const DEFAULT_RECAPTCHA_MAX_DYNAMIC_ROUNDS = 8;
|
package/dist/limits.js
CHANGED
|
@@ -1,54 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Numbers that must agree with the hosted gateway, stated once.
|
|
4
|
-
*
|
|
5
|
-
* These are not arbitrary defaults. They sit inside an ordering the server
|
|
6
|
-
* enforces, and the ordering — not any individual value — is the property worth
|
|
7
|
-
* protecting. `limits.test.ts` pins it.
|
|
8
|
-
*/
|
|
9
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
3
|
exports.DEFAULT_RECAPTCHA_MAX_DYNAMIC_ROUNDS = exports.SERVER_MAX_SERVED_ROUNDS = exports.SERVER_MAX_BILLABLE_ROUNDS = void 0;
|
|
11
|
-
|
|
12
|
-
* The server bills at most this many responses per captcha attempt.
|
|
13
|
-
*
|
|
14
|
-
* Mirrors `MAX_BILLABLE_ROUNDS_PER_SESSION` in captchakraken-gateway's
|
|
15
|
-
* `src/pricing.ts`. Declared here so the ordering below can be asserted; the
|
|
16
|
-
* gateway is what actually enforces it.
|
|
17
|
-
*/
|
|
4
|
+
// The gateway's three tiers: rounds 1-5 are billed, 6-10 are served and comped, and the 11th is refused with 409.
|
|
18
5
|
exports.SERVER_MAX_BILLABLE_ROUNDS = 5;
|
|
19
|
-
/**
|
|
20
|
-
* The server answers at most this many responses per attempt, then refuses the
|
|
21
|
-
* eleventh with 409 `solve_abandoned`.
|
|
22
|
-
*
|
|
23
|
-
* Mirrors `MAX_ROUNDS_PER_SESSION` in the gateway.
|
|
24
|
-
*/
|
|
25
6
|
exports.SERVER_MAX_SERVED_ROUNDS = 10;
|
|
26
|
-
|
|
27
|
-
* How many click → refresh → re-solve rounds the client will attempt on one
|
|
28
|
-
* reCAPTCHA 3x3 dynamic puzzle.
|
|
29
|
-
*
|
|
30
|
-
* ── WHY 8, AND WHY IT MUST STAY STRICTLY BETWEEN 5 AND 10 ───────────────────
|
|
31
|
-
*
|
|
32
|
-
* The three numbers describe one attempt in three stages:
|
|
33
|
-
*
|
|
34
|
-
* rounds 1–5 billed
|
|
35
|
-
* rounds 6–10 served, and comped
|
|
36
|
-
* round 11 refused — 409, the attempt is over
|
|
37
|
-
*
|
|
38
|
-
* 8 sits strictly inside that, with room on both sides, and both margins do a
|
|
39
|
-
* job:
|
|
40
|
-
*
|
|
41
|
-
* Above 5 — rounds 6, 7 and 8 are free. A puzzle that needs a couple of extra
|
|
42
|
-
* passes still gets them, and the customer is not charged for our model
|
|
43
|
-
* needing another look. Dropping to 5 would abandon winnable puzzles at
|
|
44
|
-
* exactly the point where continuing costs the customer nothing.
|
|
45
|
-
*
|
|
46
|
-
* Below 10 — a well-behaved client gives up BEFORE the server refuses it.
|
|
47
|
-
* Raising this to 10 or beyond means the normal end of a hard puzzle is a
|
|
48
|
-
* 409 rather than a clean local stop, which turns an ordinary outcome into an
|
|
49
|
-
* error the caller has to interpret.
|
|
50
|
-
*
|
|
51
|
-
* So: if the billable cap moves, re-derive this and move the test in the same
|
|
52
|
-
* commit. Changing one number alone silently breaks one of the two margins.
|
|
53
|
-
*/
|
|
7
|
+
// Inside the comped band with margin on both sides. If the billable cap moves, re-derive this and move limits.test.ts in the same commit.
|
|
54
8
|
exports.DEFAULT_RECAPTCHA_MAX_DYNAMIC_ROUNDS = 8;
|
package/dist/model-name.d.ts
CHANGED
|
@@ -1,23 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Where the bundled Python engine lives — the copy of `models.json` this client
|
|
3
|
-
* actually answers from.
|
|
4
|
-
*
|
|
5
|
-
* Lives HERE rather than in solver.ts because the registry lookup below is its
|
|
6
|
-
* only remaining caller-visible use, and a second copy of this path logic is
|
|
7
|
-
* how the two ports drifted apart in the first place. solver.ts imports it.
|
|
8
|
-
*
|
|
9
|
-
* When installed from npm this file is in `<pkgRoot>/dist` (compiled) or
|
|
10
|
-
* `<pkgRoot>/src` (dev), and published packages bundle the engine at
|
|
11
|
-
* `<pkgRoot>/python` (copied in by scripts/copy-python.mjs at build time). In
|
|
12
|
-
* the source development checkout it instead lives at the sibling `../python`.
|
|
13
|
-
*/
|
|
14
1
|
export declare function getBundledCliRoot(): string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* engine's layout. Re-deriving it is the same mistake one level down.
|
|
19
|
-
*/
|
|
20
|
-
export declare function resolveLoraName({ cliRoot, env }?: {
|
|
2
|
+
export declare function isHostedEndpoint(baseUrl: string | undefined, env?: NodeJS.ProcessEnv): boolean;
|
|
3
|
+
/** Hosted: the routing alias, not an arm's `lora_name`, because a routed mixture is several names and only the alias routes. A missing or broken registry falls through to the pin, never throws. */
|
|
4
|
+
export declare function resolveLoraName({ cliRoot, env, baseUrl }?: {
|
|
21
5
|
cliRoot?: string;
|
|
22
6
|
env?: NodeJS.ProcessEnv;
|
|
7
|
+
baseUrl?: string;
|
|
23
8
|
}): string;
|