@hunt-labs/bytekit-sdk 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/README.md +82 -0
- package/dist/client.d.ts +34 -1
- package/dist/client.js +12 -2
- package/dist/generated/api.d.ts +28 -8
- package/dist/resources/scrape.d.ts +0 -13
- package/dist/resources/scrape.js +0 -13
- package/dist/resources/screenshots.d.ts +9 -2
- package/dist/resources/screenshots.js +15 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,106 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
This file records only the delta between versions. For how to use the package
|
|
9
9
|
today, see [README.md](./README.md), which remains the authoritative usage guide.
|
|
10
10
|
|
|
11
|
+
## [Unreleased]
|
|
12
|
+
|
|
13
|
+
## [0.7.1] - 2026-08-11
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Generated types follow the spec's corrected error and format vocabularies** (#2959). Two
|
|
18
|
+
vocabulary corrections in `docs/api/openapi.yaml` flow through `src/generated/api.d.ts`:
|
|
19
|
+
- `ScrapeErrorEnvelope.error.code` no longer lists `quota_exhausted`. The API has emitted
|
|
20
|
+
`quota_exceeded` since #1539 and there is no throw site for `quota_exhausted` anywhere in
|
|
21
|
+
the gateway, so this removes a code that has never been sent — not one that stops being
|
|
22
|
+
sent. A consumer switching on it was matching a branch that could not be reached; the
|
|
23
|
+
live code for an exceeded quota is `quota_exceeded`. `invalid_url`, which the API does
|
|
24
|
+
emit, is unchanged and still listed.
|
|
25
|
+
- `createBulk`'s `formats` now spells the raw-HTML value `raw_html`, matching `ScrapeRequest`
|
|
26
|
+
and `createScrapeBulk`. `/v1/bulk` previously accepted only the internal `rawHtml`
|
|
27
|
+
spelling and the spec documented that; it now accepts both, so the one endpoint that
|
|
28
|
+
disagreed with the rest of the surface no longer does. `rawHtml` keeps working.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **`ByteKitError.headers` — the failing response's headers, so you can write your own backoff**
|
|
33
|
+
(#2957). This SDK performs exactly one `fetch` per call and never retries, deliberately, so that
|
|
34
|
+
retry policy stays the caller's. But the policy was unwritable: `ByteKitError` carried no
|
|
35
|
+
headers and `requestWithResponse` returns headers only on 2xx — which a rate-limited request
|
|
36
|
+
never reaches — so `Retry-After` and the `X-RateLimit-*` family were unreachable through the SDK
|
|
37
|
+
at every entry point. `err.headers` closes that:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
if (err instanceof ByteKitError && err.status === 429) {
|
|
41
|
+
const waitMs = Number(err.headers?.get('Retry-After') ?? 1) * 1000;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It is the runtime's own `Headers` object rather than a snapshot, so `get()` stays
|
|
46
|
+
case-insensitive whatever casing the wire used. **Strictly additive**: it is optional and last
|
|
47
|
+
on the constructor, follows the same `declare` discipline `details` uses, and an error
|
|
48
|
+
constructed without one carries no `headers` key at all — `'headers' in err`, spreads and
|
|
49
|
+
`JSON.stringify` are unchanged for every pre-existing construction, as are `status`, `code`,
|
|
50
|
+
`message`, `details` and both 2xx return shapes. Only **response** headers are exposed;
|
|
51
|
+
`Authorization` rides on the request and is never reachable through it.
|
|
52
|
+
`ByteKitConnectionError` is unchanged — no response, no headers to carry.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- **`screenshots.getWithResponse`'s docstring no longer promises headers that endpoint never
|
|
57
|
+
emits** (#2957). The JSDoc — the one an IDE surfaces on hover, and the one the published SDK
|
|
58
|
+
reference is generated from — claimed the documented `X-Screenshot-*` / `X-Raw-Bytes` /
|
|
59
|
+
`X-Billable-Bytes` / `X-Billing-Multiplier` headers "are on `headers`". They are not:
|
|
60
|
+
`GET /v1/screenshots/{id}` is declared with **no** `X-*` response headers, which is what
|
|
61
|
+
`ByteKit.requestWithResponse`'s own doc comment and the README have said all along, and what a
|
|
62
|
+
live GET confirms. Documentation only — no signature, return type or runtime behavior changed.
|
|
63
|
+
`screenshots.createWithResponse` (`POST /v1/screenshots`) really does emit that family, and its
|
|
64
|
+
docstring still says so.
|
|
65
|
+
|
|
66
|
+
- **README documents the `signal`-vs-`timeoutMs` precedence and the `requestTimeoutMs` escape
|
|
67
|
+
hatch** (#2957). Passing your own `AbortSignal` silently disables the constructor's `timeoutMs`
|
|
68
|
+
— the signal becomes the request's only abort source, so a client built with `timeoutMs: 200`
|
|
69
|
+
waits indefinitely if the signal never fires. That precedence was documented on
|
|
70
|
+
`RequestOptions.signal` in the types, where only a reader already inspecting the option would
|
|
71
|
+
meet it, and nowhere in the README. A new "Timeouts and cancellation" section states it with the
|
|
72
|
+
full four-row precedence table and shows `requestTimeoutMs` composed alongside a caller signal
|
|
73
|
+
(the request then aborts on whichever fires first). No behavior changed — the precedence is what
|
|
74
|
+
it always was.
|
|
75
|
+
|
|
76
|
+
- **`ScrapeWarning.code` now carries all 12 codes the server can emit** (#2948). The generated
|
|
77
|
+
union in `src/generated/api.d.ts` listed 10. `low_quality_extraction` and
|
|
78
|
+
`fragment_menu_stripped` — added to the server-side emitter union by #1701 — never reached
|
|
79
|
+
`docs/api/openapi.yaml`, so every regeneration since faithfully reproduced the gap and the
|
|
80
|
+
exported type was non-exhaustive: a `switch` over `warning.code` that TypeScript proved
|
|
81
|
+
exhaustive would silently fall through on a warning the API really returns. Widening the spec
|
|
82
|
+
and regenerating fixes the type; no runtime code changed. The other 10 codes are unaffected.
|
|
83
|
+
|
|
84
|
+
- **Gateway wire-type correction: `billing_multiplier` is a JSON number on `scrape.get()` again**
|
|
85
|
+
(#2954). `GET /v1/scrape/{id}` (and `GET /v1/scrape/bulk/{id}` items) were serializing
|
|
86
|
+
`billing_multiplier` as a JSON string (e.g. `"0.50"`) instead of a number — the pg driver
|
|
87
|
+
returns the underlying `NUMERIC(10,2)` column as a string, and the gateway's GET serializer
|
|
88
|
+
passed it through unconverted, while `POST /v1/scrape`'s create-path value (computed in JS) was
|
|
89
|
+
already correct. Fixed upstream in the gateway; this SDK required no code change, only removal
|
|
90
|
+
of the `KNOWN DRIFT (#2426)` JSDoc on `ScrapeResource.get()` that documented the workaround —
|
|
91
|
+
the static `number` type this SDK has shipped all along is accurate again. A caller that was
|
|
92
|
+
defensively coercing with `Number(...)` per the old note does not need to change anything; a
|
|
93
|
+
caller relying on the exact string form `"0.50"` (rather than doing arithmetic) will now see
|
|
94
|
+
`0.5`.
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
|
|
98
|
+
- **Alignment release — no consumer-visible change _in the alignment itself_** (the `#2948` type
|
|
99
|
+
widening above is a separate, deliberate change under this same version). `0.7.0` published to npm at
|
|
100
|
+
`2026-08-11T21:17:42.790Z`. Two doc comments, in `src/client.ts` and `src/version.ts`, were
|
|
101
|
+
reworded **after** the commit that introduced the `0.7.0` version string — they had re-spelled
|
|
102
|
+
the `X-ByteKit-Client` header name in prose, which issue #2905's pre-merge gate 1 counts. No
|
|
103
|
+
exported function, type, or runtime behavior differs from `0.7.0`.
|
|
104
|
+
|
|
105
|
+
This release exists because `check-release-drift` (#2680) is version-gated and anchors on the
|
|
106
|
+
commit that introduced a version, not on the commit whose tree was actually published. Once
|
|
107
|
+
`0.7.0` reached npm, any shipped-file change after that anchor reads as post-release drift.
|
|
108
|
+
Bumping moves the anchor past those comments. The published `0.7.0` artifact is **not** stale in
|
|
109
|
+
any way a consumer can observe — the divergence is comment text only.
|
|
110
|
+
|
|
11
111
|
## [0.7.0] - 2026-08-11
|
|
12
112
|
|
|
13
113
|
### Added
|
|
@@ -407,6 +507,11 @@ against 0.1.0 — read each one before upgrading.
|
|
|
407
507
|
(scrape, screenshot, search, and related endpoints), published under the original
|
|
408
508
|
`@rapidcrawl/sdk` name.
|
|
409
509
|
|
|
510
|
+
[Unreleased]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
511
|
+
[0.7.1]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
512
|
+
[0.7.0]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
513
|
+
[0.6.2]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
514
|
+
[0.6.1]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
410
515
|
[0.6.0]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
411
516
|
[0.5.0]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
412
517
|
[0.4.0]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
package/README.md
CHANGED
|
@@ -233,6 +233,56 @@ These siblings are purely additive: they issue the identical request and accept
|
|
|
233
233
|
identical options as their base methods, and `data` is exactly what the base method
|
|
234
234
|
resolves to — no existing return type changes.
|
|
235
235
|
|
|
236
|
+
## Timeouts and cancellation
|
|
237
|
+
|
|
238
|
+
Every request carries a **client-side** abort budget covering the whole HTTP
|
|
239
|
+
round-trip — time-to-headers _and_ the response body read. It defaults to
|
|
240
|
+
120000 ms and is set on the constructor:
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
import { ByteKit } from '@hunt-labs/bytekit-sdk';
|
|
244
|
+
|
|
245
|
+
const bounded = new ByteKit({
|
|
246
|
+
apiKey: process.env.BYTEKIT_API_KEY!,
|
|
247
|
+
timeoutMs: 30_000, // client-side abort budget for every call; 0 disables it
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`timeoutMs` is **not** `ScrapeOpts.timeout_ms`. The former is how long this SDK
|
|
252
|
+
waits on the wire; the latter is the server-side budget the gateway applies to
|
|
253
|
+
the scrape itself.
|
|
254
|
+
|
|
255
|
+
### `signal` replaces the default timeout — `requestTimeoutMs` keeps it
|
|
256
|
+
|
|
257
|
+
Passing your own `AbortSignal` **silently disables the constructor's
|
|
258
|
+
`timeoutMs`**: the signal becomes the request's only abort source, so a client
|
|
259
|
+
built with `timeoutMs: 200` waits indefinitely if the signal never fires. That
|
|
260
|
+
is deliberate — a caller who brought their own cancellation owns it — but it is
|
|
261
|
+
easy to hit by accident. The escape hatch is `requestTimeoutMs`, which is
|
|
262
|
+
composed _with_ your signal rather than replaced by it, so the request aborts on
|
|
263
|
+
whichever fires first:
|
|
264
|
+
|
|
265
|
+
| `signal` | `requestTimeoutMs` | what bounds the request |
|
|
266
|
+
| -------- | ------------------ | ------------------------------- |
|
|
267
|
+
| absent | absent | the constructor's `timeoutMs` |
|
|
268
|
+
| absent | present | `requestTimeoutMs` |
|
|
269
|
+
| present | absent | your signal **only** — no timer |
|
|
270
|
+
| present | present | whichever fires first |
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
const controller = new AbortController();
|
|
274
|
+
|
|
275
|
+
// Cancellable AND bounded: aborts on controller.abort() or after 5 s.
|
|
276
|
+
await client.scrape.create(
|
|
277
|
+
{ url: 'https://example.com' },
|
|
278
|
+
{ signal: controller.signal, requestTimeoutMs: 5_000 },
|
|
279
|
+
);
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
`0` at either level means "no SDK-side timeout". A request that never produced
|
|
283
|
+
an HTTP response at all throws `ByteKitConnectionError`, whose `code`
|
|
284
|
+
distinguishes `'timeout'` from `'aborted'` and `'connection'`.
|
|
285
|
+
|
|
236
286
|
## Error handling
|
|
237
287
|
|
|
238
288
|
Any 4xx/5xx response throws a `ByteKitError` carrying the HTTP status and
|
|
@@ -286,6 +336,38 @@ body instead (`/v1/search` returns `502 {"error":"search_provider_error"}`);
|
|
|
286
336
|
those carry no structured detail, so `err.details` stays `undefined` there —
|
|
287
337
|
`err.code` is still the machine-readable reason.
|
|
288
338
|
|
|
339
|
+
### Rate limits, `Retry-After`, and your own backoff
|
|
340
|
+
|
|
341
|
+
This SDK performs **exactly one** `fetch` per call and never retries — retry
|
|
342
|
+
policy stays yours. To make that policy writable, `err.headers` carries the
|
|
343
|
+
response headers of the failing request, so `Retry-After` and the
|
|
344
|
+
`X-RateLimit-*` family are readable straight off the error:
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
import { ByteKit, ByteKitError } from '@hunt-labs/bytekit-sdk';
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
await client.scrape.create({ url: 'https://example.com' });
|
|
351
|
+
} catch (err) {
|
|
352
|
+
if (err instanceof ByteKitError && err.status === 429) {
|
|
353
|
+
const retryAfter = err.headers?.get('Retry-After'); // string | null | undefined
|
|
354
|
+
const waitMs =
|
|
355
|
+
retryAfter === null || retryAfter === undefined ? 1000 : Number(retryAfter) * 1000;
|
|
356
|
+
console.error(`rate limited; retry in ${waitMs}ms`, err.headers?.get('X-RateLimit-Remaining'));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
It is the runtime's own `Headers` object, so `get()` is case-insensitive —
|
|
362
|
+
`get('Retry-After')` and `get('retry-after')` are the same lookup. It is present
|
|
363
|
+
on every error thrown from a real HTTP response and `undefined` on an error you
|
|
364
|
+
constructed yourself, which is why the reads above are optional-chained. Only
|
|
365
|
+
**response** headers are here: `Authorization` rides on the request and is never
|
|
366
|
+
reachable through it. `status`, `code`, `message` and `details` are unchanged.
|
|
367
|
+
|
|
368
|
+
`ByteKitConnectionError` — thrown when no HTTP response was produced at all —
|
|
369
|
+
carries no headers, because there was no response to read them from.
|
|
370
|
+
|
|
289
371
|
## Documentation
|
|
290
372
|
|
|
291
373
|
Full API reference: [bytekit.com/docs](https://bytekit.com/docs).
|
package/dist/client.d.ts
CHANGED
|
@@ -119,7 +119,40 @@ export declare class ByteKitError extends Error {
|
|
|
119
119
|
* so the key exists only when the envelope really supplied one.
|
|
120
120
|
*/
|
|
121
121
|
readonly details?: ByteKitErrorDetails;
|
|
122
|
-
|
|
122
|
+
/**
|
|
123
|
+
* The RESPONSE headers of the failing HTTP response (issue #2957).
|
|
124
|
+
*
|
|
125
|
+
* This SDK performs exactly ONE `fetch` per call and never retries — a deliberate
|
|
126
|
+
* design, so that retry policy stays the caller's. That is only a defensible position
|
|
127
|
+
* if the caller can actually IMPLEMENT a policy, and until this field existed they
|
|
128
|
+
* could not: `requestWithResponse` returns headers on 2xx only, and a rate-limited
|
|
129
|
+
* request never reaches a 2xx. `Retry-After` and the `X-RateLimit-*` family were
|
|
130
|
+
* therefore unreachable through the SDK at every entry point.
|
|
131
|
+
*
|
|
132
|
+
* ```ts
|
|
133
|
+
* catch (err) {
|
|
134
|
+
* if (err instanceof ByteKitError && err.status === 429) {
|
|
135
|
+
* const wait = Number(err.headers?.get('Retry-After') ?? 1) * 1000;
|
|
136
|
+
* }
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* It is the runtime's own `Headers` object, carried by reference rather than
|
|
141
|
+
* snapshotted into a plain record, so `get()` stays CASE-INSENSITIVE per the WHATWG
|
|
142
|
+
* spec — `get('Retry-After')` and `get('retry-after')` are the same lookup whatever
|
|
143
|
+
* casing undici put on the wire (E1). Only RESPONSE headers are here; `Authorization`
|
|
144
|
+
* lives on the REQUEST and is never reachable through it, exactly as for
|
|
145
|
+
* {@link ApiResponse.headers}.
|
|
146
|
+
*
|
|
147
|
+
* Present on every error thrown from a real HTTP response, and absent on an error
|
|
148
|
+
* constructed by hand without one. `declare` is load-bearing for the same reason it is
|
|
149
|
+
* on `details` above: `target: ES2022` turns on `useDefineForClassFields`, so a plain
|
|
150
|
+
* `headers?: …` declaration would emit a class field and DEFINE the key as `undefined`
|
|
151
|
+
* on every instance, changing `'headers' in err`, spreads and `JSON.stringify` output
|
|
152
|
+
* for every error that carries none.
|
|
153
|
+
*/
|
|
154
|
+
readonly headers?: Headers;
|
|
155
|
+
constructor(status: number, code: string, message: string, details?: ByteKitErrorDetails, headers?: Headers);
|
|
123
156
|
}
|
|
124
157
|
/**
|
|
125
158
|
* Thrown when the request never produced an HTTP response at all — DNS, socket, TLS,
|
package/dist/client.js
CHANGED
|
@@ -22,7 +22,7 @@ const DEFAULT_TIMEOUT_MS = 120_000;
|
|
|
22
22
|
export class ByteKitError extends Error {
|
|
23
23
|
status;
|
|
24
24
|
code;
|
|
25
|
-
constructor(status, code, message, details) {
|
|
25
|
+
constructor(status, code, message, details, headers) {
|
|
26
26
|
super(message);
|
|
27
27
|
this.name = 'ByteKitError';
|
|
28
28
|
this.status = status;
|
|
@@ -32,6 +32,11 @@ export class ByteKitError extends Error {
|
|
|
32
32
|
if (details !== undefined) {
|
|
33
33
|
this.details = details;
|
|
34
34
|
}
|
|
35
|
+
// Same discipline for the #2957 additive field: `headers` is OPTIONAL and LAST, so
|
|
36
|
+
// every pre-existing three- and four-argument construction is byte-identical.
|
|
37
|
+
if (headers !== undefined) {
|
|
38
|
+
this.headers = headers;
|
|
39
|
+
}
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
/**
|
|
@@ -431,7 +436,12 @@ export class ByteKit {
|
|
|
431
436
|
// leave defaults — including when the error body itself stalls and the
|
|
432
437
|
// budget aborts the read (#2546), so a stuck 500 still surfaces its status.
|
|
433
438
|
}
|
|
434
|
-
|
|
439
|
+
// `response.headers` is attached to EVERY non-2xx, from this one throw site —
|
|
440
|
+
// the canonical-envelope arm, the flat vendor-masked arm and the unparseable-body
|
|
441
|
+
// `catch` above all land here, so a rate-limited caller can read `Retry-After`
|
|
442
|
+
// whatever shape the error body took (#2957). It is the response's own `Headers`
|
|
443
|
+
// instance, so lookups stay case-insensitive (E1).
|
|
444
|
+
throw new ByteKitError(response.status, code, message, details, response.headers);
|
|
435
445
|
}
|
|
436
446
|
try {
|
|
437
447
|
return await readBody(response);
|
package/dist/generated/api.d.ts
CHANGED
|
@@ -1351,11 +1351,21 @@ export interface components {
|
|
|
1351
1351
|
* @example 100000000000
|
|
1352
1352
|
*/
|
|
1353
1353
|
included_bytes: number;
|
|
1354
|
+
/**
|
|
1355
|
+
* @description Included credits per period.
|
|
1356
|
+
* @example 100000
|
|
1357
|
+
*/
|
|
1358
|
+
included_credits: number;
|
|
1354
1359
|
/**
|
|
1355
1360
|
* @description Bandwidth top-up price per MB, in cents.
|
|
1356
1361
|
* @example 0.25
|
|
1357
1362
|
*/
|
|
1358
1363
|
topup_price_per_mb_cents: number;
|
|
1364
|
+
/**
|
|
1365
|
+
* @description Credit top-up price per 1,000 credits, in cents.
|
|
1366
|
+
* @example 150
|
|
1367
|
+
*/
|
|
1368
|
+
credit_topup_price_per_k_cents: number;
|
|
1359
1369
|
/** @example 50 */
|
|
1360
1370
|
max_concurrency: number;
|
|
1361
1371
|
/** @example 50 */
|
|
@@ -1568,7 +1578,7 @@ export interface components {
|
|
|
1568
1578
|
};
|
|
1569
1579
|
ScrapeWarning: {
|
|
1570
1580
|
/** @enum {string} */
|
|
1571
|
-
code: "lossy_table" | "complex_math" | "unsupported_element" | "extraction_fallback" | "truncated" | "query_no_match" | "mode_disabled_fallback" | "artifact_unavailable" | "llm_clean_unavailable" | "llm_clean_failed";
|
|
1581
|
+
code: "lossy_table" | "complex_math" | "unsupported_element" | "extraction_fallback" | "truncated" | "query_no_match" | "mode_disabled_fallback" | "artifact_unavailable" | "llm_clean_unavailable" | "llm_clean_failed" | "low_quality_extraction" | "fragment_menu_stripped";
|
|
1572
1582
|
message: string;
|
|
1573
1583
|
element: string | null;
|
|
1574
1584
|
};
|
|
@@ -1720,7 +1730,7 @@ export interface components {
|
|
|
1720
1730
|
stats?: components["schemas"]["ScrapeStats"];
|
|
1721
1731
|
/** @description Token-budget accounting. Present only when `token_budget` was supplied in the request. Contains `kept` (tokens in returned markdown), `total` (tokens in full pre-truncation markdown), and `truncated` (whether output was cut). Absent on uncapped requests to avoid noise. */
|
|
1722
1732
|
markdown_tokens?: components["schemas"]["ScrapeMarkdownTokens"];
|
|
1723
|
-
/** @description The multiplier applied to wire bytes to compute `billed_bytes` for this call (
|
|
1733
|
+
/** @description The multiplier applied to wire bytes to compute `billed_bytes` for this call (1.0-2.0 for format combinations on a cache miss). The value is pre-clean-markdown: when `clean_markdown: true` and the clean succeeded, the settled usage is 3× this number, and that surcharge is carried by neither this field nor the `X-Billing-Multiplier` response header — so on a successful clean neither surface predicts the amount you are billed. This field reports the BASE-endpoint composition, so every cache hit reads a flat 0.5 here whatever formats were requested — the per-endpoint format factor is applied later, at report time, by `GET /v1/usage/by-endpoint`. It can therefore differ from the `X-Billing-Multiplier` response header, which carries the composed real-endpoint value: a markdown cache hit reads 0.5 in this field and 0.75 in that header. Present whenever this call's billing amount has been finalized; omitted if unavailable. */
|
|
1724
1734
|
billing_multiplier?: number;
|
|
1725
1735
|
/** @description The actual bandwidth billed for this call — `round(content_length * billing_multiplier)`. Present alongside `billing_multiplier`. */
|
|
1726
1736
|
billed_bytes?: number;
|
|
@@ -1770,7 +1780,7 @@ export interface components {
|
|
|
1770
1780
|
id: string | null;
|
|
1771
1781
|
error: {
|
|
1772
1782
|
/** @enum {string} */
|
|
1773
|
-
code: "validation_error" | "invalid_url" | "request_too_large" | "
|
|
1783
|
+
code: "validation_error" | "invalid_url" | "request_too_large" | "payload_too_large" | "unsupported_content_type" | "rate_limited" | "upstream_error" | "blocked" | "timeout" | "internal_error";
|
|
1774
1784
|
message: string;
|
|
1775
1785
|
http_status?: number;
|
|
1776
1786
|
/** Format: date-time */
|
|
@@ -2538,14 +2548,24 @@ export interface components {
|
|
|
2538
2548
|
used_bytes: number;
|
|
2539
2549
|
limit_bytes: number;
|
|
2540
2550
|
remaining_bytes: number;
|
|
2551
|
+
/** @description Total spendable bytes remaining across purchased top-up and starter-grant lots, after active refund reservations. */
|
|
2541
2552
|
topup_bytes: number;
|
|
2553
|
+
/** @description Bytes remaining in purchased top-up lots, after active refund reservations. Starter-grant bytes are excluded. */
|
|
2554
|
+
purchased_topup_bytes: number;
|
|
2555
|
+
/** @description Bytes remaining in starter-grant lots, after active refund reservations. Purchased top-up bytes are excluded. */
|
|
2556
|
+
granted_topup_bytes: number;
|
|
2542
2557
|
rollover_bytes: number;
|
|
2543
2558
|
};
|
|
2544
2559
|
CreditBalance: {
|
|
2545
2560
|
used: number;
|
|
2546
2561
|
limit: number;
|
|
2547
2562
|
remaining: number;
|
|
2563
|
+
/** @description Total spendable credits remaining across purchased top-up and starter-grant lots, after active refund reservations. */
|
|
2548
2564
|
topup_credits: number;
|
|
2565
|
+
/** @description Credits remaining in purchased top-up lots, after active refund reservations. Starter-grant credits are excluded. */
|
|
2566
|
+
purchased_topup_credits: number;
|
|
2567
|
+
/** @description Credits remaining in starter-grant lots, after active refund reservations. Purchased top-up credits are excluded. */
|
|
2568
|
+
granted_topup_credits: number;
|
|
2549
2569
|
rollover_credits: number;
|
|
2550
2570
|
};
|
|
2551
2571
|
};
|
|
@@ -3309,7 +3329,7 @@ export interface operations {
|
|
|
3309
3329
|
"X-Raw-Bytes"?: number;
|
|
3310
3330
|
/** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
|
|
3311
3331
|
"X-Billable-Bytes"?: number;
|
|
3312
|
-
/** @description Bandwidth cost multiplier (e.g. 1.0 for raw_html-only, 1.5 for +markdown/html). Cache hits compose the endpoint format factor: raw 0.5, markdown 0.75. */
|
|
3332
|
+
/** @description Bandwidth cost multiplier (e.g. 1.0 for raw_html-only, 1.5 for +markdown/html). Cache hits compose the endpoint format factor: raw 0.5, markdown 0.75. Excludes the `clean_markdown` surcharge, exactly like the `billing_multiplier` body field: when `clean_markdown: true` and the clean succeeded, the settled usage is 3× this header's value, so neither surface predicts the amount you are billed. */
|
|
3313
3333
|
"X-Billing-Multiplier"?: number;
|
|
3314
3334
|
/** @description Credits charged for this scrape (multiplier applied to base 1.0 per format). */
|
|
3315
3335
|
"X-Scrape-Credits-Charged"?: number;
|
|
@@ -4147,7 +4167,7 @@ export interface operations {
|
|
|
4147
4167
|
* "device": "desktop",
|
|
4148
4168
|
* "country": "US",
|
|
4149
4169
|
* "formats": [
|
|
4150
|
-
* "
|
|
4170
|
+
* "raw_html"
|
|
4151
4171
|
* ],
|
|
4152
4172
|
* "device_scale_factor": 2
|
|
4153
4173
|
* },
|
|
@@ -4184,7 +4204,7 @@ export interface operations {
|
|
|
4184
4204
|
language?: string | null;
|
|
4185
4205
|
dark_mode?: boolean;
|
|
4186
4206
|
/** @description Scrape output formats (scrape entries). */
|
|
4187
|
-
formats?: ("
|
|
4207
|
+
formats?: ("raw_html" | "html" | "markdown" | "links" | "images")[];
|
|
4188
4208
|
/** @enum {string} */
|
|
4189
4209
|
wait_until?: "load" | "domcontentloaded" | "networkidle";
|
|
4190
4210
|
wait_for_selector?: string | null;
|
|
@@ -4237,7 +4257,7 @@ export interface operations {
|
|
|
4237
4257
|
language?: string | null;
|
|
4238
4258
|
/** @default false */
|
|
4239
4259
|
dark_mode?: boolean;
|
|
4240
|
-
formats?: ("
|
|
4260
|
+
formats?: ("raw_html" | "html" | "markdown" | "links" | "images")[];
|
|
4241
4261
|
/**
|
|
4242
4262
|
* @default load
|
|
4243
4263
|
* @enum {string}
|
|
@@ -5482,7 +5502,7 @@ export interface operations {
|
|
|
5482
5502
|
raw_bytes?: number | null;
|
|
5483
5503
|
/** @description Billable bytes — raw_bytes × billing_multiplier, rounded. Mirrors the X-Billable-Bytes response header. null while pending/failed. */
|
|
5484
5504
|
billable_bytes?: number | null;
|
|
5485
|
-
/** @description Billing multiplier applied to raw_bytes (e.g. 1.0 for raw scrape, 1.5 for markdown/screenshot)
|
|
5505
|
+
/** @description Billing multiplier applied to raw_bytes (e.g. 1.0 for raw scrape, 1.5 for markdown/screenshot). Unlike the scrape response body field of the same name, this row reports the real-endpoint composition — the one the X-Billing-Multiplier response header carries — so cache hits compose the endpoint format factor and a markdown cache hit reads 0.75 here while the response body field reads 0.5. Mirrors the X-Billing-Multiplier response header. null while pending/failed. */
|
|
5486
5506
|
billing_multiplier?: number | null;
|
|
5487
5507
|
duration_ms?: number | null;
|
|
5488
5508
|
/** @description How the request originated (single/bulk/monitor). */
|
|
@@ -118,19 +118,6 @@ export declare class ScrapeResource {
|
|
|
118
118
|
create(opts: ScrapeOpts, requestOptions?: RequestOptions): Promise<ScrapeCreateResponse>;
|
|
119
119
|
/**
|
|
120
120
|
* GET /v1/scrape/{id} — poll a scrape by ID
|
|
121
|
-
*
|
|
122
|
-
* KNOWN DRIFT (#2426): live staging spot-checks (two independent fetches)
|
|
123
|
-
* found the gateway serializes `billing_multiplier` as a JSON **string**
|
|
124
|
-
* (e.g. `"0.50"`) on this GET path, while the OpenAPI spec — and this
|
|
125
|
-
* derived `ScrapeGetResponse` type — declare it `number`. `POST /v1/scrape`'s
|
|
126
|
-
* success envelope for the same job serializes the identical field as a
|
|
127
|
-
* proper number, so the drift is specific to the GET path (likely a Postgres
|
|
128
|
-
* NUMERIC column round-tripping as a string on this query path). A consumer
|
|
129
|
-
* doing arithmetic on `billing_multiplier` after `get()` (e.g.
|
|
130
|
-
* `content_length * billing_multiplier`) should coerce with `Number(...)`
|
|
131
|
-
* defensively rather than trust the static type. This is a gateway/worker
|
|
132
|
-
* serialization bug, not a client bug — the fix belongs upstream in the
|
|
133
|
-
* gateway and is out of this ticket's scope.
|
|
134
121
|
*/
|
|
135
122
|
get(id: ScrapeId, requestOptions?: RequestOptions): Promise<ScrapeGetResponse>;
|
|
136
123
|
}
|
package/dist/resources/scrape.js
CHANGED
|
@@ -21,19 +21,6 @@ export class ScrapeResource {
|
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* GET /v1/scrape/{id} — poll a scrape by ID
|
|
24
|
-
*
|
|
25
|
-
* KNOWN DRIFT (#2426): live staging spot-checks (two independent fetches)
|
|
26
|
-
* found the gateway serializes `billing_multiplier` as a JSON **string**
|
|
27
|
-
* (e.g. `"0.50"`) on this GET path, while the OpenAPI spec — and this
|
|
28
|
-
* derived `ScrapeGetResponse` type — declare it `number`. `POST /v1/scrape`'s
|
|
29
|
-
* success envelope for the same job serializes the identical field as a
|
|
30
|
-
* proper number, so the drift is specific to the GET path (likely a Postgres
|
|
31
|
-
* NUMERIC column round-tripping as a string on this query path). A consumer
|
|
32
|
-
* doing arithmetic on `billing_multiplier` after `get()` (e.g.
|
|
33
|
-
* `content_length * billing_multiplier`) should coerce with `Number(...)`
|
|
34
|
-
* defensively rather than trust the static type. This is a gateway/worker
|
|
35
|
-
* serialization bug, not a client bug — the fix belongs upstream in the
|
|
36
|
-
* gateway and is out of this ticket's scope.
|
|
37
24
|
*/
|
|
38
25
|
get(id, requestOptions) {
|
|
39
26
|
return this.client.request('GET', buildPath('/v1/scrape/{id}', { segments: { id } }), undefined, requestOptions);
|
|
@@ -90,8 +90,15 @@ export declare class ScreenshotsResource {
|
|
|
90
90
|
*
|
|
91
91
|
* Same request as `screenshots.get`, and `data` is exactly what `get()`
|
|
92
92
|
* resolves to (including the #2027 failed-envelope arm). `get()`'s own return type is
|
|
93
|
-
* UNCHANGED; this is an additive sibling.
|
|
94
|
-
*
|
|
93
|
+
* UNCHANGED; this is an additive sibling.
|
|
94
|
+
*
|
|
95
|
+
* Call it for the typed body, NOT for header metadata: the spec declares
|
|
96
|
+
* `GET /v1/screenshots/{id}` with NO `X-*` response headers, and a live GET returns
|
|
97
|
+
* none, so `headers` carries only the transport's own entries (`Content-Type`, …).
|
|
98
|
+
* The `X-Screenshot-*` / `X-Raw-Bytes` / `X-Billable-Bytes` / `X-Billing-Multiplier`
|
|
99
|
+
* family is emitted by `POST /v1/screenshots` — use `screenshots.createWithResponse`
|
|
100
|
+
* to read it (issue #2957). This matches `ByteKit.requestWithResponse` and the README,
|
|
101
|
+
* which are the truth for what this endpoint emits.
|
|
95
102
|
*/
|
|
96
103
|
getWithResponse(id: ScreenshotId, requestOptions?: RequestOptions): Promise<ApiResponse<ScreenshotGetResponse>>;
|
|
97
104
|
}
|
|
@@ -50,9 +50,22 @@ export class ScreenshotsResource {
|
|
|
50
50
|
*
|
|
51
51
|
* Same request as `screenshots.get`, and `data` is exactly what `get()`
|
|
52
52
|
* resolves to (including the #2027 failed-envelope arm). `get()`'s own return type is
|
|
53
|
-
* UNCHANGED; this is an additive sibling.
|
|
54
|
-
*
|
|
53
|
+
* UNCHANGED; this is an additive sibling.
|
|
54
|
+
*
|
|
55
|
+
* Call it for the typed body, NOT for header metadata: the spec declares
|
|
56
|
+
* `GET /v1/screenshots/{id}` with NO `X-*` response headers, and a live GET returns
|
|
57
|
+
* none, so `headers` carries only the transport's own entries (`Content-Type`, …).
|
|
58
|
+
* The `X-Screenshot-*` / `X-Raw-Bytes` / `X-Billable-Bytes` / `X-Billing-Multiplier`
|
|
59
|
+
* family is emitted by `POST /v1/screenshots` — use `screenshots.createWithResponse`
|
|
60
|
+
* to read it (issue #2957). This matches `ByteKit.requestWithResponse` and the README,
|
|
61
|
+
* which are the truth for what this endpoint emits.
|
|
55
62
|
*/
|
|
63
|
+
// NOTE (#2957): the doc block above deliberately spells sibling method names in plain
|
|
64
|
+
// backticks rather than as JSDoc link tags. `scripts/generate-docs.ts` copies these
|
|
65
|
+
// comments verbatim into the published reference and DROPS a link tag without emitting
|
|
66
|
+
// anything in its place, leaving a dangling "use to read it" — the very class of broken
|
|
67
|
+
// doc this correction exists to remove. Keep it a `//` comment: the generator would
|
|
68
|
+
// publish it too if it were part of the block.
|
|
56
69
|
getWithResponse(id, requestOptions) {
|
|
57
70
|
return this.client.requestWithResponse('GET', buildPath('/v1/screenshots/{id}', { segments: { id } }), undefined, requestOptions);
|
|
58
71
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
* outbound request carries — see the emit site in `client.ts`. The header name is spelled
|
|
6
6
|
* only there, so issue #2905's pre-merge gate 1 counts exactly one occurrence in `src/`.
|
|
7
7
|
*/
|
|
8
|
-
export declare const SDK_VERSION = "0.7.
|
|
8
|
+
export declare const SDK_VERSION = "0.7.1";
|
package/dist/version.js
CHANGED