withruntime 0.11.0 → 0.11.1
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 +7 -8
- package/DAYTONA.md +7 -8
- package/E2B.md +16 -2
- package/README.md +3 -3
- package/README.src.md +3 -3
- package/VERCEL.md +3 -2
- package/compatibility-lock.json +55 -0
- package/dist/api-defaults.d.ts +1 -1
- package/dist/api-defaults.js +1 -1
- package/dist/blaxel/lookup.d.ts +2 -1
- package/dist/blaxel/lookup.js +2 -1
- package/dist/blaxel/sandbox.d.ts +7 -5
- package/dist/blaxel/sandbox.js +15 -10
- package/dist/cli.js +39 -15
- package/dist/client.d.ts +5 -1
- package/dist/client.js +19 -3
- 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.js +29 -12
- package/dist/daytona/sandbox.d.ts +8 -3
- package/dist/daytona/sandbox.js +23 -4
- package/dist/e2b/sandbox.d.ts +7 -3
- package/dist/e2b/sandbox.js +21 -7
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +6 -0
- package/dist/identity.js +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/modal/index.js +6 -2
- package/dist/network-cli.js +7 -7
- 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 +7 -5
- package/dist/products/jobs.js +7 -3
- 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/observability.d.ts +1 -1
- package/dist/products/private-network.d.ts +1 -1
- package/dist/products/secrets.d.ts +2 -2
- package/dist/runloop/index.js +6 -2
- package/dist/sandbox.d.ts +27 -19
- package/dist/sandbox.js +121 -54
- package/dist/tar.d.ts +2 -0
- package/dist/tar.js +74 -16
- package/dist/transport.d.ts +33 -7
- package/dist/transport.js +171 -36
- package/dist/types.d.ts +54 -9
- package/dist/vercel/filesystem.js +3 -1
- package/dist/vercel/sandbox.d.ts +17 -10
- package/dist/vercel/sandbox.js +26 -13
- package/dist/wait.d.ts +12 -0
- package/dist/wait.js +47 -0
- package/package.json +1 -1
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,7 +258,8 @@ 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,
|
|
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
|
|
259
263
|
* Runtime: the free trial while the account has trial time, then prepaid
|
|
260
264
|
* credit, exactly as withruntime's own create. */
|
|
261
265
|
static async create(params = {}) {
|
|
@@ -268,7 +272,8 @@ export class Sandbox {
|
|
|
268
272
|
const source = await guard(() => resolveImage(client, params));
|
|
269
273
|
const input = {
|
|
270
274
|
...(source.snapshot ? {} : { vcpu: vcpus, memoryMiB: vcpus * MEMORY_MIB_PER_VCPU }),
|
|
271
|
-
|
|
275
|
+
// No timeout, no time limit: it runs while it works (0300).
|
|
276
|
+
...(params.timeout === undefined ? {} : { timeoutSeconds: leaseSeconds(params.timeout) }),
|
|
272
277
|
onLeaseEnd: persistent ? "pause" : "stop",
|
|
273
278
|
...(params.name ? { name: params.name } : {}),
|
|
274
279
|
...(params.tags && Object.keys(params.tags).length ? { labels: params.tags } : {}),
|
|
@@ -280,7 +285,7 @@ export class Sandbox {
|
|
|
280
285
|
const sandbox = new Sandbox({
|
|
281
286
|
runtime,
|
|
282
287
|
client,
|
|
283
|
-
params: { ...params, persistent
|
|
288
|
+
params: { ...params, persistent },
|
|
284
289
|
});
|
|
285
290
|
try {
|
|
286
291
|
await sandbox.#setUp(params);
|
|
@@ -643,20 +648,25 @@ export class Sandbox {
|
|
|
643
648
|
return;
|
|
644
649
|
await this.stop().catch(() => undefined);
|
|
645
650
|
}
|
|
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.
|
|
651
|
+
/** Moves the end `duration` milliseconds later. The time limit moves at
|
|
652
|
+
* once as far as it may (an hour ahead of now); past that it is extended
|
|
653
|
+
* while this object lives. A sandbox with no time limit has no end to
|
|
654
|
+
* move, and nothing changes. */
|
|
649
655
|
async extendTimeout(duration, opts = {}) {
|
|
650
656
|
if (!Number.isFinite(duration) || duration <= 0)
|
|
651
657
|
throw new RangeError(`duration must be a positive number of milliseconds, not ${duration}.`);
|
|
652
658
|
await this.#withResume(async (runtime) => {
|
|
659
|
+
if (runtime.info.endsAt === null)
|
|
660
|
+
return;
|
|
653
661
|
this.#timeoutMs = this.timeout + duration;
|
|
654
662
|
await this.#leaseToTimeout(runtime, opts);
|
|
655
663
|
}, opts);
|
|
656
664
|
}
|
|
657
665
|
/** Extends the lease now toward the timeout, an hour ahead at most. */
|
|
658
666
|
async #leaseToTimeout(runtime, opts) {
|
|
659
|
-
|
|
667
|
+
if (runtime.info.endsAt === null)
|
|
668
|
+
return;
|
|
669
|
+
const seconds = extensionSeconds(Date.parse(runtime.info.endsAt ?? runtime.info.expiresAt), this.#until(), Date.now(), Infinity);
|
|
660
670
|
if (seconds >= 1)
|
|
661
671
|
await runtime.extend(seconds, signalOf(opts));
|
|
662
672
|
}
|
|
@@ -669,7 +679,8 @@ export class Sandbox {
|
|
|
669
679
|
}
|
|
670
680
|
/** Changes what Runtime can change on a sandbox: `timeout`, `ports`,
|
|
671
681
|
* `networkPolicy` and `snapshotExpiration`. Anything else is refused before
|
|
672
|
-
* anything changes.
|
|
682
|
+
* anything changes. A `timeout` on a sandbox with no time limit changes
|
|
683
|
+
* nothing: it runs while it works. */
|
|
673
684
|
async update(params, opts = {}) {
|
|
674
685
|
opts.signal?.throwIfAborted();
|
|
675
686
|
const allowed = new Set(["timeout", "ports", "networkPolicy", "snapshotExpiration"]);
|
|
@@ -683,13 +694,15 @@ export class Sandbox {
|
|
|
683
694
|
if (params.ports !== undefined)
|
|
684
695
|
validatePorts(params.ports);
|
|
685
696
|
const wanted = params.ports === undefined ? undefined : new Set(params.ports);
|
|
686
|
-
|
|
697
|
+
// A sandbox with no time limit has none to change (0300).
|
|
698
|
+
if (params.timeout !== undefined && this.#rt.info.endsAt !== null) {
|
|
687
699
|
const timeout = checkTimeout(params.timeout);
|
|
688
700
|
// A shorter timeout is kept when the lease has not reached it yet: the
|
|
689
701
|
// lease then stops being extended there. Runtime cannot end a lease
|
|
690
702
|
// earlier than it was given.
|
|
691
|
-
|
|
692
|
-
|
|
703
|
+
const end = this.#rt.info.endsAt ?? this.#rt.info.expiresAt;
|
|
704
|
+
if (this.#sessionStart + timeout < Date.parse(end) - 1000)
|
|
705
|
+
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
706
|
const longer = timeout > this.timeout;
|
|
694
707
|
this.#timeoutMs = timeout;
|
|
695
708
|
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
|
+
}
|