@hunt-labs/bytekit-sdk 0.7.3 → 0.8.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/CHANGELOG.md CHANGED
@@ -10,6 +10,117 @@ today, see [README.md](./README.md), which remains the authoritative usage guide
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.8.0] - 2026-08-19
14
+
15
+ ### Removed
16
+
17
+ - **BREAKING: `billing_multiplier` and `billed_bytes` are gone from the scrape success
18
+ envelope** (#3143). Read `billing` instead — a `BillingNode` that names every factor
19
+ applied to the charge, the multiplier they compose to, and the resulting billed bytes:
20
+
21
+ ```ts
22
+ // before
23
+ const spend = res.billed_bytes; // flat, base-endpoint only
24
+ // after
25
+ const spend = res.billing?.billed_bytes;
26
+ const why = res.billing?.factors; // [{ name: 'endpoint', value: 1.5, reason: 'scrape_md' }, …]
27
+ ```
28
+
29
+ This is a correction, not a rename: the two surfaces reported **different numbers for the
30
+ same charge**. The flat pair carried the BASE-endpoint composition, so a markdown cache hit
31
+ read `0.5` / `400` while the real charge — and the `X-Billing-Multiplier` header — was
32
+ `0.75` / `600`; an html-only miss read the per-format credits estimate `1.5` / `150` against
33
+ an endpoint factor of `1.0` / `100`. The flat pair also never carried the `clean_markdown`
34
+ ×3 surcharge, so on a successful clean it under-reported the amount billed by two thirds.
35
+ `billing.multiplier` composes every applied factor behind exactly one rounding, so it is the
36
+ number that predicts your invoice.
37
+
38
+ `billing` is optional and is **absent** on resources that completed before the billing node
39
+ existed. A pre-node row omits the field rather than reporting a zero node, because a zero
40
+ node would assert that a real past charge was zero. Test the node for presence
41
+ (`res.billing !== undefined`, or equivalently a plain truthiness check — `billing` is an
42
+ object or `undefined`, and an object is always truthy, so the two are the same test here).
43
+ The hazard is a condition that reaches _into_ the node: `if (res.billing?.billed_bytes)`
44
+ silently skips a genuine zero-byte charge, because `0` is falsy. Check that the node is
45
+ present, then read `billed_bytes` from it.
46
+
47
+ ```ts
48
+ // wrong — a real 0-byte charge is falsy and disappears
49
+ if (res.billing?.billed_bytes) record(res.billing.billed_bytes);
50
+ // right — presence first, value second
51
+ if (res.billing) record(res.billing.billed_bytes); // 0 is a charge, not an absence
52
+ ```
53
+
54
+ Two endpoints deliberately carry no node: `/v1/search` is billed per credit and reports
55
+ `credits_used`, and a single `/v1/fetch` reports its charge through response headers only.
56
+ The `/v1/logs` row field named `billing_multiplier` is a **different field** and is not the
57
+ envelope field this release removed. It carries the BASE settled `credits_charged` factor,
58
+ not the composed real-endpoint value the `X-Billing-Multiplier` header reports — a markdown
59
+ cache hit reads `0.5` on the logs row and `0.75` on the header.
60
+
61
+ ### Changed
62
+
63
+ - Generated `ScrapeErrorEnvelope` types now describe terminal asynchronous `scrape.failed`
64
+ webhook delivery (#1856). No runtime SDK behavior or API shape changed.
65
+
66
+ ### Fixed
67
+
68
+ - **`GET /v1/logs` entries now carry `billing_multiplier`, as a JSON number** (#3022). The
69
+ gateway had been serializing that value under an undeclared key `credits`, and as the raw
70
+ Postgres `NUMERIC(10,2)` string (`"1.50"`), while the OpenAPI spec — and therefore the
71
+ generated types in `src/generated/api.d.ts` — declared `billing_multiplier?: number | null`.
72
+ Anything typed against this package read `undefined` for the field.
73
+
74
+ **Breaking at the wire level:** the undeclared `credits` key is gone from every `/v1/logs`
75
+ entry. Code that reached past the generated types to read `credits` must read
76
+ `billing_multiplier`. No SDK method exposes this endpoint, so the only change inside this
77
+ package is the regenerated type description.
78
+
79
+ - **`change_threshold` (on `monitors.create`/`monitors.list`/`monitors.get`/
80
+ `monitors.update` responses) and `change_pct` (on `monitors.captures.list` entries)
81
+ now serialize as JSON numbers, not strings** (#3021). Both are Postgres `NUMERIC(5,2)`
82
+ columns; the gateway passed the raw driver string through unconverted (`"5.00"` /
83
+ `"7.25"`) while the OpenAPI spec's _request_ schemas already declared `number` — only
84
+ the _response_ schemas had been (incorrectly) edited to match the buggy string output.
85
+ This release fixes the gateway serializer and corrects the two response schemas to
86
+ `number` / `number | null`, so spec and runtime now agree.
87
+
88
+ **Breaking at the wire level:** `client.monitors.create()`, `client.monitors.list()`,
89
+ `client.monitors.get()`, and `client.monitors.update()` now return a JS number for
90
+ `change_threshold` instead of a string (screenshot-type monitors only); the create
91
+ response's `MonitorCreateResponse` and every other monitor route serialize through the
92
+ same `MonitorResponse` schema, so all four are affected identically.
93
+ `client.monitors.captures.list()` now returns a JS number for `change_pct` instead of a
94
+ string. Code doing `parseFloat(monitor.change_threshold)` or template-literal
95
+ interpolation keeps working; strict `typeof x === 'string'` checks or string methods
96
+ (`.trim()`, `.padStart()`) will now throw. `change_pct` is `null` (not `0`) when there is
97
+ no prior capture to diff against, unchanged from before. No SDK method-level shape
98
+ changed otherwise — the only change inside this package is the regenerated type
99
+ description.
100
+
101
+ ## [0.7.4] - 2026-08-19
102
+
103
+ ### Changed
104
+
105
+ - **`gen:version` no longer runs as part of `build`** (#3144). `scripts/gen-version.ts` writes
106
+ `src/version.ts`, a _tracked_ source file, and it was chained into the `build` script. That made
107
+ a build silently rewrite committed source whenever the file disagreed with the manifest: local
108
+ runs went green on a tree CI could fail, the resulting ` M src/version.ts` was indistinguishable
109
+ from routine build noise, and in CI the outcome depended on whether Turbo's build cache hit
110
+ (restoring `dist/**` without re-running the generator) or missed. `build` now starts at
111
+ `rm -rf dist ...`, so building this package touches nothing tracked. This changes `prepack` /
112
+ `prepublishOnly` behavior too: both call `build`, so the publish path now reads the committed
113
+ `src/version.ts` rather than regenerating it, and the committed value is what ships.
114
+ - **New `gen:version-check` script**, `pnpm gen:version && git diff --exit-code src/version.ts`,
115
+ mirroring the existing `gen:types-check` in the same manifest. It runs in `.woodpecker/ci.yaml`'s
116
+ `types-drift` step, so a manifest bump without the matching `src/version.ts` regeneration now
117
+ fails a named PR check instead of reaching `staging`. `src/__tests__/version-parity.test.ts`
118
+ stays in place as the in-suite assertion; the gate is what makes its failure reachable before
119
+ merge rather than after.
120
+
121
+ No runtime or type changes. `SDK_VERSION` and the `X-ByteKit-Client: sdk_ts/<version>` affix
122
+ behave exactly as before.
123
+
13
124
  ## [0.7.3] - 2026-08-18
14
125
 
15
126
  ### Changed
@@ -134,6 +245,16 @@ today, see [README.md](./README.md), which remains the authoritative usage guide
134
245
  Bumping moves the anchor past those comments. The published `0.7.0` artifact is **not** stale in
135
246
  any way a consumer can observe — the divergence is comment text only.
136
247
 
248
+ - **Corrected a false legacy-name claim carried since the rename (#2950).** The `0.7.0`-era note
249
+ below said the prior `rapidcrawl`/`@rapidcrawl/sdk` name "remains installable at its last
250
+ version but is deprecated." Verified 2026-08-13: both `rapidcrawl` and `@rapidcrawl/sdk` return
251
+ npm `404` ("is not in this registry"), and `npm deprecate` against either fails with the same
252
+ `404` — there is no published version left for a deprecation notice to attach to, so the claim
253
+ never held. No registry stub or deprecation was possible to publish; root `CLAUDE.md` carried
254
+ the same false claim and is corrected alongside this entry. Users of the old names should
255
+ install `@hunt-labs/bytekit-sdk` directly. No exported function, type, or runtime behavior
256
+ changes.
257
+
137
258
  ## [0.7.0] - 2026-08-11
138
259
 
139
260
  ### Added
@@ -515,8 +636,10 @@ against 0.1.0 — read each one before upgrading.
515
636
  ### Changed
516
637
 
517
638
  - Package renamed to `@hunt-labs/bytekit-sdk` (the `@bytekit` npm scope was
518
- unobtainable). The prior `rapidcrawl`/`@rapidcrawl/sdk` name remains installable at
519
- its last version but is deprecated.
639
+ unobtainable). ~~The prior `rapidcrawl`/`@rapidcrawl/sdk` name remains installable at
640
+ its last version but is deprecated.~~ **Corrected in 0.7.1 (see above): that claim
641
+ does not hold — both names 404 on npm and there is no published version left to
642
+ deprecate.**
520
643
  - Generated API types (`dist/generated/api.d.ts`) are now shipped in the tarball so
521
644
  consumers get the typed request/response surface without regenerating from the spec.
522
645
 
@@ -534,6 +657,7 @@ against 0.1.0 — read each one before upgrading.
534
657
  `@rapidcrawl/sdk` name.
535
658
 
536
659
  [Unreleased]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
660
+ [0.7.4]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
537
661
  [0.7.3]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
538
662
  [0.7.2]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
539
663
  [0.7.1]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
@@ -1436,6 +1436,93 @@ export interface components {
1436
1436
  next_cursor: string | null;
1437
1437
  has_more: boolean;
1438
1438
  };
1439
+ /**
1440
+ * @description One named multiplicative term in a charge. A factor that did not apply is
1441
+ * ABSENT from the list rather than present with `value: 1` — an entry reading
1442
+ * `cache_hit ×1` would claim a cache-hit discount had been applied. The
1443
+ * `endpoint` factor is the exception: every billed request has an endpoint, so
1444
+ * it is always listed even when its value is 1.0.
1445
+ */
1446
+ BillingFactor: {
1447
+ /**
1448
+ * @description Closed vocabulary. `endpoint` — the per-endpoint format factor.
1449
+ * `cache_hit` — the 0.5× replay discount. `clean_markdown` — the 3×
1450
+ * surcharge, present only when the LLM clean actually succeeded.
1451
+ * `phase1_render` — the screenshot/recording render-overhead factor,
1452
+ * which is never composed with `cache_hit` or `clean_markdown`.
1453
+ * Treat an unrecognised name as a term you do not model rather than as an
1454
+ * error: the product of all `value`s always equals `multiplier`.
1455
+ * @example endpoint
1456
+ * @enum {string}
1457
+ */
1458
+ name: "endpoint" | "cache_hit" | "clean_markdown" | "phase1_render";
1459
+ /**
1460
+ * @description The multiplicative value of this term.
1461
+ * @example 1.5
1462
+ */
1463
+ value: number;
1464
+ /**
1465
+ * @description Human-readable explanation of why this factor applied — for example the
1466
+ * endpoint bucket name, or `hit, age 412s`. NOT CONTRACTUAL: this string is
1467
+ * free text for display and debugging only. Its wording, its format, and
1468
+ * whether it carries any particular detail may change at any time without a
1469
+ * version bump. Never parse it, branch on it, or assert on it — read
1470
+ * `name` and `value` instead.
1471
+ * @example scrape_md
1472
+ */
1473
+ reason: string;
1474
+ };
1475
+ /**
1476
+ * @description The authoritative, self-explaining account of what this call was billed and
1477
+ * why. `multiplier` is the product of every entry in `factors`, composed in
1478
+ * list order (`endpoint` → `cache_hit` → `clean_markdown`), and
1479
+ * `billed_bytes = round(raw_bytes × multiplier)` behind exactly one rounding.
1480
+ * The factor list is the DEFINITION of the charge; the `X-Raw-Bytes` /
1481
+ * `X-Billing-Multiplier` / `X-Billable-Bytes` response headers are a rendering
1482
+ * of this same node, so where a header and this node disagree, the header is
1483
+ * the bug.
1484
+ *
1485
+ * Two billable surfaces carry no node, by design rather than by omission:
1486
+ *
1487
+ * * `POST /v1/search` is billed per credit, not per byte. Its charge is
1488
+ * reported by `credits_used`; no byte multiplier applies to it and the
1489
+ * factor vocabulary has no `search` term.
1490
+ * * Single (non-bulk) `POST /v1/fetch` returns the fetched bytes as the
1491
+ * response body, so it has no JSON envelope in which to carry a node. Its
1492
+ * charge is reported by the `X-Raw-Bytes` / `X-Billing-Multiplier` /
1493
+ * `X-Billable-Bytes` header trio alone. Items under
1494
+ * `GET /v1/fetch/bulk/{id}` DO carry the node.
1495
+ *
1496
+ * Historical rows: for a resource that completed before its billing node was
1497
+ * persisted, this field is OMITTED rather than emitted as a zero node — a zero
1498
+ * node would assert that a real past charge was zero. Treat absence as "not
1499
+ * available for this row" and read the charge from `GET /v1/usage`.
1500
+ */
1501
+ BillingNode: {
1502
+ /**
1503
+ * @description The unmultiplied basis of the charge. For byte-billed endpoints this is
1504
+ * the upstream wire bytes actually transferred. For screenshots and
1505
+ * recordings it is the Phase 1 HTML fetch's wire bytes — the only proxied
1506
+ * traffic in the happy path — never the size of the returned PNG/JPEG/MP4
1507
+ * artifact.
1508
+ * @example 1024
1509
+ */
1510
+ raw_bytes: number;
1511
+ /** @description The named terms whose product is `multiplier`, in composition order. */
1512
+ factors: components["schemas"]["BillingFactor"][];
1513
+ /**
1514
+ * @description The product of every `factors[].value` — the REAL composed multiplier for
1515
+ * this call, including the per-endpoint format factor. A markdown cache hit
1516
+ * reads 0.75 here (1.5 × 0.5).
1517
+ * @example 0.75
1518
+ */
1519
+ multiplier: number;
1520
+ /**
1521
+ * @description `round(raw_bytes × multiplier)` — the bandwidth actually settled for this call.
1522
+ * @example 768
1523
+ */
1524
+ billed_bytes: number;
1525
+ };
1439
1526
  ScrapeRequest: {
1440
1527
  /** Format: uri */
1441
1528
  url: string;
@@ -1730,10 +1817,13 @@ export interface components {
1730
1817
  stats?: components["schemas"]["ScrapeStats"];
1731
1818
  /** @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. */
1732
1819
  markdown_tokens?: components["schemas"]["ScrapeMarkdownTokens"];
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. */
1734
- billing_multiplier?: number;
1735
- /** @description The actual bandwidth billed for this call — `round(content_length * billing_multiplier)`. Present alongside `billing_multiplier`. */
1736
- billed_bytes?: number;
1820
+ /**
1821
+ * @description Itemised account of this call's charge — the basis, the named factors
1822
+ * that composed the multiplier, and the resulting billed bytes. This node
1823
+ * is the authoritative billing surface for the response body. Omitted for
1824
+ * rows persisted before the billing node existed.
1825
+ */
1826
+ billing?: components["schemas"]["BillingNode"];
1737
1827
  /** @description Custom metadata provided by the caller in the request `custom` field. Stored verbatim and round-tripped on the synchronous response and webhook delivery. Not included in `GET /v1/scrape/:id`, bulk results, or cached hits. Omitted when no custom metadata was provided. */
1738
1828
  custom?: {
1739
1829
  [key: string]: unknown;
@@ -1753,6 +1843,7 @@ export interface components {
1753
1843
  cache_age_s?: number;
1754
1844
  };
1755
1845
  /**
1846
+ * @description Terminal asynchronous scrape failures are delivered to subscribers of `failed` as this payload with `X-ByteKit-Event: scrape.failed`.
1756
1847
  * @example {
1757
1848
  * "schema_version": 1,
1758
1849
  * "status": "failed",
@@ -1947,6 +2038,13 @@ export interface components {
1947
2038
  */
1948
2039
  file_size_bytes: number | null;
1949
2040
  credits_charged: number | null;
2041
+ /**
2042
+ * @description Itemised account of this capture's charge — the Phase 1 wire bytes it
2043
+ * was billed on, the `phase1_render` factor, and the resulting billed
2044
+ * bytes. Omitted for rows that completed before the billing node was
2045
+ * persisted, and for rows that have not completed.
2046
+ */
2047
+ billing?: components["schemas"]["BillingNode"];
1950
2048
  error_code: string | null;
1951
2049
  error_message: string | null;
1952
2050
  /** Format: date-time */
@@ -2066,6 +2164,13 @@ export interface components {
2066
2164
  */
2067
2165
  file_size_bytes: number | null;
2068
2166
  credits_charged: number | null;
2167
+ /**
2168
+ * @description Itemised account of this capture's charge — the Phase 1 wire bytes it
2169
+ * was billed on, the `phase1_render` factor, and the resulting billed
2170
+ * bytes. Omitted for rows that completed before the billing node was
2171
+ * persisted, and for rows that have not completed.
2172
+ */
2173
+ billing?: components["schemas"]["BillingNode"];
2069
2174
  error_code: string | null;
2070
2175
  error_message: string | null;
2071
2176
  /** Format: date-time */
@@ -2161,7 +2266,7 @@ export interface components {
2161
2266
  webhook_url: string;
2162
2267
  webhook_headers: Record<string, never> | null;
2163
2268
  /** @description Present on screenshot monitors only. */
2164
- change_threshold?: string;
2269
+ change_threshold?: number;
2165
2270
  /** @description Present on scrape monitors only. */
2166
2271
  scrape_options?: unknown;
2167
2272
  /** @description Present on scrape monitors only. */
@@ -2203,7 +2308,7 @@ export interface components {
2203
2308
  content_hash: string | null;
2204
2309
  previous_hash: string | null;
2205
2310
  hash_distance: number | null;
2206
- change_pct: string | null;
2311
+ change_pct: number | null;
2207
2312
  has_change: boolean;
2208
2313
  title_changed: boolean | null;
2209
2314
  /**
@@ -2284,6 +2389,12 @@ export interface components {
2284
2389
  cache?: "miss" | "hit" | "bypass";
2285
2390
  /** @description Age in whole seconds of the cached source job (its `completed_at`) replayed on a `cache: hit`. Clamped to ≥ 0 to absorb clock skew. Present only on `cache: hit`; null on `miss`/`bypass`. */
2286
2391
  cache_age_s?: number | null;
2392
+ /**
2393
+ * @description Itemised account of this job's charge — the basis, the named factors
2394
+ * that composed the multiplier, and the resulting billed bytes. Omitted
2395
+ * for jobs that completed before the billing node was persisted.
2396
+ */
2397
+ billing?: components["schemas"]["BillingNode"];
2287
2398
  warnings: string[] | null;
2288
2399
  error_code: string | null;
2289
2400
  error_message: string | null;
@@ -3110,7 +3221,7 @@ export interface operations {
3110
3221
  "X-Raw-Bytes"?: number;
3111
3222
  /** @description Chargeable bytes — round(X-Raw-Bytes × X-Billing-Multiplier). */
3112
3223
  "X-Billable-Bytes"?: number;
3113
- /** @description Billing multiplier applied to raw bytes to compute billable bytes. */
3224
+ /** @description Billing multiplier applied to raw bytes to compute billable bytes. A rendering of the response body's `billing` node, which is the authoritative surface: it names each factor that composed this value. Where the two disagree, the node is correct. */
3114
3225
  "X-Billing-Multiplier"?: number;
3115
3226
  /** @description HTTP status code returned by the target site during the screenshot capture. */
3116
3227
  "X-Screenshot-Status-Code"?: number;
@@ -3145,7 +3256,7 @@ export interface operations {
3145
3256
  "X-Raw-Bytes"?: number;
3146
3257
  /** @description Chargeable bytes — round(X-Raw-Bytes × X-Billing-Multiplier). */
3147
3258
  "X-Billable-Bytes"?: number;
3148
- /** @description Billing multiplier applied to raw bytes to compute billable bytes. */
3259
+ /** @description Billing multiplier applied to raw bytes to compute billable bytes. A rendering of the response body's `billing` node, which is the authoritative surface: it names each factor that composed this value. Where the two disagree, the node is correct. */
3149
3260
  "X-Billing-Multiplier"?: number;
3150
3261
  [name: string]: unknown;
3151
3262
  };
@@ -3336,7 +3447,7 @@ export interface operations {
3336
3447
  "X-Raw-Bytes"?: number;
3337
3448
  /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
3338
3449
  "X-Billable-Bytes"?: number;
3339
- /** @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. */
3450
+ /** @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: when `clean_markdown: true` and the clean succeeded, the settled usage is 3× this header's value, so this header does not predict the amount you are billed. The response body's `billing` node is the authoritative surface — it DOES carry the `clean_markdown` factor, so its `multiplier` and `billed_bytes` are what you are charged. Where the two disagree, the node is correct. */
3340
3451
  "X-Billing-Multiplier"?: number;
3341
3452
  /** @description Credits charged for this scrape (multiplier applied to base 1.0 per format). */
3342
3453
  "X-Scrape-Credits-Charged"?: number;
@@ -3749,7 +3860,7 @@ export interface operations {
3749
3860
  "X-Raw-Bytes"?: number;
3750
3861
  /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
3751
3862
  "X-Billable-Bytes"?: number;
3752
- /** @description Bandwidth cost multiplier applied to X-Raw-Bytes. A markdown fetch bills as fetch_md (miss 1.5, hit 0.75); a raw fetch bills 1.0 on a miss, 0.5 on a cache hit. */
3863
+ /** @description Bandwidth cost multiplier applied to X-Raw-Bytes. A markdown fetch bills as fetch_md (miss 1.5, hit 0.75); a raw fetch bills 1.0 on a miss, 0.5 on a cache hit. Single `/v1/fetch` returns the fetched bytes as the body, so it carries no `billing` node — this header trio is the ONLY billing surface here. Items under `GET /v1/fetch/bulk/{id}` do carry the node. */
3753
3864
  "X-Billing-Multiplier"?: number;
3754
3865
  /** @description Back-compat duplicate of `X-Billing-Multiplier` — identical value on every path. Prefer `X-Billing-Multiplier`; this alias is retained for clients that read the `X-Fetch-*` header family. */
3755
3866
  "X-Fetch-Billing-Multiplier"?: number;
@@ -3847,7 +3958,7 @@ export interface operations {
3847
3958
  "X-Raw-Bytes"?: number;
3848
3959
  /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
3849
3960
  "X-Billable-Bytes"?: number;
3850
- /** @description Bandwidth cost multiplier applied to X-Raw-Bytes. A markdown fetch bills as fetch_md (miss 1.5, hit 0.75); a raw fetch bills 1.0 on a miss, 0.5 on a cache hit. */
3961
+ /** @description Bandwidth cost multiplier applied to X-Raw-Bytes. A markdown fetch bills as fetch_md (miss 1.5, hit 0.75); a raw fetch bills 1.0 on a miss, 0.5 on a cache hit. Single `/v1/fetch` returns the fetched bytes as the body, so it carries no `billing` node — this header trio is the ONLY billing surface here. Items under `GET /v1/fetch/bulk/{id}` do carry the node. */
3851
3962
  "X-Billing-Multiplier"?: number;
3852
3963
  /** @description Back-compat duplicate of `X-Billing-Multiplier` — identical value on every path. Prefer `X-Billing-Multiplier`; this alias is retained for clients that read the `X-Fetch-*` header family. */
3853
3964
  "X-Fetch-Billing-Multiplier"?: number;
@@ -4052,6 +4163,12 @@ export interface operations {
4052
4163
  content_url: string | null;
4053
4164
  waf_vendor: string | null;
4054
4165
  cache_hit: boolean;
4166
+ /**
4167
+ * @description Itemised account of this item's charge — the basis, the named factors
4168
+ * that composed the multiplier, and the resulting billed bytes. Omitted
4169
+ * for rows that completed before the billing node was persisted.
4170
+ */
4171
+ billing?: components["schemas"]["BillingNode"];
4055
4172
  error_code: string | null;
4056
4173
  error_message: string | null;
4057
4174
  /** Format: date-time */
@@ -4492,6 +4609,12 @@ export interface operations {
4492
4609
  /** Format: uri */
4493
4610
  url: string;
4494
4611
  credits_charged: number | null;
4612
+ /**
4613
+ * @description Itemised account of this item's charge — the basis, the named factors
4614
+ * that composed the multiplier, and the resulting billed bytes. Omitted
4615
+ * for rows that completed before the billing node was persisted.
4616
+ */
4617
+ billing?: components["schemas"]["BillingNode"];
4495
4618
  error_code: string | null;
4496
4619
  error_message: string | null;
4497
4620
  /** Format: date-time */
@@ -4855,7 +4978,7 @@ export interface operations {
4855
4978
  "X-Sitemap-ID"?: string;
4856
4979
  /** @description Gzipped results CSV wire bytes — the bandwidth-billing basis. Emitted only when `status: completed`. */
4857
4980
  "X-Raw-Bytes"?: number;
4858
- /** @description Billing multiplier applied to raw bytes (1 for sitemap). Emitted only when `status: completed`. */
4981
+ /** @description Billing multiplier applied to raw bytes (1 for sitemap). Emitted only when `status: completed`. A rendering of the response body's `billing` node, which is the authoritative surface; where the two disagree, the node is correct. */
4859
4982
  "X-Billing-Multiplier"?: number;
4860
4983
  /** @description Billable bytes = round(X-Raw-Bytes × X-Billing-Multiplier). Emitted only when `status: completed`. */
4861
4984
  "X-Billable-Bytes"?: number;
@@ -5503,7 +5626,7 @@ export interface operations {
5503
5626
  raw_bytes?: number | null;
5504
5627
  /** @description Billable bytes — raw_bytes × billing_multiplier, rounded. Mirrors the X-Billable-Bytes response header. null while pending/failed. */
5505
5628
  billable_bytes?: number | null;
5506
- /** @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. */
5629
+ /** @description BASE billing multiplier persisted for this request — the settled `credits_charged` factor, and the same factor `billable_bytes` above is derived from. Its scale is not uniform and is not a rate you can carry from one row to another: each endpoint persists its own credit unit, and the single and bulk paths of the same endpoint may persist different factors for identical options. Read this as the factor this one row settled at, and see that endpoint's own pricing for what it charges. This is a LOGS ROW field and is NOT the scrape response envelope field — the envelope carries no flat `billing_multiplier` at all; its billing surface is the `billing` node (see BillingNode). This row reports only the base settled factor, so it can differ from `billing.multiplier` and from the X-Billing-Multiplier response header, both of which report the composed real-endpoint value. null while pending/failed. */
5507
5630
  billing_multiplier?: number | null;
5508
5631
  duration_ms?: number | null;
5509
5632
  /** @description How the request originated (single/bulk/monitor). */
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.3";
8
+ export declare const SDK_VERSION = "0.8.0";
package/dist/version.js CHANGED
@@ -9,4 +9,4 @@
9
9
  * outbound request carries — see the emit site in `client.ts`. The header name is spelled
10
10
  * only there, so issue #2905's pre-merge gate 1 counts exactly one occurrence in `src/`.
11
11
  */
12
- export const SDK_VERSION = '0.7.3';
12
+ export const SDK_VERSION = '0.8.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hunt-labs/bytekit-sdk",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "description": "Official TypeScript SDK for the ByteKit API",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,10 +48,11 @@
48
48
  "url": "https://bytekit.com/contact"
49
49
  },
50
50
  "scripts": {
51
- "build": "pnpm gen:version && rm -rf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo && tsc -p tsconfig.build.json && mkdir -p dist/generated && cp src/generated/api.d.ts dist/generated/api.d.ts",
51
+ "build": "rm -rf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo && tsc -p tsconfig.build.json && mkdir -p dist/generated && cp src/generated/api.d.ts dist/generated/api.d.ts",
52
52
  "gen:types": "openapi-typescript ../../docs/api/openapi.yaml -o src/generated/api.d.ts",
53
53
  "gen:version": "tsx scripts/gen-version.ts",
54
54
  "gen:types-check": "pnpm gen:types && git diff --exit-code src/generated/api.d.ts",
55
+ "gen:version-check": "pnpm gen:version && git diff --exit-code src/version.ts",
55
56
  "generate:docs": "tsx scripts/generate-docs.ts",
56
57
  "typecheck": "tsc --noEmit",
57
58
  "test": "vitest run"