@hunt-labs/bytekit-sdk 0.2.2 → 0.4.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.
@@ -1,5 +1,12 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit, RequestOptions } from '../client.js';
2
+ import type { operations } from '../generated/api.js';
2
3
  import type { BulkId } from '../types.js';
4
+ /** Body of POST /v1/fetch/bulk. */
5
+ export type FetchBulkCreateRequest = operations['createFetchBulk']['requestBody']['content']['application/json'];
6
+ /** 202 payload of POST /v1/fetch/bulk — bulk fetch jobs are always async. */
7
+ export type FetchBulkCreateResponse = operations['createFetchBulk']['responses'][202]['content']['application/json'];
8
+ /** 200 payload of GET /v1/fetch/bulk/{id}. */
9
+ export type FetchBulkGetResponse = operations['getFetchBulk']['responses'][200]['content']['application/json'];
3
10
  /**
4
11
  * Options for fetch endpoints.
5
12
  *
@@ -8,9 +15,32 @@ import type { BulkId } from '../types.js';
8
15
  */
9
16
  export interface FetchOpts {
10
17
  url: string;
11
- format?: string;
18
+ /** Output format. `'markdown'` runs the HTML→markdown pipeline; `'html'` returns raw HTML. Narrowed to the spec union — off-spec values (e.g. `'pdf'`) are rejected at compile time. */
19
+ format?: 'markdown' | 'html';
12
20
  country?: string;
13
21
  timeout_ms?: number;
22
+ /** Markdown processing mode. Only used when `format=markdown`. article/raw/llm. */
23
+ markdown_mode?: 'article' | 'raw' | 'llm';
24
+ /** BM25 query string for relevance-ranked filtering. Only used when `format=markdown`. */
25
+ markdown_query?: string;
26
+ /** Link rendering style. Only used when `format=markdown`. */
27
+ markdown_links?: 'inline' | 'references' | 'none' | 'text';
28
+ /** Image retention mode. Only used when `format=markdown`. */
29
+ markdown_images?: 'inline' | 'references' | 'none' | 'text';
30
+ /** Append a `Links:` footer to the markdown output. Only used when `format=markdown`. */
31
+ with_links_summary?: boolean;
32
+ /** Append an `Images:` footer to the markdown output. Only used when `format=markdown`. */
33
+ with_images_summary?: boolean;
34
+ /** Compact whitespace output. Only used when `format=markdown`. */
35
+ markdown_compact?: boolean;
36
+ /** Filter low-signal images. Only used when `format=markdown`. */
37
+ markdown_filter_images?: boolean;
38
+ /** When true, `formats.links`/`formats.images` return rich objects and a top-level `tables` array is included. Only used when `format=markdown`. */
39
+ markdown_include_media?: boolean;
40
+ /** When true, enables markdown-pipeline and tag-filter warnings for affected html/markdown requests. */
41
+ markdown_include_warnings?: boolean;
42
+ /** When true, includes a top-level `stats` object (chars, tokens, blocks). Only used when `format=markdown`. */
43
+ markdown_include_stats?: boolean;
14
44
  /**
15
45
  * How long a freshly fetched URL may be served from cache. Matches the
16
46
  * OpenAPI `FetchRequest.cache_ttl` schema: a duration string (`"48h"`,
@@ -26,29 +56,116 @@ export interface FetchOpts {
26
56
  */
27
57
  custom?: Record<string, unknown>;
28
58
  }
