withruntime 0.11.0 → 0.11.2
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 +8 -9
- package/DAYTONA.md +8 -9
- package/E2B.md +63 -21
- package/README.md +6 -5
- package/README.src.md +6 -5
- package/VERCEL.md +3 -2
- package/compatibility-lock.json +69 -14
- package/dist/api-defaults.d.ts +1 -1
- package/dist/api-defaults.js +1 -1
- package/dist/blaxel/errors.js +4 -4
- package/dist/blaxel/lookup.d.ts +2 -1
- package/dist/blaxel/lookup.js +2 -1
- package/dist/blaxel/sandbox.d.ts +8 -7
- package/dist/blaxel/sandbox.js +16 -12
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +99 -27
- package/dist/client.d.ts +16 -60
- package/dist/client.js +14 -103
- package/dist/compat/files.js +5 -1
- package/dist/compat/lease.d.ts +1 -0
- package/dist/compat/lease.js +14 -8
- package/dist/credentials.d.ts +9 -0
- package/dist/credentials.js +26 -4
- package/dist/daytona/daytona.d.ts +1 -2
- package/dist/daytona/daytona.js +30 -14
- package/dist/daytona/sandbox.d.ts +9 -4
- package/dist/daytona/sandbox.js +24 -5
- package/dist/e2b/client.d.ts +15 -2
- package/dist/e2b/client.js +61 -7
- package/dist/e2b/commands.d.ts +3 -0
- package/dist/e2b/commands.js +16 -5
- package/dist/e2b/errors.d.ts +26 -2
- package/dist/e2b/errors.js +38 -5
- package/dist/e2b/filesystem.d.ts +1 -1
- package/dist/e2b/filesystem.js +82 -16
- package/dist/e2b/index.d.ts +2 -2
- package/dist/e2b/index.js +2 -2
- package/dist/e2b/sandbox.d.ts +25 -12
- package/dist/e2b/sandbox.js +196 -165
- package/dist/e2b/unsupported.d.ts +19 -0
- package/dist/e2b/unsupported.js +21 -0
- package/dist/e2b/users.d.ts +9 -0
- package/dist/e2b/users.js +22 -0
- package/dist/errors.d.ts +10 -4
- package/dist/errors.js +18 -10
- package/dist/identity.js +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/machine.d.ts +180 -0
- package/dist/machine.js +504 -0
- package/dist/modal/index.js +6 -2
- package/dist/network-cli.js +7 -7
- package/dist/openai-agents/index.d.ts +1 -1
- package/dist/openai-agents/index.js +1 -1
- package/dist/products/browser.d.ts +2 -1
- package/dist/products/browser.js +9 -19
- package/dist/products/desktop.d.ts +2 -1
- package/dist/products/desktop.js +5 -30
- package/dist/products/jobs.d.ts +6 -5
- package/dist/products/jobs.js +6 -3
- package/dist/products/limits.d.ts +4 -10
- package/dist/products/mcp.d.ts +5 -1
- package/dist/products/mcp.js +29 -8
- package/dist/products/network-products.d.ts +1 -1
- package/dist/products/network-products.js +1 -1
- package/dist/products/network.d.ts +1 -1
- package/dist/products/observability.d.ts +1 -1
- package/dist/products/private-network.d.ts +1 -1
- package/dist/products/secrets.d.ts +3 -3
- package/dist/products/switching.d.ts +2 -3
- package/dist/runloop/index.js +6 -2
- package/dist/sandbox.d.ts +7 -84
- package/dist/sandbox.js +58 -345
- package/dist/tar.d.ts +2 -0
- package/dist/tar.js +74 -16
- package/dist/transport.d.ts +36 -8
- package/dist/transport.js +174 -37
- package/dist/types.d.ts +102 -12
- package/dist/vercel/filesystem.js +3 -1
- package/dist/vercel/sandbox.d.ts +18 -12
- package/dist/vercel/sandbox.js +27 -15
- package/dist/wait.d.ts +12 -0
- package/dist/wait.js +47 -0
- package/package.json +1 -1
|
@@ -119,7 +119,9 @@ export class FileSystem {
|
|
|
119
119
|
const result = await this.#call(syscall, path, () => this.#ctx.run(argv, options));
|
|
120
120
|
if (result.exitCode === 0)
|
|
121
121
|
return result.stdout;
|
|
122
|
-
|
|
122
|
+
// dash, the sh of Debian and Ubuntu (a Runtime sandbox's), says "cannot
|
|
123
|
+
// create ...: Directory nonexistent" for a missing parent.
|
|
124
|
+
if (/No such file or directory|Directory nonexistent/.test(result.stderr))
|
|
123
125
|
throw fsError("ENOENT", syscall, path);
|
|
124
126
|
if (syscall === "unlink" || syscall === "rm")
|
|
125
127
|
throw fsError("EACCES", syscall, path);
|
package/dist/vercel/sandbox.d.ts
CHANGED
|
@@ -9,7 +9,9 @@ import { Snapshot } from "./snapshot.js";
|
|
|
9
9
|
* 2026). Runtime gives 2 vCPU and 4096 MiB. */
|
|
10
10
|
export declare const DEFAULT_VCPUS = 2;
|
|
11
11
|
export declare const MEMORY_MIB_PER_VCPU = 2048;
|
|
12
|
-
/** Vercel's default timeout, 5 minutes.
|
|
12
|
+
/** Vercel's default timeout, 5 minutes. Not sent: a sandbox created with no
|
|
13
|
+
* timeout has no time limit on Runtime, running while it works and pausing
|
|
14
|
+
* when idle (0300). Kept for code that imports it. */
|
|
13
15
|
export declare const DEFAULT_TIMEOUT_MS = 300000;
|
|
14
16
|
/** Vercel's working directory; `/workspace` on Runtime. */
|
|
15
17
|
export declare const HOME = "/vercel/sandbox";
|
|
@@ -40,9 +42,10 @@ export interface CreateSandboxParams extends Credentials {
|
|
|
40
42
|
/** Shared at public HTTPS addresses (Runtime previews); `domain(port)`
|
|
41
43
|
* answers from them. */
|
|
42
44
|
ports?: number[];
|
|
43
|
-
/** Milliseconds
|
|
44
|
-
*
|
|
45
|
-
*
|
|
45
|
+
/** Milliseconds, at least 60 s: when it stops. Leave it out for no time
|
|
46
|
+
* limit: it runs while it works and pauses when idle. Over an hour, the
|
|
47
|
+
* hour-long limit is extended while this object lives, up to the timeout
|
|
48
|
+
* (`sandbox.timeout`). */
|
|
46
49
|
timeout?: number;
|
|
47
50
|
resources?: {
|
|
48
51
|
vcpus: number;
|
|
@@ -135,15 +138,16 @@ export declare class Sandbox {
|
|
|
135
138
|
get cwd(): string;
|
|
136
139
|
get status(): "pending" | "running" | "stopping" | "stopped";
|
|
137
140
|
/** Milliseconds from the start of the session: the timeout given at
|
|
138
|
-
* create, with every extension, or the
|
|
141
|
+
* create, with every extension, or the time limit of a sandbox found by
|
|
142
|
+
* name. 0 for one with no time limit, which runs while it works. */
|
|
139
143
|
get timeout(): number;
|
|
140
144
|
get expiresAt(): Date;
|
|
141
145
|
get tags(): Record<string, string>;
|
|
142
146
|
get sourceSnapshotId(): string | undefined;
|
|
143
147
|
/** Creates a sandbox and waits until it runs. Vercel's defaults: 2 vCPUs,
|
|
144
|
-
* 2048 MiB per vCPU,
|
|
145
|
-
*
|
|
146
|
-
* credit, exactly as withruntime's own create. */
|
|
148
|
+
* 2048 MiB per vCPU, persistent. With no `timeout` it has no time limit: it
|
|
149
|
+
* runs while it works and pauses when idle. A `timeout` is kept as given. Funding is left to
|
|
150
|
+
* Runtime: the included usage first, then prepaid credit, exactly as withruntime's own create. */
|
|
147
151
|
static create(params?: CreateSandboxParams): Promise<Sandbox & AsyncDisposable>;
|
|
148
152
|
/** A sandbox by name (or Runtime id), woken if it is paused unless
|
|
149
153
|
* `resume: false`. */
|
|
@@ -269,9 +273,10 @@ export declare class Sandbox {
|
|
|
269
273
|
signal?: AbortSignal;
|
|
270
274
|
}): Promise<void>;
|
|
271
275
|
[Symbol.asyncDispose](): Promise<void>;
|
|
272
|
-
/** Moves the end `duration` milliseconds later. The
|
|
273
|
-
* as far as it may (an hour ahead of now); past that it is extended
|
|
274
|
-
* this object lives.
|
|
276
|
+
/** Moves the end `duration` milliseconds later. The time limit moves at
|
|
277
|
+
* once as far as it may (an hour ahead of now); past that it is extended
|
|
278
|
+
* while this object lives. A sandbox with no time limit has no end to
|
|
279
|
+
* move, and nothing changes. */
|
|
275
280
|
extendTimeout(duration: number, opts?: {
|
|
276
281
|
signal?: AbortSignal;
|
|
277
282
|
}): Promise<void>;
|
|
@@ -281,7 +286,8 @@ export declare class Sandbox {
|
|
|
281
286
|
}): Promise<NetworkPolicy>;
|
|
282
287
|
/** Changes what Runtime can change on a sandbox: `timeout`, `ports`,
|
|
283
288
|
* `networkPolicy` and `snapshotExpiration`. Anything else is refused before
|
|
284
|
-
* anything changes.
|
|
289
|
+
* anything changes. A `timeout` on a sandbox with no time limit changes
|
|
290
|
+
* nothing: it runs while it works. */
|
|
285
291
|
update(params: {
|
|
286
292
|
timeout?: number;
|
|
287
293
|
ports?: number[];
|
package/dist/vercel/sandbox.js
CHANGED
|
@@ -13,7 +13,9 @@ import { Snapshot } from "./snapshot.js";
|
|
|
13
13
|
* 2026). Runtime gives 2 vCPU and 4096 MiB. */
|
|
14
14
|
export const DEFAULT_VCPUS = 2;
|
|
15
15
|
export const MEMORY_MIB_PER_VCPU = 2048;
|
|
16
|
-
/** Vercel's default timeout, 5 minutes.
|
|
16
|
+
/** Vercel's default timeout, 5 minutes. Not sent: a sandbox created with no
|
|
17
|
+
* timeout has no time limit on Runtime, running while it works and pausing
|
|
18
|
+
* when idle (0300). Kept for code that imports it. */
|
|
17
19
|
export const DEFAULT_TIMEOUT_MS = 300_000;
|
|
18
20
|
const MIN_LEASE_SECONDS = 60;
|
|
19
21
|
/** Extend a long timeout's lease when less than this is left. */
|
|
@@ -235,7 +237,8 @@ export class Sandbox {
|
|
|
235
237
|
return statusOf(this.#rt.state);
|
|
236
238
|
}
|
|
237
239
|
/** Milliseconds from the start of the session: the timeout given at
|
|
238
|
-
* create, with every extension, or the
|
|
240
|
+
* create, with every extension, or the time limit of a sandbox found by
|
|
241
|
+
* name. 0 for one with no time limit, which runs while it works. */
|
|
239
242
|
get timeout() {
|
|
240
243
|
return this.#timeoutMs ?? this.#rt.info.timeoutSeconds * 1000;
|
|
241
244
|
}
|
|
@@ -255,9 +258,9 @@ export class Sandbox {
|
|
|
255
258
|
}
|
|
256
259
|
// ---- create, get, list ------------------------------------------------
|
|
257
260
|
/** Creates a sandbox and waits until it runs. Vercel's defaults: 2 vCPUs,
|
|
258
|
-
* 2048 MiB per vCPU,
|
|
259
|
-
*
|
|
260
|
-
* credit, exactly as withruntime's own create. */
|
|
261
|
+
* 2048 MiB per vCPU, persistent. With no `timeout` it has no time limit: it
|
|
262
|
+
* runs while it works and pauses when idle. A `timeout` is kept as given. Funding is left to
|
|
263
|
+
* Runtime: the included usage first, then prepaid credit, exactly as withruntime's own create. */
|
|
261
264
|
static async create(params = {}) {
|
|
262
265
|
refuseCreate(params);
|
|
263
266
|
const client = clientFor(params);
|
|
@@ -268,7 +271,8 @@ export class Sandbox {
|
|
|
268
271
|
const source = await guard(() => resolveImage(client, params));
|
|
269
272
|
const input = {
|
|
270
273
|
...(source.snapshot ? {} : { vcpu: vcpus, memoryMiB: vcpus * MEMORY_MIB_PER_VCPU }),
|
|
271
|
-
|
|
274
|
+
// No timeout, no time limit: it runs while it works (0300).
|
|
275
|
+
...(params.timeout === undefined ? {} : { timeoutSeconds: leaseSeconds(params.timeout) }),
|
|
272
276
|
onLeaseEnd: persistent ? "pause" : "stop",
|
|
273
277
|
...(params.name ? { name: params.name } : {}),
|
|
274
278
|
...(params.tags && Object.keys(params.tags).length ? { labels: params.tags } : {}),
|
|
@@ -280,7 +284,7 @@ export class Sandbox {
|
|
|
280
284
|
const sandbox = new Sandbox({
|
|
281
285
|
runtime,
|
|
282
286
|
client,
|
|
283
|
-
params: { ...params, persistent
|
|
287
|
+
params: { ...params, persistent },
|
|
284
288
|
});
|
|
285
289
|
try {
|
|
286
290
|
await sandbox.#setUp(params);
|
|
@@ -643,20 +647,25 @@ export class Sandbox {
|
|
|
643
647
|
return;
|
|
644
648
|
await this.stop().catch(() => undefined);
|
|
645
649
|
}
|
|
646
|
-
/** Moves the end `duration` milliseconds later. The
|
|
647
|
-
* as far as it may (an hour ahead of now); past that it is extended
|
|
648
|
-
* this object lives.
|
|
650
|
+
/** Moves the end `duration` milliseconds later. The time limit moves at
|
|
651
|
+
* once as far as it may (an hour ahead of now); past that it is extended
|
|
652
|
+
* while this object lives. A sandbox with no time limit has no end to
|
|
653
|
+
* move, and nothing changes. */
|
|
649
654
|
async extendTimeout(duration, opts = {}) {
|
|
650
655
|
if (!Number.isFinite(duration) || duration <= 0)
|
|
651
656
|
throw new RangeError(`duration must be a positive number of milliseconds, not ${duration}.`);
|
|
652
657
|
await this.#withResume(async (runtime) => {
|
|
658
|
+
if (runtime.info.endsAt === null)
|
|
659
|
+
return;
|
|
653
660
|
this.#timeoutMs = this.timeout + duration;
|
|
654
661
|
await this.#leaseToTimeout(runtime, opts);
|
|
655
662
|
}, opts);
|
|
656
663
|
}
|
|
657
664
|
/** Extends the lease now toward the timeout, an hour ahead at most. */
|
|
658
665
|
async #leaseToTimeout(runtime, opts) {
|
|
659
|
-
|
|
666
|
+
if (runtime.info.endsAt === null)
|
|
667
|
+
return;
|
|
668
|
+
const seconds = extensionSeconds(Date.parse(runtime.info.endsAt ?? runtime.info.expiresAt), this.#until(), Date.now(), Infinity);
|
|
660
669
|
if (seconds >= 1)
|
|
661
670
|
await runtime.extend(seconds, signalOf(opts));
|
|
662
671
|
}
|
|
@@ -669,7 +678,8 @@ export class Sandbox {
|
|
|
669
678
|
}
|
|
670
679
|
/** Changes what Runtime can change on a sandbox: `timeout`, `ports`,
|
|
671
680
|
* `networkPolicy` and `snapshotExpiration`. Anything else is refused before
|
|
672
|
-
* anything changes.
|
|
681
|
+
* anything changes. A `timeout` on a sandbox with no time limit changes
|
|
682
|
+
* nothing: it runs while it works. */
|
|
673
683
|
async update(params, opts = {}) {
|
|
674
684
|
opts.signal?.throwIfAborted();
|
|
675
685
|
const allowed = new Set(["timeout", "ports", "networkPolicy", "snapshotExpiration"]);
|
|
@@ -683,13 +693,15 @@ export class Sandbox {
|
|
|
683
693
|
if (params.ports !== undefined)
|
|
684
694
|
validatePorts(params.ports);
|
|
685
695
|
const wanted = params.ports === undefined ? undefined : new Set(params.ports);
|
|
686
|
-
|
|
696
|
+
// A sandbox with no time limit has none to change (0300).
|
|
697
|
+
if (params.timeout !== undefined && this.#rt.info.endsAt !== null) {
|
|
687
698
|
const timeout = checkTimeout(params.timeout);
|
|
688
699
|
// A shorter timeout is kept when the lease has not reached it yet: the
|
|
689
700
|
// lease then stops being extended there. Runtime cannot end a lease
|
|
690
701
|
// earlier than it was given.
|
|
691
|
-
|
|
692
|
-
|
|
702
|
+
const end = this.#rt.info.endsAt ?? this.#rt.info.expiresAt;
|
|
703
|
+
if (this.#sessionStart + timeout < Date.parse(end) - 1000)
|
|
704
|
+
throw new NotSupportedError("A timeout that ends earlier than the current lease", `The lease runs to ${end}; call stop() when the work is done, or pass a timeout that ends after it.`);
|
|
693
705
|
const longer = timeout > this.timeout;
|
|
694
706
|
this.#timeoutMs = timeout;
|
|
695
707
|
if (longer)
|
package/dist/wait.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RequestOptions } from "./transport.js";
|
|
2
|
+
/** A wait that an abort ends at once, rejecting with the signal's reason. */
|
|
3
|
+
export declare function pause(ms: number, signal?: AbortSignal): Promise<void>;
|
|
4
|
+
export declare function abortError(signal: AbortSignal): Error;
|
|
5
|
+
/**
|
|
6
|
+
* Calls `attempt` until it stops answering one of `codes` (something is
|
|
7
|
+
* still installing), within one budget: the caller's `timeoutMs`, else ten
|
|
8
|
+
* minutes. Each try gets what is left of it; a wait between tries ends at once
|
|
9
|
+
* on abort, and no try starts once the budget cannot cover the wait the API
|
|
10
|
+
* asked for: the installing error is thrown instead.
|
|
11
|
+
*/
|
|
12
|
+
export declare function whileInstalling<T>(codes: readonly string[], options: RequestOptions | undefined, attempt: (options: RequestOptions) => Promise<T>): Promise<T>;
|
package/dist/wait.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** A wait that an abort ends at once, rejecting with the signal's reason. */
|
|
2
|
+
export function pause(ms, signal) {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
if (signal?.aborted)
|
|
5
|
+
return reject(abortError(signal));
|
|
6
|
+
const timer = setTimeout(() => {
|
|
7
|
+
signal?.removeEventListener("abort", stop);
|
|
8
|
+
resolve();
|
|
9
|
+
}, ms);
|
|
10
|
+
function stop() {
|
|
11
|
+
clearTimeout(timer);
|
|
12
|
+
reject(abortError(signal));
|
|
13
|
+
}
|
|
14
|
+
signal?.addEventListener("abort", stop, { once: true });
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export function abortError(signal) {
|
|
18
|
+
return signal.reason instanceof Error ? signal.reason : new Error("Aborted");
|
|
19
|
+
}
|
|
20
|
+
/** How long a start waits for a first install (Chromium, the desktop) when
|
|
21
|
+
* the caller sets no deadline. */
|
|
22
|
+
const INSTALL_WAIT_MS = 600_000;
|
|
23
|
+
/**
|
|
24
|
+
* Calls `attempt` until it stops answering one of `codes` (something is
|
|
25
|
+
* still installing), within one budget: the caller's `timeoutMs`, else ten
|
|
26
|
+
* minutes. Each try gets what is left of it; a wait between tries ends at once
|
|
27
|
+
* on abort, and no try starts once the budget cannot cover the wait the API
|
|
28
|
+
* asked for: the installing error is thrown instead.
|
|
29
|
+
*/
|
|
30
|
+
export async function whileInstalling(codes, options, attempt) {
|
|
31
|
+
const deadline = performance.now() + (options?.timeoutMs || INSTALL_WAIT_MS);
|
|
32
|
+
for (;;) {
|
|
33
|
+
if (options?.signal?.aborted)
|
|
34
|
+
throw abortError(options.signal);
|
|
35
|
+
const left = Math.max(1, Math.ceil(deadline - performance.now()));
|
|
36
|
+
try {
|
|
37
|
+
return await attempt(options?.timeoutMs ? { ...options, timeoutMs: left } : { ...options });
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
const code = error.code;
|
|
41
|
+
const wait = error.retryAfterMs ?? 10_000;
|
|
42
|
+
if (!code || !codes.includes(code) || performance.now() + wait > deadline)
|
|
43
|
+
throw error;
|
|
44
|
+
await pause(wait, options?.signal);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|