nonecap 0.12.1 → 0.13.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/README.md CHANGED
@@ -36,11 +36,48 @@ const solve = await nc.solve({
36
36
  console.log(solve.token); // the hCaptcha token, ready to submit
37
37
  console.log(solve.resp_key); // hcaptcha.getRespKey() equivalent, for sites that verify the pair
38
38
  console.log(solve.user_agent); // submit the token with this User-Agent: some sites check the browser version
39
- console.log(solve.warnings); // e.g. proxy_session_refused: tokens you reported through this proxy session or its exit IP were refused; a different exit IP is more likely to pass
39
+ console.log(solve.warnings); // e.g. proxy_session_refused: tokens you reported through this proxy session or its exit IP were refused; a different exit IP is more likely to pass (or, when your proxy changed its exit IP during the solve, use a sticky session per solve)
40
40
  ```
41
41
 
42
42
  `solve()` submits the captcha and waits until it is done, using the API's long-poll so you are not hammering it with requests. It returns the solved solve, or throws if the solve fails or your timeout runs out.
43
43
 
44
+ ## MCP server (Claude Code, Cursor, and other MCP clients)
45
+
46
+ The package also ships `nonecap-mcp`, a stdio [MCP](https://modelcontextprotocol.io) server, so an AI agent can solve hCaptcha through your NoneCap account.
47
+
48
+ Claude Code:
49
+
50
+ ```sh
51
+ claude mcp add nonecap --env NONECAP_API_KEY=<your key> -- npx -y -p nonecap@latest nonecap-mcp
52
+ ```
53
+
54
+ Cursor (`~/.cursor/mcp.json`), Claude Desktop (`claude_desktop_config.json`), and most other clients take the same JSON:
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "nonecap": {
60
+ "command": "npx",
61
+ "args": ["-y", "-p", "nonecap@latest", "nonecap-mcp"],
62
+ "env": { "NONECAP_API_KEY": "<your key>" }
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ Tools:
69
+
70
+ | Tool | What it does |
71
+ | --- | --- |
72
+ | `solve_hcaptcha` | Solve an hCaptcha (`sitekey`, `url`; optional `type`, `rqdata`, `user_agent`, `proxy`, `wait_seconds`) and return the solve with its `token`. If the solve is still running after `wait_seconds` (default 45, at most 50, inside the 60 s that clients built on the official MCP SDK allow by default), it returns the solve id and status so the agent polls `get_solve` instead of solving again. |
73
+ | `get_solve` | Get a solve by id, optionally waiting up to 50 seconds for it to finish. |
74
+ | `cancel_solve` | Cancel a pending or running solve. |
75
+ | `list_solves` | List your recent solves. |
76
+ | `get_account` | Your credit balance and your plan's solves left today. |
77
+ | `report_solve_outcome` | Tell NoneCap whether the site accepted a token. |
78
+
79
+ A failed call comes back as a tool error whose JSON carries the API's error code (`insufficient_credits`, `sitekey_rate_limited`, a failed solve's `proxy_error`, …), plus `retry_after` when the API sent one. Set `NONECAP_BASE_URL` to point the server at a different API host.
80
+
44
81
  ## Handling failures
45
82
 
46
83
  Every error this library throws extends `NoneCapError`, so you can catch the whole family or pick out the one you care about.
@@ -0,0 +1,212 @@
1
+ dist/mcp.cjs (the nonecap-mcp bin) bundles the following packages. Their licenses follow.
2
+
3
+ ========================================================================
4
+ @modelcontextprotocol/sdk@1.32.2
5
+ ========================================================================
6
+
7
+ MIT License
8
+
9
+ Copyright (c) 2024 Anthropic, PBC
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ ========================================================================
30
+ ajv-formats@3.0.1
31
+ ========================================================================
32
+
33
+ MIT License
34
+
35
+ Copyright (c) 2020 Evgeny Poberezkin
36
+
37
+ Permission is hereby granted, free of charge, to any person obtaining a copy
38
+ of this software and associated documentation files (the "Software"), to deal
39
+ in the Software without restriction, including without limitation the rights
40
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41
+ copies of the Software, and to permit persons to whom the Software is
42
+ furnished to do so, subject to the following conditions:
43
+
44
+ The above copyright notice and this permission notice shall be included in all
45
+ copies or substantial portions of the Software.
46
+
47
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53
+ SOFTWARE.
54
+
55
+ ========================================================================
56
+ ajv@8.20.0
57
+ ========================================================================
58
+
59
+ The MIT License (MIT)
60
+
61
+ Copyright (c) 2015-2021 Evgeny Poberezkin
62
+
63
+ Permission is hereby granted, free of charge, to any person obtaining a copy
64
+ of this software and associated documentation files (the "Software"), to deal
65
+ in the Software without restriction, including without limitation the rights
66
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
67
+ copies of the Software, and to permit persons to whom the Software is
68
+ furnished to do so, subject to the following conditions:
69
+
70
+ The above copyright notice and this permission notice shall be included in all
71
+ copies or substantial portions of the Software.
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
76
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
77
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
78
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
79
+ SOFTWARE.
80
+
81
+ ========================================================================
82
+ fast-deep-equal@3.1.3
83
+ ========================================================================
84
+
85
+ MIT License
86
+
87
+ Copyright (c) 2017 Evgeny Poberezkin
88
+
89
+ Permission is hereby granted, free of charge, to any person obtaining a copy
90
+ of this software and associated documentation files (the "Software"), to deal
91
+ in the Software without restriction, including without limitation the rights
92
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
93
+ copies of the Software, and to permit persons to whom the Software is
94
+ furnished to do so, subject to the following conditions:
95
+
96
+ The above copyright notice and this permission notice shall be included in all
97
+ copies or substantial portions of the Software.
98
+
99
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
100
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
101
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
102
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
103
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
104
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
105
+ SOFTWARE.
106
+
107
+ ========================================================================
108
+ fast-uri@3.1.9
109
+ ========================================================================
110
+
111
+ Copyright (c) 2011-2021, Gary Court until https://github.com/garycourt/uri-js/commit/a1acf730b4bba3f1097c9f52e7d9d3aba8cdcaae
112
+ Copyright (c) 2021-present The Fastify team <https://github.com/fastify/fastify#team>
113
+ All rights reserved.
114
+
115
+ Redistribution and use in source and binary forms, with or without
116
+ modification, are permitted provided that the following conditions are met:
117
+ * Redistributions of source code must retain the above copyright
118
+ notice, this list of conditions and the following disclaimer.
119
+ * Redistributions in binary form must reproduce the above copyright
120
+ notice, this list of conditions and the following disclaimer in the
121
+ documentation and/or other materials provided with the distribution.
122
+ * The names of any contributors may not be used to endorse or promote
123
+ products derived from this software without specific prior written
124
+ permission.
125
+
126
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
127
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
128
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
129
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
130
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
131
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
132
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
133
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
134
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
135
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
136
+
137
+ * * *
138
+
139
+ The complete list of contributors can be found at:
140
+ - https://github.com/garycourt/uri-js/graphs/contributors
141
+
142
+ ========================================================================
143
+ json-schema-traverse@1.0.0
144
+ ========================================================================
145
+
146
+ MIT License
147
+
148
+ Copyright (c) 2017 Evgeny Poberezkin
149
+
150
+ Permission is hereby granted, free of charge, to any person obtaining a copy
151
+ of this software and associated documentation files (the "Software"), to deal
152
+ in the Software without restriction, including without limitation the rights
153
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
154
+ copies of the Software, and to permit persons to whom the Software is
155
+ furnished to do so, subject to the following conditions:
156
+
157
+ The above copyright notice and this permission notice shall be included in all
158
+ copies or substantial portions of the Software.
159
+
160
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
162
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
163
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
164
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
165
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
166
+ SOFTWARE.
167
+
168
+ ========================================================================
169
+ zod-to-json-schema@3.25.2
170
+ ========================================================================
171
+
172
+ ISC License
173
+
174
+ Copyright (c) 2020, Stefan Terdell
175
+
176
+ Permission to use, copy, modify, and/or distribute this software for any
177
+ purpose with or without fee is hereby granted, provided that the above
178
+ copyright notice and this permission notice appear in all copies.
179
+
180
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
181
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
182
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
183
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
184
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
185
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
186
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
187
+
188
+ ========================================================================
189
+ zod@4.6.7
190
+ ========================================================================
191
+
192
+ MIT License
193
+
194
+ Copyright (c) 2025 Colin McDonnell
195
+
196
+ Permission is hereby granted, free of charge, to any person obtaining a copy
197
+ of this software and associated documentation files (the "Software"), to deal
198
+ in the Software without restriction, including without limitation the rights
199
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
200
+ copies of the Software, and to permit persons to whom the Software is
201
+ furnished to do so, subject to the following conditions:
202
+
203
+ The above copyright notice and this permission notice shall be included in all
204
+ copies or substantial portions of the Software.
205
+
206
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
207
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
208
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
209
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
210
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
211
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
212
+ SOFTWARE.
package/dist/index.cjs CHANGED
@@ -139,7 +139,7 @@ function errorFromResponse(status, code, message, param, extra = {}) {
139
139
  }
140
140
 
141
141
  // src/version.ts
142
- var VERSION = "0.12.1";
142
+ var VERSION = "0.13.0";
143
143
 
144
144
  // src/client.ts
145
145
  var DEFAULT_BASE_URL = "https://api.nonecap.com";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/version.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ErrorCode, Solve } from \"./types.js\";\n\n/**\n * Base class for every error this library throws. Catch `NoneCapError` to\n * handle all of them, or catch a subclass to handle one kind.\n */\nexport class NoneCapError extends Error {\n /** Machine-readable error code from the API envelope, when there is one. */\n readonly code: ErrorCode | undefined;\n /** HTTP status, when the error came from a response. */\n readonly status: number | undefined;\n /** The request field that was rejected, for validation errors. */\n readonly param: string | null;\n /** The API's correlation id for this request (`X-Request-Id`); quote it to support. */\n readonly requestId: string | undefined;\n /** Seconds to wait before retrying, when the API sent `Retry-After`. */\n readonly retryAfter: number | undefined;\n\n constructor(\n message: string,\n opts: {\n code?: ErrorCode;\n status?: number;\n param?: string | null;\n requestId?: string;\n retryAfter?: number;\n } = {},\n ) {\n super(message);\n this.name = new.target.name;\n this.code = opts.code;\n this.status = opts.status;\n this.param = opts.param ?? null;\n this.requestId = opts.requestId;\n this.retryAfter = opts.retryAfter;\n // Restore the prototype chain when compiled down to ES5-era targets.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** 401 — the API key is missing, malformed, or revoked. */\nexport class AuthenticationError extends NoneCapError {}\n\n/** 403 — the key is valid but not allowed to do this (scope or locked account). */\nexport class PermissionError extends NoneCapError {}\n\n/** 402 — the account is out of credits. */\nexport class InsufficientCreditsError extends NoneCapError {}\n\n/** 402 — this API key reached its own credit limit (the account may still have credits). */\nexport class KeyCreditLimitError extends InsufficientCreditsError {}\n\n/** 422 / 400 — the request was rejected. `param` names the offending field. */\nexport class ValidationError extends NoneCapError {}\n\n/** 413 — the request body exceeds the route's size limit. */\nexport class PayloadTooLargeError extends ValidationError {}\n\n/** 415 — a JSON route was called without `Content-Type: application/json`. */\nexport class UnsupportedMediaTypeError extends ValidationError {}\n\n/** 404 — no such resource. */\nexport class NotFoundError extends NoneCapError {}\n\n/** 409 — the solve is already in a terminal state (e.g. cancelling a finished solve). */\nexport class ConflictError extends NoneCapError {}\n\n/** 429 — back off and retry; `retryAfter` (seconds) is set when the API sent it. */\nexport class RateLimitError extends NoneCapError {}\n\n/** 429 — too many solves in flight for this account. Wait for one to finish. */\nexport class ConcurrencyLimitError extends RateLimitError {}\n\n/** 429 — hCaptcha is refusing challenges for this sitekey, so the submit was shed.\n * Wait `retryAfter` seconds; the message says whether a different proxy pool can help. */\nexport class SitekeyRateLimitedError extends RateLimitError {}\n\n/** 429 — nearly every recent solve through the proxy you supplied failed because the\n * proxy refused the connection, so submits through it are shed. Fix the proxy or\n * switch exit; `retryAfter` says when the next submit is let through to re-check it. */\nexport class ProxyUnavailableError extends RateLimitError {}\n\n/** 429 — your account has a submit rate cap on this sitekey and reached it for the\n * trailing minute, or your own-proxy sessions for this sitekey are at their limit.\n * Nothing was charged; wait `retryAfter` seconds. */\nexport class RateCappedError extends RateLimitError {}\n\n/** 422 — {@link NoneCap.recognize} produced no answer for these images, or the challenge\n * type is not supported. Nothing was charged. */\nexport class RecognitionFailedError extends NoneCapError {}\n\n/** 5xx, or a response that wasn't the expected shape. `requestId` is the id to quote. */\nexport class APIError extends NoneCapError {}\n\n/** 503 — new solves are paused for maintenance. Retry shortly. */\nexport class ServiceUnavailableError extends APIError {}\n\n/** The request never reached the API (DNS, TCP, TLS, timeout, offline). */\nexport class ConnectionError extends NoneCapError {}\n\n/**\n * Thrown by {@link NoneCap.solve} when a solve reaches a terminal state without\n * a token: `failed`, `expired`, or `cancelled`. The full solve is attached so\n * you can inspect `solve.error` and timings.\n */\nexport class SolveFailedError extends NoneCapError {\n readonly solve: Solve;\n\n constructor(solve: Solve) {\n const detail = solve.error ? `${solve.error.code}: ${solve.error.message}` : solve.status;\n super(`Solve ${solve.id} ${solve.status} (${detail})`, {\n code: undefined,\n status: undefined,\n });\n this.solve = solve;\n }\n\n /** `solve.error.code`, e.g. `proxy_error`; the status when no error object came back. */\n get solveCode(): string {\n return this.solve.error?.code ?? this.solve.status;\n }\n\n /** `solve.error.reason`, the typed sub-reason, or null. */\n get reason(): string | null {\n return this.solve.error?.reason ?? null;\n }\n\n /** Whether re-submitting the same request unchanged can succeed. */\n get retryable(): boolean {\n return this.solve.error?.retryable ?? false;\n }\n}\n\n/**\n * Thrown by {@link NoneCap.solve} (and {@link SolveHandle.result}) when the\n * client-side timeout elapses first. When the timeout came from waiting on a\n * solve, `solveId` and the last-known `solve` are attached so you can still\n * cancel the in-flight solve. They are `undefined` for transport-level timeouts.\n */\nexport class TimeoutError extends NoneCapError {\n /** The id of the in-flight solve, when the timeout came from a solve wait. */\n readonly solveId: string | undefined;\n /** The last-known solve state, so you can cancel it after a wait timed out. */\n readonly solve: Solve | undefined;\n\n constructor(\n message: string,\n opts: {\n code?: ErrorCode;\n status?: number;\n param?: string | null;\n solveId?: string;\n solve?: Solve;\n } = {},\n ) {\n super(message, opts);\n this.solveId = opts.solveId;\n this.solve = opts.solve;\n }\n}\n\n/** Map an API error envelope (plus HTTP status) to the right error subclass. */\nexport function errorFromResponse(\n status: number,\n code: ErrorCode | undefined,\n message: string,\n param: string | null,\n extra: { requestId?: string; retryAfter?: number } = {},\n): NoneCapError {\n const opts = { code, status, param, ...extra };\n switch (code) {\n case \"unauthorized\":\n return new AuthenticationError(message, opts);\n case \"forbidden\":\n case \"account_locked\":\n return new PermissionError(message, opts);\n case \"insufficient_credits\":\n return new InsufficientCreditsError(message, opts);\n case \"key_credit_limit_exceeded\":\n return new KeyCreditLimitError(message, opts);\n case \"invalid_request\":\n case \"validation_error\":\n case \"expired_window\":\n return new ValidationError(message, opts);\n case \"payload_too_large\":\n return new PayloadTooLargeError(message, opts);\n case \"unsupported_media_type\":\n return new UnsupportedMediaTypeError(message, opts);\n case \"not_found\":\n case \"not_eligible\":\n return new NotFoundError(message, opts);\n case \"conflict\":\n return new ConflictError(message, opts);\n case \"concurrency_limit_exceeded\":\n return new ConcurrencyLimitError(message, opts);\n case \"sitekey_rate_limited\":\n return new SitekeyRateLimitedError(message, opts);\n case \"proxy_unavailable\":\n return new ProxyUnavailableError(message, opts);\n case \"rate_capped\":\n return new RateCappedError(message, opts);\n case \"rate_limited\":\n case \"ext_daily_limit\":\n return new RateLimitError(message, opts);\n case \"recognition_failed\":\n return new RecognitionFailedError(message, opts);\n case \"maintenance\":\n return new ServiceUnavailableError(message, opts);\n default:\n return new APIError(message, opts);\n }\n}\n","/**\n * The published package version, sent as the `User-Agent` on every request.\n *\n * Hardcoded rather than imported from package.json: a JSON import would need\n * `resolveJsonModule` and would resolve differently under the ESM and CJS\n * builds. Bump it in the SAME commit as package.json: the drift check is the\n * `Version constant matches package.json` step in ci.yml and lives ONLY there,\n * so `npm test` and `tsc` both stay green on a mismatch (test/version.test.ts\n * asserts the User-Agent uses VERSION, never that VERSION is right).\n */\nexport const VERSION = \"0.12.1\";\n","import {\n APIError,\n ConflictError,\n ConnectionError,\n NoneCapError,\n SolveFailedError,\n TimeoutError,\n errorFromResponse,\n} from \"./errors.js\";\nimport type {\n Account,\n ErrorCode,\n Feedback,\n FeedbackBatch,\n FeedbackReport,\n RecognitionOutcome,\n RecognitionOutcomeResult,\n RecognizeAreaSelectParams,\n RecognizeAreaSelectResult,\n RecognizeBinaryParams,\n RecognizeBinaryResult,\n RecognizeParams,\n RecognizeResult,\n RecognizeTasklistAreaSelectResult,\n RecognizeTasklistBinaryResult,\n RecognizeTasklistDragDropResult,\n RecognizeTasklistParams,\n Solve,\n SolveCreateParams,\n SolveList,\n SolveListParams,\n SolveStatus,\n} from \"./types.js\";\n\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.nonecap.com\";\nconst USER_AGENT = `nonecap-js/${VERSION}`;\n/** The API caps server-side long-poll at 90 seconds. */\nconst MAX_WAIT_SECONDS = 90;\n/** The API caps one `POST /v1/feedback` call at 500 items. */\nexport const FEEDBACK_BATCH_MAX = 500;\nconst TERMINAL: ReadonlySet<SolveStatus> = new Set([\n \"solved\",\n \"failed\",\n \"cancelled\",\n \"expired\",\n]);\n\n/** Is this a terminal solve status? */\nexport function isTerminal(status: SolveStatus): boolean {\n return TERMINAL.has(status);\n}\n\n/** A `fetch` implementation. Defaults to the global `fetch`. */\nexport type FetchLike = (\n input: string,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Options for constructing a {@link NoneCap} client. */\nexport interface NoneCapOptions {\n /** Your NoneCap API key. Find it at https://dashboard.nonecap.com. */\n apiKey: string;\n /** Override the API base URL. Defaults to https://api.nonecap.com. */\n baseURL?: string;\n /**\n * Per-request timeout in milliseconds for a single HTTP call. Defaults to\n * 100000 (just above the 90s server long-poll). Note this bounds one HTTP\n * round trip, not the whole {@link NoneCap.solve} wait — use the `timeout`\n * option on `solve()` for that.\n */\n timeout?: number;\n /** Inject a custom `fetch` (for testing, proxies, or non-standard runtimes). */\n fetch?: FetchLike;\n}\n\n/** Per-call options for the long-polling endpoints. */\nexport interface WaitOptions {\n /**\n * Hold the connection open up to this many seconds (1–90) waiting for the\n * solve to finish before responding. Omit to return immediately.\n */\n wait?: number;\n /** Abort the request. */\n signal?: AbortSignal;\n}\n\n/** Options for {@link NoneCap.solve} and {@link SolveHandle.result}. */\nexport interface SolveHelperOptions {\n /**\n * Give up after this many milliseconds and throw {@link TimeoutError}.\n * Defaults to 180000 (3 minutes).\n */\n timeout?: number;\n /** Abort waiting. */\n signal?: AbortSignal;\n}\n\n/** Options for {@link NoneCap.solves.start}. */\nexport interface SolveStartOptions {\n /** Abort the submission. */\n signal?: AbortSignal;\n}\n\ninterface RequestOptions {\n query?: Record<string, string | number | undefined>;\n body?: unknown;\n signal?: AbortSignal;\n /** Override the per-request timeout for this call (used by long polls). */\n timeout?: number;\n /** HTTP statuses to treat as success in addition to 2xx (e.g. 202). */\n expect?: number[];\n}\n\n/**\n * The NoneCap API client.\n *\n * ```ts\n * const nc = new NoneCap({ apiKey: process.env.NONECAP_KEY! });\n * const { token } = await nc.solve({ type: \"hcaptcha\", sitekey, url });\n * ```\n */\nexport class NoneCap {\n readonly #apiKey: string;\n readonly #baseURL: string;\n readonly #timeout: number;\n readonly #fetch: FetchLike;\n\n constructor(options: NoneCapOptions) {\n if (!options || !options.apiKey) {\n throw new NoneCapError(\n \"A NoneCap API key is required. Pass it as `new NoneCap({ apiKey })`.\",\n );\n }\n this.#apiKey = options.apiKey;\n this.#baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.#timeout = options.timeout ?? 100_000;\n const f = options.fetch ?? (globalThis.fetch as FetchLike | undefined);\n if (!f) {\n throw new NoneCapError(\n \"No `fetch` available. Use Node 18+, or pass a `fetch` in the client options.\",\n );\n }\n this.#fetch = f;\n }\n\n /** Operations on solves. */\n readonly solves = {\n /** Submit a solve. Pass `{ wait }` to hold the connection until it finishes. */\n create: (params: SolveCreateParams, options: WaitOptions = {}): Promise<Solve> =>\n this.#request<Solve>(\"POST\", \"/v1/solves\", {\n body: params,\n query: { wait: options.wait },\n signal: options.signal,\n timeout: this.#timeoutForWait(options.wait),\n expect: [202],\n }),\n\n /** Fetch a solve by id. Pass `{ wait }` to long-poll until it finishes. */\n retrieve: (id: string, options: WaitOptions = {}): Promise<Solve> =>\n this.#request<Solve>(\"GET\", `/v1/solves/${encodeURIComponent(id)}`, {\n query: { wait: options.wait },\n signal: options.signal,\n timeout: this.#timeoutForWait(options.wait),\n expect: [202],\n }),\n\n /** Cancel a pending or in-flight solve. */\n cancel: (id: string, options: { signal?: AbortSignal } = {}): Promise<Solve> =>\n this.#request<Solve>(\"DELETE\", `/v1/solves/${encodeURIComponent(id)}`, {\n signal: options.signal,\n }),\n\n /**\n * Submit a solve and return a {@link SolveHandle} for it.\n *\n * Unlike {@link NoneCap.solve}, this returns as soon as the submission is\n * accepted, so `handle.id` is available immediately. Use the handle to\n * `cancel()` the solve or `await handle.result()` for the finished solve.\n *\n * ```ts\n * const handle = await nc.solves.start({ type: \"hcaptcha\", sitekey, url });\n * // ...later, e.g. on shutdown:\n * await handle.cancel();\n * // or wait for it:\n * const { token } = await handle.result();\n * ```\n */\n start: async (\n params: SolveCreateParams,\n options: SolveStartOptions = {},\n ): Promise<SolveHandle> => {\n const solve = await this.solves.create(params, { signal: options.signal });\n return new SolveHandle(this, solve);\n },\n\n /** Fetch one page of solves. */\n list: (params: SolveListParams = {}, options: { signal?: AbortSignal } = {}): Promise<SolveList> =>\n this.#request<SolveList>(\"GET\", \"/v1/solves\", {\n query: {\n limit: params.limit,\n starting_after: params.starting_after,\n status: params.status,\n type: params.type,\n },\n signal: options.signal,\n }),\n\n /**\n * Iterate every solve across pages, newest first.\n *\n * ```ts\n * for await (const solve of nc.solves.listAll()) { ... }\n * ```\n */\n listAll: (\n params: SolveListParams = {},\n options: { signal?: AbortSignal } = {},\n ): AsyncIterableIterator<Solve> => this.#listAll(params, options),\n };\n\n /**\n * Report what your downstream target did with the tokens we minted.\n *\n * Feedback is free, own-solves-only, and idempotent per solve id: reporting\n * the same solve again corrects the earlier verdict. Only `solved` solves can\n * be reported, and only within the API's reporting window (~30 days from the\n * solve; corrections to an already-reported solve are never re-gated by it).\n */\n readonly feedback = {\n /**\n * Report one solve's downstream outcome, returning the recorded feedback.\n *\n * Unlike {@link NoneCap.feedback.reportMany}, a rejected report throws:\n * {@link NotFoundError} if the solve isn't yours or never minted a token,\n * {@link ValidationError} if a field is wrong or the reporting window closed.\n *\n * ```ts\n * await nc.feedback.report({ solve_id: solve.id, outcome: \"rejected\", reason: \"...\" });\n * ```\n */\n report: (report: FeedbackReport, options: { signal?: AbortSignal } = {}): Promise<Feedback> => {\n const { solve_id, ...fields } = report;\n return this.#request<Feedback>(\n \"POST\",\n `/v1/solves/${encodeURIComponent(solve_id)}/feedback`,\n { body: toWireFields(fields), signal: options.signal },\n );\n },\n\n /**\n * Report many verdicts at once — the path to use at volume. Buffer verdicts\n * as you learn them and flush them here.\n *\n * The call succeeds even when individual items are rejected: each is\n * resolved on its own so one stale id never discards the rest. Check\n * `failed` rather than relying on a thrown error.\n *\n * More than {@link FEEDBACK_BATCH_MAX} reports are split across sequential\n * requests and merged into one result, in request order. An empty array is\n * a no-op that returns an empty batch without a request.\n *\n * ```ts\n * const batch = await nc.feedback.reportMany(buffer);\n * if (batch.failed) console.warn(batch.results.filter((r) => r.status === \"error\"));\n * ```\n */\n reportMany: async (\n reports: readonly FeedbackReport[],\n options: { signal?: AbortSignal } = {},\n ): Promise<FeedbackBatch> => {\n const merged: FeedbackBatch = {\n object: \"feedback_batch\",\n recorded: 0,\n updated: 0,\n unchanged: 0,\n failed: 0,\n results: [],\n };\n // Chunks are sent in order and the server upserts last-write-wins, so a\n // solve reported twice still ends at its last value. Duplicates split\n // across a chunk boundary each get written, though, so the earlier one\n // reports `recorded`/`updated` where a single request would say\n // `unchanged`.\n for (let i = 0; i < reports.length; i += FEEDBACK_BATCH_MAX) {\n const batch = await this.#request<FeedbackBatch>(\"POST\", \"/v1/feedback\", {\n body: { feedback: reports.slice(i, i + FEEDBACK_BATCH_MAX).map(toWireReport) },\n signal: options.signal,\n });\n merged.recorded += batch.recorded;\n merged.updated += batch.updated;\n merged.unchanged += batch.unchanged;\n merged.failed += batch.failed;\n merged.results.push(...batch.results);\n }\n return merged;\n },\n };\n\n /** Fetch your account, including the current credit balance. */\n me(options: { signal?: AbortSignal } = {}): Promise<Account> {\n return this.#request<Account>(\"GET\", \"/v1/me\", { signal: options.signal });\n }\n\n /**\n * Recognize a challenge's images: send the instruction and images, get the\n * answer back in the same response. No token, no polling.\n *\n * An answered call's charge is final. Throws {@link RecognitionFailedError}\n * when no answer came back (nothing is charged then), {@link ValidationError}\n * for a malformed request.\n *\n * ```ts\n * const { id, data } = await nc.recognize({\n * type: \"hcaptcha\",\n * task: \"Please click each image containing a bus\",\n * image_data: tiles, // base64\n * });\n * ```\n */\n recognize(params: RecognizeBinaryParams, options?: { signal?: AbortSignal }): Promise<RecognizeBinaryResult>;\n recognize(params: RecognizeAreaSelectParams, options?: { signal?: AbortSignal }): Promise<RecognizeAreaSelectResult>;\n recognize(\n params: RecognizeTasklistParams<\"image_label_binary\">,\n options?: { signal?: AbortSignal },\n ): Promise<RecognizeTasklistBinaryResult>;\n recognize(\n params: RecognizeTasklistParams<\"image_label_area_select\">,\n options?: { signal?: AbortSignal },\n ): Promise<RecognizeTasklistAreaSelectResult>;\n recognize(\n params: RecognizeTasklistParams<\"image_drag_drop\">,\n options?: { signal?: AbortSignal },\n ): Promise<RecognizeTasklistDragDropResult>;\n recognize(params: RecognizeParams, options?: { signal?: AbortSignal }): Promise<RecognizeResult>;\n recognize(params: RecognizeParams, options: { signal?: AbortSignal } = {}): Promise<RecognizeResult> {\n return this.#request<RecognizeResult>(\"POST\", \"/v1/recognize\", {\n body: params,\n signal: options.signal,\n });\n }\n\n /**\n * Report whether a {@link NoneCap.recognize} answer worked on the challenge.\n * Optional and free; it feeds NoneCap's accuracy stats and never refunds the\n * call. The first report for an id sticks: a repeat returns it unchanged.\n */\n reportRecognitionOutcome(\n id: string,\n result: RecognitionOutcome,\n options: { signal?: AbortSignal } = {},\n ): Promise<RecognitionOutcomeResult> {\n return this.#request<RecognitionOutcomeResult>(\"POST\", \"/v1/recognize/outcome\", {\n body: { id, result },\n signal: options.signal,\n });\n }\n\n /**\n * Submit a solve and wait for it to finish, returning the solved solve.\n *\n * Uses the server's long-poll under the hood and keeps polling until the\n * solve is terminal or `timeout` elapses. Throws {@link SolveFailedError} if\n * the solve fails/expires/is cancelled, or {@link TimeoutError} on timeout.\n *\n * This is sugar for `(await solves.start(params)).result(options)`. When you\n * need to cancel the solve while it runs, use {@link NoneCap.solves.start}\n * and keep the {@link SolveHandle}.\n */\n async solve(params: SolveCreateParams, options: SolveHelperOptions = {}): Promise<Solve> {\n const handle = await this.solves.start(params, { signal: options.signal });\n return handle.result(options);\n }\n\n // -- internals ------------------------------------------------------------\n\n #timeoutForWait(wait?: number): number | undefined {\n if (wait === undefined) return undefined;\n // Give the socket a margin beyond the server's long-poll window.\n return wait * 1000 + 15_000;\n }\n\n async *#listAll(\n params: SolveListParams,\n options: { signal?: AbortSignal },\n ): AsyncIterableIterator<Solve> {\n let cursor = params.starting_after;\n for (;;) {\n const page = await this.solves.list({ ...params, starting_after: cursor }, options);\n for (const solve of page.data) yield solve;\n if (!page.has_more || page.data.length === 0) return;\n cursor = page.data[page.data.length - 1]!.id;\n }\n }\n\n async #request<T>(method: string, path: string, options: RequestOptions = {}): Promise<T> {\n const url = new URL(this.#baseURL + path);\n if (options.query) {\n for (const [key, value] of Object.entries(options.query)) {\n if (value !== undefined && value !== \"\") url.searchParams.set(key, String(value));\n }\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.#apiKey}`,\n Accept: \"application/json\",\n // Browsers drop this as a forbidden header; on Node it identifies the SDK.\n \"User-Agent\": USER_AGENT,\n };\n let bodyInit: string | undefined;\n if (options.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n bodyInit = JSON.stringify(options.body);\n }\n\n const controller = new AbortController();\n const timeoutMs = options.timeout ?? this.#timeout;\n const timer = setTimeout(() => controller.abort(new TimeoutError(`Request timed out after ${timeoutMs}ms.`)), timeoutMs);\n const onAbort = () => controller.abort(options.signal?.reason);\n if (options.signal) {\n if (options.signal.aborted) onAbort();\n else options.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n let res: Response;\n try {\n res = await this.#fetch(url.toString(), {\n method,\n headers,\n body: bodyInit,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof TimeoutError) throw err;\n if (isAbort(err)) {\n // A caller-supplied signal aborting surfaces as the caller's reason.\n if (options.signal?.aborted) throw options.signal.reason instanceof Error\n ? options.signal.reason\n : new NoneCapError(\"Request aborted.\");\n throw new TimeoutError(`Request timed out after ${timeoutMs}ms.`);\n }\n throw new ConnectionError(\n `Could not reach the NoneCap API at ${this.#baseURL}: ${(err as Error).message}`,\n );\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", onAbort);\n }\n\n return this.#parse<T>(res, options.expect ?? []);\n }\n\n async #parse<T>(res: Response, expect: number[]): Promise<T> {\n const text = await res.text();\n let json: unknown;\n if (text) {\n try {\n json = JSON.parse(text);\n } catch {\n throw new APIError(\n `Unexpected non-JSON response (HTTP ${res.status}): ${text.slice(0, 200)}`,\n { status: res.status },\n );\n }\n }\n\n if (res.ok || expect.includes(res.status)) {\n return json as T;\n }\n\n const envelope = json as\n | { error?: { code?: ErrorCode; message?: string; param?: string | null; request_id?: string } }\n | undefined;\n const apiError = envelope?.error;\n const retryAfterRaw = res.headers.get(\"retry-after\");\n const retryAfter = retryAfterRaw !== null && /^\\d+$/.test(retryAfterRaw) ? Number(retryAfterRaw) : undefined;\n throw errorFromResponse(\n res.status,\n apiError?.code,\n apiError?.message ?? `HTTP ${res.status}`,\n apiError?.param ?? null,\n { requestId: apiError?.request_id ?? res.headers.get(\"x-request-id\") ?? undefined, retryAfter },\n );\n }\n}\n\n/**\n * A handle on a started solve, returned by {@link NoneCap.solves.start}.\n *\n * The handle is the cancellable lifecycle object for one solve. It is a plain\n * object, not a promise: `await`ing it does nothing useful. Wait for the result\n * with {@link SolveHandle.result}, and cancel with {@link SolveHandle.cancel}.\n * You do not construct it yourself — `solves.start()` hands you one with `id`\n * already resolved.\n */\nexport class SolveHandle {\n /** The id of the started solve, available as soon as `start()` resolved. */\n readonly id: string;\n\n readonly #client: NoneCap;\n /** The latest solve state we have seen, from the create, polls, or cancel. */\n #solve: Solve;\n /**\n * The cached TERMINAL outcome: resolves to the solved solve, or rejects with\n * {@link SolveFailedError} if terminal-but-not-solved. Only ever set once the\n * solve actually reaches a terminal state, so it is safe to replay forever. A\n * timed-out wait does NOT settle this — it is retryable.\n */\n #terminal: Promise<Solve> | undefined;\n /** The poll currently in flight, shared by concurrent result() callers. */\n #inflight: Promise<Solve> | undefined;\n\n constructor(client: NoneCap, solve: Solve) {\n this.#client = client;\n this.#solve = solve;\n this.id = solve.id;\n }\n\n /** The last-known solve state for this handle. */\n get solve(): Solve {\n return this.#solve;\n }\n\n /**\n * Long-poll until the solve is terminal, returning the solved solve. Throws\n * {@link SolveFailedError} if it fails/expires/is cancelled, or\n * {@link TimeoutError} on timeout (with `solveId`/`solve` attached so you can\n * still {@link SolveHandle.cancel} it).\n *\n * Memoizes the *terminal* outcome: once the solve actually finishes, every\n * later call returns that same settled result. A {@link TimeoutError} is not\n * memoized — it just means this wait gave up, so a later call (e.g. with a\n * larger `timeout`) resumes polling. Concurrent calls share one in-flight\n * poll, so they never issue duplicate requests. The first caller's\n * `timeout`/`signal` drive the shared poll; a later call starts a fresh one.\n */\n result(options: SolveHelperOptions = {}): Promise<Solve> {\n if (this.#terminal) return this.#terminal;\n if (this.#inflight) return this.#inflight;\n const run = this.#poll(options).finally(() => {\n // Free the slot so a retry can re-poll after a timeout; a terminal\n // outcome is already memoized in #terminal and wins on the next call.\n if (this.#inflight === run) this.#inflight = undefined;\n });\n this.#inflight = run;\n return run;\n }\n\n /**\n * Cancel the solve. Cancelled solves are never charged, so this is for clean\n * shutdown / freeing slots / stopping early, not cost protection.\n *\n * If the solve already reached a terminal state the API answers 409; that is\n * not an error a caller cares about, so this swallows {@link ConflictError}\n * and returns the current solve state instead. A cancel that lands on a\n * terminal state (cancelled, or whatever the 409-swallow read back) settles\n * this handle's {@link SolveHandle.result}, so any in-flight or later wait\n * stops polling and reflects that terminal state.\n */\n async cancel(options: { signal?: AbortSignal } = {}): Promise<Solve> {\n try {\n this.#solve = await this.#client.solves.cancel(this.id, options);\n } catch (err) {\n if (!(err instanceof ConflictError)) throw err;\n // Already terminal — report the real state rather than the 409.\n this.#solve = await this.#client.solves.retrieve(this.id, options);\n }\n if (!this.#terminal && isTerminal(this.#solve.status)) this.#cacheTerminal();\n return this.#solve;\n }\n\n /**\n * Build and memoize the terminal outcome from the current `#solve`. The\n * precondition is that `#solve` is terminal and `#terminal` is unset.\n */\n #cacheTerminal(): Promise<Solve> {\n const settled =\n this.#solve.status === \"solved\"\n ? Promise.resolve(this.#solve)\n : Promise.reject(new SolveFailedError(this.#solve));\n // Never let the memoized rejection surface as an unhandled rejection; real\n // callers read it explicitly through result().\n settled.catch(() => {});\n this.#terminal = settled;\n return settled;\n }\n\n async #poll(options: SolveHelperOptions): Promise<Solve> {\n const timeout = options.timeout ?? 180_000;\n const deadline = Date.now() + timeout;\n\n for (;;) {\n // cancel() (or a previous poll) may have already settled this handle.\n if (this.#terminal) return this.#terminal;\n if (isTerminal(this.#solve.status)) return this.#cacheTerminal();\n if (Date.now() >= deadline) {\n throw new TimeoutError(\n `Solve ${this.id} did not finish within ${timeout}ms (last status: ${this.#solve.status}).`,\n { solveId: this.id, solve: this.#solve },\n );\n }\n this.#solve = await this.#client.solves.retrieve(this.id, {\n wait: waitSeconds(deadline),\n signal: options.signal,\n });\n }\n }\n}\n\n/**\n * The `wait` value for the next long-poll: whole seconds until `deadline`,\n * clamped to the server's 1–90 window. The floor of 1 keeps the param valid,\n * so callers must decide whether the deadline has passed with the clock, not\n * with this return value.\n */\nfunction waitSeconds(deadline: number): number {\n const remaining = Math.ceil((deadline - Date.now()) / 1000);\n return Math.max(1, Math.min(MAX_WAIT_SECONDS, remaining));\n}\n\nfunction isAbort(err: unknown): boolean {\n return err instanceof Error && err.name === \"AbortError\";\n}\n\n/** The fields of a report, ready for the wire: a `Date` becomes an ISO string. */\nfunction toWireFields(fields: Omit<FeedbackReport, \"solve_id\">): Record<string, unknown> {\n const wire: Record<string, unknown> = { outcome: fields.outcome };\n if (fields.reason !== undefined) wire.reason = fields.reason;\n if (fields.context !== undefined) wire.context = fields.context;\n if (fields.reported_at !== undefined) {\n wire.reported_at =\n fields.reported_at instanceof Date ? fields.reported_at.toISOString() : fields.reported_at;\n }\n return wire;\n}\n\nfunction toWireReport(report: FeedbackReport): Record<string, unknown> {\n const { solve_id, ...fields } = report;\n return { solve_id, ...toWireFields(fields) };\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/version.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ErrorCode, Solve } from \"./types.js\";\n\n/**\n * Base class for every error this library throws. Catch `NoneCapError` to\n * handle all of them, or catch a subclass to handle one kind.\n */\nexport class NoneCapError extends Error {\n /** Machine-readable error code from the API envelope, when there is one. */\n readonly code: ErrorCode | undefined;\n /** HTTP status, when the error came from a response. */\n readonly status: number | undefined;\n /** The request field that was rejected, for validation errors. */\n readonly param: string | null;\n /** The API's correlation id for this request (`X-Request-Id`); quote it to support. */\n readonly requestId: string | undefined;\n /** Seconds to wait before retrying, when the API sent `Retry-After`. */\n readonly retryAfter: number | undefined;\n\n constructor(\n message: string,\n opts: {\n code?: ErrorCode;\n status?: number;\n param?: string | null;\n requestId?: string;\n retryAfter?: number;\n } = {},\n ) {\n super(message);\n this.name = new.target.name;\n this.code = opts.code;\n this.status = opts.status;\n this.param = opts.param ?? null;\n this.requestId = opts.requestId;\n this.retryAfter = opts.retryAfter;\n // Restore the prototype chain when compiled down to ES5-era targets.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** 401 — the API key is missing, malformed, or revoked. */\nexport class AuthenticationError extends NoneCapError {}\n\n/** 403 — the key is valid but not allowed to do this (scope or locked account). */\nexport class PermissionError extends NoneCapError {}\n\n/** 402 — the account is out of credits. */\nexport class InsufficientCreditsError extends NoneCapError {}\n\n/** 402 — this API key reached its own credit limit (the account may still have credits). */\nexport class KeyCreditLimitError extends InsufficientCreditsError {}\n\n/** 422 / 400 — the request was rejected. `param` names the offending field. */\nexport class ValidationError extends NoneCapError {}\n\n/** 413 — the request body exceeds the route's size limit. */\nexport class PayloadTooLargeError extends ValidationError {}\n\n/** 415 — a JSON route was called without `Content-Type: application/json`. */\nexport class UnsupportedMediaTypeError extends ValidationError {}\n\n/** 404 — no such resource. */\nexport class NotFoundError extends NoneCapError {}\n\n/** 409 — the solve is already in a terminal state (e.g. cancelling a finished solve). */\nexport class ConflictError extends NoneCapError {}\n\n/** 429 — back off and retry; `retryAfter` (seconds) is set when the API sent it. */\nexport class RateLimitError extends NoneCapError {}\n\n/** 429 — too many solves in flight for this account. Wait for one to finish. */\nexport class ConcurrencyLimitError extends RateLimitError {}\n\n/** 429 — hCaptcha is refusing challenges for this sitekey, so the submit was shed.\n * Wait `retryAfter` seconds; the message says whether a different proxy pool can help. */\nexport class SitekeyRateLimitedError extends RateLimitError {}\n\n/** 429 — nearly every recent solve through the proxy you supplied failed because the\n * proxy refused the connection, so submits through it are shed. Fix the proxy or\n * switch exit; `retryAfter` says when the next submit is let through to re-check it. */\nexport class ProxyUnavailableError extends RateLimitError {}\n\n/** 429 — your account has a submit rate cap on this sitekey and reached it for the\n * trailing minute, or your own-proxy sessions for this sitekey are at their limit.\n * Nothing was charged; wait `retryAfter` seconds. */\nexport class RateCappedError extends RateLimitError {}\n\n/** 422 — {@link NoneCap.recognize} produced no answer for these images, or the challenge\n * type is not supported. Nothing was charged. */\nexport class RecognitionFailedError extends NoneCapError {}\n\n/** 5xx, or a response that wasn't the expected shape. `requestId` is the id to quote. */\nexport class APIError extends NoneCapError {}\n\n/** 503 — new solves are paused for maintenance. Retry shortly. */\nexport class ServiceUnavailableError extends APIError {}\n\n/** The request never reached the API (DNS, TCP, TLS, timeout, offline). */\nexport class ConnectionError extends NoneCapError {}\n\n/**\n * Thrown by {@link NoneCap.solve} when a solve reaches a terminal state without\n * a token: `failed`, `expired`, or `cancelled`. The full solve is attached so\n * you can inspect `solve.error` and timings.\n */\nexport class SolveFailedError extends NoneCapError {\n readonly solve: Solve;\n\n constructor(solve: Solve) {\n const detail = solve.error ? `${solve.error.code}: ${solve.error.message}` : solve.status;\n super(`Solve ${solve.id} ${solve.status} (${detail})`, {\n code: undefined,\n status: undefined,\n });\n this.solve = solve;\n }\n\n /** `solve.error.code`, e.g. `proxy_error`; the status when no error object came back. */\n get solveCode(): string {\n return this.solve.error?.code ?? this.solve.status;\n }\n\n /** `solve.error.reason`, the typed sub-reason, or null. */\n get reason(): string | null {\n return this.solve.error?.reason ?? null;\n }\n\n /** Whether re-submitting the same request unchanged can succeed. */\n get retryable(): boolean {\n return this.solve.error?.retryable ?? false;\n }\n}\n\n/**\n * Thrown by {@link NoneCap.solve} (and {@link SolveHandle.result}) when the\n * client-side timeout elapses first. When the timeout came from waiting on a\n * solve, `solveId` and the last-known `solve` are attached so you can still\n * cancel the in-flight solve. They are `undefined` for transport-level timeouts.\n */\nexport class TimeoutError extends NoneCapError {\n /** The id of the in-flight solve, when the timeout came from a solve wait. */\n readonly solveId: string | undefined;\n /** The last-known solve state, so you can cancel it after a wait timed out. */\n readonly solve: Solve | undefined;\n\n constructor(\n message: string,\n opts: {\n code?: ErrorCode;\n status?: number;\n param?: string | null;\n solveId?: string;\n solve?: Solve;\n } = {},\n ) {\n super(message, opts);\n this.solveId = opts.solveId;\n this.solve = opts.solve;\n }\n}\n\n/** Map an API error envelope (plus HTTP status) to the right error subclass. */\nexport function errorFromResponse(\n status: number,\n code: ErrorCode | undefined,\n message: string,\n param: string | null,\n extra: { requestId?: string; retryAfter?: number } = {},\n): NoneCapError {\n const opts = { code, status, param, ...extra };\n switch (code) {\n case \"unauthorized\":\n return new AuthenticationError(message, opts);\n case \"forbidden\":\n case \"account_locked\":\n return new PermissionError(message, opts);\n case \"insufficient_credits\":\n return new InsufficientCreditsError(message, opts);\n case \"key_credit_limit_exceeded\":\n return new KeyCreditLimitError(message, opts);\n case \"invalid_request\":\n case \"validation_error\":\n case \"expired_window\":\n return new ValidationError(message, opts);\n case \"payload_too_large\":\n return new PayloadTooLargeError(message, opts);\n case \"unsupported_media_type\":\n return new UnsupportedMediaTypeError(message, opts);\n case \"not_found\":\n case \"not_eligible\":\n return new NotFoundError(message, opts);\n case \"conflict\":\n return new ConflictError(message, opts);\n case \"concurrency_limit_exceeded\":\n return new ConcurrencyLimitError(message, opts);\n case \"sitekey_rate_limited\":\n return new SitekeyRateLimitedError(message, opts);\n case \"proxy_unavailable\":\n return new ProxyUnavailableError(message, opts);\n case \"rate_capped\":\n return new RateCappedError(message, opts);\n case \"rate_limited\":\n case \"ext_daily_limit\":\n return new RateLimitError(message, opts);\n case \"recognition_failed\":\n return new RecognitionFailedError(message, opts);\n case \"maintenance\":\n return new ServiceUnavailableError(message, opts);\n default:\n return new APIError(message, opts);\n }\n}\n","/**\n * The published package version, sent as the `User-Agent` on every request.\n *\n * Hardcoded rather than imported from package.json: a JSON import would need\n * `resolveJsonModule` and would resolve differently under the ESM and CJS\n * builds. Bump it in the SAME commit as package.json: the drift check is the\n * `Version constant matches package.json` step in ci.yml and lives ONLY there,\n * so `npm test` and `tsc` both stay green on a mismatch (test/version.test.ts\n * asserts the User-Agent uses VERSION, never that VERSION is right).\n */\nexport const VERSION = \"0.13.0\";\n","import {\n APIError,\n ConflictError,\n ConnectionError,\n NoneCapError,\n SolveFailedError,\n TimeoutError,\n errorFromResponse,\n} from \"./errors.js\";\nimport type {\n Account,\n ErrorCode,\n Feedback,\n FeedbackBatch,\n FeedbackReport,\n RecognitionOutcome,\n RecognitionOutcomeResult,\n RecognizeAreaSelectParams,\n RecognizeAreaSelectResult,\n RecognizeBinaryParams,\n RecognizeBinaryResult,\n RecognizeParams,\n RecognizeResult,\n RecognizeTasklistAreaSelectResult,\n RecognizeTasklistBinaryResult,\n RecognizeTasklistDragDropResult,\n RecognizeTasklistParams,\n Solve,\n SolveCreateParams,\n SolveList,\n SolveListParams,\n SolveStatus,\n} from \"./types.js\";\n\nimport { VERSION } from \"./version.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.nonecap.com\";\nconst USER_AGENT = `nonecap-js/${VERSION}`;\n/** The API caps server-side long-poll at 90 seconds. */\nconst MAX_WAIT_SECONDS = 90;\n/** The API caps one `POST /v1/feedback` call at 500 items. */\nexport const FEEDBACK_BATCH_MAX = 500;\nconst TERMINAL: ReadonlySet<SolveStatus> = new Set([\n \"solved\",\n \"failed\",\n \"cancelled\",\n \"expired\",\n]);\n\n/** Is this a terminal solve status? */\nexport function isTerminal(status: SolveStatus): boolean {\n return TERMINAL.has(status);\n}\n\n/** A `fetch` implementation. Defaults to the global `fetch`. */\nexport type FetchLike = (\n input: string,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Options for constructing a {@link NoneCap} client. */\nexport interface NoneCapOptions {\n /** Your NoneCap API key. Find it at https://dashboard.nonecap.com. */\n apiKey: string;\n /** Override the API base URL. Defaults to https://api.nonecap.com. */\n baseURL?: string;\n /**\n * Per-request timeout in milliseconds for a single HTTP call. Defaults to\n * 100000 (just above the 90s server long-poll). Note this bounds one HTTP\n * round trip, not the whole {@link NoneCap.solve} wait — use the `timeout`\n * option on `solve()` for that.\n */\n timeout?: number;\n /** Inject a custom `fetch` (for testing, proxies, or non-standard runtimes). */\n fetch?: FetchLike;\n}\n\n/** Per-call options for the long-polling endpoints. */\nexport interface WaitOptions {\n /**\n * Hold the connection open up to this many seconds (1–90) waiting for the\n * solve to finish before responding. Omit to return immediately.\n */\n wait?: number;\n /** Abort the request. */\n signal?: AbortSignal;\n}\n\n/** Options for {@link NoneCap.solve} and {@link SolveHandle.result}. */\nexport interface SolveHelperOptions {\n /**\n * Give up after this many milliseconds and throw {@link TimeoutError}.\n * Defaults to 180000 (3 minutes).\n */\n timeout?: number;\n /** Abort waiting. */\n signal?: AbortSignal;\n}\n\n/** Options for {@link NoneCap.solves.start}. */\nexport interface SolveStartOptions {\n /** Abort the submission. */\n signal?: AbortSignal;\n}\n\ninterface RequestOptions {\n query?: Record<string, string | number | undefined>;\n body?: unknown;\n signal?: AbortSignal;\n /** Override the per-request timeout for this call (used by long polls). */\n timeout?: number;\n /** HTTP statuses to treat as success in addition to 2xx (e.g. 202). */\n expect?: number[];\n}\n\n/**\n * The NoneCap API client.\n *\n * ```ts\n * const nc = new NoneCap({ apiKey: process.env.NONECAP_KEY! });\n * const { token } = await nc.solve({ type: \"hcaptcha\", sitekey, url });\n * ```\n */\nexport class NoneCap {\n readonly #apiKey: string;\n readonly #baseURL: string;\n readonly #timeout: number;\n readonly #fetch: FetchLike;\n\n constructor(options: NoneCapOptions) {\n if (!options || !options.apiKey) {\n throw new NoneCapError(\n \"A NoneCap API key is required. Pass it as `new NoneCap({ apiKey })`.\",\n );\n }\n this.#apiKey = options.apiKey;\n this.#baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.#timeout = options.timeout ?? 100_000;\n const f = options.fetch ?? (globalThis.fetch as FetchLike | undefined);\n if (!f) {\n throw new NoneCapError(\n \"No `fetch` available. Use Node 18+, or pass a `fetch` in the client options.\",\n );\n }\n this.#fetch = f;\n }\n\n /** Operations on solves. */\n readonly solves = {\n /** Submit a solve. Pass `{ wait }` to hold the connection until it finishes. */\n create: (params: SolveCreateParams, options: WaitOptions = {}): Promise<Solve> =>\n this.#request<Solve>(\"POST\", \"/v1/solves\", {\n body: params,\n query: { wait: options.wait },\n signal: options.signal,\n timeout: this.#timeoutForWait(options.wait),\n expect: [202],\n }),\n\n /** Fetch a solve by id. Pass `{ wait }` to long-poll until it finishes. */\n retrieve: (id: string, options: WaitOptions = {}): Promise<Solve> =>\n this.#request<Solve>(\"GET\", `/v1/solves/${encodeURIComponent(id)}`, {\n query: { wait: options.wait },\n signal: options.signal,\n timeout: this.#timeoutForWait(options.wait),\n expect: [202],\n }),\n\n /** Cancel a pending or in-flight solve. */\n cancel: (id: string, options: { signal?: AbortSignal } = {}): Promise<Solve> =>\n this.#request<Solve>(\"DELETE\", `/v1/solves/${encodeURIComponent(id)}`, {\n signal: options.signal,\n }),\n\n /**\n * Submit a solve and return a {@link SolveHandle} for it.\n *\n * Unlike {@link NoneCap.solve}, this returns as soon as the submission is\n * accepted, so `handle.id` is available immediately. Use the handle to\n * `cancel()` the solve or `await handle.result()` for the finished solve.\n *\n * ```ts\n * const handle = await nc.solves.start({ type: \"hcaptcha\", sitekey, url });\n * // ...later, e.g. on shutdown:\n * await handle.cancel();\n * // or wait for it:\n * const { token } = await handle.result();\n * ```\n */\n start: async (\n params: SolveCreateParams,\n options: SolveStartOptions = {},\n ): Promise<SolveHandle> => {\n const solve = await this.solves.create(params, { signal: options.signal });\n return new SolveHandle(this, solve);\n },\n\n /** Fetch one page of solves. */\n list: (params: SolveListParams = {}, options: { signal?: AbortSignal } = {}): Promise<SolveList> =>\n this.#request<SolveList>(\"GET\", \"/v1/solves\", {\n query: {\n limit: params.limit,\n starting_after: params.starting_after,\n status: params.status,\n type: params.type,\n },\n signal: options.signal,\n }),\n\n /**\n * Iterate every solve across pages, newest first.\n *\n * ```ts\n * for await (const solve of nc.solves.listAll()) { ... }\n * ```\n */\n listAll: (\n params: SolveListParams = {},\n options: { signal?: AbortSignal } = {},\n ): AsyncIterableIterator<Solve> => this.#listAll(params, options),\n };\n\n /**\n * Report what your downstream target did with the tokens we minted.\n *\n * Feedback is free, own-solves-only, and idempotent per solve id: reporting\n * the same solve again corrects the earlier verdict. Only `solved` solves can\n * be reported, and only within the API's reporting window (~30 days from the\n * solve; corrections to an already-reported solve are never re-gated by it).\n */\n readonly feedback = {\n /**\n * Report one solve's downstream outcome, returning the recorded feedback.\n *\n * Unlike {@link NoneCap.feedback.reportMany}, a rejected report throws:\n * {@link NotFoundError} if the solve isn't yours or never minted a token,\n * {@link ValidationError} if a field is wrong or the reporting window closed.\n *\n * ```ts\n * await nc.feedback.report({ solve_id: solve.id, outcome: \"rejected\", reason: \"...\" });\n * ```\n */\n report: (report: FeedbackReport, options: { signal?: AbortSignal } = {}): Promise<Feedback> => {\n const { solve_id, ...fields } = report;\n return this.#request<Feedback>(\n \"POST\",\n `/v1/solves/${encodeURIComponent(solve_id)}/feedback`,\n { body: toWireFields(fields), signal: options.signal },\n );\n },\n\n /**\n * Report many verdicts at once — the path to use at volume. Buffer verdicts\n * as you learn them and flush them here.\n *\n * The call succeeds even when individual items are rejected: each is\n * resolved on its own so one stale id never discards the rest. Check\n * `failed` rather than relying on a thrown error.\n *\n * More than {@link FEEDBACK_BATCH_MAX} reports are split across sequential\n * requests and merged into one result, in request order. An empty array is\n * a no-op that returns an empty batch without a request.\n *\n * ```ts\n * const batch = await nc.feedback.reportMany(buffer);\n * if (batch.failed) console.warn(batch.results.filter((r) => r.status === \"error\"));\n * ```\n */\n reportMany: async (\n reports: readonly FeedbackReport[],\n options: { signal?: AbortSignal } = {},\n ): Promise<FeedbackBatch> => {\n const merged: FeedbackBatch = {\n object: \"feedback_batch\",\n recorded: 0,\n updated: 0,\n unchanged: 0,\n failed: 0,\n results: [],\n };\n // Chunks are sent in order and the server upserts last-write-wins, so a\n // solve reported twice still ends at its last value. Duplicates split\n // across a chunk boundary each get written, though, so the earlier one\n // reports `recorded`/`updated` where a single request would say\n // `unchanged`.\n for (let i = 0; i < reports.length; i += FEEDBACK_BATCH_MAX) {\n const batch = await this.#request<FeedbackBatch>(\"POST\", \"/v1/feedback\", {\n body: { feedback: reports.slice(i, i + FEEDBACK_BATCH_MAX).map(toWireReport) },\n signal: options.signal,\n });\n merged.recorded += batch.recorded;\n merged.updated += batch.updated;\n merged.unchanged += batch.unchanged;\n merged.failed += batch.failed;\n merged.results.push(...batch.results);\n }\n return merged;\n },\n };\n\n /** Fetch your account, including the current credit balance. */\n me(options: { signal?: AbortSignal } = {}): Promise<Account> {\n return this.#request<Account>(\"GET\", \"/v1/me\", { signal: options.signal });\n }\n\n /**\n * Recognize a challenge's images: send the instruction and images, get the\n * answer back in the same response. No token, no polling.\n *\n * An answered call's charge is final. Throws {@link RecognitionFailedError}\n * when no answer came back (nothing is charged then), {@link ValidationError}\n * for a malformed request.\n *\n * ```ts\n * const { id, data } = await nc.recognize({\n * type: \"hcaptcha\",\n * task: \"Please click each image containing a bus\",\n * image_data: tiles, // base64\n * });\n * ```\n */\n recognize(params: RecognizeBinaryParams, options?: { signal?: AbortSignal }): Promise<RecognizeBinaryResult>;\n recognize(params: RecognizeAreaSelectParams, options?: { signal?: AbortSignal }): Promise<RecognizeAreaSelectResult>;\n recognize(\n params: RecognizeTasklistParams<\"image_label_binary\">,\n options?: { signal?: AbortSignal },\n ): Promise<RecognizeTasklistBinaryResult>;\n recognize(\n params: RecognizeTasklistParams<\"image_label_area_select\">,\n options?: { signal?: AbortSignal },\n ): Promise<RecognizeTasklistAreaSelectResult>;\n recognize(\n params: RecognizeTasklistParams<\"image_drag_drop\">,\n options?: { signal?: AbortSignal },\n ): Promise<RecognizeTasklistDragDropResult>;\n recognize(params: RecognizeParams, options?: { signal?: AbortSignal }): Promise<RecognizeResult>;\n recognize(params: RecognizeParams, options: { signal?: AbortSignal } = {}): Promise<RecognizeResult> {\n return this.#request<RecognizeResult>(\"POST\", \"/v1/recognize\", {\n body: params,\n signal: options.signal,\n });\n }\n\n /**\n * Report whether a {@link NoneCap.recognize} answer worked on the challenge.\n * Optional and free; it feeds NoneCap's accuracy stats and never refunds the\n * call. The first report for an id sticks: a repeat returns it unchanged.\n */\n reportRecognitionOutcome(\n id: string,\n result: RecognitionOutcome,\n options: { signal?: AbortSignal } = {},\n ): Promise<RecognitionOutcomeResult> {\n return this.#request<RecognitionOutcomeResult>(\"POST\", \"/v1/recognize/outcome\", {\n body: { id, result },\n signal: options.signal,\n });\n }\n\n /**\n * Submit a solve and wait for it to finish, returning the solved solve.\n *\n * Uses the server's long-poll under the hood and keeps polling until the\n * solve is terminal or `timeout` elapses. Throws {@link SolveFailedError} if\n * the solve fails/expires/is cancelled, or {@link TimeoutError} on timeout.\n *\n * This is sugar for `(await solves.start(params)).result(options)`. When you\n * need to cancel the solve while it runs, use {@link NoneCap.solves.start}\n * and keep the {@link SolveHandle}.\n */\n async solve(params: SolveCreateParams, options: SolveHelperOptions = {}): Promise<Solve> {\n const handle = await this.solves.start(params, { signal: options.signal });\n return handle.result(options);\n }\n\n // -- internals ------------------------------------------------------------\n\n #timeoutForWait(wait?: number): number | undefined {\n if (wait === undefined) return undefined;\n // Give the socket a margin beyond the server's long-poll window.\n return wait * 1000 + 15_000;\n }\n\n async *#listAll(\n params: SolveListParams,\n options: { signal?: AbortSignal },\n ): AsyncIterableIterator<Solve> {\n let cursor = params.starting_after;\n for (;;) {\n const page = await this.solves.list({ ...params, starting_after: cursor }, options);\n for (const solve of page.data) yield solve;\n if (!page.has_more || page.data.length === 0) return;\n cursor = page.data[page.data.length - 1]!.id;\n }\n }\n\n async #request<T>(method: string, path: string, options: RequestOptions = {}): Promise<T> {\n const url = new URL(this.#baseURL + path);\n if (options.query) {\n for (const [key, value] of Object.entries(options.query)) {\n if (value !== undefined && value !== \"\") url.searchParams.set(key, String(value));\n }\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.#apiKey}`,\n Accept: \"application/json\",\n // Browsers drop this as a forbidden header; on Node it identifies the SDK.\n \"User-Agent\": USER_AGENT,\n };\n let bodyInit: string | undefined;\n if (options.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n bodyInit = JSON.stringify(options.body);\n }\n\n const controller = new AbortController();\n const timeoutMs = options.timeout ?? this.#timeout;\n const timer = setTimeout(() => controller.abort(new TimeoutError(`Request timed out after ${timeoutMs}ms.`)), timeoutMs);\n const onAbort = () => controller.abort(options.signal?.reason);\n if (options.signal) {\n if (options.signal.aborted) onAbort();\n else options.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n let res: Response;\n try {\n res = await this.#fetch(url.toString(), {\n method,\n headers,\n body: bodyInit,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof TimeoutError) throw err;\n if (isAbort(err)) {\n // A caller-supplied signal aborting surfaces as the caller's reason.\n if (options.signal?.aborted) throw options.signal.reason instanceof Error\n ? options.signal.reason\n : new NoneCapError(\"Request aborted.\");\n throw new TimeoutError(`Request timed out after ${timeoutMs}ms.`);\n }\n throw new ConnectionError(\n `Could not reach the NoneCap API at ${this.#baseURL}: ${(err as Error).message}`,\n );\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", onAbort);\n }\n\n return this.#parse<T>(res, options.expect ?? []);\n }\n\n async #parse<T>(res: Response, expect: number[]): Promise<T> {\n const text = await res.text();\n let json: unknown;\n if (text) {\n try {\n json = JSON.parse(text);\n } catch {\n throw new APIError(\n `Unexpected non-JSON response (HTTP ${res.status}): ${text.slice(0, 200)}`,\n { status: res.status },\n );\n }\n }\n\n if (res.ok || expect.includes(res.status)) {\n return json as T;\n }\n\n const envelope = json as\n | { error?: { code?: ErrorCode; message?: string; param?: string | null; request_id?: string } }\n | undefined;\n const apiError = envelope?.error;\n const retryAfterRaw = res.headers.get(\"retry-after\");\n const retryAfter = retryAfterRaw !== null && /^\\d+$/.test(retryAfterRaw) ? Number(retryAfterRaw) : undefined;\n throw errorFromResponse(\n res.status,\n apiError?.code,\n apiError?.message ?? `HTTP ${res.status}`,\n apiError?.param ?? null,\n { requestId: apiError?.request_id ?? res.headers.get(\"x-request-id\") ?? undefined, retryAfter },\n );\n }\n}\n\n/**\n * A handle on a started solve, returned by {@link NoneCap.solves.start}.\n *\n * The handle is the cancellable lifecycle object for one solve. It is a plain\n * object, not a promise: `await`ing it does nothing useful. Wait for the result\n * with {@link SolveHandle.result}, and cancel with {@link SolveHandle.cancel}.\n * You do not construct it yourself — `solves.start()` hands you one with `id`\n * already resolved.\n */\nexport class SolveHandle {\n /** The id of the started solve, available as soon as `start()` resolved. */\n readonly id: string;\n\n readonly #client: NoneCap;\n /** The latest solve state we have seen, from the create, polls, or cancel. */\n #solve: Solve;\n /**\n * The cached TERMINAL outcome: resolves to the solved solve, or rejects with\n * {@link SolveFailedError} if terminal-but-not-solved. Only ever set once the\n * solve actually reaches a terminal state, so it is safe to replay forever. A\n * timed-out wait does NOT settle this — it is retryable.\n */\n #terminal: Promise<Solve> | undefined;\n /** The poll currently in flight, shared by concurrent result() callers. */\n #inflight: Promise<Solve> | undefined;\n\n constructor(client: NoneCap, solve: Solve) {\n this.#client = client;\n this.#solve = solve;\n this.id = solve.id;\n }\n\n /** The last-known solve state for this handle. */\n get solve(): Solve {\n return this.#solve;\n }\n\n /**\n * Long-poll until the solve is terminal, returning the solved solve. Throws\n * {@link SolveFailedError} if it fails/expires/is cancelled, or\n * {@link TimeoutError} on timeout (with `solveId`/`solve` attached so you can\n * still {@link SolveHandle.cancel} it).\n *\n * Memoizes the *terminal* outcome: once the solve actually finishes, every\n * later call returns that same settled result. A {@link TimeoutError} is not\n * memoized — it just means this wait gave up, so a later call (e.g. with a\n * larger `timeout`) resumes polling. Concurrent calls share one in-flight\n * poll, so they never issue duplicate requests. The first caller's\n * `timeout`/`signal` drive the shared poll; a later call starts a fresh one.\n */\n result(options: SolveHelperOptions = {}): Promise<Solve> {\n if (this.#terminal) return this.#terminal;\n if (this.#inflight) return this.#inflight;\n const run = this.#poll(options).finally(() => {\n // Free the slot so a retry can re-poll after a timeout; a terminal\n // outcome is already memoized in #terminal and wins on the next call.\n if (this.#inflight === run) this.#inflight = undefined;\n });\n this.#inflight = run;\n return run;\n }\n\n /**\n * Cancel the solve. Cancelled solves are never charged, so this is for clean\n * shutdown / freeing slots / stopping early, not cost protection.\n *\n * If the solve already reached a terminal state the API answers 409; that is\n * not an error a caller cares about, so this swallows {@link ConflictError}\n * and returns the current solve state instead. A cancel that lands on a\n * terminal state (cancelled, or whatever the 409-swallow read back) settles\n * this handle's {@link SolveHandle.result}, so any in-flight or later wait\n * stops polling and reflects that terminal state.\n */\n async cancel(options: { signal?: AbortSignal } = {}): Promise<Solve> {\n try {\n this.#solve = await this.#client.solves.cancel(this.id, options);\n } catch (err) {\n if (!(err instanceof ConflictError)) throw err;\n // Already terminal — report the real state rather than the 409.\n this.#solve = await this.#client.solves.retrieve(this.id, options);\n }\n if (!this.#terminal && isTerminal(this.#solve.status)) this.#cacheTerminal();\n return this.#solve;\n }\n\n /**\n * Build and memoize the terminal outcome from the current `#solve`. The\n * precondition is that `#solve` is terminal and `#terminal` is unset.\n */\n #cacheTerminal(): Promise<Solve> {\n const settled =\n this.#solve.status === \"solved\"\n ? Promise.resolve(this.#solve)\n : Promise.reject(new SolveFailedError(this.#solve));\n // Never let the memoized rejection surface as an unhandled rejection; real\n // callers read it explicitly through result().\n settled.catch(() => {});\n this.#terminal = settled;\n return settled;\n }\n\n async #poll(options: SolveHelperOptions): Promise<Solve> {\n const timeout = options.timeout ?? 180_000;\n const deadline = Date.now() + timeout;\n\n for (;;) {\n // cancel() (or a previous poll) may have already settled this handle.\n if (this.#terminal) return this.#terminal;\n if (isTerminal(this.#solve.status)) return this.#cacheTerminal();\n if (Date.now() >= deadline) {\n throw new TimeoutError(\n `Solve ${this.id} did not finish within ${timeout}ms (last status: ${this.#solve.status}).`,\n { solveId: this.id, solve: this.#solve },\n );\n }\n this.#solve = await this.#client.solves.retrieve(this.id, {\n wait: waitSeconds(deadline),\n signal: options.signal,\n });\n }\n }\n}\n\n/**\n * The `wait` value for the next long-poll: whole seconds until `deadline`,\n * clamped to the server's 1–90 window. The floor of 1 keeps the param valid,\n * so callers must decide whether the deadline has passed with the clock, not\n * with this return value.\n */\nfunction waitSeconds(deadline: number): number {\n const remaining = Math.ceil((deadline - Date.now()) / 1000);\n return Math.max(1, Math.min(MAX_WAIT_SECONDS, remaining));\n}\n\nfunction isAbort(err: unknown): boolean {\n return err instanceof Error && err.name === \"AbortError\";\n}\n\n/** The fields of a report, ready for the wire: a `Date` becomes an ISO string. */\nfunction toWireFields(fields: Omit<FeedbackReport, \"solve_id\">): Record<string, unknown> {\n const wire: Record<string, unknown> = { outcome: fields.outcome };\n if (fields.reason !== undefined) wire.reason = fields.reason;\n if (fields.context !== undefined) wire.context = fields.context;\n if (fields.reported_at !== undefined) {\n wire.reported_at =\n fields.reported_at instanceof Date ? fields.reported_at.toISOString() : fields.reported_at;\n }\n return wire;\n}\n\nfunction toWireReport(report: FeedbackReport): Record<string, unknown> {\n const { solve_id, ...fields } = report;\n return { solve_id, ...toWireFields(fields) };\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -141,7 +141,10 @@ interface Solve {
141
141
  * Advisories about this solve; empty when there is none. `proxy_session_refused`:
142
142
  * the last token(s) you reported through this solve's `proxy` session or its exit IP
143
143
  * were rejected (`feedback.report`). A different exit IP is more likely to pass, so
144
- * switch to one for your next solves. `proxy_recommended`: this page is much more likely to accept a
144
+ * switch to one for your next solves. When your proxy changed its exit IP during the solve, the
145
+ * same code advises a sticky session per solve instead, with the token submitted through that
146
+ * same session, and on a page that is much more likely to accept a token solved through the same
147
+ * connection you submit it from it does so from the first such solve. `proxy_recommended`: this page is much more likely to accept a
145
148
  * token solved through the same connection you submit it from, and this solve did not run
146
149
  * through yours; send your proxy in `proxy`, and make sure it works. The solve still runs.
147
150
  * Absent on responses from API versions before the field.
package/dist/index.d.ts CHANGED
@@ -141,7 +141,10 @@ interface Solve {
141
141
  * Advisories about this solve; empty when there is none. `proxy_session_refused`:
142
142
  * the last token(s) you reported through this solve's `proxy` session or its exit IP
143
143
  * were rejected (`feedback.report`). A different exit IP is more likely to pass, so
144
- * switch to one for your next solves. `proxy_recommended`: this page is much more likely to accept a
144
+ * switch to one for your next solves. When your proxy changed its exit IP during the solve, the
145
+ * same code advises a sticky session per solve instead, with the token submitted through that
146
+ * same session, and on a page that is much more likely to accept a token solved through the same
147
+ * connection you submit it from it does so from the first such solve. `proxy_recommended`: this page is much more likely to accept a
145
148
  * token solved through the same connection you submit it from, and this solve did not run
146
149
  * through yours; send your proxy in `proxy`, and make sure it works. The solve still runs.
147
150
  * Absent on responses from API versions before the field.
package/dist/index.js CHANGED
@@ -137,7 +137,7 @@ function errorFromResponse(status, code, message, param, extra = {}) {
137
137
  }
138
138
 
139
139
  // src/version.ts
140
- var VERSION = "0.12.1";
140
+ var VERSION = "0.13.0";
141
141
 
142
142
  // src/client.ts
143
143
  var DEFAULT_BASE_URL = "https://api.nonecap.com";