59
+ /**
60
+ * The query params `GET /v1/fetch` accepts, in serialization order.
61
+ *
62
+ * This is the single source of truth for BOTH halves of the GET path: the
63
+ * {@link FetchGetOpts} key set and the query string the builder emits. Keeping
64
+ * them derived from one list is what makes "accepted by the type but dropped by
65
+ * the serializer" — the #2539 bug — unrepresentable. The list itself is pinned to
66
+ * the generated `getFetch` query type by `_AssertFetchGetQueryKeysCoverSpec`
67
+ * below, so it cannot drift away from the spec silently.
68
+ */
69
+ declare const FETCH_GET_QUERY_KEYS: readonly ["url", "format", "country", "timeout_ms", "cache_ttl"];
70
+ type FetchGetQueryKey = (typeof FETCH_GET_QUERY_KEYS)[number];
71
+ /**
72
+ * Options accepted by `fetch.get` (GET /v1/fetch).
73
+ *
74
+ * A strict subset of {@link FetchOpts}: only the five params the spec's
75
+ * `GET /v1/fetch` actually declares. Everything else on the POST body —
76
+ * `custom` (#2481) and the eleven `markdown_*` / `with_*` tuning fields (#2539) —
77
+ * has no GET query param and was silently dropped by the query builder, so it is
78
+ * excluded here and passing it is a compile error. Use `create()` (POST) for
79
+ * those.
80
+ */
81
+ export type FetchGetOpts = Pick<FetchOpts, FetchGetQueryKey>;
82
+ /** Cache-lookup outcome reported in the `X-Fetch-Cache` response header. */
83
+ export type FetchCacheStatus = 'hit' | 'miss' | 'bypass';
84
+ /**
85
+ * The result of `fetch.create` / `fetch.get`.
86
+ *
87
+ * `/v1/fetch` returns the fetched content AS the response body (text/html,
88
+ * text/markdown, or raw binary passthrough) with metadata carried in `X-Fetch-*`
89
+ * headers on the response — it is NOT a JSON envelope. `body` is therefore the raw
90
+ * content string, never a parsed object, and the named fields decode the
91
+ * headers the docs call out. Anything not surfaced here is available on
92
+ * `headers` (e.g. `X-Fetch-Duration-Ms`, `X-Fetch-Waf-Vendor`).
93
+ */
94
+ export interface FetchResult {
95
+ /**
96
+ * The raw response body exactly as returned — never `JSON.parse`d. Decoded as
97
+ * UTF-8: for text content (HTML, markdown, JSON-as-string) this is exact, but for
98
+ * true binary content (images, PDFs, etc. — `/v1/fetch` supports raw passthrough)
99
+ * any byte sequence that isn't valid UTF-8 is silently replaced with U+FFFD. Use
100
+ * {@link FetchResult.bytes} when the content may be binary.
101
+ */
102
+ body: string;
103
+ /**
104
+ * The raw response body as bytes, byte-for-byte identical to the wire content —
105
+ * lossless for both text and true binary content (images, PDFs, etc.). Prefer
106
+ * this over `body` whenever the fetched content might not be UTF-8 text.
107
+ */
108
+ bytes: Uint8Array;
109
+ /** `X-Fetch-ID` — unique fetch id (`ft_…`), or `null` if the header is absent. */
110
+ id: string | null;
111
+ /** `X-Fetch-Credits-Charged` parsed as a number, or `null` if absent/unparseable. */
112
+ creditsCharged: number | null;
113
+ /** `X-Fetch-Cache` — `hit` | `miss` | `bypass`, or `null` if absent. */
114
+ cache: FetchCacheStatus | null;
115
+ /**
116
+ * `X-Fetch-Custom` — base64-encoded echo of the request's `custom` payload,
117
+ * or `null` when the request sent no `custom`.
118
+ */
119
+ custom: string | null;
120
+ /** The response `Content-Type` (e.g. `text/html`), or `null` if absent. */
121
+ contentType: string | null;
122
+ /** The full header set on the response, for any `X-Fetch-*` value not surfaced above. */
123
+ headers: Headers;
124
+ }
29
125
  export declare class FetchResource {
30
126
  private readonly client;
31
127
  readonly bulk: FetchBulkResource;
32
- constructor(client: RapidCrawl);
128
+ constructor(client: ByteKit);
33
129
  /**
34
130
  * POST /v1/fetch — fetch URL content via POST body.
35
131
  *
36
- * Returns content directly (not ID-based).
132
+ * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
133
+ * The body is returned verbatim — a JSON-serving upstream comes back as the
134
+ * raw JSON string, not a parsed object.
135
+ *
136
+ * `requestOptions` carries the CLIENT-side abort budget (`requestTimeoutMs`) and an
137
+ * optional caller `signal`. It matters most here: the gateway's own ceiling for a
138
+ * fetch is 60 s, so without a per-call budget a slow upstream holds the caller for
139
+ * the constructor default (2 minutes) rather than a duration the caller chose.
37
140
  */
38
- create(opts: FetchOpts): Promise<unknown>;
141
+ create(opts: FetchOpts, requestOptions?: RequestOptions): Promise<FetchResult>;
39
142
  /**
40
143
  * GET /v1/fetch — fetch URL content via query params.
41
144
  *
42
- * Returns content directly (not ID-based).
145
+ * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
146
+ *
147
+ * Accepts only the five params the spec declares for this endpoint. `custom`
148
+ * (#2481) and the `markdown_*` / `with_*` tuning fields (#2539) are POST-body
149
+ * options with no GET query param — they were silently dropped by this builder,
150
+ * so they are now compile errors instead. Use `create()` (POST) for those.
151
+ *
152
+ * The query string is built by iterating `FETCH_GET_QUERY_KEYS`, the same list
153
+ * `FetchGetOpts` is derived from, so every accepted option is necessarily
154
+ * serialized.
155
+ *
156
+ * `requestOptions` carries the CLIENT-side abort budget (`requestTimeoutMs`) and an
157
+ * optional caller `signal`. As on `create`, the gateway's own ceiling for a fetch is
158
+ * 60 s, so a per-call budget is what keeps a slow upstream from holding the caller
159
+ * for the constructor default.
43
160
  */
44
- get(opts: FetchOpts): Promise<unknown>;
161
+ get(opts: FetchGetOpts, requestOptions?: RequestOptions): Promise<FetchResult>;
45
162
  }
