@hunt-labs/bytekit-sdk 0.2.0 → 0.3.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,4 +1,4 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit } from '../client.js';
2
2
  import type { operations } from '../generated/api.js';
3
3
  import type { ApiKeyId } from '../types.js';
4
4
  /**
@@ -36,13 +36,13 @@ export type UpdateApiKeyResponse = operations['updateApiKey']['responses'][200][
36
36
  export declare class AccountResource {
37
37
  private readonly client;
38
38
  readonly apiKeys: ApiKeysResource;
39
- constructor(client: RapidCrawl);
39
+ constructor(client: ByteKit);
40
40
  /** GET /v1/account — get the authenticated account */
41
41
  get(): Promise<GetAccountResponse>;
42
42
  }
43
43
  declare class ApiKeysResource {
44
44
  private readonly client;
45
- constructor(client: RapidCrawl);
45
+ constructor(client: ByteKit);
46
46
  /**
47
47
  * POST /v1/account/api-keys — create a new API key.
48
48
  *
@@ -63,10 +63,9 @@ declare class ApiKeysResource {
63
63
  * declares `content?: never`, so there is no JSON arm to derive a payload
64
64
  * from — hence `Promise<void>`.
65
65
  *
66
- * KNOWN DRIFT: `client.request()` calls `response.json()` unconditionally,
67
- * which throws on the gateway's empty 204 body — so this method currently
68
- * rejects at runtime. The fix belongs in `client.ts` (tracked separately);
69
- * typing it here states the intended contract rather than encoding the bug.
66
+ * `client.request()` short-circuits an empty body (204 or any empty response)
67
+ * to `undefined` before it would parse the body as JSON (#2450), so this
68
+ * method resolves cleanly on the gateway's empty 204 body.
70
69
  */
71
70
  revoke(id: ApiKeyId): Promise<void>;
72
71
  /** POST /v1/account/api-keys/{id}/reveal — reveal the plaintext API key value */
@@ -43,10 +43,9 @@ class ApiKeysResource {
43
43
  * declares `content?: never`, so there is no JSON arm to derive a payload
44
44
  * from — hence `Promise<void>`.
45
45
  *
46
- * KNOWN DRIFT: `client.request()` calls `response.json()` unconditionally,
47
- * which throws on the gateway's empty 204 body — so this method currently
48
- * rejects at runtime. The fix belongs in `client.ts` (tracked separately);
49
- * typing it here states the intended contract rather than encoding the bug.
46
+ * `client.request()` short-circuits an empty body (204 or any empty response)
47
+ * to `undefined` before it would parse the body as JSON (#2450), so this
48
+ * method resolves cleanly on the gateway's empty 204 body.
50
49
  */
51
50
  revoke(id) {
52
51
  return this.client.request('DELETE', `/v1/account/api-keys/${id}`);
@@ -1,20 +1,31 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit } from '../client.js';
2
+ import type { operations } from '../generated/api.js';
2
3
  import type { BulkId } from '../types.js';
4
+ /** Body of POST /v1/bulk. */
5
+ export type BulkCreateRequest = operations['createBulk']['requestBody']['content']['application/json'];
6
+ /** 202 payload of POST /v1/bulk — bulk jobs are always async. */
7
+ export type BulkCreateResponse = operations['createBulk']['responses'][202]['content']['application/json'];
8
+ /** 200 payload of GET /v1/bulk/{id}. */
9
+ export type BulkGetResponse = operations['getBulk']['responses'][200]['content']['application/json'];
10
+ /** 200 payload of DELETE /v1/bulk/{id} — cancels an in-flight job. */
11
+ export type BulkCancelResponse = operations['deleteBulk']['responses'][200]['content']['application/json'];
12
+ /** 200 payload of GET /v1/bulk/{id}/screenshots. */
13
+ export type ListBulkScreenshotsResponse = operations['listBulkScreenshots']['responses'][200]['content']['application/json'];
3
14
  export declare class BulkResource {
4
15
  private readonly client;
5
16
  readonly screenshots: BulkScreenshotsResource;
6
- constructor(client: RapidCrawl);
17
+ constructor(client: ByteKit);
7
18
  /** POST /v1/bulk — create a bulk screenshots job */
8
- create(opts: Record<string, unknown>): Promise<unknown>;
19
+ create(opts: BulkCreateRequest): Promise<BulkCreateResponse>;
9
20
  /** GET /v1/bulk/{id} — get a bulk job status */
10
- get(id: BulkId): Promise<unknown>;
21
+ get(id: BulkId): Promise<BulkGetResponse>;
11
22
  /** DELETE /v1/bulk/{id} — cancel an in-flight bulk job */
12
- cancel(id: BulkId): Promise<unknown>;
23
+ cancel(id: BulkId): Promise<BulkCancelResponse>;
13
24
  }
14
25
  declare class BulkScreenshotsResource {
15
26
  private readonly client;
16
- constructor(client: RapidCrawl);
27
+ constructor(client: ByteKit);
17
28
  /** GET /v1/bulk/{id}/screenshots — list screenshots in a bulk job */
18
- list(id: BulkId): Promise<unknown>;
29
+ list(id: BulkId): Promise<ListBulkScreenshotsResponse>;
19
30
  }
20
31
  export {};
@@ -1,5 +1,12 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit } 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,87 @@ export interface FetchOpts {
26
56
  */
27
57
  custom?: Record<string, unknown>;
28
58
  }
59
+ /**
60
+ * Options accepted by `fetch.get` (GET /v1/fetch).
61
+ *
62
+ * Identical to {@link FetchOpts} minus `custom`: the spec's `GET /v1/fetch` has
63
+ * no `custom` query param, so it is excluded here — passing it is a compile
64
+ * error rather than a silently-dropped option (#2481).
65
+ */
66
+ export type FetchGetOpts = Omit<FetchOpts, 'custom'>;
67
+ /** Cache-lookup outcome reported in the `X-Fetch-Cache` response header. */
68
+ export type FetchCacheStatus = 'hit' | 'miss' | 'bypass';
69
+ /**
70
+ * The result of `fetch.create` / `fetch.get`.
71
+ *
72
+ * `/v1/fetch` returns the fetched content AS the response body (text/html,
73
+ * text/markdown, or raw binary passthrough) with metadata carried in `X-Fetch-*`
74
+ * response headers — it is NOT a JSON envelope. `body` is therefore the raw
75
+ * content string, never a parsed object, and the named fields decode the
76
+ * headers the docs call out. Anything not surfaced here is available on
77
+ * `headers` (e.g. `X-Fetch-Duration-Ms`, `X-Fetch-Waf-Vendor`).
78
+ */
79
+ export interface FetchResult {
80
+ /**
81
+ * The raw response body exactly as returned — never `JSON.parse`d. Decoded as
82
+ * UTF-8: for text content (HTML, markdown, JSON-as-string) this is exact, but for
83
+ * true binary content (images, PDFs, etc. — `/v1/fetch` supports raw passthrough)
84
+ * any byte sequence that isn't valid UTF-8 is silently replaced with U+FFFD. Use
85
+ * {@link FetchResult.bytes} when the content may be binary.
86
+ */
87
+ body: string;
88
+ /**
89
+ * The raw response body as bytes, byte-for-byte identical to the wire content —
90
+ * lossless for both text and true binary content (images, PDFs, etc.). Prefer
91
+ * this over `body` whenever the fetched content might not be UTF-8 text.
92
+ */
93
+ bytes: Uint8Array;
94
+ /** `X-Fetch-ID` — unique fetch id (`ft_…`), or `null` if the header is absent. */
95
+ id: string | null;
96
+ /** `X-Fetch-Credits-Charged` parsed as a number, or `null` if absent/unparseable. */
97
+ creditsCharged: number | null;
98
+ /** `X-Fetch-Cache` — `hit` | `miss` | `bypass`, or `null` if absent. */
99
+ cache: FetchCacheStatus | null;
100
+ /**
101
+ * `X-Fetch-Custom` — base64-encoded echo of the request's `custom` payload,
102
+ * or `null` when the request sent no `custom`.
103
+ */
104
+ custom: string | null;
105
+ /** The response `Content-Type` (e.g. `text/html`), or `null` if absent. */
106
+ contentType: string | null;
107
+ /** The full response headers, for any `X-Fetch-*` value not surfaced above. */
108
+ headers: Headers;
109
+ }
29
110
  export declare class FetchResource {
30
111
  private readonly client;
31
112
  readonly bulk: FetchBulkResource;
32
- constructor(client: RapidCrawl);
113
+ constructor(client: ByteKit);
33
114
  /**
34
115
  * POST /v1/fetch — fetch URL content via POST body.
35
116
  *
36
- * Returns content directly (not ID-based).
117
+ * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
118
+ * The body is returned verbatim — a JSON-serving upstream comes back as the
119
+ * raw JSON string, not a parsed object.
37
120
  */
38
- create(opts: FetchOpts): Promise<unknown>;
121
+ create(opts: FetchOpts): Promise<FetchResult>;
39
122
  /**
40
123
  * GET /v1/fetch — fetch URL content via query params.
41
124
  *
42
- * Returns content directly (not ID-based).
125
+ * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
126
+ *
127
+ * `custom` is intentionally absent from the accepted opts: the spec's
128
+ * `GET /v1/fetch` has no `custom` query param and the value was never
129
+ * serialized, so passing it is a compile error rather than a silent drop
130
+ * (#2481). Use `create()` (POST) when you need to echo a `custom` payload.
43
131
  */
44
- get(opts: FetchOpts): Promise<unknown>;
132
+ get(opts: FetchGetOpts): Promise<FetchResult>;
45
133
  }
46
134
  declare class FetchBulkResource {
47
135
  private readonly client;
48
- constructor(client: RapidCrawl);
136
+ constructor(client: ByteKit);
49
137
  /** POST /v1/fetch/bulk — create a bulk fetch job */
50
- create(opts: Record<string, unknown>): Promise<unknown>;
138
+ create(opts: FetchBulkCreateRequest): Promise<FetchBulkCreateResponse>;
51
139
  /** GET /v1/fetch/bulk/{id} — get a bulk fetch job */
52
- get(id: BulkId): Promise<unknown>;
140
+ get(id: BulkId): Promise<FetchBulkGetResponse>;
53
141
  }
54
142
  export {};
@@ -1,3 +1,23 @@
1
+ const CACHE_STATUSES = ['hit', 'miss', 'bypass'];
2
+ /** Build a typed {@link FetchResult} from a raw body + response headers. */
3
+ function toFetchResult(raw) {
4
+ const { body, bytes, headers } = raw;
5
+ const creditsRaw = headers.get('X-Fetch-Credits-Charged');
6
+ const credits = creditsRaw === null ? NaN : Number(creditsRaw);
7
+ const cacheRaw = headers.get('X-Fetch-Cache');
8
+ return {
9
+ body,
10
+ bytes,
11
+ id: headers.get('X-Fetch-ID'),
12
+ creditsCharged: Number.isFinite(credits) ? credits : null,
13
+ cache: cacheRaw !== null && CACHE_STATUSES.includes(cacheRaw)
14
+ ? cacheRaw
15
+ : null,
16
+ custom: headers.get('X-Fetch-Custom'),
17
+ contentType: headers.get('Content-Type'),
18
+ headers,
19
+ };
20
+ }
1
21
  export class FetchResource {
2
22
  client;
3
23
  bulk;
@@ -8,17 +28,24 @@ export class FetchResource {
8
28
  /**
9
29
  * POST /v1/fetch — fetch URL content via POST body.
10
30
  *
11
- * Returns content directly (not ID-based).
31
+ * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
32
+ * The body is returned verbatim — a JSON-serving upstream comes back as the
33
+ * raw JSON string, not a parsed object.
12
34
  */
13
- create(opts) {
14
- return this.client.request('POST', '/v1/fetch', opts);
35
+ async create(opts) {
36
+ return toFetchResult(await this.client.requestRaw('POST', '/v1/fetch', opts));
15
37
  }
16
38
  /**
17
39
  * GET /v1/fetch — fetch URL content via query params.
18
40
  *
19
- * Returns content directly (not ID-based).
41
+ * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
42
+ *
43
+ * `custom` is intentionally absent from the accepted opts: the spec's
44
+ * `GET /v1/fetch` has no `custom` query param and the value was never
45
+ * serialized, so passing it is a compile error rather than a silent drop
46
+ * (#2481). Use `create()` (POST) when you need to echo a `custom` payload.
20
47
  */
21
- get(opts) {
48
+ async get(opts) {
22
49
  const params = new URLSearchParams();
23
50
  params.set('url', opts.url);
24
51
  if (opts.format !== undefined)
@@ -29,7 +56,7 @@ export class FetchResource {
29
56
  params.set('timeout_ms', String(opts.timeout_ms));
30
57
  if (opts.cache_ttl !== undefined)
31
58
  params.set('cache_ttl', String(opts.cache_ttl));
32
- return this.client.request('GET', `/v1/fetch?${params.toString()}`);
59
+ return toFetchResult(await this.client.requestRaw('GET', `/v1/fetch?${params.toString()}`));
33
60
  }
34
61
  }
35
62
  class FetchBulkResource {
@@ -1,27 +1,66 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit } 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
+ * A `type` alias (not an `interface`) so it carries an implicit index signature and stays
8
+ * assignable to {@link toQueryString}'s `Record<string, string | number | undefined>` param
9
+ * (interfaces do not get the implicit index signature; type aliases do).
10
+ */
11
+ export type ListMonitorsParams = {
12
+ limit?: number;
13
+ cursor?: string;
14
+ status?: string;
15
+ };
16
+ /** Body of POST /v1/monitors. */
17
+ export type MonitorCreateRequest = operations['createMonitor']['requestBody']['content']['application/json'];
18
+ /** 201 payload of POST /v1/monitors. */
19
+ export type MonitorCreateResponse = operations['createMonitor']['responses'][201]['content']['application/json'];
20
+ /** 200 payload of GET /v1/monitors — the paginated monitor list. */
21
+ export type ListMonitorsResponse = operations['listMonitors']['responses'][200]['content']['application/json'];
22
+ /** 200 payload of GET /v1/monitors/{id} — a single monitor. */
23
+ export type MonitorResponse = operations['getMonitor']['responses'][200]['content']['application/json'];
24
+ /** Body of PATCH /v1/monitors/{id}. */
25
+ export type MonitorUpdateRequest = operations['updateMonitor']['requestBody']['content']['application/json'];
26
+ /** 200 payload of PATCH /v1/monitors/{id}. */
27
+ export type UpdateMonitorResponse = operations['updateMonitor']['responses'][200]['content']['application/json'];
28
+ /** 200 payload of GET /v1/monitors/{id}/captures — the paginated capture list. */
29
+ export type ListMonitorCapturesResponse = operations['listMonitorCaptures']['responses'][200]['content']['application/json'];
3
30
  export declare class MonitorsResource {
4
31
  private readonly client;
5
32
  readonly captures: MonitorCapturesResource;
6
- constructor(client: RapidCrawl);
33
+ constructor(client: ByteKit);
7
34
  /**
8
35
  * POST /v1/monitors — create a page-change monitor (screenshot or scrape capture).
9
36
  * 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
37
  */
11
- create(opts: Record<string, unknown>): Promise<unknown>;
12
- /** GET /v1/monitors — list all monitors for the account */
13
- list(): Promise<unknown>;
38
+ create(opts: MonitorCreateRequest): Promise<MonitorCreateResponse>;
39
+ /**
40
+ * GET /v1/monitors — list monitors for the account.
41
+ *
42
+ * `params` is optional and each key is omitted-when-absent, so `list()` with no argument
43
+ * serializes the bare `/v1/monitors` URL unchanged — existing zero-arg callers are unaffected.
44
+ */
45
+ list(params?: ListMonitorsParams): Promise<ListMonitorsResponse>;
14
46
  /** GET /v1/monitors/{id} — get a monitor by ID */
15
- get(id: MonitorId): Promise<unknown>;
47
+ get(id: MonitorId): Promise<MonitorResponse>;
16
48
  /** 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>;
49
+ update(id: MonitorId, opts: MonitorUpdateRequest): Promise<UpdateMonitorResponse>;
50
+ /**
51
+ * DELETE /v1/monitors/{id} — delete a monitor.
52
+ *
53
+ * Returns 204 No Content (`operations['deleteMonitor']['responses'][204]`
54
+ * declares `content?: never`), so there is no JSON arm to derive a payload
55
+ * from — hence `Promise<void>`. `client.request()` short-circuits the empty
56
+ * body to `undefined` before it would parse as JSON (#2450).
57
+ */
58
+ delete(id: MonitorId): Promise<void>;
20
59
  }
21
60
  declare class MonitorCapturesResource {
22
61
  private readonly client;
23
- constructor(client: RapidCrawl);
62
+ constructor(client: ByteKit);
24
63
  /** GET /v1/monitors/{id}/captures — list captures for a monitor */
25
- list(id: MonitorId): Promise<unknown>;
64
+ list(id: MonitorId): Promise<ListMonitorCapturesResponse>;
26
65
  }
27
66
  export {};
@@ -1,3 +1,4 @@
1
+ import { toQueryString } from './query-string.js';
1
2
  export class MonitorsResource {
2
3
  client;
3
4
  captures;
@@ -12,9 +13,14 @@ export class MonitorsResource {
12
13
  create(opts) {
13
14
  return this.client.request('POST', '/v1/monitors', opts);
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) {
23
+ return this.client.request('GET', `/v1/monitors${toQueryString(params)}`);
18
24
  }
19
25
  /** GET /v1/monitors/{id} — get a monitor by ID */
20
26
  get(id) {
@@ -24,7 +30,14 @@ export class MonitorsResource {
24
30
  update(id, opts) {
25
31
  return this.client.request('PATCH', `/v1/monitors/${id}`, opts);
26
32
  }
27
- /** DELETE /v1/monitors/{id} — delete a monitor */
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
+ */
28
41
  delete(id) {
29
42
  return this.client.request('DELETE', `/v1/monitors/${id}`);
30
43
  }
@@ -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,4 +1,4 @@
1
- import type { RapidCrawl, RequestOptions } from '../client.js';
1
+ import type { ByteKit, RequestOptions } from '../client.js';
2
2
  import type { operations } from '../generated/api.js';
3
3
  import type { ScrapeId, BulkId } from '../types.js';
4
4
  /**
@@ -21,7 +21,11 @@ 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';
25
29
  /** Options for POST /v1/scrape. */
26
30
  export interface ScrapeOpts {
27
31
  url: string;
@@ -41,6 +45,12 @@ export interface ScrapeOpts {
41
45
  markdown_query?: string;
42
46
  /** Link rendering style in the markdown output. */
43
47
  markdown_links?: MarkdownLinks;
48
+ /** Image retention mode in the markdown output. Distinct from `markdown_filter_images` (which drops low-signal images before conversion). */
49
+ markdown_images?: MarkdownImages;
50
+ /** When true, appends a `Links:` footer to the markdown output. Automatically enabled when `markdown_links` is `'references'`. */
51
+ with_links_summary?: boolean;
52
+ /** When true, appends an `Images:` footer to the markdown output. */
53
+ with_images_summary?: boolean;
44
54
  /** Collapse excessive whitespace for a more compact output. */
45
55
  markdown_compact?: boolean;
46
56
  /** Filter low-signal images from the markdown output. */
@@ -51,6 +61,20 @@ export interface ScrapeOpts {
51
61
  markdown_include_warnings?: boolean;
52
62
  /** When true, the response includes a top-level `stats` object with `ScrapeStats` (chars, tokens, blocks). Only effective when `markdown` is in `formats`. */
53
63
  markdown_include_stats?: boolean;
64
+ /** Maximum token count for the markdown output. Truncates at the last paragraph → sentence → token boundary under the limit. Absent → no truncation. */
65
+ token_budget?: number;
66
+ /** Tokenizer encoding hint for `token_budget`. `cl100k_base` (default) matches GPT-4/4o; `o200k_base` matches GPT-4o-mini / o-series. */
67
+ token_encoding?: TokenEncoding;
68
+ /** When true, emulate a mobile device (mobile UA + viewport). Default false (desktop). Part of the cache key, so mobile and desktop responses cache independently. */
69
+ mobile?: boolean;
70
+ /** 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`. */
71
+ remove_base64_images?: boolean;
72
+ /** 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`. */
73
+ include_tags?: string[];
74
+ /** HTML element names (not CSS selectors) to strip from `html`/`markdown` output. Applied after `include_tags`. Does not affect `raw_html`. */
75
+ exclude_tags?: string[];
76
+ /** 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. */
77
+ clean_markdown?: boolean;
54
78
  /**
55
79
  * How long a freshly fetched URL may be served from cache. `'0'`/`0` skips the
56
80
  * cache read (the result is still written), `'Nh'`/`'Nd'` set a TTL (capped at
@@ -70,7 +94,7 @@ export interface ScrapeOpts {
70
94
  export declare class ScrapeResource {
71
95
  private readonly client;
72
96
  readonly bulk: ScrapeBulkResource;
73
- constructor(client: RapidCrawl);
97
+ constructor(client: ByteKit);
74
98
  /**
75
99
  * POST /v1/scrape — create a scrape job.
76
100
  *
@@ -102,7 +126,7 @@ export declare class ScrapeResource {
102
126
  }
103
127
  declare class ScrapeBulkResource {
104
128
  private readonly client;
105
- constructor(client: RapidCrawl);
129
+ constructor(client: ByteKit);
106
130
  /** POST /v1/scrape/bulk — create a bulk scrape job */
107
131
  create(opts: ScrapeBulkCreateRequest): Promise<ScrapeBulkCreateResponse>;
108
132
  /** GET /v1/scrape/bulk/{id} — get a bulk scrape job */
@@ -1,4 +1,4 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit } from '../client.js';
2
2
  import type { operations } from '../generated/api.js';
3
3
  import type { ScreenshotId } from '../types.js';
4
4
  /** The `createScreenshot` request body exactly as the OpenAPI spec declares it. */
@@ -47,9 +47,18 @@ export type ScreenshotCreateResponse = operations['createScreenshot']['responses
47
47
  export type ScreenshotGetResponse = operations['getScreenshot']['responses'][200]['content']['application/json'] | operations['getScreenshot']['responses'][202]['content']['application/json'];
48
48
  export declare class ScreenshotsResource {
49
49
  private readonly client;
50
- constructor(client: RapidCrawl);
51
- /** POST /v1/screenshots — capture a screenshot */
52
- create(opts: ScreenshotCreateRequest): Promise<ScreenshotCreateResponse>;
50
+ constructor(client: ByteKit);
51
+ /**
52
+ * POST /v1/screenshots — capture a screenshot.
53
+ *
54
+ * `params.async` maps to the `?async=true` query param (queued 202 capture). It is a QUERY
55
+ * param on `createScreenshot`, distinct from scrape where `async` is a body field. `params` is
56
+ * optional and `async` omitted-when-absent: `create(opts)` with no second argument posts to the
57
+ * bare `/v1/screenshots` URL unchanged — existing single-arg callers are unaffected.
58
+ */
59
+ create(opts: ScreenshotCreateRequest, params?: {
60
+ async?: boolean;
61
+ }): Promise<ScreenshotCreateResponse>;
53
62
  /**
54
63
  * GET /v1/screenshots/{id} — poll a screenshot by ID.
55
64
  *
@@ -3,9 +3,17 @@ export class ScreenshotsResource {
3
3
  constructor(client) {
4
4
  this.client = client;
5
5
  }
6
- /** POST /v1/screenshots — capture a screenshot */
7
- create(opts) {
8
- return this.client.request('POST', '/v1/screenshots', opts);
6
+ /**
7
+ * POST /v1/screenshots — capture a screenshot.
8
+ *
9
+ * `params.async` maps to the `?async=true` query param (queued 202 capture). It is a QUERY
10
+ * param on `createScreenshot`, distinct from scrape where `async` is a body field. `params` is
11
+ * optional and `async` omitted-when-absent: `create(opts)` with no second argument posts to the
12
+ * bare `/v1/screenshots` URL unchanged — existing single-arg callers are unaffected.
13
+ */
14
+ create(opts, params) {
15
+ const suffix = params?.async === true ? '?async=true' : '';
16
+ return this.client.request('POST', `/v1/screenshots${suffix}`, opts);
9
17
  }
10
18
  /**
11
19
  * GET /v1/screenshots/{id} — poll a screenshot by ID.
@@ -1,8 +1,8 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit } from '../client.js';
2
2
  import type { SearchOpts, SearchResponse } from '../types.js';
3
3
  export declare class SearchResource {
4
4
  private readonly client;
5
- constructor(client: RapidCrawl);
5
+ constructor(client: ByteKit);
6
6
  /** POST /v1/search — run a web search and return ranked organic results. */
7
7
  query(opts: SearchOpts): Promise<SearchResponse>;
8
8
  }
@@ -1,10 +1,17 @@
1
- import type { RapidCrawl } from '../client.js';
1
+ import type { ByteKit } from '../client.js';
2
+ import type { operations } from '../generated/api.js';
2
3
  import type { SitemapId } from '../types.js';
4
+ /** Body of POST /v1/sitemap. */
5
+ export type SitemapCreateRequest = operations['createSitemap']['requestBody']['content']['application/json'];
6
+ /** 202 payload of POST /v1/sitemap — sitemap crawls are always async. */
7
+ export type SitemapCreateResponse = operations['createSitemap']['responses'][202]['content']['application/json'];
8
+ /** 200 payload of GET /v1/sitemap/{id}. */
9
+ export type SitemapGetResponse = operations['getSitemap']['responses'][200]['content']['application/json'];
3
10
  export declare class SitemapResource {
4
11
  private readonly client;
5
- constructor(client: RapidCrawl);
12
+ constructor(client: ByteKit);
6
13
  /** POST /v1/sitemap — start a sitemap crawl */
7
- create(opts: Record<string, unknown>): Promise<unknown>;
14
+ create(opts: SitemapCreateRequest): Promise<SitemapCreateResponse>;
8
15
  /** GET /v1/sitemap/{id} — get a sitemap job by ID */
9
- get(id: SitemapId): Promise<unknown>;
16
+ get(id: SitemapId): Promise<SitemapGetResponse>;
10
17
  }
@@ -0,0 +1,31 @@
1
+ import type { ByteKit } from '../client.js';
2
+ import type { operations } from '../generated/api.js';
3
+ /** 200 payload of GET /v1/usage — current billing period usage summary. */
4
+ export type GetUsageResponse = operations['getUsage']['responses'][200]['content']['application/json'];
5
+ /**
6
+ * Query params of GET /v1/usage/daily.
7
+ * Derived from the generated OpenAPI types so it stays in sync with the spec.
8
+ */
9
+ export type GetUsageDailyParams = NonNullable<operations['getUsageDaily']['parameters']['query']>;
10
+ /** 200 payload of GET /v1/usage/daily — per-day usage breakdown. */
11
+ export type GetUsageDailyResponse = operations['getUsageDaily']['responses'][200]['content']['application/json'];
12
+ /** Query params of GET /v1/usage/by-endpoint. */
13
+ export type GetUsageByEndpointParams = NonNullable<operations['getUsageByEndpoint']['parameters']['query']>;
14
+ /** 200 payload of GET /v1/usage/by-endpoint — per-endpoint bandwidth breakdown. */
15
+ export type GetUsageByEndpointResponse = operations['getUsageByEndpoint']['responses'][200]['content']['application/json'];
16
+ export declare class UsageResource {
17
+ private readonly client;
18
+ constructor(client: ByteKit);
19
+ /** GET /v1/usage — get current billing period usage. */
20
+ get(): Promise<GetUsageResponse>;
21
+ /**
22
+ * GET /v1/usage/daily — get daily usage breakdown.
23
+ * Default range is the last 30 days; max range is 366 days.
24
+ */
25
+ daily(params?: GetUsageDailyParams): Promise<GetUsageDailyResponse>;
26
+ /**
27
+ * GET /v1/usage/by-endpoint — get per-endpoint bandwidth breakdown.
28
+ * Default range is the last 30 days; max range is 366 days.
29
+ */
30
+ byEndpoint(params?: GetUsageByEndpointParams): Promise<GetUsageByEndpointResponse>;
31
+ }