withruntime 0.9.0 → 0.10.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/BLAXEL.md +4 -4
- package/DAYTONA.md +13 -7
- package/E2B.md +12 -8
- package/README.md +15 -7
- package/README.src.md +15 -7
- package/VERCEL.md +13 -3
- package/compatibility-lock.json +84 -8
- package/dist/blaxel/errors.js +1 -1
- package/dist/blaxel/lookup.d.ts +3 -2
- package/dist/blaxel/lookup.js +3 -2
- package/dist/blaxel/pagination.d.ts +2 -2
- package/dist/blaxel/pagination.js +45 -17
- package/dist/blaxel/preview.d.ts +2 -1
- package/dist/blaxel/preview.js +15 -13
- package/dist/blaxel/process.js +56 -10
- package/dist/blaxel/sandbox.d.ts +2 -0
- package/dist/blaxel/sandbox.js +2 -0
- package/dist/blaxel/snapshot.js +3 -5
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +189 -54
- package/dist/client.d.ts +29 -3
- package/dist/client.js +40 -11
- package/dist/cloudflare/identity.d.ts +7 -0
- package/dist/cloudflare/identity.js +13 -0
- package/dist/cloudflare/index.d.ts +9 -0
- package/dist/cloudflare/index.js +47 -9
- package/dist/cloudflare/worker.d.ts +4 -0
- package/dist/cloudflare/worker.js +166 -16
- package/dist/codesandbox/guest-service.js +57 -20
- package/dist/codesandbox/index.js +42 -8
- package/dist/compat/core.d.ts +9 -8
- package/dist/compat/core.js +60 -21
- package/dist/compat/files.js +22 -4
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +107 -38
- package/dist/daytona/daytona.js +11 -4
- package/dist/daytona/filesystem.d.ts +17 -4
- package/dist/daytona/filesystem.js +121 -38
- package/dist/daytona/index.d.ts +1 -1
- package/dist/daytona/sandbox.d.ts +1 -1
- package/dist/daytona/sandbox.js +16 -7
- package/dist/e2b/client.js +1 -1
- package/dist/e2b/commands.d.ts +30 -8
- package/dist/e2b/commands.js +142 -54
- package/dist/e2b/index.d.ts +1 -0
- package/dist/e2b/index.js +1 -0
- package/dist/e2b/pty.d.ts +24 -0
- package/dist/e2b/pty.js +80 -0
- package/dist/e2b/sandbox.d.ts +2 -1
- package/dist/e2b/sandbox.js +49 -15
- package/dist/file-source.d.ts +16 -0
- package/dist/file-source.js +162 -0
- package/dist/freestyle/index.d.ts +9 -1
- package/dist/freestyle/index.js +38 -5
- package/dist/index.d.ts +2 -1
- package/dist/login.js +16 -10
- package/dist/modal/index.js +2 -1
- package/dist/network-cli.js +111 -43
- package/dist/openai-agents/index.js +9 -45
- package/dist/page.d.ts +1 -1
- package/dist/page.js +2 -2
- package/dist/products/index.d.ts +12 -0
- package/dist/products/index.js +10 -0
- package/dist/products/observability.d.ts +44 -0
- package/dist/products/observability.js +6 -0
- package/dist/products/previews.d.ts +8 -2
- package/dist/products/previews.js +11 -3
- package/dist/products/volumes.d.ts +42 -0
- package/dist/products/volumes.js +36 -0
- package/dist/products/watch.js +61 -8
- package/dist/proxy.js +3 -1
- package/dist/runloop/index.d.ts +13 -27
- package/dist/runloop/index.js +149 -52
- package/dist/sandbox.d.ts +37 -8
- package/dist/sandbox.js +432 -68
- package/dist/snapshots.d.ts +9 -4
- package/dist/sprites/index.js +69 -33
- package/dist/tar.d.ts +3 -1
- package/dist/tar.js +140 -14
- package/dist/transport.d.ts +4 -7
- package/dist/transport.js +205 -122
- package/dist/vercel/command.d.ts +1 -1
- package/dist/vercel/command.js +3 -2
- package/dist/vercel/errors.d.ts +1 -1
- package/dist/vercel/errors.js +7 -1
- package/dist/vercel/sandbox.d.ts +8 -8
- package/dist/vercel/sandbox.js +154 -59
- package/dist/vercel/snapshot.d.ts +3 -2
- package/dist/vercel/snapshot.js +9 -5
- package/package.json +2 -1
package/dist/runloop/index.js
CHANGED
|
@@ -93,10 +93,16 @@ export class Devboxes {
|
|
|
93
93
|
executions;
|
|
94
94
|
diskSnapshots;
|
|
95
95
|
transitions = new Map();
|
|
96
|
-
transition(id, operation) {
|
|
96
|
+
transition(id, operation, signal) {
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- rejects with the caller's abort reason as is, as the upstream SDK does
|
|
98
|
+
if (signal?.aborted)
|
|
99
|
+
return Promise.reject(signal.reason);
|
|
97
100
|
const pending = (this.transitions.get(id) ?? Promise.resolve())
|
|
98
101
|
.catch(() => undefined)
|
|
99
|
-
.then(
|
|
102
|
+
.then(() => {
|
|
103
|
+
signal?.throwIfAborted();
|
|
104
|
+
return operation();
|
|
105
|
+
});
|
|
100
106
|
this.transitions.set(id, pending);
|
|
101
107
|
void pending
|
|
102
108
|
.finally(() => {
|
|
@@ -104,7 +110,23 @@ export class Devboxes {
|
|
|
104
110
|
this.transitions.delete(id);
|
|
105
111
|
})
|
|
106
112
|
.catch(() => undefined);
|
|
107
|
-
|
|
113
|
+
if (!signal)
|
|
114
|
+
return pending;
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- rejects with the caller's abort reason as is, as the upstream SDK does
|
|
117
|
+
const abort = () => reject(signal.reason);
|
|
118
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
119
|
+
pending.then((value) => {
|
|
120
|
+
signal.removeEventListener("abort", abort);
|
|
121
|
+
resolve(value);
|
|
122
|
+
}, (error) => {
|
|
123
|
+
signal.removeEventListener("abort", abort);
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- passes the pending call's own failure through unchanged
|
|
125
|
+
reject(error);
|
|
126
|
+
});
|
|
127
|
+
if (signal.aborted)
|
|
128
|
+
abort();
|
|
129
|
+
});
|
|
108
130
|
}
|
|
109
131
|
constructor(runtime) {
|
|
110
132
|
this.runtime = runtime;
|
|
@@ -112,6 +134,7 @@ export class Devboxes {
|
|
|
112
134
|
this.diskSnapshots = new DiskSnapshots(runtime);
|
|
113
135
|
}
|
|
114
136
|
async create(input = {}, options = {}) {
|
|
137
|
+
options.signal?.throwIfAborted();
|
|
115
138
|
only("Runloop", input, [
|
|
116
139
|
"name",
|
|
117
140
|
"metadata",
|
|
@@ -153,22 +176,27 @@ export class Devboxes {
|
|
|
153
176
|
idlePauseSeconds: 0,
|
|
154
177
|
onLeaseEnd: "stop",
|
|
155
178
|
}, input.environment_variables ?? undefined, async (sandbox) => {
|
|
156
|
-
for (const [path, content] of Object.entries(input.file_mounts ?? {}))
|
|
157
|
-
|
|
179
|
+
for (const [path, content] of Object.entries(input.file_mounts ?? {})) {
|
|
180
|
+
options.signal?.throwIfAborted();
|
|
181
|
+
await sandbox.files.write(path, content, {
|
|
182
|
+
signal: options.signal,
|
|
183
|
+
timeoutMs: options.timeout,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
158
186
|
for (const command of p.launch_commands ?? [])
|
|
159
187
|
await sandbox.exec(command, {
|
|
160
|
-
...(await execOptions(sandbox)),
|
|
188
|
+
...(await execOptions(sandbox, { signal: options.signal }, nativeOptions(options))),
|
|
161
189
|
check: true,
|
|
162
190
|
signal: options.signal,
|
|
163
191
|
});
|
|
164
|
-
});
|
|
192
|
+
}, nativeOptions(options));
|
|
165
193
|
return view(sandbox);
|
|
166
194
|
}
|
|
167
195
|
createAndAwaitRunning(input, options) {
|
|
168
196
|
return this.create(input, options);
|
|
169
197
|
}
|
|
170
|
-
async retrieve(id) {
|
|
171
|
-
return view(await lookup(this.runtime, id));
|
|
198
|
+
async retrieve(id, options = {}) {
|
|
199
|
+
return view(await lookup(this.runtime, id, nativeOptions(options)));
|
|
172
200
|
}
|
|
173
201
|
async awaitRunning(id, options = {}) {
|
|
174
202
|
return this.waitForStatus(id, "running", options);
|
|
@@ -237,7 +265,13 @@ export class Devboxes {
|
|
|
237
265
|
throw new TypeError("limit must be positive");
|
|
238
266
|
const values = [];
|
|
239
267
|
let cursor = null;
|
|
268
|
+
const seenCursors = new Set();
|
|
240
269
|
do {
|
|
270
|
+
if (cursor !== null) {
|
|
271
|
+
if (seenCursors.has(cursor))
|
|
272
|
+
throw new Error("Pagination returned a repeated cursor");
|
|
273
|
+
seenCursors.add(cursor);
|
|
274
|
+
}
|
|
241
275
|
const page = await this.runtime.transport.json({
|
|
242
276
|
method: "GET",
|
|
243
277
|
path: "/v1/sandboxes",
|
|
@@ -268,9 +302,14 @@ export class Devboxes {
|
|
|
268
302
|
const data = values.slice(offset, offset + (query.limit ?? 20));
|
|
269
303
|
return new DevboxViewsCursorIDPage(data, offset + data.length < values.length, query.include_total_count === false ? 0 : values.length, (after) => this.listPage({ ...query, starting_after: after }, options));
|
|
270
304
|
}
|
|
271
|
-
suspend(id) {
|
|
305
|
+
suspend(id, options = {}) {
|
|
306
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- rejects with the caller's abort reason as is, as the upstream SDK does
|
|
307
|
+
if (options.signal?.aborted)
|
|
308
|
+
return Promise.reject(options.signal.reason);
|
|
309
|
+
if (options.idempotencyKey !== undefined)
|
|
310
|
+
return Promise.reject(new CompatibilityError("Runloop", "caller idempotency keys for compound suspend"));
|
|
272
311
|
return this.transition(id, async () => {
|
|
273
|
-
const s = await lookup(this.runtime, id);
|
|
312
|
+
const s = await lookup(this.runtime, id, nativeOptions(options));
|
|
274
313
|
if (s.state === "stopped") {
|
|
275
314
|
if (s.info.persistent && s.info.labels[SUSPENDED] === "true")
|
|
276
315
|
return view(s);
|
|
@@ -278,41 +317,56 @@ export class Devboxes {
|
|
|
278
317
|
}
|
|
279
318
|
// ARCHITECTURE.md section 10: paid disk persistence must be admitted
|
|
280
319
|
// before stop; an uncertain stop keeps retention enabled to preserve bytes.
|
|
281
|
-
await s.update({ persistent: true, labels: { ...s.info.labels, [SUSPENDED]: "true" } });
|
|
282
|
-
await s.stop();
|
|
320
|
+
await s.update({ persistent: true, labels: { ...s.info.labels, [SUSPENDED]: "true" } }, nativeOptions(options));
|
|
321
|
+
await s.stop(nativeOptions(options));
|
|
283
322
|
return view(s);
|
|
284
|
-
});
|
|
323
|
+
}, options.signal);
|
|
285
324
|
}
|
|
286
|
-
resume(id) {
|
|
325
|
+
resume(id, options = {}) {
|
|
326
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- rejects with the caller's abort reason as is, as the upstream SDK does
|
|
327
|
+
if (options.signal?.aborted)
|
|
328
|
+
return Promise.reject(options.signal.reason);
|
|
329
|
+
if (options.idempotencyKey !== undefined)
|
|
330
|
+
return Promise.reject(new CompatibilityError("Runloop", "caller idempotency keys for compound resume"));
|
|
287
331
|
return this.transition(id, async () => {
|
|
288
|
-
const s = await lookup(this.runtime, id);
|
|
332
|
+
const s = await lookup(this.runtime, id, nativeOptions(options));
|
|
289
333
|
if (s.state === "stopped") {
|
|
290
334
|
if (!s.info.persistent || s.info.labels[SUSPENDED] !== "true")
|
|
291
335
|
throw new Error("A shut down Devbox cannot be resumed");
|
|
292
|
-
await s.restart();
|
|
336
|
+
await s.restart(nativeOptions(options));
|
|
293
337
|
}
|
|
294
338
|
else if (s.state === "paused" || s.state === "pausing") {
|
|
295
339
|
// Migrate older adapter pauses through the same disk-only boundary.
|
|
296
|
-
await s.update({ persistent: true, labels: { ...s.info.labels, [SUSPENDED]: "true" } });
|
|
297
|
-
await s.stop();
|
|
298
|
-
await s.restart();
|
|
340
|
+
await s.update({ persistent: true, labels: { ...s.info.labels, [SUSPENDED]: "true" } }, nativeOptions(options));
|
|
341
|
+
await s.stop(nativeOptions(options));
|
|
342
|
+
await s.restart(nativeOptions(options));
|
|
299
343
|
}
|
|
300
344
|
else
|
|
301
|
-
await s.waitFor("running");
|
|
345
|
+
await s.waitFor("running", nativeOptions(options));
|
|
302
346
|
if (s.info.labels[SUSPENDED] !== undefined) {
|
|
303
347
|
const labels = { ...s.info.labels };
|
|
304
348
|
delete labels[SUSPENDED];
|
|
305
|
-
await s.update({ labels });
|
|
349
|
+
await s.update({ labels }, nativeOptions(options));
|
|
306
350
|
}
|
|
307
351
|
return view(s);
|
|
308
|
-
});
|
|
352
|
+
}, options.signal);
|
|
309
353
|
}
|
|
310
|
-
shutdown(id) {
|
|
354
|
+
shutdown(id, params = {}, options = {}) {
|
|
355
|
+
if (requestOptions(params))
|
|
356
|
+
return this.shutdown(id, {}, params);
|
|
357
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- rejects with the caller's abort reason as is, as the upstream SDK does
|
|
358
|
+
if (options.signal?.aborted)
|
|
359
|
+
return Promise.reject(options.signal.reason);
|
|
360
|
+
if (options.idempotencyKey !== undefined)
|
|
361
|
+
return Promise.reject(new CompatibilityError("Runloop", "caller idempotency keys for compound shutdown"));
|
|
362
|
+
only("Runloop shutdown", params, ["force"]);
|
|
363
|
+
if (params.force !== undefined && params.force !== "false")
|
|
364
|
+
return Promise.reject(new CompatibilityError("Runloop", "forced shutdown during snapshots"));
|
|
311
365
|
return this.transition(id, async () => {
|
|
312
|
-
const s = await lookup(this.runtime, id);
|
|
313
|
-
await destroy(s);
|
|
366
|
+
const s = await lookup(this.runtime, id, nativeOptions(options));
|
|
367
|
+
await destroy(s, nativeOptions(options));
|
|
314
368
|
return view(s);
|
|
315
|
-
});
|
|
369
|
+
}, options.signal);
|
|
316
370
|
}
|
|
317
371
|
executeSync(id, body, options) {
|
|
318
372
|
return this.executions.executeSync(id, body, options);
|
|
@@ -324,13 +378,15 @@ export class Devboxes {
|
|
|
324
378
|
const execution = await this.executeAsync(id, body, options);
|
|
325
379
|
return this.executions.awaitCompleted(id, execution.execution_id, options);
|
|
326
380
|
}
|
|
327
|
-
async readFileContents(id, body) {
|
|
381
|
+
async readFileContents(id, body, options = {}) {
|
|
382
|
+
options.signal?.throwIfAborted();
|
|
328
383
|
only("Runloop read", body, ["file_path"]);
|
|
329
|
-
return (await lookup(this.runtime, id)).files.readText(body.file_path);
|
|
384
|
+
return (await lookup(this.runtime, id, nativeOptions(options))).files.readText(body.file_path, nativeOptions(options));
|
|
330
385
|
}
|
|
331
|
-
async writeFileContents(id, body) {
|
|
386
|
+
async writeFileContents(id, body, options = {}) {
|
|
387
|
+
options.signal?.throwIfAborted();
|
|
332
388
|
only("Runloop write", body, ["file_path", "contents"]);
|
|
333
|
-
await (await lookup(this.runtime, id)).files.write(body.file_path, body.contents);
|
|
389
|
+
await (await lookup(this.runtime, id, nativeOptions(options))).files.write(body.file_path, body.contents, nativeOptions(options));
|
|
334
390
|
return result(id, { stdout: "", stderr: "", exitCode: 0, timedOut: false });
|
|
335
391
|
}
|
|
336
392
|
async snapshotDisk(id, body = {}, options = {}) {
|
|
@@ -364,52 +420,92 @@ export class Executions {
|
|
|
364
420
|
only("Runloop execute", body, ["command", "shell_name", "attach_stdin"]);
|
|
365
421
|
if (body.attach_stdin)
|
|
366
422
|
throw new TypeError("attach_stdin requires executeAsync");
|
|
367
|
-
|
|
368
|
-
|
|
423
|
+
options.signal?.throwIfAborted();
|
|
424
|
+
const s = await lookup(this.runtime, id, nativeOptions(options));
|
|
425
|
+
return result(id, await s.exec(await shellCommand(s, body.command, body.shell_name, {}, nativeOptions(options)), await execOptions(s, {
|
|
369
426
|
signal: options.signal,
|
|
370
427
|
timeoutMs: options.timeout,
|
|
371
428
|
idempotencyKey: options.idempotencyKey,
|
|
372
429
|
onStdout: () => { },
|
|
373
|
-
})));
|
|
430
|
+
}, nativeOptions(options))));
|
|
374
431
|
}
|
|
375
432
|
async executeAsync(id, body, options = {}) {
|
|
376
433
|
only("Runloop execute", body, ["command", "shell_name", "attach_stdin"]);
|
|
377
434
|
if (body.shell_name && body.attach_stdin)
|
|
378
435
|
throw new CompatibilityError("Runloop", "interactive stdin in a named shell");
|
|
379
|
-
|
|
380
|
-
const
|
|
381
|
-
|
|
436
|
+
options.signal?.throwIfAborted();
|
|
437
|
+
const s = await lookup(this.runtime, id, nativeOptions(options));
|
|
438
|
+
const p = await s.spawn(await shellCommand(s, body.command, body.shell_name, {}, nativeOptions(options)), {
|
|
439
|
+
...(await execOptions(s, {
|
|
440
|
+
signal: options.signal,
|
|
441
|
+
idempotencyKey: options.idempotencyKey,
|
|
442
|
+
}, nativeOptions(options))),
|
|
382
443
|
stdin: body.attach_stdin ? "pipe" : undefined,
|
|
444
|
+
request: nativeOptions(options),
|
|
383
445
|
});
|
|
384
446
|
return { devbox_id: id, execution_id: p.id, status: "running" };
|
|
385
447
|
}
|
|
386
|
-
async retrieve(id, execution) {
|
|
387
|
-
|
|
448
|
+
async retrieve(id, execution, query = {}, options = {}) {
|
|
449
|
+
if (requestOptions(query))
|
|
450
|
+
return this.retrieve(id, execution, {}, query);
|
|
451
|
+
options.signal?.throwIfAborted();
|
|
452
|
+
only("Runloop execution retrieve", query, ["last_n"]);
|
|
453
|
+
if (query.last_n !== undefined)
|
|
454
|
+
throw new CompatibilityError("Runloop", "execution output tail selection (last_n)");
|
|
455
|
+
const p = await (await lookup(this.runtime, id, nativeOptions(options))).processes.get(execution, nativeOptions(options));
|
|
388
456
|
return p.info.state === "running"
|
|
389
457
|
? { devbox_id: id, execution_id: execution, status: "running" }
|
|
390
|
-
: {
|
|
458
|
+
: {
|
|
459
|
+
...result(id, await p.wait({ signal: options.signal })),
|
|
460
|
+
execution_id: execution,
|
|
461
|
+
status: "completed",
|
|
462
|
+
};
|
|
391
463
|
}
|
|
392
464
|
async awaitCompleted(id, execution, options = {}) {
|
|
393
|
-
|
|
465
|
+
options.signal?.throwIfAborted();
|
|
466
|
+
const p = await (await lookup(this.runtime, id, nativeOptions(options))).processes.get(execution, nativeOptions(options));
|
|
394
467
|
return {
|
|
395
468
|
...result(id, await p.wait({ signal: options.signal })),
|
|
396
469
|
execution_id: execution,
|
|
397
470
|
status: "completed",
|
|
398
471
|
};
|
|
399
472
|
}
|
|
400
|
-
async kill(id, execution, body = {}) {
|
|
473
|
+
async kill(id, execution, body = {}, options = {}) {
|
|
474
|
+
if (requestOptions(body))
|
|
475
|
+
return this.kill(id, execution, {}, body);
|
|
476
|
+
options.signal?.throwIfAborted();
|
|
401
477
|
only("Runloop kill", body, ["kill_process_group"]);
|
|
402
478
|
if (body.kill_process_group)
|
|
403
479
|
throw new CompatibilityError("Runloop", "kill_process_group");
|
|
404
|
-
await (await (await lookup(this.runtime, id)).processes.get(execution)).kill("SIGKILL");
|
|
405
|
-
return this.retrieve(id, execution);
|
|
406
|
-
}
|
|
407
|
-
async sendStdIn(id, execution, body = {}) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
480
|
+
await (await (await lookup(this.runtime, id, nativeOptions(options))).processes.get(execution, nativeOptions(options))).kill("SIGKILL", nativeOptions(options));
|
|
481
|
+
return this.retrieve(id, execution, {}, options);
|
|
482
|
+
}
|
|
483
|
+
async sendStdIn(id, execution, body = {}, options = {}) {
|
|
484
|
+
if (requestOptions(body) &&
|
|
485
|
+
(body.signal === undefined || (typeof body.signal === "object" && body.signal !== null)))
|
|
486
|
+
return this.sendStdIn(id, execution, {}, body);
|
|
487
|
+
options.signal?.throwIfAborted();
|
|
488
|
+
only("Runloop stdin", body, ["text", "signal"]);
|
|
489
|
+
const text = "text" in body ? body.text : undefined;
|
|
490
|
+
const bodySignal = body.signal;
|
|
491
|
+
if (text !== undefined && text !== null && typeof text !== "string")
|
|
492
|
+
throw new TypeError("Runloop stdin text must be a string");
|
|
493
|
+
if (bodySignal !== undefined &&
|
|
494
|
+
bodySignal !== null &&
|
|
495
|
+
bodySignal !== "EOF" &&
|
|
496
|
+
bodySignal !== "INTERRUPT")
|
|
497
|
+
throw new TypeError("Runloop stdin signal must be EOF or INTERRUPT");
|
|
498
|
+
if (options.idempotencyKey !== undefined && (text || bodySignal === "EOF"))
|
|
499
|
+
throw new CompatibilityError("Runloop", "caller idempotency keys for process input; native offsets protect transport retries");
|
|
500
|
+
const p = await (await lookup(this.runtime, id, nativeOptions(options))).processes.get(execution, nativeOptions(options));
|
|
501
|
+
if (text || bodySignal === "EOF")
|
|
502
|
+
await p.write(text ?? "", {
|
|
503
|
+
eof: bodySignal === "EOF",
|
|
504
|
+
signal: options.signal,
|
|
505
|
+
timeoutMs: options.timeout,
|
|
506
|
+
});
|
|
507
|
+
if (bodySignal === "INTERRUPT")
|
|
508
|
+
await p.kill("SIGINT", nativeOptions(options));
|
|
413
509
|
return { devbox_id: id, execution_id: execution, success: true };
|
|
414
510
|
}
|
|
415
511
|
async *streamStdoutUpdates(id, execution, query = {}, options = {}) {
|
|
@@ -419,7 +515,8 @@ export class Executions {
|
|
|
419
515
|
yield* this.stream(id, execution, "stderr", query, options);
|
|
420
516
|
}
|
|
421
517
|
async *stream(id, execution, channel, query, options) {
|
|
422
|
-
|
|
518
|
+
options.signal?.throwIfAborted();
|
|
519
|
+
const p = await (await lookup(this.runtime, id, nativeOptions(options))).processes.get(execution, nativeOptions(options));
|
|
423
520
|
let offset = 0;
|
|
424
521
|
const from = Number(query.offset ?? 0);
|
|
425
522
|
for await (const event of p.output({ signal: options.signal }))
|
package/dist/sandbox.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { CommandResult, DeletedSandbox, ExecOptions, FileEntry, OutputEvent
|
|
|
5
5
|
import { type SandboxExtensions } from "./products/index.js";
|
|
6
6
|
import type { Snapshot, SnapshotOptions } from "./snapshots.js";
|
|
7
7
|
import { Tunnel, type PortForward } from "./tunnel.js";
|
|
8
|
+
import type { StreamUploadSource } from "./file-source.js";
|
|
8
9
|
/** DELETE /v1/sandboxes/{id}, for `sandbox.delete()` and
|
|
9
10
|
* `runtime.sandboxes.delete(id)`. */
|
|
10
11
|
export declare function deleteSandbox(t: Transport, id: string, options?: RequestOptions): Promise<DeletedSandbox>;
|
|
@@ -67,6 +68,8 @@ export declare class Sandbox implements AsyncDisposable {
|
|
|
67
68
|
rows?: number;
|
|
68
69
|
};
|
|
69
70
|
outputEncoding?: "utf8" | "base64";
|
|
71
|
+
/** HTTP request options, independently of the process execution deadline. */
|
|
72
|
+
request?: RequestOptions;
|
|
70
73
|
}): Promise<Process>;
|
|
71
74
|
/** An interactive terminal over a WebSocket. Bytes you write are typed;
|
|
72
75
|
* onData receives what the terminal prints. */
|
|
@@ -210,8 +213,8 @@ export declare class Processes {
|
|
|
210
213
|
private readonly t;
|
|
211
214
|
private readonly sandboxId;
|
|
212
215
|
constructor(t: Transport, sandboxId: string);
|
|
213
|
-
list(): Promise<ProcessInfo[]>;
|
|
214
|
-
get(processId: string): Promise<Process>;
|
|
216
|
+
list(options?: RequestOptions): Promise<ProcessInfo[]>;
|
|
217
|
+
get(processId: string, options?: RequestOptions): Promise<Process>;
|
|
215
218
|
/** Output events from `cursor` until the process exits, across stream slices. */
|
|
216
219
|
follow(processId: string, options?: {
|
|
217
220
|
cursor?: number;
|
|
@@ -241,12 +244,13 @@ export declare class Process {
|
|
|
241
244
|
wait(options?: {
|
|
242
245
|
signal?: AbortSignal;
|
|
243
246
|
}): Promise<CommandResult>;
|
|
244
|
-
/** Sends input. Offsets
|
|
247
|
+
/** Sends input. Offsets protect transport retries; signal and timeoutMs cover
|
|
248
|
+
* the whole logical write, including its queue and backpressure. */
|
|
245
249
|
write(data: string | Uint8Array, options?: {
|
|
246
250
|
eof?: boolean;
|
|
247
|
-
}): Promise<void>;
|
|
248
|
-
kill(signal?: "SIGTERM" | "SIGKILL" | "SIGINT" | "SIGHUP" | "SIGQUIT" | "SIGUSR1" | "SIGUSR2"): Promise<void>;
|
|
249
|
-
resize(cols: number, rows: number): Promise<void>;
|
|
251
|
+
} & Pick<RequestOptions, "signal" | "timeoutMs">): Promise<void>;
|
|
252
|
+
kill(signal?: "SIGTERM" | "SIGKILL" | "SIGINT" | "SIGHUP" | "SIGQUIT" | "SIGUSR1" | "SIGUSR2", options?: RequestOptions): Promise<void>;
|
|
253
|
+
resize(cols: number, rows: number, options?: RequestOptions): Promise<void>;
|
|
250
254
|
refresh(): Promise<ProcessInfo>;
|
|
251
255
|
}
|
|
252
256
|
export declare class Terminal {
|
|
@@ -319,6 +323,18 @@ export declare class Files {
|
|
|
319
323
|
path: string;
|
|
320
324
|
size: number;
|
|
321
325
|
}>;
|
|
326
|
+
/** Uploads byte streams with bounded memory on Node/Bun. Unknown-length
|
|
327
|
+
* inputs stage once in a private local temporary file; known local files
|
|
328
|
+
* and Blobs avoid that extra disk copy. Paths are local file paths. */
|
|
329
|
+
writeStream(path: string, input: StreamUploadSource | Uint8Array, writeOptions?: RequestOptions & {
|
|
330
|
+
mode?: number;
|
|
331
|
+
onProgress?: (progress: {
|
|
332
|
+
bytesSent: number;
|
|
333
|
+
}) => void;
|
|
334
|
+
}): Promise<{
|
|
335
|
+
path: string;
|
|
336
|
+
size: number;
|
|
337
|
+
}>;
|
|
322
338
|
/** Directory entries; `depth` goes deeper, `glob` filters (e.g. "**\/*.py"). */
|
|
323
339
|
list(path?: string, options?: {
|
|
324
340
|
depth?: number;
|
|
@@ -343,6 +359,19 @@ export declare class Files {
|
|
|
343
359
|
rename(from: string, to: string, options?: {
|
|
344
360
|
overwrite?: boolean;
|
|
345
361
|
} & RequestOptions): Promise<void>;
|
|
362
|
+
/** Packs a directory as archive bytes; `gzip: false` returns plain tar.
|
|
363
|
+
* Exclusions are relative paths, not globs. `user: root` selects guest root. */
|
|
364
|
+
archive(path: string, options?: RequestOptions & {
|
|
365
|
+
gzip?: boolean;
|
|
366
|
+
exclude?: string[];
|
|
367
|
+
user?: "sandbox" | "root";
|
|
368
|
+
}): Promise<Uint8Array>;
|
|
369
|
+
/** Unpacks archive bytes in a directory with the sandbox user's rights by
|
|
370
|
+
* default; `user: root` explicitly selects root inside this guest. */
|
|
371
|
+
unarchive(path: string, bytes: Uint8Array, options?: RequestOptions & {
|
|
372
|
+
gzip?: boolean;
|
|
373
|
+
user?: "sandbox" | "root";
|
|
374
|
+
}): Promise<void>;
|
|
346
375
|
/** Copies a local file or directory into the sandbox. A directory travels as
|
|
347
376
|
* one gzipped tar to the API's folder routes, and the sandbox's own `tar`
|
|
348
377
|
* unpacks it as it arrives, making the folder. */
|
|
@@ -350,9 +379,9 @@ export declare class Files {
|
|
|
350
379
|
/** Copies a file or directory out of the sandbox. A file streams to disk,
|
|
351
380
|
* any size, checked against its length; a directory comes as one tar from
|
|
352
381
|
* the API's folder route. */
|
|
353
|
-
download(remotePath: string, localPath: string): Promise<void>;
|
|
382
|
+
download(remotePath: string, localPath: string, options?: RequestOptions): Promise<void>;
|
|
354
383
|
}
|
|
355
384
|
export declare function sandboxPage(t: Transport, body: {
|
|
356
385
|
data: SandboxInfo[];
|
|
357
386
|
nextCursor: string | null;
|
|
358
|
-
}, query: Record<string, unknown
|
|
387
|
+
}, query: Record<string, unknown>, options?: RequestOptions): Page<Sandbox>;
|