@itsoltech/basal-client 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -1
- package/dist/cjs/batches.cjs +312 -0
- package/dist/cjs/batches.d.cts +214 -0
- package/dist/cjs/errors.cjs +97 -0
- package/dist/cjs/errors.d.cts +59 -0
- package/dist/cjs/index.cjs +131 -55
- package/dist/cjs/index.d.cts +23 -15
- package/dist/cjs/resources.cjs +206 -0
- package/dist/cjs/resources.d.cts +48 -0
- package/dist/esm/batches.d.ts +214 -0
- package/dist/esm/batches.js +300 -0
- package/dist/esm/errors.d.ts +59 -0
- package/dist/esm/errors.js +85 -0
- package/dist/esm/index.d.ts +23 -15
- package/dist/esm/index.js +114 -40
- package/dist/esm/resources.d.ts +48 -0
- package/dist/esm/resources.js +201 -0
- package/package.json +1 -1
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Batches = exports.Files = void 0;
|
|
4
|
+
const errors_cjs_1 = require("./errors.cjs");
|
|
5
|
+
const batches_cjs_1 = require("./batches.cjs");
|
|
6
|
+
const TERMINAL = new Set(batches_cjs_1.TERMINAL_BATCH_STATUSES);
|
|
7
|
+
const COMMON_KEYS = new Set(["endpoint", "completion_window", "metadata", "output_expires_after"]);
|
|
8
|
+
const MAX_TIMER_MS = 2_147_483_647;
|
|
9
|
+
function duration(value, fallback, name) {
|
|
10
|
+
if (value === undefined)
|
|
11
|
+
return fallback;
|
|
12
|
+
if (!Number.isFinite(value) || value <= 0 || value > MAX_TIMER_MS)
|
|
13
|
+
throw new TypeError(`${name} must be positive and at most ${MAX_TIMER_MS}`);
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
/** Resolves after `ms`, or rejects with `signal.reason` on abort; the timer and listener are always removed. */
|
|
17
|
+
function sleep(ms, signal) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
if (signal.aborted) {
|
|
20
|
+
reject(signal.reason);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const onAbort = () => { clearTimeout(timer); reject(signal.reason); };
|
|
24
|
+
const timer = setTimeout(() => { signal.removeEventListener("abort", onAbort); resolve(); }, ms);
|
|
25
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function expiresAfter(value) {
|
|
29
|
+
if (value === undefined || value === null)
|
|
30
|
+
return;
|
|
31
|
+
if (typeof value !== "object" || value.anchor !== "created_at" || !Number.isSafeInteger(value.seconds) || value.seconds < 0) {
|
|
32
|
+
throw new TypeError("output_expires_after needs anchor created_at and whole seconds");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Common parameters of the `requests` form, checked before the upload so a local mistake leaves no orphan file.
|
|
36
|
+
* Metadata limits stay with the server, as in `createBatch`.
|
|
37
|
+
*/
|
|
38
|
+
function commonParams(params) {
|
|
39
|
+
for (const [key, value] of Object.entries(params)) {
|
|
40
|
+
if (value !== undefined && key !== "requests" && !COMMON_KEYS.has(key))
|
|
41
|
+
throw new TypeError(`unsupported batch parameter ${JSON.stringify(key)}`);
|
|
42
|
+
}
|
|
43
|
+
const { endpoint, completion_window, metadata, output_expires_after } = params;
|
|
44
|
+
if (endpoint !== undefined && endpoint !== "/v1/basal")
|
|
45
|
+
throw new TypeError("endpoint must be /v1/basal");
|
|
46
|
+
if (completion_window !== undefined && completion_window !== "24h")
|
|
47
|
+
throw new TypeError("completion_window must be 24h");
|
|
48
|
+
if (metadata !== undefined && metadata !== null) {
|
|
49
|
+
if (typeof metadata !== "object" || Array.isArray(metadata) || Object.values(metadata).some(v => typeof v !== "string")) {
|
|
50
|
+
throw new TypeError("metadata must be an object of string values");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
expiresAfter(output_expires_after);
|
|
54
|
+
const common = {};
|
|
55
|
+
for (const key of COMMON_KEYS)
|
|
56
|
+
if (params[key] !== undefined)
|
|
57
|
+
Object.assign(common, { [key]: params[key] });
|
|
58
|
+
return common;
|
|
59
|
+
}
|
|
60
|
+
function randomKey() {
|
|
61
|
+
const random = new Uint8Array(16);
|
|
62
|
+
globalThis.crypto.getRandomValues(random);
|
|
63
|
+
return `basal-sdk-${Array.from(random, b => b.toString(16).padStart(2, "0")).join("")}`;
|
|
64
|
+
}
|
|
65
|
+
/** `client.files`: resource names for the flat Files methods, with the same behavior. */
|
|
66
|
+
class Files {
|
|
67
|
+
#client;
|
|
68
|
+
constructor(client) { this.#client = client; }
|
|
69
|
+
/** `uploadFile`. */
|
|
70
|
+
create(request, options = {}) { return this.#client.uploadFile(request, options); }
|
|
71
|
+
/** `getFile`. */
|
|
72
|
+
retrieve(fileId, options = {}) { return this.#client.getFile(fileId, options); }
|
|
73
|
+
/** `listFiles`. */
|
|
74
|
+
list(options = {}) { return this.#client.listFiles(options); }
|
|
75
|
+
/** `deleteFile`. */
|
|
76
|
+
delete(fileId, options = {}) { return this.#client.deleteFile(fileId, options); }
|
|
77
|
+
/** `downloadFile`: raw bytes, buffered up to `maxBytes` (default `maxResponseBytes`). */
|
|
78
|
+
content(fileId, options = {}) { return this.#client.downloadFile(fileId, options); }
|
|
79
|
+
}
|
|
80
|
+
exports.Files = Files;
|
|
81
|
+
/** `client.batches`: resource names for the flat Batch methods plus `create({requests})`, `wait` and `results`.
|
|
82
|
+
* Nothing runs in the background and nothing is retried.
|
|
83
|
+
*/
|
|
84
|
+
class Batches {
|
|
85
|
+
#client;
|
|
86
|
+
constructor(client) { this.#client = client; }
|
|
87
|
+
/** `{input_file_id, ...}` is `createBatch`. `{requests, ...}` validates and writes the JSONL in memory, uploads it,
|
|
88
|
+
* then creates the batch with `idempotencyKey` (generated when omitted). A create failure after the upload raises
|
|
89
|
+
* `BasalBatchSubmissionError` with the file id and key; the file is kept.
|
|
90
|
+
*/
|
|
91
|
+
async create(params, options = {}) {
|
|
92
|
+
if (!params || typeof params !== "object")
|
|
93
|
+
throw new TypeError("batch parameters must be an object");
|
|
94
|
+
const fromFile = params.input_file_id !== undefined;
|
|
95
|
+
if (fromFile === (params.requests !== undefined))
|
|
96
|
+
throw new TypeError("pass exactly one of input_file_id or requests");
|
|
97
|
+
const { uploadTimeoutMs, ...createOptions } = options;
|
|
98
|
+
if (fromFile) {
|
|
99
|
+
if (uploadTimeoutMs !== undefined)
|
|
100
|
+
throw new TypeError("uploadTimeoutMs applies only to requests");
|
|
101
|
+
return this.#client.createBatch(params, createOptions);
|
|
102
|
+
}
|
|
103
|
+
const common = commonParams(params);
|
|
104
|
+
const idempotencyKey = createOptions.idempotencyKey ?? randomKey();
|
|
105
|
+
(0, batches_cjs_1.idempotencyHeader)(idempotencyKey);
|
|
106
|
+
duration(uploadTimeoutMs, 1, "uploadTimeoutMs");
|
|
107
|
+
const content = (0, batches_cjs_1.serializeBatchRequests)(params.requests);
|
|
108
|
+
const transfer = {};
|
|
109
|
+
if (createOptions.signal !== undefined)
|
|
110
|
+
transfer.signal = createOptions.signal;
|
|
111
|
+
if (uploadTimeoutMs !== undefined)
|
|
112
|
+
transfer.timeoutMs = uploadTimeoutMs;
|
|
113
|
+
const file = await this.#client.uploadFile({ file: content, filename: "batch_input.jsonl" }, transfer);
|
|
114
|
+
if (!file || typeof file.id !== "string" || !file.id)
|
|
115
|
+
throw new errors_cjs_1.BasalProtocolError("Basal upload response has no file id");
|
|
116
|
+
try {
|
|
117
|
+
return await this.#client.createBatch({ ...common, input_file_id: file.id }, { ...createOptions, idempotencyKey });
|
|
118
|
+
}
|
|
119
|
+
catch (cause) {
|
|
120
|
+
throw new errors_cjs_1.BasalBatchSubmissionError(file, idempotencyKey, { cause });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** `getBatch`. */
|
|
124
|
+
retrieve(batchId, options = {}) { return this.#client.getBatch(batchId, options); }
|
|
125
|
+
/** `listBatches`. */
|
|
126
|
+
list(options = {}) { return this.#client.listBatches(options); }
|
|
127
|
+
/** `cancelBatch`: requests cancellation and returns without waiting. */
|
|
128
|
+
cancel(batchId, options = {}) { return this.#client.cancelBatch(batchId, options); }
|
|
129
|
+
/** Retrieve until the status is `completed`, `failed`, `expired` or `cancelled` and return that batch (check
|
|
130
|
+
* `status`, `errors` and `request_counts`). The first retrieve is immediate. `timeoutMs` bounds the whole wait,
|
|
131
|
+
* aborting an in-flight retrieve, and raises `BasalBatchTimeoutError` without cancelling the batch. HTTP and
|
|
132
|
+
* transport errors propagate without retries; an abort rejects with `BasalTransportError` (cause: the reason).
|
|
133
|
+
*/
|
|
134
|
+
async wait(batchId, options = {}) {
|
|
135
|
+
(0, batches_cjs_1.resourcePath)("v1/batches", batchId);
|
|
136
|
+
const timeoutMs = duration(options.timeoutMs, 600_000, "timeoutMs");
|
|
137
|
+
const pollIntervalMs = duration(options.pollIntervalMs, 5_000, "pollIntervalMs");
|
|
138
|
+
const { signal } = options;
|
|
139
|
+
const controller = new AbortController();
|
|
140
|
+
const forward = () => controller.abort(signal?.reason);
|
|
141
|
+
signal?.addEventListener("abort", forward, { once: true });
|
|
142
|
+
if (signal?.aborted)
|
|
143
|
+
forward();
|
|
144
|
+
const expired = new Error("Basal batch wait timed out");
|
|
145
|
+
// Timers use a monotonic clock, so wall-clock changes do not move the deadline.
|
|
146
|
+
const timer = setTimeout(() => controller.abort(expired), timeoutMs);
|
|
147
|
+
let last = null;
|
|
148
|
+
try {
|
|
149
|
+
for (;;) {
|
|
150
|
+
try {
|
|
151
|
+
last = await this.#client.getBatch(batchId, { signal: controller.signal });
|
|
152
|
+
if (TERMINAL.has(last.status))
|
|
153
|
+
return last;
|
|
154
|
+
await sleep(pollIntervalMs, controller.signal);
|
|
155
|
+
}
|
|
156
|
+
catch (cause) {
|
|
157
|
+
if (controller.signal.reason === expired && (cause === expired || cause instanceof errors_cjs_1.BasalTransportError)) {
|
|
158
|
+
throw new errors_cjs_1.BasalBatchTimeoutError(batchId, last, timeoutMs, { cause });
|
|
159
|
+
}
|
|
160
|
+
if (controller.signal.aborted && cause === controller.signal.reason) {
|
|
161
|
+
throw new errors_cjs_1.BasalTransportError("Basal batch wait aborted", { cause });
|
|
162
|
+
}
|
|
163
|
+
throw cause;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
clearTimeout(timer);
|
|
169
|
+
signal?.removeEventListener("abort", forward);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/** Records of a finished batch: the output file, then the error file (once if both ids are equal). Does not wait:
|
|
173
|
+
* a non-terminal batch raises `BasalBatchNotReadyError`. Expired and cancelled batches yield their partial results;
|
|
174
|
+
* a completed batch can yield failed records. Batch-level validation errors are in `retrieve`/`wait`, not here.
|
|
175
|
+
* Each file is downloaded whole (bounded by `maxBytes`) and parsed one line at a time; a malformed line raises
|
|
176
|
+
* `BasalBatchResultError` after the earlier records were yielded.
|
|
177
|
+
*/
|
|
178
|
+
results(batchId, options = {}) {
|
|
179
|
+
(0, batches_cjs_1.resourcePath)("v1/batches", batchId);
|
|
180
|
+
duration(options.timeoutMs, 1, "timeoutMs");
|
|
181
|
+
if (options.maxBytes !== undefined && (!Number.isSafeInteger(options.maxBytes) || options.maxBytes <= 0)) {
|
|
182
|
+
throw new TypeError("maxBytes must be a positive safe integer");
|
|
183
|
+
}
|
|
184
|
+
return this.#results(batchId, options);
|
|
185
|
+
}
|
|
186
|
+
async *#results(batchId, options) {
|
|
187
|
+
const request = options.signal === undefined ? {} : { signal: options.signal };
|
|
188
|
+
const batch = await this.#client.getBatch(batchId, request);
|
|
189
|
+
if (!TERMINAL.has(batch.status))
|
|
190
|
+
throw new errors_cjs_1.BasalBatchNotReadyError(batchId, batch);
|
|
191
|
+
const ids = [];
|
|
192
|
+
for (const id of [batch.output_file_id, batch.error_file_id]) {
|
|
193
|
+
if (id === null || id === undefined)
|
|
194
|
+
continue;
|
|
195
|
+
if (typeof id !== "string" || !id)
|
|
196
|
+
throw new errors_cjs_1.BasalProtocolError("Basal batch has an invalid result file id");
|
|
197
|
+
if (!ids.includes(id))
|
|
198
|
+
ids.push(id);
|
|
199
|
+
}
|
|
200
|
+
for (const fileId of ids) {
|
|
201
|
+
const content = await this.#client.downloadFile(fileId, options);
|
|
202
|
+
yield* (0, batches_cjs_1.readBatchResultLines)(content, fileId);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
exports.Batches = Batches;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type Batch, type BatchCreateOptions, type BatchCreateParams, type BatchList, type BatchResultLine, type BatchResultsOptions, type BatchWaitOptions, type DeletedFile, type DownloadOptions, type FileList, type FileObject, type ListFilesOptions, type ListOptions, type RequestOptions, type TransferOptions, type UploadFileRequest } from "./batches.cjs";
|
|
2
|
+
import type { BasalClient } from "./index.cjs";
|
|
3
|
+
/** `client.files`: resource names for the flat Files methods, with the same behavior. */
|
|
4
|
+
export declare class Files {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(client: BasalClient);
|
|
7
|
+
/** `uploadFile`. */
|
|
8
|
+
create(request: UploadFileRequest, options?: TransferOptions): Promise<FileObject>;
|
|
9
|
+
/** `getFile`. */
|
|
10
|
+
retrieve(fileId: string, options?: RequestOptions): Promise<FileObject>;
|
|
11
|
+
/** `listFiles`. */
|
|
12
|
+
list(options?: ListFilesOptions): Promise<FileList>;
|
|
13
|
+
/** `deleteFile`. */
|
|
14
|
+
delete(fileId: string, options?: RequestOptions): Promise<DeletedFile>;
|
|
15
|
+
/** `downloadFile`: raw bytes, buffered up to `maxBytes` (default `maxResponseBytes`). */
|
|
16
|
+
content(fileId: string, options?: DownloadOptions): Promise<Uint8Array>;
|
|
17
|
+
}
|
|
18
|
+
/** `client.batches`: resource names for the flat Batch methods plus `create({requests})`, `wait` and `results`.
|
|
19
|
+
* Nothing runs in the background and nothing is retried.
|
|
20
|
+
*/
|
|
21
|
+
export declare class Batches {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(client: BasalClient);
|
|
24
|
+
/** `{input_file_id, ...}` is `createBatch`. `{requests, ...}` validates and writes the JSONL in memory, uploads it,
|
|
25
|
+
* then creates the batch with `idempotencyKey` (generated when omitted). A create failure after the upload raises
|
|
26
|
+
* `BasalBatchSubmissionError` with the file id and key; the file is kept.
|
|
27
|
+
*/
|
|
28
|
+
create(params: BatchCreateParams, options?: BatchCreateOptions): Promise<Batch>;
|
|
29
|
+
/** `getBatch`. */
|
|
30
|
+
retrieve(batchId: string, options?: RequestOptions): Promise<Batch>;
|
|
31
|
+
/** `listBatches`. */
|
|
32
|
+
list(options?: ListOptions): Promise<BatchList>;
|
|
33
|
+
/** `cancelBatch`: requests cancellation and returns without waiting. */
|
|
34
|
+
cancel(batchId: string, options?: RequestOptions): Promise<Batch>;
|
|
35
|
+
/** Retrieve until the status is `completed`, `failed`, `expired` or `cancelled` and return that batch (check
|
|
36
|
+
* `status`, `errors` and `request_counts`). The first retrieve is immediate. `timeoutMs` bounds the whole wait,
|
|
37
|
+
* aborting an in-flight retrieve, and raises `BasalBatchTimeoutError` without cancelling the batch. HTTP and
|
|
38
|
+
* transport errors propagate without retries; an abort rejects with `BasalTransportError` (cause: the reason).
|
|
39
|
+
*/
|
|
40
|
+
wait(batchId: string, options?: BatchWaitOptions): Promise<Batch>;
|
|
41
|
+
/** Records of a finished batch: the output file, then the error file (once if both ids are equal). Does not wait:
|
|
42
|
+
* a non-terminal batch raises `BasalBatchNotReadyError`. Expired and cancelled batches yield their partial results;
|
|
43
|
+
* a completed batch can yield failed records. Batch-level validation errors are in `retrieve`/`wait`, not here.
|
|
44
|
+
* Each file is downloaded whole (bounded by `maxBytes`) and parsed one line at a time; a malformed line raises
|
|
45
|
+
* `BasalBatchResultError` after the earlier records were yielded.
|
|
46
|
+
*/
|
|
47
|
+
results(batchId: string, options?: BatchResultsOptions): AsyncGenerator<BatchResultLine, void, undefined>;
|
|
48
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { DecisionRequest, JsonValue } from "./index.js";
|
|
2
|
+
/** Batch and Files wire types (`contracts/batches/openapi.json`). Times are Unix seconds.
|
|
3
|
+
* Unknown response fields are preserved at runtime; `(string & {})` keeps enums open to future server values.
|
|
4
|
+
*/
|
|
5
|
+
export type FilePurpose = "batch" | "batch_output";
|
|
6
|
+
export interface FileObject {
|
|
7
|
+
id: string;
|
|
8
|
+
object: "file";
|
|
9
|
+
bytes: number;
|
|
10
|
+
created_at: number;
|
|
11
|
+
expires_at: number | null;
|
|
12
|
+
/** As uploaded, or `batch_<id>_output.jsonl` / `batch_<id>_error.jsonl` for results; never a server path. */
|
|
13
|
+
filename: string;
|
|
14
|
+
purpose: FilePurpose | (string & {});
|
|
15
|
+
/** Always `processed` (OpenAI compatibility). */
|
|
16
|
+
status: "processed" | (string & {});
|
|
17
|
+
status_details: string | null;
|
|
18
|
+
}
|
|
19
|
+
export interface DeletedFile {
|
|
20
|
+
id: string;
|
|
21
|
+
object: "file";
|
|
22
|
+
deleted: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface ListPage<T> {
|
|
25
|
+
object: "list";
|
|
26
|
+
data: T[];
|
|
27
|
+
first_id: string | null;
|
|
28
|
+
last_id: string | null;
|
|
29
|
+
has_more: boolean;
|
|
30
|
+
}
|
|
31
|
+
export type FileList = ListPage<FileObject>;
|
|
32
|
+
export type BatchList = ListPage<Batch>;
|
|
33
|
+
/** At most 16 pairs, keys of 1–64 and values of up to 512 characters, in insertion order (checked by the server).
|
|
34
|
+
* JavaScript enumerates integer-like keys first; use textual keys when order matters.
|
|
35
|
+
*/
|
|
36
|
+
export type Metadata = Record<string, string>;
|
|
37
|
+
export interface ExpiresAfter {
|
|
38
|
+
anchor: "created_at";
|
|
39
|
+
seconds: number;
|
|
40
|
+
}
|
|
41
|
+
export type BatchStatus = "validating" | "failed" | "in_progress" | "finalizing" | "completed" | "expired" | "cancelling" | "cancelled";
|
|
42
|
+
export type BatchErrorCode = "empty_file" | "empty_line" | "invalid_json_line" | "line_too_large" | "too_many_records" | "invalid_custom_id" | "duplicate_custom_id" | "invalid_method" | "invalid_url" | "stream_unsupported" | "invalid_body" | "model_not_found" | "mixed_models" | "budget_exceeded" | "host_budget_exceeded" | "unbounded_feature" | "input_changed" | "batch_expired" | "errors_truncated";
|
|
43
|
+
export interface RequestCounts {
|
|
44
|
+
total: number;
|
|
45
|
+
completed: number;
|
|
46
|
+
failed: number;
|
|
47
|
+
}
|
|
48
|
+
export interface BatchErrorEntry {
|
|
49
|
+
code: BatchErrorCode | (string & {});
|
|
50
|
+
message: string;
|
|
51
|
+
param: string | null;
|
|
52
|
+
line: number | null;
|
|
53
|
+
}
|
|
54
|
+
export interface BatchErrors {
|
|
55
|
+
object: "list";
|
|
56
|
+
data: BatchErrorEntry[];
|
|
57
|
+
}
|
|
58
|
+
export interface Batch {
|
|
59
|
+
id: string;
|
|
60
|
+
object: "batch";
|
|
61
|
+
endpoint: "/v1/basal" | (string & {});
|
|
62
|
+
model: string | null;
|
|
63
|
+
errors: BatchErrors | null;
|
|
64
|
+
input_file_id: string;
|
|
65
|
+
completion_window: "24h" | (string & {});
|
|
66
|
+
status: BatchStatus | (string & {});
|
|
67
|
+
output_file_id: string | null;
|
|
68
|
+
error_file_id: string | null;
|
|
69
|
+
created_at: number;
|
|
70
|
+
in_progress_at: number | null;
|
|
71
|
+
/** End of the 24h inference window; export may finish later. */
|
|
72
|
+
expires_at: number;
|
|
73
|
+
finalizing_at: number | null;
|
|
74
|
+
completed_at: number | null;
|
|
75
|
+
failed_at: number | null;
|
|
76
|
+
expired_at: number | null;
|
|
77
|
+
cancelling_at: number | null;
|
|
78
|
+
cancelled_at: number | null;
|
|
79
|
+
request_counts: RequestCounts;
|
|
80
|
+
metadata: Metadata | null;
|
|
81
|
+
}
|
|
82
|
+
/** `POST /v1/batches` body. `endpoint` and `completion_window` default to their only accepted values. */
|
|
83
|
+
export interface CreateBatchRequest {
|
|
84
|
+
input_file_id: string;
|
|
85
|
+
endpoint?: "/v1/basal";
|
|
86
|
+
completion_window?: "24h";
|
|
87
|
+
metadata?: Metadata | null;
|
|
88
|
+
/** Lifetime of each result file, anchored at its creation. */
|
|
89
|
+
output_expires_after?: ExpiresAfter | null;
|
|
90
|
+
}
|
|
91
|
+
/** One line of an input file; `body` is the native `/v1/basal` request (see `buildRequest`). */
|
|
92
|
+
export interface BatchInputLine {
|
|
93
|
+
custom_id: string;
|
|
94
|
+
method?: "POST";
|
|
95
|
+
url?: "/v1/basal";
|
|
96
|
+
body: DecisionRequest;
|
|
97
|
+
}
|
|
98
|
+
/** One line of a result file. `response.body` is the native answer: a `DecisionResponse` for status 200, otherwise
|
|
99
|
+
* the native error body. `error` is set when the record has no response (e.g. `batch_expired`, `result_too_large`).
|
|
100
|
+
*/
|
|
101
|
+
export interface BatchResultLine {
|
|
102
|
+
id: string;
|
|
103
|
+
custom_id: string;
|
|
104
|
+
response: {
|
|
105
|
+
status_code: number;
|
|
106
|
+
request_id: string;
|
|
107
|
+
body: {
|
|
108
|
+
[key: string]: JsonValue;
|
|
109
|
+
};
|
|
110
|
+
} | null;
|
|
111
|
+
error: {
|
|
112
|
+
code: string;
|
|
113
|
+
message: string;
|
|
114
|
+
} | null;
|
|
115
|
+
}
|
|
116
|
+
/** Common options of Batch and Files calls. */
|
|
117
|
+
export interface RequestOptions {
|
|
118
|
+
signal?: AbortSignal;
|
|
119
|
+
}
|
|
120
|
+
/** Upload and download options; `timeoutMs` replaces the client deadline for this call only. */
|
|
121
|
+
export interface TransferOptions extends RequestOptions {
|
|
122
|
+
timeoutMs?: number;
|
|
123
|
+
}
|
|
124
|
+
export interface DownloadOptions extends TransferOptions {
|
|
125
|
+
/** Byte cap of this download; defaults to the client's `maxResponseBytes`. The body is buffered in memory. */
|
|
126
|
+
maxBytes?: number;
|
|
127
|
+
}
|
|
128
|
+
export interface CreateBatchOptions extends RequestOptions {
|
|
129
|
+
/** 1–128 visible ASCII characters; a replay with the same request data returns the existing batch. */
|
|
130
|
+
idempotencyKey?: string;
|
|
131
|
+
}
|
|
132
|
+
export interface ListOptions extends RequestOptions {
|
|
133
|
+
after?: string;
|
|
134
|
+
limit?: number;
|
|
135
|
+
}
|
|
136
|
+
export interface ListFilesOptions extends ListOptions {
|
|
137
|
+
purpose?: FilePurpose;
|
|
138
|
+
}
|
|
139
|
+
/** Caller-owned upload content. The SDK never fetches URLs or reads paths; a stream is consumed and locked. */
|
|
140
|
+
export type UploadContent = Uint8Array | ArrayBuffer | Blob | ReadableStream<Uint8Array>;
|
|
141
|
+
export interface UploadFileRequest {
|
|
142
|
+
file: UploadContent;
|
|
143
|
+
/** 1–255 UTF-8 bytes without control characters or backslashes; stored as given, never used as a path. */
|
|
144
|
+
filename: string;
|
|
145
|
+
purpose?: "batch";
|
|
146
|
+
/** File lifetime (server default 30 days). */
|
|
147
|
+
expires_after?: ExpiresAfter;
|
|
148
|
+
}
|
|
149
|
+
/** Parameters shared by both `batches.create` forms. Defaults: `endpoint: "/v1/basal"`, `completion_window: "24h"`. */
|
|
150
|
+
export interface BatchCreateCommonParams {
|
|
151
|
+
endpoint?: "/v1/basal";
|
|
152
|
+
completion_window?: "24h";
|
|
153
|
+
metadata?: Metadata | null;
|
|
154
|
+
/** Lifetime of each result file, anchored at its creation. */
|
|
155
|
+
output_expires_after?: ExpiresAfter | null;
|
|
156
|
+
}
|
|
157
|
+
/** Create a batch from an uploaded input file; the same request as `createBatch`. */
|
|
158
|
+
export interface BatchCreateFromFileParams extends BatchCreateCommonParams {
|
|
159
|
+
input_file_id: string;
|
|
160
|
+
requests?: never;
|
|
161
|
+
}
|
|
162
|
+
/** Create a batch from records: the SDK writes JSONL in memory, uploads it (`purpose=batch`), then creates the batch. */
|
|
163
|
+
export interface BatchCreateFromRequestsParams extends BatchCreateCommonParams {
|
|
164
|
+
/** 1–50 000 records, unique `custom_id` (1–256 UTF-8 bytes), at most 200 000 000 bytes of JSONL in total. */
|
|
165
|
+
requests: Iterable<BatchInputLine>;
|
|
166
|
+
input_file_id?: never;
|
|
167
|
+
}
|
|
168
|
+
/** Exactly one of `input_file_id` or `requests`. */
|
|
169
|
+
export type BatchCreateParams = BatchCreateFromFileParams | BatchCreateFromRequestsParams;
|
|
170
|
+
export interface BatchCreateOptions extends CreateBatchOptions {
|
|
171
|
+
/** Deadline of the input upload (`requests` form only); defaults to the client `timeoutMs`. */
|
|
172
|
+
uploadTimeoutMs?: number;
|
|
173
|
+
}
|
|
174
|
+
export interface BatchWaitOptions extends RequestOptions {
|
|
175
|
+
/** Deadline of the whole wait, including in-flight retrieves and sleeps; default 600 000 ms. */
|
|
176
|
+
timeoutMs?: number;
|
|
177
|
+
/** Delay between retrieves; default 5000 ms. The first retrieve is immediate. */
|
|
178
|
+
pollIntervalMs?: number;
|
|
179
|
+
}
|
|
180
|
+
/** Each result file is downloaded whole into memory (up to `maxBytes`, default the client `maxResponseBytes`) and
|
|
181
|
+
* parsed one line at a time; `timeoutMs` is the deadline of each download.
|
|
182
|
+
*/
|
|
183
|
+
export type BatchResultsOptions = DownloadOptions;
|
|
184
|
+
/** Client-side bounds of `batches.create({requests})`, equal to the server defaults; a server may be configured lower. */
|
|
185
|
+
export declare const MAX_BATCH_REQUESTS = 50000;
|
|
186
|
+
export declare const MAX_BATCH_INPUT_BYTES = 200000000;
|
|
187
|
+
export declare const TERMINAL_BATCH_STATUSES: readonly BatchStatus[];
|
|
188
|
+
/** Path segment of a resource id. `.` and `..` would be resolved as dot segments by URL parsing. */
|
|
189
|
+
export declare function resourcePath(prefix: string, id: string, suffix?: string): string;
|
|
190
|
+
export declare function listPath(path: string, options: ListFilesOptions): string;
|
|
191
|
+
export declare function idempotencyHeader(key: string | undefined): Record<string, string>;
|
|
192
|
+
export declare function createBody(request: CreateBatchRequest): CreateBatchRequest;
|
|
193
|
+
/** A multipart body; a stream body is created per request and stops its source when `signal` aborts. */
|
|
194
|
+
export interface Multipart {
|
|
195
|
+
contentType: string;
|
|
196
|
+
body: Blob | ((signal: AbortSignal) => ReadableStream<Uint8Array>);
|
|
197
|
+
}
|
|
198
|
+
/** Multipart form of an upload: `expires_after[...]`, then `purpose`, then the file part last (the server reserves the
|
|
199
|
+
* upload session at the file part, so expiry fields must precede it).
|
|
200
|
+
*/
|
|
201
|
+
export declare function uploadForm(request: UploadFileRequest): Multipart;
|
|
202
|
+
/** JSONL input file of native records (`method` POST and `url` /v1/basal are filled in). Never sends anything. */
|
|
203
|
+
export declare function batchInput(lines: Iterable<BatchInputLine>): Uint8Array;
|
|
204
|
+
/** Parse downloaded result bytes (output or error file) into lines. Never fetches anything. */
|
|
205
|
+
export declare function parseBatchResults(content: Uint8Array): BatchResultLine[];
|
|
206
|
+
/** Validated JSONL of `batches.create({requests})`: nonempty, supported envelope, unique ids and the bounds above.
|
|
207
|
+
* The result is held in memory (at most `MAX_BATCH_INPUT_BYTES`). Never sends anything.
|
|
208
|
+
*/
|
|
209
|
+
export declare function serializeBatchRequests(requests: Iterable<BatchInputLine>): Blob;
|
|
210
|
+
/** Result lines of one downloaded file, decoded and checked one line at a time (no list of all lines). A final LF is
|
|
211
|
+
* optional; any other empty line, invalid UTF-8 (a BOM included), JSON or envelope raises `BasalBatchResultError`.
|
|
212
|
+
* Unknown fields are preserved.
|
|
213
|
+
*/
|
|
214
|
+
export declare function readBatchResultLines(content: Uint8Array, fileId: string): Generator<BatchResultLine, void, undefined>;
|