46
163
  declare class FetchBulkResource {
47
164
  private readonly client;
48
- constructor(client: RapidCrawl);
165
+ constructor(client: ByteKit);
49
166
  /** POST /v1/fetch/bulk — create a bulk fetch job */
50
- create(opts: Record<string, unknown>): Promise<unknown>;
167
+ create(opts: FetchBulkCreateRequest, requestOptions?: RequestOptions): Promise<FetchBulkCreateResponse>;
51
168
  /** GET /v1/fetch/bulk/{id} — get a bulk fetch job */
52
- get(id: BulkId): Promise<unknown>;
169
+ get(id: BulkId, requestOptions?: RequestOptions): Promise<FetchBulkGetResponse>;
53
170
  }
54
171
  export {};
@@ -1,3 +1,34 @@
1
+ /**
2
+ * The query params `GET /v1/fetch` accepts, in serialization order.
3
+ *
4
+ * This is the single source of truth for BOTH halves of the GET path: the
5
+ * {@link FetchGetOpts} key set and the query string the builder emits. Keeping
6
+ * them derived from one list is what makes "accepted by the type but dropped by
7
+ * the serializer" — the #2539 bug — unrepresentable. The list itself is pinned to
8
+ * the generated `getFetch` query type by `_AssertFetchGetQueryKeysCoverSpec`
9
+ * below, so it cannot drift away from the spec silently.
10
+ */
11
+ const FETCH_GET_QUERY_KEYS = ['url', 'format', 'country', 'timeout_ms', 'cache_ttl'];
12
+ const CACHE_STATUSES = ['hit', 'miss', 'bypass'];
13
+ /** Build a typed {@link FetchResult} from a raw body + its header set. */
14
+ function toFetchResult(raw) {
15
+ const { body, bytes, headers } = raw;
16
+ const creditsRaw = headers.get('X-Fetch-Credits-Charged');
17
+ const credits = creditsRaw === null ? NaN : Number(creditsRaw);
18
+ const cacheRaw = headers.get('X-Fetch-Cache');
19
+ return {
20
+ body,
21
+ bytes,
22
+ id: headers.get('X-Fetch-ID'),
23
+ creditsCharged: Number.isFinite(credits) ? credits : null,
24
+ cache: cacheRaw !== null && CACHE_STATUSES.includes(cacheRaw)
25
+ ? cacheRaw
26
+ : null,
27
+ custom: headers.get('X-Fetch-Custom'),
28
+ contentType: headers.get('Content-Type'),
29
+ headers,
30
+ };
31
+ }
1
32
  export class FetchResource {
2
33
  client;
3
34
  bulk;
@@ -8,28 +39,45 @@ export class FetchResource {
8
39
  /**
9
40
  * POST /v1/fetch — fetch URL content via POST body.
10
41
  *
11
- * Returns content directly (not ID-based).
42
+ * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
43
+ * The body is returned verbatim — a JSON-serving upstream comes back as the
44
+ * raw JSON string, not a parsed object.
45
+ *
46
+ * `requestOptions` carries the CLIENT-side abort budget (`requestTimeoutMs`) and an
47
+ * optional caller `signal`. It matters most here: the gateway's own ceiling for a
48
+ * fetch is 60 s, so without a per-call budget a slow upstream holds the caller for
49
+ * the constructor default (2 minutes) rather than a duration the caller chose.
12
50
  */
13
- create(opts) {
14
- return this.client.request('POST', '/v1/fetch', opts);
51
+ async create(opts, requestOptions) {
52
+ return toFetchResult(await this.client.requestRaw('POST', '/v1/fetch', opts, requestOptions));
15
53
  }
16
54
  /**
17
55
  * GET /v1/fetch — fetch URL content via query params.
18
56
  *
19
- * Returns content directly (not ID-based).
57
+ * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
58
+ *
59
+ * Accepts only the five params the spec declares for this endpoint. `custom`
60
+ * (#2481) and the `markdown_*` / `with_*` tuning fields (#2539) are POST-body
61
+ * options with no GET query param — they were silently dropped by this builder,
62
+ * so they are now compile errors instead. Use `create()` (POST) for those.
63
+ *
64
+ * The query string is built by iterating `FETCH_GET_QUERY_KEYS`, the same list
65
+ * `FetchGetOpts` is derived from, so every accepted option is necessarily
66
+ * serialized.
67
+ *
68
+ * `requestOptions` carries the CLIENT-side abort budget (`requestTimeoutMs`) and an
69
+ * optional caller `signal`. As on `create`, the gateway's own ceiling for a fetch is
70
+ * 60 s, so a per-call budget is what keeps a slow upstream from holding the caller
71
+ * for the constructor default.
20
72
  */
21
- get(opts) {
73
+ async get(opts, requestOptions) {
22
74
  const params = new URLSearchParams();
23
- params.set('url', opts.url);
24
- if (opts.format !== undefined)
25
- params.set('format', opts.format);
26
- if (opts.country !== undefined)
27
- params.set('country', opts.country);
28
- if (opts.timeout_ms !== undefined)
29
- params.set('timeout_ms', String(opts.timeout_ms));
30
- if (opts.cache_ttl !== undefined)
31
- params.set('cache_ttl', String(opts.cache_ttl));
32
- return this.client.request('GET', `/v1/fetch?${params.toString()}`);
75
+ for (const key of FETCH_GET_QUERY_KEYS) {
76
+ const value = opts[key];
77
+ if (value !== undefined)
78
+ params.set(key, String(value));
79
+ }
80
+ return toFetchResult(await this.client.requestRaw('GET', `/v1/fetch?${params.toString()}`, undefined, requestOptions));
33
81
  }
34
82
  }
35
83
  class FetchBulkResource {
@@ -38,11 +86,11 @@ class FetchBulkResource {
38
86
  this.client = client;
39
87
  }
40
88
  /** POST /v1/fetch/bulk — create a bulk fetch job */
41
- create(opts) {
42
- return this.client.request('POST', '/v1/fetch/bulk', opts);
89
+ create(opts, requestOptions) {
90
+ return this.client.request('POST', '/v1/fetch/bulk', opts, requestOptions);
43
91
  }
44
92
  /** GET /v1/fetch/bulk/{id} — get a bulk fetch job */
45
- get(id) {
46
- return this.client.request('GET', `/v1/fetch/bulk/${id}`);
93
+ get(id, requestOptions) {
94
+ return this.client.request('GET', `/v1/fetch/bulk/${id}`, undefined, requestOptions);
47
95
  }
48
96
  }
@@ -1,27 +1,85 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit, RequestOptions } from '../client.js';
2
+ import type { operations } from '../generated/api.js';
2
3
  import type { MonitorId } from '../types.js';
4
+ /**
5
+ * Query params of GET /v1/monitors — all optional, omitted when unset.
6
+ *
7
+ * DERIVED from the generated `listMonitors` query type (#2547), never hand-authored:
8
+ * `status` was previously typed a bare `string`, so a typo like `'activee'` compiled and
9
+ * only failed as a 422 on the wire. Deriving it pins the filter to the spec enum, exactly
10
+ * as {@link ListWebhookDeliveriesParams} does for `/v1/webhook-deliveries`.
11
+ *
12
+ * Still a `type` alias (not an `interface`) so it carries an implicit index signature and
13
+ * stays assignable to {@link toQueryString}'s `Record<string, string | number | undefined>`
14
+ * param (interfaces do not get the implicit index signature; type aliases do).
15
+ */
16
+ export type ListMonitorsParams = NonNullable<operations['listMonitors']['parameters']['query']>;
17
+ /**
18
+ * Lifecycle status a monitor can be filtered by — the spec enum behind
19
+ * {@link ListMonitorsParams.status}. Exported so callers (and the CLI) can name it.
20
+ */
21
+ export type MonitorStatus = NonNullable<ListMonitorsParams['status']>;
22
+ /** The `createMonitor` request body exactly as the OpenAPI spec declares it. */
23
+ type MonitorRequestSpec = operations['createMonitor']['requestBody']['content']['application/json'];
24
+ /**
25
+ * Body of POST /v1/monitors — `url`, `interval_type`, `webhook_url` required,
26
+ * every other field optional.
27
+ *
28
+ * Same `defaultNonNullable` drift documented on `ScreenshotCreateRequest`
29
+ * (screenshots.ts:12-31, follow-up #2540): the spec's
30
+ * `required: [url, interval_type, webhook_url]` is narrow, but `type`,
31
+ * `change_threshold`, and `notify_on` carry `default:` and `openapi-typescript`
32
+ * v7 promotes them to non-optional in the generated type. Relaxed here so the
33
+ * spec-minimal `create(...)` compiles — still DERIVED from the operation type,
34
+ * never hand-authored.
35
+ */
36
+ export type MonitorCreateRequest = Partial<MonitorRequestSpec> & Pick<MonitorRequestSpec, 'url' | 'interval_type' | 'webhook_url'>;
37
+ /** 201 payload of POST /v1/monitors. */
38
+ export type MonitorCreateResponse = operations['createMonitor']['responses'][201]['content']['application/json'];
39
+ /** 200 payload of GET /v1/monitors — the paginated monitor list. */
40
+ export type ListMonitorsResponse = operations['listMonitors']['responses'][200]['content']['application/json'];
41
+ /** 200 payload of GET /v1/monitors/{id} — a single monitor. */
42
+ export type MonitorResponse = operations['getMonitor']['responses'][200]['content']['application/json'];
43
+ /** Body of PATCH /v1/monitors/{id}. */
44
+ export type MonitorUpdateRequest = operations['updateMonitor']['requestBody']['content']['application/json'];
45
+ /** 200 payload of PATCH /v1/monitors/{id}. */
46
+ export type UpdateMonitorResponse = operations['updateMonitor']['responses'][200]['content']['application/json'];
47
+ /** 200 payload of GET /v1/monitors/{id}/captures — the paginated capture list. */
48
+ export type ListMonitorCapturesResponse = operations['listMonitorCaptures']['responses'][200]['content']['application/json'];
3
49
  export declare class MonitorsResource {
4
50
  private readonly client;
5
51
  readonly captures: MonitorCapturesResource;
6
- constructor(client: RapidCrawl);
52
+ constructor(client: ByteKit);
7
53
  /**
8
54
  * POST /v1/monitors — create a page-change monitor (screenshot or scrape capture).
9
55
  * First-capture behavior is the same for both types: the first capture is a silent baseline (has_change=false, change_pct=null) with no change_detected webhook, whether the monitor is `scrape` or `screenshot`. From the second capture onward both types diff against the previous capture.
10
56
  */
11
- create(opts: Record<string, unknown>): Promise<unknown>;
12
- /** GET /v1/monitors — list all monitors for the account */
13
- list(): Promise<unknown>;
57
+ create(opts: MonitorCreateRequest, requestOptions?: RequestOptions): Promise<MonitorCreateResponse>;
58
+ /**
59
+ * GET /v1/monitors — list monitors for the account.
60
+ *
61
+ * `params` is optional and each key is omitted-when-absent, so `list()` with no argument
62
+ * serializes the bare `/v1/monitors` URL unchanged — existing zero-arg callers are unaffected.
63
+ */
64
+ list(params?: ListMonitorsParams, requestOptions?: RequestOptions): Promise<ListMonitorsResponse>;
14
65
  /** GET /v1/monitors/{id} — get a monitor by ID */
15
- get(id: MonitorId): Promise<unknown>;
66
+ get(id: MonitorId, requestOptions?: RequestOptions): Promise<MonitorResponse>;
16
67
  /** PATCH /v1/monitors/{id} — update a monitor */
17
- update(id: MonitorId, opts: Record<string, unknown>): Promise<unknown>;
18
- /** DELETE /v1/monitors/{id} — delete a monitor */
19
- delete(id: MonitorId): Promise<unknown>;
68
+ update(id: MonitorId, opts: MonitorUpdateRequest, requestOptions?: RequestOptions): Promise<UpdateMonitorResponse>;
69
+ /**
70
+ * DELETE /v1/monitors/{id} — delete a monitor.
71
+ *
72
+ * Returns 204 No Content (`operations['deleteMonitor']['responses'][204]`
73
+ * declares `content?: never`), so there is no JSON arm to derive a payload
74
+ * from — hence `Promise<void>`. `client.request()` short-circuits the empty
75
+ * body to `undefined` before it would parse as JSON (#2450).
76
+ */
77
+ delete(id: MonitorId, requestOptions?: RequestOptions): Promise<void>;
20
78
  }
21
79
  declare class MonitorCapturesResource {
22
80
  private readonly client;
23
- constructor(client: RapidCrawl);
81
+ constructor(client: ByteKit);
24
82
  /** GET /v1/monitors/{id}/captures — list captures for a monitor */
25
- list(id: MonitorId): Promise<unknown>;
83
+ list(id: MonitorId, requestOptions?: RequestOptions): Promise<ListMonitorCapturesResponse>;
26
84
  }
27
85
  export {};
@@ -1,3 +1,4 @@
1
+ import { toQueryString } from './query-string.js';
1
2
  export class MonitorsResource {
2
3
  client;
3
4
  captures;
@@ -9,24 +10,36 @@ export class MonitorsResource {
9
10
  * POST /v1/monitors — create a page-change monitor (screenshot or scrape capture).
10
11
  * First-capture behavior is the same for both types: the first capture is a silent baseline (has_change=false, change_pct=null) with no change_detected webhook, whether the monitor is `scrape` or `screenshot`. From the second capture onward both types diff against the previous capture.
11
12
  */
12
- create(opts) {
13
- return this.client.request('POST', '/v1/monitors', opts);
13
+ create(opts, requestOptions) {
14
+ return this.client.request('POST', '/v1/monitors', opts, requestOptions);
14
15
  }
15
- /** GET /v1/monitors — list all monitors for the account */
16
- list() {
17
- return this.client.request('GET', '/v1/monitors');
16
+ /**
17
+ * GET /v1/monitors — list monitors for the account.
18
+ *
19
+ * `params` is optional and each key is omitted-when-absent, so `list()` with no argument
20
+ * serializes the bare `/v1/monitors` URL unchanged — existing zero-arg callers are unaffected.
21
+ */
22
+ list(params, requestOptions) {
23
+ return this.client.request('GET', `/v1/monitors${toQueryString(params)}`, undefined, requestOptions);
18
24
  }
19
25
  /** GET /v1/monitors/{id} — get a monitor by ID */
20
- get(id) {
21
- return this.client.request('GET', `/v1/monitors/${id}`);
26
+ get(id, requestOptions) {
27
+ return this.client.request('GET', `/v1/monitors/${id}`, undefined, requestOptions);
22
28
  }
23
29
  /** PATCH /v1/monitors/{id} — update a monitor */
24
- update(id, opts) {
25
- return this.client.request('PATCH', `/v1/monitors/${id}`, opts);
30
+ update(id, opts, requestOptions) {
31
+ return this.client.request('PATCH', `/v1/monitors/${id}`, opts, requestOptions);
26
32
  }
27
- /** DELETE /v1/monitors/{id} — delete a monitor */
28
- delete(id) {
29
- return this.client.request('DELETE', `/v1/monitors/${id}`);
33
+ /**
34
+ * DELETE /v1/monitors/{id} — delete a monitor.
35
+ *
36
+ * Returns 204 No Content (`operations['deleteMonitor']['responses'][204]`
37
+ * declares `content?: never`), so there is no JSON arm to derive a payload
38
+ * from — hence `Promise<void>`. `client.request()` short-circuits the empty
39
+ * body to `undefined` before it would parse as JSON (#2450).
40
+ */
41
+ delete(id, requestOptions) {
42
+ return this.client.request('DELETE', `/v1/monitors/${id}`, undefined, requestOptions);
30
43
  }
31
44
  }
32
45
  class MonitorCapturesResource {
@@ -35,7 +48,7 @@ class MonitorCapturesResource {
35
48
  this.client = client;
36
49
  }
37
50
  /** GET /v1/monitors/{id}/captures — list captures for a monitor */
38
- list(id) {
39
- return this.client.request('GET', `/v1/monitors/${id}/captures`);
51
+ list(id, requestOptions) {
52
+ return this.client.request('GET', `/v1/monitors/${id}/captures`, undefined, requestOptions);
40
53
  }
41
54
  }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Serialize a flat params object to a `?a=1&b=2` query string, omitting `undefined` values.
3
+ *
4
+ * Returns `''` (not `'?'`) for a `undefined` param bag or one whose every value is `undefined`,
5
+ * so a caller can unconditionally append the result to a path and get a bare URL when no params
6
+ * are set. This is the single query-string serializer shared across the query-param resources
7
+ * (`usage`, `webhooks`, `monitors`) — extracting it keeps their omit-when-absent semantics
8
+ * byte-identical rather than drifting across per-file copies.
9
+ */
10
+ export declare function toQueryString(params: Record<string, string | number | undefined> | undefined): string;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Serialize a flat params object to a `?a=1&b=2` query string, omitting `undefined` values.
3
+ *
4
+ * Returns `''` (not `'?'`) for a `undefined` param bag or one whose every value is `undefined`,
5
+ * so a caller can unconditionally append the result to a path and get a bare URL when no params
6
+ * are set. This is the single query-string serializer shared across the query-param resources
7
+ * (`usage`, `webhooks`, `monitors`) — extracting it keeps their omit-when-absent semantics
8
+ * byte-identical rather than drifting across per-file copies.
9
+ */
10
+ export function toQueryString(params) {
11
+ if (!params)
12
+ return '';
13
+ const search = new URLSearchParams();
14
+ for (const [key, value] of Object.entries(params)) {
15
+ if (value !== undefined)
16
+ search.set(key, String(value));
17
+ }
18
+ const qs = search.toString();
19
+ return qs ? `?${qs}` : '';
20
+ }
@@ -1,5 +1,5 @@
1
- import type { RapidCrawl, RequestOptions } from '../client.js';
2
- import type { operations } from '../generated/api.js';
1
+ import type { ByteKit, RequestOptions } from '../client.js';
2
+ import type { components, operations } from '../generated/api.js';
3
3
  import type { ScrapeId, BulkId } from '../types.js';
4
4
  /**
5
5
  * Response of POST /v1/scrape — a 200 sync success envelope or a 202 queued
@@ -21,13 +21,27 @@ export type ScrapeBulkGetResponse = operations['getScrapeBulk']['responses'][200
21
21
  /** Markdown processing mode for the pipeline. */
22
22
  export type MarkdownMode = 'article' | 'raw' | 'llm';
23
23
  /** Link rendering style in the markdown output. */
24
- export type MarkdownLinks = 'inline' | 'references' | 'none';
24
+ export type MarkdownLinks = 'inline' | 'references' | 'none' | 'text';
25
+ /** Image retention mode in the markdown output. */
26
+ export type MarkdownImages = 'inline' | 'references' | 'none' | 'text';
27
+ /** Tokenizer encoding hint for `token_budget`. */
28
+ export type TokenEncoding = 'cl100k_base' | 'o200k_base';
29
+ /**
30
+ * A cookie to set before loading the page — the spec's `Cookie` schema verbatim
31
+ * (`name` and `value` required; `domain`, `path`, `secure`, `httpOnly` optional).
32
+ *
33
+ * DERIVED from the generated schema (#2547), never hand-authored: `cookies` was
34
+ * previously an open bag of untyped records, so a nameless cookie compiled and only
35
+ * failed as a 422 on the wire.
36
+ */
37
+ export type ScrapeCookie = components['schemas']['Cookie'];
25
38
  /** Options for POST /v1/scrape. */
26
39
  export interface ScrapeOpts {
27
40
  url: string;
28
41
  formats?: Array<'raw_html' | 'html' | 'markdown' | 'links' | 'images'>;
29
42
  country?: string;
30
- cookies?: Array<Record<string, unknown>>;
43
+ /** Cookies to set before loading the page. `name` and `value` are required (spec `Cookie` schema). */
44
+ cookies?: ScrapeCookie[];
31
45
  headers?: Record<string, string>;
32
46
  delay_ms?: number;
33
47
  /** SERVER-side scrape budget in ms — how long the gateway may spend on the scrape itself. For the CLIENT-side abort budget (when this SDK gives up on the wire), see `RequestOptions.requestTimeoutMs`. */
@@ -41,6 +55,12 @@ export interface ScrapeOpts {
41
55
  markdown_query?: string;
42
56
  /** Link rendering style in the markdown output. */
43
57
  markdown_links?: MarkdownLinks;
58
+ /** Image retention mode in the markdown output. Distinct from `markdown_filter_images` (which drops low-signal images before conversion). */
59
+ markdown_images?: MarkdownImages;
60
+ /** When true, appends a `Links:` footer to the markdown output. Automatically enabled when `markdown_links` is `'references'`. */
61
+ with_links_summary?: boolean;
62
+ /** When true, appends an `Images:` footer to the markdown output. */
63
+ with_images_summary?: boolean;
44
64
  /** Collapse excessive whitespace for a more compact output. */
45
65
  markdown_compact?: boolean;
46
66
  /** Filter low-signal images from the markdown output. */
@@ -51,6 +71,20 @@ export interface ScrapeOpts {
51
71
  markdown_include_warnings?: boolean;
52
72
  /** When true, the response includes a top-level `stats` object with `ScrapeStats` (chars, tokens, blocks). Only effective when `markdown` is in `formats`. */
53
73
  markdown_include_stats?: boolean;
74
+ /** Maximum token count for the markdown output. Truncates at the last paragraph → sentence → token boundary under the limit. Absent → no truncation. */
75
+ token_budget?: number;
76
+ /** Tokenizer encoding hint for `token_budget`. `cl100k_base` (default) matches GPT-4/4o; `o200k_base` matches GPT-4o-mini / o-series. */
77
+ token_encoding?: TokenEncoding;
78
+ /** When true, emulate a mobile device (mobile UA + viewport). Default false (desktop). Part of the cache key, so mobile and desktop responses cache independently. */
79
+ mobile?: boolean;
80
+ /** When true (default), base64-encoded `data:` image sources are stripped before markdown conversion and from `html` output. Set false to preserve them. Does not affect `raw_html`. */
81
+ remove_base64_images?: boolean;
82
+ /** HTML element names (not CSS selectors) to keep. When non-empty, only content within these elements is included in `html`/`markdown` output. Applied before `exclude_tags`. Does not affect `raw_html`. */
83
+ include_tags?: string[];
84
+ /** HTML element names (not CSS selectors) to strip from `html`/`markdown` output. Applied after `include_tags`. Does not affect `raw_html`. */
85
+ exclude_tags?: string[];
86
+ /** When true and `markdown` is in `formats`, the converted markdown is sent to Groq for cleaning before return. Graceful degradation on any Groq failure. Billing: 3× credits and bytes applied only when cleaning succeeds. */
87
+ clean_markdown?: boolean;
54
88
  /**
55
89
  * How long a freshly fetched URL may be served from cache. `'0'`/`0` skips the
56
90
  * cache read (the result is still written), `'Nh'`/`'Nd'` set a TTL (capped at
@@ -70,7 +104,7 @@ export interface ScrapeOpts {
70
104
  export declare class ScrapeResource {
71
105
  private readonly client;
72
106
  readonly bulk: ScrapeBulkResource;
73
- constructor(client: RapidCrawl);
107
+ constructor(client: ByteKit);
74
108
  /**
75
109
  * POST /v1/scrape — create a scrape job.
76
110
  *
@@ -102,10 +136,15 @@ export declare class ScrapeResource {
102
136
  }
103
137
  declare class ScrapeBulkResource {
104
138
  private readonly client;
105
- constructor(client: RapidCrawl);
106
- /** POST /v1/scrape/bulk — create a bulk scrape job */
107
- create(opts: ScrapeBulkCreateRequest): Promise<ScrapeBulkCreateResponse>;
139
+ constructor(client: ByteKit);
140
+ /**
141
+ * POST /v1/scrape/bulk — create a bulk scrape job.
142
+ *
143
+ * `requestOptions` carries the CLIENT-side abort budget (`requestTimeoutMs`) and an
144
+ * optional caller `signal`; both override the constructor's `timeoutMs` default.
145
+ */
146
+ create(opts: ScrapeBulkCreateRequest, requestOptions?: RequestOptions): Promise<ScrapeBulkCreateResponse>;
108
147
  /** GET /v1/scrape/bulk/{id} — get a bulk scrape job */
109
- get(id: BulkId): Promise<ScrapeBulkGetResponse>;
148
+ get(id: BulkId, requestOptions?: RequestOptions): Promise<ScrapeBulkGetResponse>;
110
149
  }
111
150
  export {};
@@ -43,12 +43,17 @@ class ScrapeBulkResource {
43
43
  constructor(client) {
44
44
  this.client = client;
45
45
  }
46
- /** POST /v1/scrape/bulk — create a bulk scrape job */
47
- create(opts) {
48
- return this.client.request('POST', '/v1/scrape/bulk', opts);
46
+ /**
47
+ * POST /v1/scrape/bulk — create a bulk scrape job.
48
+ *
49
+ * `requestOptions` carries the CLIENT-side abort budget (`requestTimeoutMs`) and an
50
+ * optional caller `signal`; both override the constructor's `timeoutMs` default.
51
+ */
52
+ create(opts, requestOptions) {
53
+ return this.client.request('POST', '/v1/scrape/bulk', opts, requestOptions);
49
54
  }
50
55
  /** GET /v1/scrape/bulk/{id} — get a bulk scrape job */
51
- get(id) {
52
- return this.client.request('GET', `/v1/scrape/bulk/${id}`);
56
+ get(id, requestOptions) {
57
+ return this.client.request('GET', `/v1/scrape/bulk/${id}`, undefined, requestOptions);
53
58
  }
54
59
  }