@genspark/sb-box 0.0.0-stage → 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,1167 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ AuthenticationError: () => AuthenticationError,
34
+ BackgroundCommand: () => BackgroundCommand,
35
+ ClientDisconnectedError: () => ClientDisconnectedError,
36
+ CommandTimeoutError: () => CommandTimeoutError,
37
+ Commands: () => Commands,
38
+ ConflictError: () => ConflictError,
39
+ DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
40
+ DiskLostError: () => DiskLostError,
41
+ Files: () => Files,
42
+ ForbiddenError: () => ForbiddenError,
43
+ InsufficientCreditsError: () => InsufficientCreditsError,
44
+ InterpreterStartFailedError: () => InterpreterStartFailedError,
45
+ InterpreterUnavailableError: () => InterpreterUnavailableError,
46
+ LimitError: () => LimitError,
47
+ MemoryExpiredError: () => MemoryExpiredError,
48
+ NotFoundError: () => NotFoundError,
49
+ PlanRequiredError: () => PlanRequiredError,
50
+ Pty: () => Pty,
51
+ PtySession: () => PtySession,
52
+ PtyWebSocket: () => PtyWebSocket,
53
+ RegionRetiredError: () => RegionRetiredError,
54
+ SDK_VERSION: () => SDK_VERSION,
55
+ Sandbox: () => Sandbox,
56
+ Sandboxes: () => Sandboxes,
57
+ SbBox: () => SbBox,
58
+ SbBoxConnectionError: () => SbBoxConnectionError,
59
+ SbBoxError: () => SbBoxError,
60
+ ServerError: () => ServerError,
61
+ TemplateBuildError: () => TemplateBuildError,
62
+ Templates: () => Templates,
63
+ ValidationError: () => ValidationError,
64
+ WaitTimeoutError: () => WaitTimeoutError,
65
+ describeBody: () => describeBody,
66
+ errorFromResponse: () => errorFromResponse,
67
+ parseSse: () => parseSse,
68
+ redact: () => redact
69
+ });
70
+ module.exports = __toCommonJS(index_exports);
71
+
72
+ // src/errors.ts
73
+ var KEY_RE = /gsk-[A-Za-z0-9._-]+/g;
74
+ function redact(text) {
75
+ return text.replace(KEY_RE, "gsk-REDACTED");
76
+ }
77
+ var SbBoxError = class extends Error {
78
+ status;
79
+ code;
80
+ /** Parsed response body (or the raw text when it was not JSON). */
81
+ detail;
82
+ /** Seconds from a `Retry-After` header, when the server sent one. */
83
+ retryAfter;
84
+ requestId;
85
+ constructor(init) {
86
+ super(redact(init.message));
87
+ this.name = new.target.name;
88
+ this.status = init.status;
89
+ this.code = init.code;
90
+ this.detail = init.detail;
91
+ this.retryAfter = init.retryAfter;
92
+ this.requestId = init.requestId;
93
+ }
94
+ /** A named field from the error body (`plan`, `limit`, `balance`, `recovery`, …). */
95
+ field(name) {
96
+ const d = this.detail;
97
+ if (d && typeof d === "object") {
98
+ const o = d;
99
+ if (name in o) return o[name];
100
+ const inner = o.detail;
101
+ if (inner && typeof inner === "object" && name in inner) {
102
+ return inner[name];
103
+ }
104
+ }
105
+ return void 0;
106
+ }
107
+ };
108
+ var ValidationError = class extends SbBoxError {
109
+ };
110
+ var AuthenticationError = class extends SbBoxError {
111
+ };
112
+ var InsufficientCreditsError = class extends SbBoxError {
113
+ get balance() {
114
+ return this.field("balance");
115
+ }
116
+ };
117
+ var ForbiddenError = class extends SbBoxError {
118
+ };
119
+ var PlanRequiredError = class extends ForbiddenError {
120
+ get plan() {
121
+ return this.field("plan");
122
+ }
123
+ get upgrade() {
124
+ return this.field("upgrade");
125
+ }
126
+ };
127
+ var NotFoundError = class extends SbBoxError {
128
+ };
129
+ var RegionRetiredError = class extends NotFoundError {
130
+ get region() {
131
+ return this.field("region");
132
+ }
133
+ };
134
+ var CommandTimeoutError = class extends SbBoxError {
135
+ get killed() {
136
+ return this.field("killed") === true;
137
+ }
138
+ };
139
+ var ConflictError = class extends SbBoxError {
140
+ };
141
+ var LimitError = class extends ConflictError {
142
+ get plan() {
143
+ return this.field("plan");
144
+ }
145
+ get limit() {
146
+ return this.field("limit");
147
+ }
148
+ get current() {
149
+ return this.field("current");
150
+ }
151
+ get requested() {
152
+ return this.field("requested");
153
+ }
154
+ };
155
+ var InterpreterUnavailableError = class extends ConflictError {
156
+ };
157
+ var DiskLostError = class extends SbBoxError {
158
+ };
159
+ var MemoryExpiredError = class extends SbBoxError {
160
+ get recovery() {
161
+ return this.field("recovery") ?? [];
162
+ }
163
+ };
164
+ var ClientDisconnectedError = class extends SbBoxError {
165
+ };
166
+ var ServerError = class extends SbBoxError {
167
+ };
168
+ var InterpreterStartFailedError = class extends ServerError {
169
+ };
170
+ var SbBoxConnectionError = class extends SbBoxError {
171
+ constructor(message, cause) {
172
+ super({ status: 0, message });
173
+ if (cause !== void 0) this.cause = cause;
174
+ }
175
+ };
176
+ var TemplateBuildError = class extends SbBoxError {
177
+ templateId;
178
+ buildError;
179
+ constructor(templateId, buildError, detail) {
180
+ super({ status: 0, message: `template ${templateId} build failed: ${buildError ?? "unknown error"}`, detail });
181
+ this.templateId = templateId;
182
+ this.buildError = buildError;
183
+ }
184
+ };
185
+ var WaitTimeoutError = class extends SbBoxError {
186
+ constructor(message) {
187
+ super({ status: 0, message });
188
+ }
189
+ };
190
+ function pick(obj, key) {
191
+ if (obj && typeof obj === "object" && key in obj) return obj[key];
192
+ return void 0;
193
+ }
194
+ function describeBody(body, fallback) {
195
+ if (typeof body === "string") return { message: body || fallback };
196
+ if (!body || typeof body !== "object") return { message: fallback };
197
+ const detail = pick(body, "detail");
198
+ if (typeof detail === "string") return { message: detail };
199
+ if (detail && typeof detail === "object") {
200
+ const code2 = pick(detail, "code");
201
+ const msg = pick(detail, "message") ?? pick(detail, "error");
202
+ return { code: typeof code2 === "string" ? code2 : void 0, message: typeof msg === "string" ? msg : JSON.stringify(detail) };
203
+ }
204
+ const err = pick(body, "error");
205
+ if (typeof err === "string") {
206
+ const code2 = pick(body, "code");
207
+ return { code: typeof code2 === "string" ? code2 : void 0, message: err };
208
+ }
209
+ const reason = pick(body, "reason");
210
+ if (typeof reason === "string") {
211
+ const rec = pick(body, "recovery");
212
+ return { code: reason, message: Array.isArray(rec) ? `${reason} (recovery: ${rec.join(", ")})` : reason };
213
+ }
214
+ const message = pick(body, "message");
215
+ if (typeof message === "string") {
216
+ const errors = pick(body, "errors");
217
+ return { message: Array.isArray(errors) && errors.length ? `${message}: ${JSON.stringify(errors)}` : message };
218
+ }
219
+ const code = pick(body, "code");
220
+ return { code: typeof code === "string" ? code : void 0, message: fallback };
221
+ }
222
+ function errorFromResponse(status, body, headers) {
223
+ const { code, message } = describeBody(body, `HTTP ${status}`);
224
+ const ra = headers.get("retry-after");
225
+ const retryAfter = ra != null && ra !== "" && !Number.isNaN(Number(ra)) ? Number(ra) : void 0;
226
+ const init = {
227
+ status,
228
+ code,
229
+ message,
230
+ detail: body,
231
+ retryAfter,
232
+ requestId: headers.get("x-request-id") ?? void 0
233
+ };
234
+ switch (status) {
235
+ case 400:
236
+ case 422:
237
+ return new ValidationError(init);
238
+ case 401:
239
+ return new AuthenticationError(init);
240
+ case 402:
241
+ return new InsufficientCreditsError(init);
242
+ case 403:
243
+ return code === "sb_box_plan_required" ? new PlanRequiredError(init) : new ForbiddenError(init);
244
+ case 404:
245
+ return code === "sb_box_region_retired" ? new RegionRetiredError(init) : new NotFoundError(init);
246
+ case 408:
247
+ return new CommandTimeoutError(init);
248
+ case 409:
249
+ if (code && code.endsWith("_limit")) return new LimitError(init);
250
+ if (code === "sb_box_interpreter_unavailable") return new InterpreterUnavailableError(init);
251
+ return new ConflictError(init);
252
+ case 410:
253
+ return new DiskLostError(init);
254
+ case 428:
255
+ return new MemoryExpiredError(init);
256
+ case 499:
257
+ return new ClientDisconnectedError(init);
258
+ case 502:
259
+ return code === "sb_box_interpreter_start_failed" ? new InterpreterStartFailedError(init) : new ServerError(init);
260
+ default:
261
+ return status >= 500 ? new ServerError(init) : new SbBoxError(init);
262
+ }
263
+ }
264
+
265
+ // src/http.ts
266
+ var SDK_VERSION = "0.1.0";
267
+ var DEFAULT_BASE_URL = "https://www.genspark.ai/api/sb-box/v1";
268
+ var BACKOFF_MS = [500, 1e3, 2e3];
269
+ function sleep(ms, signal) {
270
+ return new Promise((resolve, reject) => {
271
+ const t = setTimeout(resolve, ms);
272
+ signal?.addEventListener("abort", () => {
273
+ clearTimeout(t);
274
+ reject(signal.reason);
275
+ }, { once: true });
276
+ });
277
+ }
278
+ var Http = class {
279
+ opts;
280
+ constructor(opts) {
281
+ this.opts = opts;
282
+ }
283
+ url(path, query) {
284
+ const u = new URL(this.opts.baseUrl.replace(/\/+$/, "") + path);
285
+ if (query) {
286
+ for (const [k, v] of Object.entries(query)) {
287
+ if (v !== void 0 && v !== null && v !== "") u.searchParams.set(k, String(v));
288
+ }
289
+ }
290
+ return u.toString();
291
+ }
292
+ async request(path, opts = {}) {
293
+ const res = await this.send(path, { ...opts, raw: false });
294
+ return res;
295
+ }
296
+ async raw(path, opts = {}) {
297
+ return await this.send(path, { ...opts, raw: true });
298
+ }
299
+ async send(path, opts) {
300
+ const method = opts.method ?? "GET";
301
+ const headers = {
302
+ "X-Api-Key": this.opts.apiKey,
303
+ "User-Agent": this.opts.userAgent,
304
+ Accept: opts.raw ? "*/*" : "application/json",
305
+ ...opts.headers
306
+ };
307
+ let body;
308
+ if (opts.json !== void 0) {
309
+ headers["Content-Type"] = "application/json";
310
+ body = JSON.stringify(opts.json);
311
+ } else if (opts.body !== void 0) {
312
+ headers["Content-Type"] = opts.contentType ?? "application/octet-stream";
313
+ body = opts.body;
314
+ }
315
+ const url = this.url(path, opts.query);
316
+ const timeoutMs = (opts.timeout ?? this.opts.timeout) * 1e3;
317
+ const maxAttempts = opts.retry ? 1 + Math.max(0, this.opts.retries) : 1;
318
+ let attempt = 0;
319
+ while (true) {
320
+ attempt++;
321
+ const ac = new AbortController();
322
+ const onAbort = () => ac.abort(opts.signal?.reason);
323
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
324
+ const timer = setTimeout(() => ac.abort(new Error(`request timed out after ${timeoutMs / 1e3}s`)), timeoutMs);
325
+ let res;
326
+ try {
327
+ res = await this.opts.fetch(url, { method, headers, body, signal: ac.signal });
328
+ } catch (e) {
329
+ clearTimeout(timer);
330
+ opts.signal?.removeEventListener("abort", onAbort);
331
+ if (opts.signal?.aborted) throw e;
332
+ if (opts.retry && attempt < maxAttempts) {
333
+ await sleep(jitter(BACKOFF_MS[Math.min(attempt - 1, BACKOFF_MS.length - 1)]));
334
+ continue;
335
+ }
336
+ const msg = e instanceof Error ? e.message : String(e);
337
+ throw new SbBoxConnectionError(`${method} ${path}: ${redact(msg)}`, e);
338
+ }
339
+ if (opts.raw && res.ok) {
340
+ const release = () => {
341
+ clearTimeout(timer);
342
+ opts.signal?.removeEventListener("abort", onAbort);
343
+ };
344
+ if (opts.bodyDeadline === false || !res.body) {
345
+ release();
346
+ return res;
347
+ }
348
+ return withBodyDeadline(res, ac.signal, release, `${method} ${path}: stream timed out after ${timeoutMs / 1e3}s`);
349
+ }
350
+ if (res.ok) {
351
+ try {
352
+ return await this.parseBody(res);
353
+ } finally {
354
+ clearTimeout(timer);
355
+ opts.signal?.removeEventListener("abort", onAbort);
356
+ }
357
+ }
358
+ let parsed;
359
+ try {
360
+ parsed = await this.parseBody(res);
361
+ } catch {
362
+ parsed = void 0;
363
+ } finally {
364
+ clearTimeout(timer);
365
+ opts.signal?.removeEventListener("abort", onAbort);
366
+ }
367
+ const err = errorFromResponse(res.status, parsed, res.headers);
368
+ if (res.status === 503 && opts.retryOn503Until !== void 0) {
369
+ const waitMs = (err.retryAfter ?? 2) * 1e3;
370
+ if (Date.now() + waitMs <= opts.retryOn503Until) {
371
+ await sleep(waitMs, opts.signal);
372
+ continue;
373
+ }
374
+ }
375
+ if (opts.retry && attempt < maxAttempts && [502, 503, 504].includes(res.status)) {
376
+ await sleep(jitter(BACKOFF_MS[Math.min(attempt - 1, BACKOFF_MS.length - 1)]), opts.signal);
377
+ continue;
378
+ }
379
+ throw err;
380
+ }
381
+ }
382
+ async parseBody(res) {
383
+ const ct = res.headers.get("content-type") ?? "";
384
+ const text = await res.text();
385
+ if (!text) return void 0;
386
+ if (ct.includes("json")) {
387
+ try {
388
+ return JSON.parse(text);
389
+ } catch {
390
+ return text;
391
+ }
392
+ }
393
+ try {
394
+ return JSON.parse(text);
395
+ } catch {
396
+ return text;
397
+ }
398
+ }
399
+ };
400
+ function withBodyDeadline(res, signal, release, timeoutMsg) {
401
+ const reader = res.body.getReader();
402
+ const body = new ReadableStream({
403
+ async pull(controller) {
404
+ let chunk;
405
+ try {
406
+ chunk = await reader.read();
407
+ } catch (e) {
408
+ release();
409
+ const err = signal.aborted ? new SbBoxConnectionError(redact(timeoutMsg), e) : new SbBoxConnectionError(redact(e instanceof Error ? e.message : String(e)), e);
410
+ controller.error(err);
411
+ return;
412
+ }
413
+ if (chunk.done) {
414
+ release();
415
+ controller.close();
416
+ return;
417
+ }
418
+ controller.enqueue(chunk.value);
419
+ },
420
+ async cancel(reason) {
421
+ release();
422
+ await reader.cancel(reason).catch(() => void 0);
423
+ }
424
+ });
425
+ return new Response(body, { status: res.status, statusText: res.statusText, headers: res.headers });
426
+ }
427
+ function jitter(ms) {
428
+ return ms * (0.75 + Math.random() * 0.5);
429
+ }
430
+ function ensureStringMap(name, m) {
431
+ if (m === void 0) return void 0;
432
+ for (const [k, v] of Object.entries(m)) {
433
+ if (typeof v !== "string") {
434
+ throw new SbBoxError({ status: 0, message: `${name}.${k} must be a string (got ${typeof v})` });
435
+ }
436
+ }
437
+ return m;
438
+ }
439
+
440
+ // src/sse.ts
441
+ async function* parseSse(body) {
442
+ const reader = body.getReader();
443
+ const decoder = new TextDecoder();
444
+ let buf = "";
445
+ let event = "";
446
+ let data = [];
447
+ let id;
448
+ const flush = () => {
449
+ if (!event && data.length === 0) return void 0;
450
+ const msg = { event: event || "message", data: data.join("\n"), id };
451
+ event = "";
452
+ data = [];
453
+ id = void 0;
454
+ return msg;
455
+ };
456
+ try {
457
+ while (true) {
458
+ const { value, done } = await reader.read();
459
+ if (done) break;
460
+ buf += decoder.decode(value, { stream: true });
461
+ let nl;
462
+ while ((nl = buf.indexOf("\n")) >= 0) {
463
+ let line = buf.slice(0, nl);
464
+ buf = buf.slice(nl + 1);
465
+ if (line.endsWith("\r")) line = line.slice(0, -1);
466
+ if (line === "") {
467
+ const m2 = flush();
468
+ if (m2) yield m2;
469
+ continue;
470
+ }
471
+ if (line.startsWith(":")) continue;
472
+ const colon = line.indexOf(":");
473
+ const field = colon < 0 ? line : line.slice(0, colon);
474
+ let value2 = colon < 0 ? "" : line.slice(colon + 1);
475
+ if (value2.startsWith(" ")) value2 = value2.slice(1);
476
+ if (field === "event") event = value2;
477
+ else if (field === "data") data.push(value2);
478
+ else if (field === "id") id = value2;
479
+ }
480
+ }
481
+ buf += decoder.decode();
482
+ if (buf.trim()) {
483
+ const colon = buf.indexOf(":");
484
+ const field = colon < 0 ? buf : buf.slice(0, colon);
485
+ const value = colon < 0 ? "" : buf.slice(colon + 1).replace(/^ /, "");
486
+ if (field === "data") data.push(value);
487
+ else if (field === "event") event = value;
488
+ }
489
+ const m = flush();
490
+ if (m) yield m;
491
+ } finally {
492
+ reader.releaseLock();
493
+ }
494
+ }
495
+ function parseJsonData(msg) {
496
+ if (!msg.data) return void 0;
497
+ try {
498
+ return JSON.parse(msg.data);
499
+ } catch {
500
+ return void 0;
501
+ }
502
+ }
503
+
504
+ // src/sandbox.ts
505
+ var DEFAULT_SHELL = ["/bin/sh", "-c"];
506
+ function argv(command) {
507
+ if (typeof command === "string") return [...DEFAULT_SHELL, command];
508
+ if (!Array.isArray(command) || command.length === 0) throw new TypeError("command must be a non-empty argv array or a shell string");
509
+ return command;
510
+ }
511
+ function execBody(command, opts, withTimeout, max) {
512
+ const body = { command: argv(command) };
513
+ if (opts.cwd) body.cwd = opts.cwd;
514
+ const env2 = ensureStringMap("envVars", opts.envVars);
515
+ if (env2) body.envVars = env2;
516
+ if (opts.user) body.user = opts.user;
517
+ if (withTimeout) {
518
+ const t = opts.timeout ?? 60;
519
+ if (max !== void 0 && t > max) throw new RangeError(`timeout must be <= ${max} seconds`);
520
+ body.timeout = t;
521
+ }
522
+ return body;
523
+ }
524
+ async function* execEvents(res) {
525
+ if (!res.body) return;
526
+ let execId;
527
+ for await (const m of parseSse(res.body)) {
528
+ const d = parseJsonData(m) ?? {};
529
+ switch (m.event) {
530
+ case "execId":
531
+ execId = typeof d.execId === "string" ? d.execId : void 0;
532
+ break;
533
+ case "stdout":
534
+ case "stderr":
535
+ yield { kind: m.event, data: String(d.data ?? ""), execId };
536
+ break;
537
+ case "exit":
538
+ yield { kind: "exit", exitCode: Number(d.exitCode ?? 0), execId };
539
+ return;
540
+ case "error":
541
+ yield { kind: "error", data: String(d.error ?? m.data), stage: typeof d.stage === "string" ? d.stage : void 0, execId };
542
+ return;
543
+ default:
544
+ break;
545
+ }
546
+ }
547
+ }
548
+ var BackgroundCommand = class {
549
+ constructor(http, sandboxId, execId, pid) {
550
+ this.http = http;
551
+ this.sandboxId = sandboxId;
552
+ this.execId = execId;
553
+ this.pid = pid;
554
+ }
555
+ http;
556
+ sandboxId;
557
+ execId;
558
+ pid;
559
+ p(suffix) {
560
+ return `/sandboxes/${encodeURIComponent(this.sandboxId)}/commands/${encodeURIComponent(this.execId)}${suffix}`;
561
+ }
562
+ async input(data) {
563
+ const r = await this.http.request(this.p("/input"), { method: "POST", json: { data } });
564
+ return r.written;
565
+ }
566
+ async close() {
567
+ await this.http.request(this.p("/close"), { method: "POST" });
568
+ }
569
+ /** Block until the command exits; returns its exit code. `timeout` is seconds (default 600). */
570
+ async wait(timeout = 600) {
571
+ const r = await this.http.request(this.p("/wait"), { method: "POST", timeout: timeout + 30 });
572
+ return r.exitCode;
573
+ }
574
+ async kill(signal = 9) {
575
+ await this.http.request(`/sandboxes/${encodeURIComponent(this.sandboxId)}/commands/kill`, {
576
+ method: "POST",
577
+ json: { pid: this.pid, signal }
578
+ });
579
+ }
580
+ /** Stream the command's output. Resolves to an empty stream if the server already reaped it. */
581
+ async *connect() {
582
+ let res;
583
+ try {
584
+ res = await this.http.raw(this.p("/connect"), { headers: { Accept: "text/event-stream" }, timeout: 3600, bodyDeadline: false });
585
+ } catch (e) {
586
+ if (e instanceof NotFoundError) return;
587
+ throw e;
588
+ }
589
+ yield* execEvents(res);
590
+ }
591
+ };
592
+ var Commands = class {
593
+ constructor(http, sandboxId) {
594
+ this.http = http;
595
+ this.sandboxId = sandboxId;
596
+ }
597
+ http;
598
+ sandboxId;
599
+ p(suffix) {
600
+ return `/sandboxes/${encodeURIComponent(this.sandboxId)}/commands${suffix}`;
601
+ }
602
+ async start(command, opts = {}) {
603
+ const r = await this.http.request(this.p("/start"), {
604
+ method: "POST",
605
+ json: execBody(command, opts, false),
606
+ timeout: 120
607
+ });
608
+ return new BackgroundCommand(this.http, this.sandboxId, r.execId, r.pid);
609
+ }
610
+ async list() {
611
+ return this.http.request(this.p(""), { retry: true });
612
+ }
613
+ async kill(pid, signal = 9) {
614
+ await this.http.request(this.p("/kill"), { method: "POST", json: { pid, signal } });
615
+ }
616
+ async sendStdin(pid, data) {
617
+ await this.http.request(this.p("/send-stdin"), { method: "POST", json: { pid, data } });
618
+ }
619
+ };
620
+ var Files = class {
621
+ constructor(http, sandboxId) {
622
+ this.http = http;
623
+ this.sandboxId = sandboxId;
624
+ }
625
+ http;
626
+ sandboxId;
627
+ p(suffix) {
628
+ return `/sandboxes/${encodeURIComponent(this.sandboxId)}/files${suffix}`;
629
+ }
630
+ /** Write bytes (or a UTF-8 string). Returns the byte count written. */
631
+ async write(path, data, opts = {}) {
632
+ const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
633
+ const r = await this.http.request(this.p("/stream"), {
634
+ method: "POST",
635
+ body: bytes,
636
+ query: { path, user: opts.user },
637
+ timeout: 600
638
+ });
639
+ return r.written;
640
+ }
641
+ async read(path, opts = {}) {
642
+ const res = await this.http.raw(this.p("/stream"), { query: { path, user: opts.user }, timeout: 600, retry: true });
643
+ return new Uint8Array(await res.arrayBuffer());
644
+ }
645
+ async readText(path, opts = {}) {
646
+ const bytes = await this.read(path, opts);
647
+ return new TextDecoder(opts.encoding ?? "utf-8").decode(bytes);
648
+ }
649
+ async list(path = "/", opts = {}) {
650
+ return this.http.request(this.p("/list"), { query: { path, user: opts.user }, retry: true });
651
+ }
652
+ };
653
+ var PtySession = class {
654
+ constructor(http, sandboxId, execId, pid) {
655
+ this.http = http;
656
+ this.sandboxId = sandboxId;
657
+ this.execId = execId;
658
+ this.pid = pid;
659
+ }
660
+ http;
661
+ sandboxId;
662
+ execId;
663
+ pid;
664
+ p(suffix) {
665
+ return `/sandboxes/${encodeURIComponent(this.sandboxId)}/pty/${encodeURIComponent(this.execId)}${suffix}`;
666
+ }
667
+ async input(data) {
668
+ const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
669
+ await this.http.request(this.p("/input"), { method: "POST", body: bytes });
670
+ }
671
+ async resize(rows, cols) {
672
+ await this.http.request(this.p("/resize"), { method: "POST", json: { rows, cols } });
673
+ }
674
+ async kill() {
675
+ await this.http.request(this.p("/kill"), { method: "POST" });
676
+ }
677
+ /** Stream terminal output (SSE). Ends with a `exit` event. */
678
+ async *connect() {
679
+ const res = await this.http.raw(this.p("/connect"), { headers: { Accept: "text/event-stream" }, timeout: 3600, bodyDeadline: false });
680
+ if (!res.body) return;
681
+ for await (const m of parseSse(res.body)) {
682
+ const d = parseJsonData(m) ?? {};
683
+ if (m.event === "data") yield { kind: "data", data: String(d.data ?? "") };
684
+ else if (m.event === "exit") {
685
+ yield { kind: "exit", exitCode: d.exitCode === void 0 ? void 0 : Number(d.exitCode), reason: typeof d.reason === "string" ? d.reason : void 0 };
686
+ return;
687
+ }
688
+ }
689
+ }
690
+ };
691
+ var PtyWebSocket = class {
692
+ constructor(ws) {
693
+ this.ws = ws;
694
+ }
695
+ ws;
696
+ input(data) {
697
+ this.ws.send(JSON.stringify({ type: "stdin", data }));
698
+ }
699
+ resize(rows, cols) {
700
+ this.ws.send(JSON.stringify({ type: "resize", rows, cols }));
701
+ }
702
+ kill() {
703
+ this.ws.send(JSON.stringify({ type: "kill" }));
704
+ }
705
+ close() {
706
+ this.ws.close();
707
+ }
708
+ };
709
+ var Pty = class {
710
+ constructor(http, sandboxId) {
711
+ this.http = http;
712
+ this.sandboxId = sandboxId;
713
+ }
714
+ http;
715
+ sandboxId;
716
+ async open(opts = {}) {
717
+ const json = {
718
+ command: opts.command ?? ["/bin/bash"],
719
+ rows: opts.rows ?? 24,
720
+ cols: opts.cols ?? 80
721
+ };
722
+ if (opts.cwd) json.cwd = opts.cwd;
723
+ const env2 = ensureStringMap("envVars", opts.envVars);
724
+ if (env2) json.envVars = env2;
725
+ const r = await this.http.request(
726
+ `/sandboxes/${encodeURIComponent(this.sandboxId)}/pty`,
727
+ { method: "POST", json, timeout: 120 }
728
+ );
729
+ return new PtySession(this.http, this.sandboxId, r.execId, r.pid);
730
+ }
731
+ /**
732
+ * Open a terminal over WebSocket. Uses the global `WebSocket` (Node 22+, browsers) or the
733
+ * optional `ws` package. Resolves once the socket is open and the start frame is sent.
734
+ */
735
+ async connectWs(opts = {}, handlers = {}) {
736
+ const url = new URL(this.http.url(`/sandboxes/${encodeURIComponent(this.sandboxId)}/ws/pty`));
737
+ url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
738
+ const headers = { "X-Api-Key": this.http.opts.apiKey, "User-Agent": this.http.opts.userAgent };
739
+ let ws;
740
+ const G = globalThis;
741
+ if (G.WebSocket) {
742
+ url.searchParams.set("api_key", this.http.opts.apiKey);
743
+ ws = new G.WebSocket(url.toString());
744
+ } else {
745
+ let mod;
746
+ try {
747
+ mod = await import("ws");
748
+ } catch {
749
+ throw new SbBoxError({ status: 0, message: "pty.connectWs needs a WebSocket implementation: upgrade to Node 22+ or `npm install ws`" });
750
+ }
751
+ const Ctor = mod.default ?? mod.WebSocket;
752
+ ws = new Ctor(url.toString(), { headers });
753
+ }
754
+ await new Promise((resolve, reject) => {
755
+ ws.addEventListener("open", () => resolve());
756
+ ws.addEventListener("error", (ev) => reject(new SbBoxError({ status: 0, message: `pty websocket error: ${ev.message ?? "connection failed"}` })));
757
+ });
758
+ const start = {};
759
+ if (opts.command) start.command = opts.command;
760
+ if (opts.cwd) start.cwd = opts.cwd;
761
+ if (opts.rows) start.rows = opts.rows;
762
+ if (opts.cols) start.cols = opts.cols;
763
+ if (opts.envVars) start.envVars = ensureStringMap("envVars", opts.envVars);
764
+ ws.send(JSON.stringify(start));
765
+ ws.addEventListener("message", (ev) => {
766
+ let frame;
767
+ try {
768
+ frame = JSON.parse(String(ev.data));
769
+ } catch {
770
+ return;
771
+ }
772
+ if (frame.type === "stdout") handlers.onData?.(String(frame.data ?? ""), typeof frame.seq === "number" ? frame.seq : void 0);
773
+ else if (frame.type === "exit") handlers.onExit?.(Number(frame.exitCode ?? 0));
774
+ else if (frame.type === "error") handlers.onError?.(String(frame.error ?? ""));
775
+ });
776
+ return new PtyWebSocket(ws);
777
+ }
778
+ };
779
+ var Sandbox = class _Sandbox {
780
+ constructor(http, info) {
781
+ this.http = http;
782
+ this._info = info;
783
+ this.commands = new Commands(http, info.id);
784
+ this.files = new Files(http, info.id);
785
+ this.pty = new Pty(http, info.id);
786
+ }
787
+ http;
788
+ commands;
789
+ files;
790
+ pty;
791
+ _info;
792
+ /** The last record seen for this sandbox (call `refresh()` to update). */
793
+ get info() {
794
+ return this._info;
795
+ }
796
+ get id() {
797
+ return this._info.id;
798
+ }
799
+ get state() {
800
+ return this._info.state;
801
+ }
802
+ get templateId() {
803
+ return this._info.templateId ?? this._info.template_id;
804
+ }
805
+ get region() {
806
+ return this._info.region;
807
+ }
808
+ get metadata() {
809
+ return this._info.metadata ?? {};
810
+ }
811
+ get versions() {
812
+ return this._info.versions ?? [];
813
+ }
814
+ get createdAt() {
815
+ return this._info.createdAt ?? this._info.created_at;
816
+ }
817
+ get frozenAt() {
818
+ return this._info.frozenAt;
819
+ }
820
+ get timeoutAt() {
821
+ return this._info.timeoutAt;
822
+ }
823
+ /** Token to reach a sandbox created with `allowPublicTraffic: false` (create response only). */
824
+ get trafficAccessToken() {
825
+ return this._info.trafficAccessToken;
826
+ }
827
+ /** Public URL of a port inside the sandbox. */
828
+ portUrl(port) {
829
+ const tpl = this._info.portUrl;
830
+ if (!tpl) throw new SbBoxError({ status: 0, message: `sandbox ${this.id} has no portUrl` });
831
+ return tpl.replace("{port}", String(port));
832
+ }
833
+ p(suffix = "") {
834
+ return `/sandboxes/${encodeURIComponent(this.id)}${suffix}`;
835
+ }
836
+ update(info) {
837
+ this._info = { ...this._info, ...info };
838
+ return this;
839
+ }
840
+ async refresh() {
841
+ return this.update(await this.http.request(this.p(), { retry: true }));
842
+ }
843
+ async kill() {
844
+ await this.http.request(this.p(), { method: "DELETE", retry: true });
845
+ }
846
+ /** Freeze. The server may answer 202 (still freezing); with `wait` (default) we poll until `frozen`. */
847
+ async freeze(opts = {}) {
848
+ const r = await this.http.request(this.p("/freeze"), { method: "POST", retry: true, timeout: 120 });
849
+ if (r.id) this.update(r);
850
+ else if (r.state) this._info = { ...this._info, state: r.state };
851
+ if (opts.wait === false || this.state === "frozen") return this;
852
+ return this.waitForState("frozen", { timeout: opts.timeout ?? 90, interval: opts.interval ?? 2 });
853
+ }
854
+ async waitForState(target, opts = {}) {
855
+ const targets = Array.isArray(target) ? target : [target];
856
+ const deadline = Date.now() + (opts.timeout ?? 90) * 1e3;
857
+ const interval = (opts.interval ?? 2) * 1e3;
858
+ while (true) {
859
+ await this.refresh();
860
+ if (targets.includes(this.state)) return this;
861
+ if (Date.now() + interval > deadline) {
862
+ throw new WaitTimeoutError(`sandbox ${this.id} is ${this.state}, not ${targets.join("/")}, after ${opts.timeout ?? 90}s`);
863
+ }
864
+ await new Promise((r) => setTimeout(r, interval));
865
+ }
866
+ }
867
+ async resume(opts = {}) {
868
+ const json = {};
869
+ if (opts.timeout !== void 0) json.timeout = opts.timeout;
870
+ return this.update(await this.http.request(this.p("/resume"), { method: "POST", json, retry: true, timeout: 120 }));
871
+ }
872
+ async rollback(opts = {}) {
873
+ const json = { version: opts.version ?? 0 };
874
+ if (opts.timeout !== void 0) json.timeout = opts.timeout;
875
+ return this.update(await this.http.request(this.p("/rollback"), { method: "POST", json, timeout: 120 }));
876
+ }
877
+ /** Clone into a new sandbox owned by the caller. Retries on 503 + Retry-After until `timeout` (s). */
878
+ async clone(opts = {}) {
879
+ const json = { version: opts.version ?? 0 };
880
+ const md = ensureStringMap("metadata", opts.metadata);
881
+ if (md) json.metadata = md;
882
+ const total = opts.timeout ?? 120;
883
+ const info = await this.http.request(this.p("/clone"), {
884
+ method: "POST",
885
+ json,
886
+ timeout: 120,
887
+ retryOn503Until: Date.now() + total * 1e3
888
+ });
889
+ return new _Sandbox(this.http, info);
890
+ }
891
+ /** Set the lifetime deadline in seconds from now; 0 clears it. */
892
+ async setTimeout(seconds) {
893
+ await this.http.request(this.p("/timeout"), { method: "POST", json: { timeout: seconds }, retry: true });
894
+ }
895
+ async reset(opts = {}) {
896
+ const total = opts.timeout ?? 120;
897
+ return this.update(await this.http.request(this.p("/reset"), {
898
+ method: "POST",
899
+ timeout: 120,
900
+ retryOn503Until: Date.now() + total * 1e3
901
+ }));
902
+ }
903
+ async metrics(opts = {}) {
904
+ return this.http.request(this.p("/metrics"), { query: { start: opts.start, end: opts.end }, retry: true });
905
+ }
906
+ async grant(userId, opts = {}) {
907
+ const json = { perm: opts.perm ?? "read" };
908
+ if (opts.expiresAt) json.expires_at = opts.expiresAt;
909
+ if (opts.reason) json.reason = opts.reason;
910
+ return this.http.request(this.p(`/grants/${encodeURIComponent(userId)}`), { method: "PUT", json });
911
+ }
912
+ async grants() {
913
+ return this.http.request(this.p("/grants"), { retry: true });
914
+ }
915
+ async revoke(userId) {
916
+ await this.http.request(this.p(`/grants/${encodeURIComponent(userId)}`), { method: "DELETE" });
917
+ }
918
+ /** Run a command and wait for it. A non-zero exit is returned, not thrown. */
919
+ async exec(command, opts = {}) {
920
+ const body = execBody(command, opts, true, 600);
921
+ return this.http.request(this.p("/exec"), {
922
+ method: "POST",
923
+ json: body,
924
+ timeout: body.timeout + 30
925
+ });
926
+ }
927
+ /** Run a command and stream its output as it is produced. */
928
+ async *execStream(command, opts = {}) {
929
+ const body = execBody(command, opts, true, 600);
930
+ const res = await this.http.raw(this.p("/sse/exec"), {
931
+ method: "POST",
932
+ json: body,
933
+ headers: { Accept: "text/event-stream" },
934
+ timeout: body.timeout + 30
935
+ });
936
+ yield* execEvents(res);
937
+ }
938
+ /** Execute code in the sandbox's stateful interpreter. */
939
+ async runCode(code, opts = {}) {
940
+ const timeout = opts.timeout ?? 60;
941
+ if (timeout > 540) throw new RangeError("runCode timeout must be <= 540 seconds");
942
+ const json = { code, language: opts.language ?? "python", timeout };
943
+ if (opts.contextId) json.contextId = opts.contextId;
944
+ const env2 = ensureStringMap("envVars", opts.envVars);
945
+ if (env2) json.envVars = env2;
946
+ if (opts.images) json.images = opts.images;
947
+ return this.http.request(this.p("/run-code"), { method: "POST", json, timeout: timeout + 30 });
948
+ }
949
+ };
950
+
951
+ // src/templates.ts
952
+ var Templates = class {
953
+ constructor(http) {
954
+ this.http = http;
955
+ }
956
+ http;
957
+ /** Start a build. Async: poll `get()` or use `waitReady()`. */
958
+ async build(opts) {
959
+ if (!opts.image && !opts.dockerfile) throw new TypeError("templates.build: image or dockerfile is required");
960
+ const body = {};
961
+ for (const [k, v] of Object.entries(opts)) if (v !== void 0) body[k] = v;
962
+ return this.http.request("/templates/build", { method: "POST", json: body, timeout: 120 });
963
+ }
964
+ /** Poll until the template is `ready`; throws `TemplateBuildError` on `error`. */
965
+ async waitReady(templateId, opts = {}) {
966
+ const timeout = (opts.timeout ?? 600) * 1e3;
967
+ const interval = (opts.interval ?? 5) * 1e3;
968
+ const deadline = Date.now() + timeout;
969
+ while (true) {
970
+ const t = await this.get(templateId);
971
+ if (t.status === "ready") return t;
972
+ if (t.status === "error") throw new TemplateBuildError(templateId, t.buildError, t);
973
+ if (Date.now() + interval > deadline) {
974
+ throw new WaitTimeoutError(`template ${templateId} still ${t.status} after ${timeout / 1e3}s`);
975
+ }
976
+ await new Promise((r) => setTimeout(r, interval));
977
+ }
978
+ }
979
+ async list() {
980
+ const r = await this.http.request("/templates", { retry: true });
981
+ return r.templates ?? [];
982
+ }
983
+ async shared() {
984
+ return this.http.request("/templates/shared", { retry: true });
985
+ }
986
+ async get(templateId) {
987
+ return this.http.request(`/templates/${encodeURIComponent(templateId)}`, { retry: true });
988
+ }
989
+ async delete(templateId) {
990
+ await this.http.request(`/templates/${encodeURIComponent(templateId)}`, { method: "DELETE" });
991
+ }
992
+ async grant(templateId, userId, opts = {}) {
993
+ const json = { perm: opts.perm ?? "read" };
994
+ if (opts.expiresAt) json.expires_at = opts.expiresAt;
995
+ if (opts.reason) json.reason = opts.reason;
996
+ return this.http.request(
997
+ `/templates/${encodeURIComponent(templateId)}/grants/${encodeURIComponent(userId)}`,
998
+ { method: "PUT", json }
999
+ );
1000
+ }
1001
+ async grants(templateId) {
1002
+ return this.http.request(`/templates/${encodeURIComponent(templateId)}/grants`, { retry: true });
1003
+ }
1004
+ async revoke(templateId, userId) {
1005
+ await this.http.request(
1006
+ `/templates/${encodeURIComponent(templateId)}/grants/${encodeURIComponent(userId)}`,
1007
+ { method: "DELETE" }
1008
+ );
1009
+ }
1010
+ };
1011
+
1012
+ // src/client.ts
1013
+ function env(name) {
1014
+ const p = globalThis.process;
1015
+ return p?.env?.[name];
1016
+ }
1017
+ var Sandboxes = class {
1018
+ constructor(http) {
1019
+ this.http = http;
1020
+ }
1021
+ http;
1022
+ async create(opts = {}) {
1023
+ const json = {};
1024
+ if (opts.templateId) json.templateId = opts.templateId;
1025
+ else json.templateName = opts.template ?? "base";
1026
+ if (opts.timeout !== void 0) json.timeout = opts.timeout;
1027
+ if (opts.onTimeout) json.lifecycle = { onTimeout: opts.onTimeout };
1028
+ const md = ensureStringMap("metadata", opts.metadata);
1029
+ if (md) json.metadata = md;
1030
+ const ev = ensureStringMap("envVars", opts.envVars);
1031
+ if (ev) json.envVars = ev;
1032
+ if (opts.network) json.network = opts.network;
1033
+ const info = await this.http.request("/sandboxes", { method: "POST", json, timeout: 120 });
1034
+ return new Sandbox(this.http, info);
1035
+ }
1036
+ /** Compact rows. `state` filters (one or many); omitted = every live state. */
1037
+ async list(state) {
1038
+ const s = state === void 0 ? void 0 : Array.isArray(state) ? state.join(",") : state;
1039
+ const r = await this.http.request("/sandboxes", { query: { state: s }, retry: true });
1040
+ return r.sandboxes ?? [];
1041
+ }
1042
+ async shared() {
1043
+ const rows = await this.http.request("/sandboxes/shared", { retry: true });
1044
+ return rows.map((r) => new Sandbox(this.http, r));
1045
+ }
1046
+ async get(sandboxId) {
1047
+ const info = await this.http.request(`/sandboxes/${encodeURIComponent(sandboxId)}`, { retry: true });
1048
+ return new Sandbox(this.http, info);
1049
+ }
1050
+ /** Alias of `get()`. */
1051
+ connect(sandboxId) {
1052
+ return this.get(sandboxId);
1053
+ }
1054
+ handle(id) {
1055
+ return new Sandbox(this.http, { id, state: "unknown" });
1056
+ }
1057
+ async kill(sandboxId) {
1058
+ return this.handle(sandboxId).kill();
1059
+ }
1060
+ async freeze(sandboxId, opts = {}) {
1061
+ return this.handle(sandboxId).freeze(opts);
1062
+ }
1063
+ async resume(sandboxId, opts = {}) {
1064
+ return this.handle(sandboxId).resume(opts);
1065
+ }
1066
+ async rollback(sandboxId, opts = {}) {
1067
+ return this.handle(sandboxId).rollback(opts);
1068
+ }
1069
+ async clone(sandboxId, opts = {}) {
1070
+ return this.handle(sandboxId).clone(opts);
1071
+ }
1072
+ async setTimeout(sandboxId, seconds) {
1073
+ return this.handle(sandboxId).setTimeout(seconds);
1074
+ }
1075
+ async reset(sandboxId, opts = {}) {
1076
+ return this.handle(sandboxId).reset(opts);
1077
+ }
1078
+ async metrics(sandboxId, opts = {}) {
1079
+ return this.handle(sandboxId).metrics(opts);
1080
+ }
1081
+ async grant(sandboxId, userId, opts = {}) {
1082
+ return this.handle(sandboxId).grant(userId, opts);
1083
+ }
1084
+ async grants(sandboxId) {
1085
+ return this.handle(sandboxId).grants();
1086
+ }
1087
+ async revoke(sandboxId, userId) {
1088
+ return this.handle(sandboxId).revoke(userId);
1089
+ }
1090
+ };
1091
+ var SbBox = class {
1092
+ templates;
1093
+ sandboxes;
1094
+ baseUrl;
1095
+ http;
1096
+ constructor(opts = {}) {
1097
+ const apiKey = opts.apiKey ?? env("SBBOX_API_KEY") ?? env("GSK_API_KEY");
1098
+ if (!apiKey) {
1099
+ throw new SbBoxError({ status: 0, message: "SB-Box API key missing: pass { apiKey } or set SBBOX_API_KEY (or GSK_API_KEY)" });
1100
+ }
1101
+ const f = opts.fetch ?? globalThis.fetch;
1102
+ if (typeof f !== "function") {
1103
+ throw new SbBoxError({ status: 0, message: "global fetch is not available: use Node 18+ or pass { fetch }" });
1104
+ }
1105
+ this.baseUrl = (opts.baseUrl ?? env("SBBOX_BASE_URL") ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
1106
+ const ua = `sbbox-typescript-sdk/${SDK_VERSION} (+https://www.genspark.ai/sb-box/docs)` + (opts.userAgentSuffix ? ` ${opts.userAgentSuffix}` : "");
1107
+ this.http = new Http({
1108
+ apiKey,
1109
+ baseUrl: this.baseUrl,
1110
+ timeout: opts.timeout ?? 60,
1111
+ retries: opts.retries ?? 3,
1112
+ userAgent: ua,
1113
+ fetch: f
1114
+ });
1115
+ this.templates = new Templates(this.http);
1116
+ this.sandboxes = new Sandboxes(this.http);
1117
+ }
1118
+ regions() {
1119
+ return this.http.request("/regions", { retry: true });
1120
+ }
1121
+ limits() {
1122
+ return this.http.request("/limits", { retry: true });
1123
+ }
1124
+ usage(days = 30) {
1125
+ return this.http.request("/usage", { query: { days }, retry: true });
1126
+ }
1127
+ };
1128
+ // Annotate the CommonJS export names for ESM import in node:
1129
+ 0 && (module.exports = {
1130
+ AuthenticationError,
1131
+ BackgroundCommand,
1132
+ ClientDisconnectedError,
1133
+ CommandTimeoutError,
1134
+ Commands,
1135
+ ConflictError,
1136
+ DEFAULT_BASE_URL,
1137
+ DiskLostError,
1138
+ Files,
1139
+ ForbiddenError,
1140
+ InsufficientCreditsError,
1141
+ InterpreterStartFailedError,
1142
+ InterpreterUnavailableError,
1143
+ LimitError,
1144
+ MemoryExpiredError,
1145
+ NotFoundError,
1146
+ PlanRequiredError,
1147
+ Pty,
1148
+ PtySession,
1149
+ PtyWebSocket,
1150
+ RegionRetiredError,
1151
+ SDK_VERSION,
1152
+ Sandbox,
1153
+ Sandboxes,
1154
+ SbBox,
1155
+ SbBoxConnectionError,
1156
+ SbBoxError,
1157
+ ServerError,
1158
+ TemplateBuildError,
1159
+ Templates,
1160
+ ValidationError,
1161
+ WaitTimeoutError,
1162
+ describeBody,
1163
+ errorFromResponse,
1164
+ parseSse,
1165
+ redact
1166
+ });
1167
+ //# sourceMappingURL=index.cjs.map