withruntime 0.11.1 → 0.12.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 +3 -3
- package/COMPATIBILITY.md +74 -9
- package/DAYTONA.md +33 -5
- package/E2B.md +137 -48
- package/README.md +11 -9
- package/README.src.md +11 -9
- package/VERCEL.md +43 -5
- package/compatibility-lock.json +58 -49
- package/dist/billing-cli.d.ts +1 -1
- package/dist/billing-cli.js +77 -1
- package/dist/blaxel/errors.d.ts +14 -0
- package/dist/blaxel/errors.js +33 -4
- package/dist/blaxel/index.d.ts +2 -2
- package/dist/blaxel/index.js +4 -4
- package/dist/blaxel/interpreter.d.ts +2 -5
- package/dist/blaxel/sandbox.d.ts +15 -7
- package/dist/blaxel/sandbox.js +64 -9
- package/dist/blaxel/snapshot.d.ts +4 -0
- package/dist/blaxel/snapshot.js +4 -0
- package/dist/cli/logs.d.ts +21 -0
- package/dist/cli/logs.js +188 -0
- package/dist/cli/logs.test.d.ts +1 -0
- package/dist/cli/logs.test.js +272 -0
- package/dist/cli-extras.d.ts +3 -3
- package/dist/cli-extras.js +17 -12
- package/dist/cli-words.d.ts +10 -1
- package/dist/cli-words.js +18 -0
- package/dist/cli.d.ts +6 -2
- package/dist/cli.js +468 -219
- package/dist/client.d.ts +13 -63
- package/dist/client.js +35 -124
- package/dist/cloudflare/errors.d.ts +143 -0
- package/dist/cloudflare/errors.js +167 -0
- package/dist/cloudflare/index.d.ts +175 -6
- package/dist/cloudflare/index.js +416 -26
- package/dist/cloudflare/interpreter.d.ts +119 -0
- package/dist/cloudflare/interpreter.js +223 -0
- package/dist/cloudflare/streams.d.ts +38 -0
- package/dist/cloudflare/streams.js +145 -0
- package/dist/cloudflare/watch.d.ts +9 -0
- package/dist/cloudflare/watch.js +24 -0
- package/dist/codesandbox/index.d.ts +216 -28
- package/dist/codesandbox/index.js +478 -78
- package/dist/compat/core.d.ts +18 -0
- package/dist/compat/core.js +29 -0
- package/dist/compat/files.d.ts +1 -0
- package/dist/compat/files.js +25 -5
- package/dist/daytona/computer-use.d.ts +13 -4
- package/dist/daytona/computer-use.js +66 -8
- package/dist/daytona/daytona.d.ts +7 -2
- package/dist/daytona/daytona.js +31 -5
- package/dist/daytona/errors.d.ts +11 -0
- package/dist/daytona/errors.js +18 -0
- package/dist/daytona/filesystem.js +2 -1
- package/dist/daytona/image.d.ts +13 -9
- package/dist/daytona/image.js +18 -12
- package/dist/daytona/index.d.ts +1 -1
- package/dist/daytona/sandbox.d.ts +9 -3
- package/dist/daytona/sandbox.js +17 -3
- package/dist/domains/index.d.ts +9 -0
- package/dist/domains/index.js +10 -0
- package/dist/e2b/client.d.ts +15 -2
- package/dist/e2b/client.js +61 -7
- package/dist/e2b/commands.d.ts +4 -1
- package/dist/e2b/commands.js +17 -7
- package/dist/e2b/errors.d.ts +43 -2
- package/dist/e2b/errors.js +78 -6
- package/dist/e2b/filesystem.d.ts +1 -1
- package/dist/e2b/filesystem.js +82 -16
- package/dist/e2b/index.d.ts +3 -3
- package/dist/e2b/index.js +2 -2
- package/dist/e2b/sandbox.d.ts +50 -35
- package/dist/e2b/sandbox.js +228 -185
- package/dist/e2b/unsupported.d.ts +19 -0
- package/dist/e2b/unsupported.js +22 -1
- package/dist/e2b/users.d.ts +9 -0
- package/dist/e2b/users.js +22 -0
- package/dist/errors.d.ts +14 -5
- package/dist/errors.js +28 -14
- package/dist/freestyle/index.d.ts +285 -37
- package/dist/freestyle/index.js +656 -144
- package/dist/identity.d.ts +3 -0
- package/dist/identity.js +27 -0
- package/dist/images/index.d.ts +9 -0
- package/dist/images/index.js +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/ips/index.d.ts +9 -0
- package/dist/ips/index.js +10 -0
- package/dist/jobs/index.d.ts +9 -0
- package/dist/jobs/index.js +10 -0
- package/dist/keys.js +2 -0
- package/dist/login.js +2 -0
- package/dist/machine.d.ts +189 -0
- package/dist/machine.js +521 -0
- package/dist/mcp.js +1 -1
- package/dist/modal/index.d.ts +339 -61
- package/dist/modal/index.js +781 -121
- package/dist/network-cli.d.ts +3 -1
- package/dist/network-cli.js +78 -36
- package/dist/networks/index.d.ts +11 -0
- package/dist/networks/index.js +10 -0
- package/dist/openai-agents/index.d.ts +1 -1
- package/dist/openai-agents/index.js +1 -1
- package/dist/ports/index.d.ts +9 -0
- package/dist/ports/index.js +10 -0
- package/dist/product-names.d.ts +52 -0
- package/dist/product-names.js +164 -0
- package/dist/product-renames.d.ts +103 -0
- package/dist/product-renames.js +189 -0
- package/dist/products/apps.d.ts +176 -0
- package/dist/products/apps.js +165 -0
- package/dist/products/billing.d.ts +41 -0
- package/dist/products/billing.js +13 -0
- package/dist/products/browser.d.ts +10 -0
- package/dist/products/browsers.d.ts +71 -0
- package/dist/products/browsers.js +102 -0
- package/dist/products/builds.d.ts +126 -0
- package/dist/products/builds.js +221 -0
- package/dist/products/index.d.ts +3 -16
- package/dist/products/index.js +3 -14
- package/dist/products/jobs.d.ts +19 -3
- package/dist/products/jobs.js +28 -12
- package/dist/products/limits.d.ts +4 -10
- package/dist/products/logs.d.ts +245 -0
- package/dist/products/logs.js +274 -0
- package/dist/products/logs.test.d.ts +1 -0
- package/dist/products/logs.test.js +343 -0
- package/dist/products/network-products.d.ts +38 -7
- package/dist/products/network-products.js +31 -18
- package/dist/products/network.d.ts +1 -1
- package/dist/products/observability.d.ts +3 -2
- package/dist/products/private-network.js +1 -1
- package/dist/products/queues.d.ts +149 -0
- package/dist/products/queues.js +213 -0
- package/dist/products/referrals.d.ts +21 -7
- package/dist/products/referrals.js +3 -3
- package/dist/products/secrets.d.ts +8 -4
- package/dist/products/secrets.js +39 -18
- package/dist/products/signed-requests.d.ts +21 -0
- package/dist/products/signed-requests.js +11 -0
- package/dist/products/streams.d.ts +73 -0
- package/dist/products/streams.js +17 -0
- package/dist/products/switching.d.ts +37 -10
- package/dist/products/switching.js +4 -3
- package/dist/products/volumes.d.ts +3 -0
- package/dist/record-cli.d.ts +23 -0
- package/dist/record-cli.js +308 -0
- package/dist/renamed-products.d.ts +38 -0
- package/dist/renamed-products.js +34 -0
- package/dist/runloop/index.d.ts +9 -2
- package/dist/runloop/index.js +29 -8
- package/dist/runloop/sdk.d.ts +131 -0
- package/dist/runloop/sdk.js +167 -0
- package/dist/sandbox.d.ts +10 -94
- package/dist/sandbox.js +22 -371
- package/dist/sandboxes/index.d.ts +11 -0
- package/dist/sandboxes/index.js +12 -0
- package/dist/snapshots/index.d.ts +9 -0
- package/dist/snapshots/index.js +11 -0
- package/dist/snapshots.d.ts +7 -4
- package/dist/sprites/index.d.ts +343 -31
- package/dist/sprites/index.js +866 -84
- package/dist/ssh.d.ts +1 -1
- package/dist/ssh.js +11 -11
- package/dist/terminal.d.ts +24 -0
- package/dist/terminal.js +32 -0
- package/dist/transport.d.ts +18 -2
- package/dist/transport.js +61 -6
- package/dist/tunnel.js +1 -1
- package/dist/types.d.ts +116 -8
- package/dist/vercel/sandbox.d.ts +1 -2
- package/dist/vercel/sandbox.js +6 -5
- package/dist/vercel/snapshot.js +10 -2
- package/dist/volumes/index.d.ts +9 -0
- package/dist/volumes/index.js +10 -0
- package/package.json +48 -2
package/dist/ssh.d.ts
CHANGED
|
@@ -16,6 +16,6 @@ export declare function sshKey(env: NodeJS.ProcessEnv): Promise<{
|
|
|
16
16
|
export declare function resolveSandbox(runtime: Runtime, target: string): Promise<Sandbox>;
|
|
17
17
|
export declare function sshConfig(env: NodeJS.ProcessEnv): Promise<string>;
|
|
18
18
|
export declare function sshCommand(argv: string[], env: NodeJS.ProcessEnv, out: Out, connect: () => Promise<Runtime>, me: string): Promise<number>;
|
|
19
|
-
/** `runtime
|
|
19
|
+
/** `runtime sandboxes port-forward <id> 5432 8080:3000 ...` */
|
|
20
20
|
export declare function portForwardCommand(argv: string[], out: Out, connect: () => Promise<Runtime>, me: string): Promise<number>;
|
|
21
21
|
export {};
|
package/dist/ssh.js
CHANGED
|
@@ -6,12 +6,12 @@ import { isAbsolute, join } from "node:path";
|
|
|
6
6
|
import { RuntimeError } from "./errors.js";
|
|
7
7
|
import { VERSION } from "./transport.js";
|
|
8
8
|
const UUID = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
|
|
9
|
-
export const SSH_HELP = (me) => `${me}
|
|
10
|
-
${me}
|
|
9
|
+
export const SSH_HELP = (me) => `${me} sandboxes ssh <id|name> [-- <command...>] Log in over SSH (an interactive shell, or run the command)
|
|
10
|
+
${me} sandboxes ssh config [--install] The ssh config for \`ssh <id|name>.runtime\`, also from
|
|
11
11
|
VS Code Remote-SSH and JetBrains Gateway; --install adds
|
|
12
12
|
it to ~/.ssh/config
|
|
13
|
-
${me}
|
|
14
|
-
${me}
|
|
13
|
+
${me} sandboxes ssh proxy <id|name>[.runtime] ProxyCommand mode: SSH on stdin and stdout
|
|
14
|
+
${me} sandboxes port-forward <id|name> <port|local:remote>... [--address 127.0.0.1]
|
|
15
15
|
Forward local ports to ports in the sandbox, until Ctrl-C
|
|
16
16
|
|
|
17
17
|
SSH and port forwarding go through Runtime's API with your key: the sandbox opens
|
|
@@ -63,7 +63,7 @@ export async function resolveSandbox(runtime, target) {
|
|
|
63
63
|
: `No live sandbox is named ${name}.`,
|
|
64
64
|
code: page.data.length ? "ambiguous_name" : "sandbox_not_found",
|
|
65
65
|
status: 0,
|
|
66
|
-
hint: "Use its id: runtime
|
|
66
|
+
hint: "Use its id: runtime sandboxes ls",
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
const quote = (text) => /^[A-Za-z0-9_./:@=-]+$/.test(text) ? text : `'${text.replace(/'/g, "'\\''")}'`;
|
|
@@ -193,7 +193,7 @@ export async function sshCommand(argv, env, out, connect, me) {
|
|
|
193
193
|
}
|
|
194
194
|
if (first === "proxy") {
|
|
195
195
|
if (!second)
|
|
196
|
-
throw usageError(`Give the host: ${me}
|
|
196
|
+
throw usageError(`Give the host: ${me} sandboxes ssh proxy <id>.runtime`, me);
|
|
197
197
|
return proxy(await connect(), second, await publicKey());
|
|
198
198
|
}
|
|
199
199
|
const runtime = await connect();
|
|
@@ -223,7 +223,7 @@ export async function sshCommand(argv, env, out, connect, me) {
|
|
|
223
223
|
message: `Could not run ssh: ${error.message}`,
|
|
224
224
|
code: "ssh_missing",
|
|
225
225
|
status: 0,
|
|
226
|
-
hint: "Install OpenSSH, or use `runtime
|
|
226
|
+
hint: "Install OpenSSH, or use `runtime sandboxes shell <id>`, which needs nothing.",
|
|
227
227
|
})));
|
|
228
228
|
child.on("exit", (code) => resolve(code ?? 255));
|
|
229
229
|
});
|
|
@@ -233,10 +233,10 @@ function usageError(message, me) {
|
|
|
233
233
|
message,
|
|
234
234
|
code: "usage",
|
|
235
235
|
status: 0,
|
|
236
|
-
hint: `Run \`${me}
|
|
236
|
+
hint: `Run \`${me} sandboxes ssh help\`.`,
|
|
237
237
|
});
|
|
238
238
|
}
|
|
239
|
-
/** `runtime
|
|
239
|
+
/** `runtime sandboxes port-forward <id> 5432 8080:3000 ...` */
|
|
240
240
|
export async function portForwardCommand(argv, out, connect, me) {
|
|
241
241
|
const at = argv.indexOf("--address");
|
|
242
242
|
const address = at === -1 ? "127.0.0.1" : argv[at + 1];
|
|
@@ -244,10 +244,10 @@ export async function portForwardCommand(argv, out, connect, me) {
|
|
|
244
244
|
const [target, ...specs] = positional;
|
|
245
245
|
if (!target || !specs.length || !address)
|
|
246
246
|
throw new RuntimeError({
|
|
247
|
-
message: `Give a sandbox and at least one port: ${me}
|
|
247
|
+
message: `Give a sandbox and at least one port: ${me} sandboxes port-forward <id> 5432 8080:3000`,
|
|
248
248
|
code: "usage",
|
|
249
249
|
status: 0,
|
|
250
|
-
hint: `Run \`${me}
|
|
250
|
+
hint: `Run \`${me} sandboxes ssh help\`.`,
|
|
251
251
|
});
|
|
252
252
|
const ports = specs.map((spec) => {
|
|
253
253
|
const match = /^(?:(\d{1,5}):)?(\d{1,5})$/.exec(spec);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text that came from someone else's program, made safe to print on a
|
|
3
|
+
* terminal: log lines, labels, anything a customer's code wrote. Printed raw,
|
|
4
|
+
* an escape sequence in it could clear or rewrite the screen, set the
|
|
5
|
+
* clipboard (OSC 52), forge a link (OSC 8) or reorder what is read (Unicode
|
|
6
|
+
* direction overrides). Each such character is shown as its \uXXXX escape
|
|
7
|
+
* instead, so nothing is hidden and nothing acts. Tab stays; a newline inside
|
|
8
|
+
* one value is escaped too, so a line on screen is always one value.
|
|
9
|
+
*
|
|
10
|
+
* Only for a terminal: a pipe or a file gets the bytes as they are.
|
|
11
|
+
*/
|
|
12
|
+
export declare function terminalSafe(text: string): string;
|
|
13
|
+
/** As {@link terminalSafe}, for a stream of lines: its newlines stay. */
|
|
14
|
+
export declare function terminalSafeLines(text: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Writes a log stream (a sandbox process's, an image build's, a job run's) to
|
|
17
|
+
* `to`: escaped on a terminal, as written to a pipe or a file, or with `raw`.
|
|
18
|
+
* Not for `exec` or an attached process, whose output is the customer's own
|
|
19
|
+
* terminal session.
|
|
20
|
+
*/
|
|
21
|
+
export declare function logStream(to: {
|
|
22
|
+
isTTY?: boolean;
|
|
23
|
+
write(text: string): unknown;
|
|
24
|
+
}, raw: boolean): (text: string) => void;
|
package/dist/terminal.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text that came from someone else's program, made safe to print on a
|
|
3
|
+
* terminal: log lines, labels, anything a customer's code wrote. Printed raw,
|
|
4
|
+
* an escape sequence in it could clear or rewrite the screen, set the
|
|
5
|
+
* clipboard (OSC 52), forge a link (OSC 8) or reorder what is read (Unicode
|
|
6
|
+
* direction overrides). Each such character is shown as its \uXXXX escape
|
|
7
|
+
* instead, so nothing is hidden and nothing acts. Tab stays; a newline inside
|
|
8
|
+
* one value is escaped too, so a line on screen is always one value.
|
|
9
|
+
*
|
|
10
|
+
* Only for a terminal: a pipe or a file gets the bytes as they are.
|
|
11
|
+
*/
|
|
12
|
+
export function terminalSafe(text) {
|
|
13
|
+
return text.replace(UNSAFE, escaped);
|
|
14
|
+
}
|
|
15
|
+
/** As {@link terminalSafe}, for a stream of lines: its newlines stay. */
|
|
16
|
+
export function terminalSafeLines(text) {
|
|
17
|
+
return text.replace(UNSAFE_BUT_NEWLINE, escaped);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Writes a log stream (a sandbox process's, an image build's, a job run's) to
|
|
21
|
+
* `to`: escaped on a terminal, as written to a pipe or a file, or with `raw`.
|
|
22
|
+
* Not for `exec` or an attached process, whose output is the customer's own
|
|
23
|
+
* terminal session.
|
|
24
|
+
*/
|
|
25
|
+
export function logStream(to, raw) {
|
|
26
|
+
return (text) => void to.write(to.isTTY && !raw ? terminalSafeLines(text) : text);
|
|
27
|
+
}
|
|
28
|
+
const escaped = (char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
29
|
+
// C0 but tab, DEL, C1, and the Unicode marks and overrides that reorder text.
|
|
30
|
+
const CONTROLS = String.raw `\x00-\x08\x0b-\x1f\x7f-\x9f--`;
|
|
31
|
+
const UNSAFE = new RegExp(String.raw `[\n${CONTROLS}]`, "g");
|
|
32
|
+
const UNSAFE_BUT_NEWLINE = new RegExp(`[${CONTROLS}]`, "g");
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RuntimeError } from "./errors.js";
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.12.0";
|
|
3
3
|
export declare const DEFAULT_BASE_URL = "https://api.withruntime.com";
|
|
4
4
|
/** Runtime's API as code inside a Runtime sandbox reaches it: the sandbox's
|
|
5
5
|
* own host sends each request on to DEFAULT_BASE_URL over HTTPS. The API runs
|
|
@@ -50,7 +50,7 @@ export type Call = RequestOptions & {
|
|
|
50
50
|
retry?: boolean;
|
|
51
51
|
/** How long to keep retrying, with the same key and input, a refusal that
|
|
52
52
|
* clears when a sandbox stops or a host frees room (WAITS_FOR_ROOM): a
|
|
53
|
-
* full
|
|
53
|
+
* full slots without credit, a full quota, a full region. Then the refusal is thrown as
|
|
54
54
|
* it came. Only a create sets it; 0 or absent fails at once. */
|
|
55
55
|
waitForCapacityMs?: number;
|
|
56
56
|
/** Called each time a call waits for room, with the refusal it is waiting
|
|
@@ -84,6 +84,13 @@ export declare const DEFAULT_MAX_CONNECTIONS = 48;
|
|
|
84
84
|
* served, and wait rather than fail. Streams (a command's output, a download,
|
|
85
85
|
* a watch) take at most `maxConnections` less KEPT_FOR_CALLS of them. A
|
|
86
86
|
* terminal or tunnel's WebSocket is not counted. */
|
|
87
|
+
/** AbortSignal.timeout in whole milliseconds, rounded up, never under 1.
|
|
88
|
+
* Node throws ERR_OUT_OF_RANGE on a fraction (Bun accepts one), so a
|
|
89
|
+
* customer's timeoutMs of 1500.5 would be a RangeError instead of a request;
|
|
90
|
+
* the live promise probe broke this way on 9 October 2026 (d3cd4bfbd). Every
|
|
91
|
+
* deadline the SDK makes from a customer's or a computed value goes through
|
|
92
|
+
* this. */
|
|
93
|
+
export declare function timeoutSignal(ms: number): AbortSignal;
|
|
87
94
|
export declare class Transport {
|
|
88
95
|
#private;
|
|
89
96
|
readonly baseUrl: string;
|
|
@@ -103,6 +110,8 @@ export declare class Transport {
|
|
|
103
110
|
/** Connections held at once, answers and streams together; the rest
|
|
104
111
|
* wait their turn. Default 48: one address may hold 64 to the API. */
|
|
105
112
|
maxConnections?: number;
|
|
113
|
+
/** Called each time a call has to wait for one of those connections. */
|
|
114
|
+
onQueued?: (maxConnections: number) => void;
|
|
106
115
|
/** How long a create waits for room. Default 120 000; 0 fails at once. */
|
|
107
116
|
waitForCapacityMs?: number;
|
|
108
117
|
});
|
|
@@ -126,7 +135,14 @@ export declare class Transport {
|
|
|
126
135
|
/** A WebSocket to an API path, authenticated with the same key. */
|
|
127
136
|
websocket(path: string, query?: Query): Promise<WebSocket>;
|
|
128
137
|
}
|
|
138
|
+
/** CLOUD.md section 4: a call under a renamed product word is answered with a
|
|
139
|
+
* Warning naming the new word. It is printed once per process, to stderr, so
|
|
140
|
+
* a loop does not drown its own output and stdout stays the caller's. */
|
|
141
|
+
export declare function sayRenamed(header: string | null, say?: (line: string) => void): void;
|
|
129
142
|
/** A download that ended short of (or past) the length the API promised. */
|
|
130
143
|
export declare function incompleteDownload(got: number, expected: number): RuntimeError;
|
|
131
144
|
/** No key given, none in RUNTIME_API_KEY, and none saved by `runtime login`. */
|
|
132
145
|
export declare function missingKey(): RuntimeError;
|
|
146
|
+
/** Whether a fetch failure is a connection that never opened: its code, or
|
|
147
|
+
* one of its causes', says so. A timeout or a reset never counts. */
|
|
148
|
+
export declare function neverSent(cause: unknown): boolean;
|
package/dist/transport.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ConnectionError, DELIBERATE, errorFor, NOTHING_RAN, RuntimeError, WAITS_FOR_ROOM, } from "./errors.js";
|
|
2
2
|
import { describeRoute, envFetch, openWebSocket } from "./proxy.js";
|
|
3
|
-
|
|
3
|
+
import { warningText } from "./product-renames.js";
|
|
4
|
+
export const VERSION = "0.12.0";
|
|
4
5
|
export const DEFAULT_BASE_URL = "https://api.withruntime.com";
|
|
5
6
|
/** Runtime's API as code inside a Runtime sandbox reaches it: the sandbox's
|
|
6
7
|
* own host sends each request on to DEFAULT_BASE_URL over HTTPS. The API runs
|
|
@@ -120,7 +121,7 @@ function abortReason(signal) {
|
|
|
120
121
|
}
|
|
121
122
|
/** At most `maximum` holders at once; the rest wait their turn, first come
|
|
122
123
|
* first served. */
|
|
123
|
-
function slots(maximum) {
|
|
124
|
+
function slots(maximum, onWait) {
|
|
124
125
|
let active = 0;
|
|
125
126
|
const waiting = [];
|
|
126
127
|
return {
|
|
@@ -130,6 +131,7 @@ function slots(maximum) {
|
|
|
130
131
|
active++;
|
|
131
132
|
return;
|
|
132
133
|
}
|
|
134
|
+
onWait?.();
|
|
133
135
|
await new Promise((resolve, reject) => {
|
|
134
136
|
const ready = () => {
|
|
135
137
|
signal?.removeEventListener("abort", abort);
|
|
@@ -171,6 +173,15 @@ const KEPT_FOR_CALLS = 8;
|
|
|
171
173
|
* served, and wait rather than fail. Streams (a command's output, a download,
|
|
172
174
|
* a watch) take at most `maxConnections` less KEPT_FOR_CALLS of them. A
|
|
173
175
|
* terminal or tunnel's WebSocket is not counted. */
|
|
176
|
+
/** AbortSignal.timeout in whole milliseconds, rounded up, never under 1.
|
|
177
|
+
* Node throws ERR_OUT_OF_RANGE on a fraction (Bun accepts one), so a
|
|
178
|
+
* customer's timeoutMs of 1500.5 would be a RangeError instead of a request;
|
|
179
|
+
* the live promise probe broke this way on 9 October 2026 (d3cd4bfbd). Every
|
|
180
|
+
* deadline the SDK makes from a customer's or a computed value goes through
|
|
181
|
+
* this. */
|
|
182
|
+
export function timeoutSignal(ms) {
|
|
183
|
+
return AbortSignal.timeout(Math.max(1, Math.ceil(ms)));
|
|
184
|
+
}
|
|
174
185
|
export class Transport {
|
|
175
186
|
baseUrl;
|
|
176
187
|
#apiKey;
|
|
@@ -203,8 +214,9 @@ export class Transport {
|
|
|
203
214
|
this.#maxRetries = options.maxRetries ?? 4;
|
|
204
215
|
this.#client = options.client ?? `sdk-js/${VERSION}`;
|
|
205
216
|
const most = Math.max(1, options.maxConnections ?? DEFAULT_MAX_CONNECTIONS);
|
|
206
|
-
|
|
207
|
-
this.#
|
|
217
|
+
const queued = options.onQueued && (() => options.onQueued(most));
|
|
218
|
+
this.#slots = slots(most, queued);
|
|
219
|
+
this.#streams = slots(Math.max(1, most - KEPT_FOR_CALLS), queued);
|
|
208
220
|
this.waitForCapacityMs = Math.max(0, options.waitForCapacityMs ?? 120_000);
|
|
209
221
|
}
|
|
210
222
|
/** The key, found once on first use when it was not given. */
|
|
@@ -243,7 +255,7 @@ export class Transport {
|
|
|
243
255
|
#prepare(call) {
|
|
244
256
|
const timeoutMs = call.timeoutMs ?? this.#timeoutMs;
|
|
245
257
|
const roomMs = Math.max(0, call.waitForCapacityMs ?? 0);
|
|
246
|
-
const deadline = timeoutMs === 0 ? undefined :
|
|
258
|
+
const deadline = timeoutMs === 0 ? undefined : timeoutSignal(timeoutMs + roomMs);
|
|
247
259
|
const signal = deadline
|
|
248
260
|
? call.signal
|
|
249
261
|
? AbortSignal.any([call.signal, deadline])
|
|
@@ -312,6 +324,8 @@ export class Transport {
|
|
|
312
324
|
// An answer that ran nothing is sent again until the call's deadline.
|
|
313
325
|
const idleUntil = call.deadlineAt ?? performance.now() + NOTHING_RAN_MS;
|
|
314
326
|
let idleAttempt = 0;
|
|
327
|
+
// The last try never left, and was sent again at once.
|
|
328
|
+
let resentAtOnce = false;
|
|
315
329
|
for (;;) {
|
|
316
330
|
let response;
|
|
317
331
|
let inCallback = false;
|
|
@@ -342,6 +356,7 @@ export class Transport {
|
|
|
342
356
|
await response.body?.cancel().catch(() => { });
|
|
343
357
|
throw new TypeError(`fetch failed: Runtime answered a redirect (${response.status}).`);
|
|
344
358
|
}
|
|
359
|
+
sayRenamed(response.headers.get("warning"));
|
|
345
360
|
/* An answer that took longer than the API holds its headers (90 s)
|
|
346
361
|
comes as a 200 sent early, and then its JSON: the answer, or
|
|
347
362
|
{"error": ...} when the work failed after the status went
|
|
@@ -437,7 +452,14 @@ export class Transport {
|
|
|
437
452
|
throw cause;
|
|
438
453
|
if (signal?.aborted || !retry || attempt >= this.#maxRetries)
|
|
439
454
|
throw this.#connectionError(call, cause);
|
|
440
|
-
|
|
455
|
+
// A connection that never opened sent no byte of the request, so
|
|
456
|
+
// the next try, which may reach another server, goes at once; once
|
|
457
|
+
// in a row, so an API that is down is not hammered. Anything that
|
|
458
|
+
// may have reached a server (a reset, a timeout, a cut answer)
|
|
459
|
+
// keeps the backoff and its key's rules.
|
|
460
|
+
const atOnce = response === undefined && neverSent(cause) && !resentAtOnce;
|
|
461
|
+
resentAtOnce = atOnce;
|
|
462
|
+
await this.#rest(atOnce ? Math.random() * 50 : backoff(attempt), signal, gate).catch((cause) => {
|
|
441
463
|
throw cause instanceof RuntimeError ? cause : this.#connectionError(call, cause);
|
|
442
464
|
});
|
|
443
465
|
}
|
|
@@ -626,6 +648,17 @@ export class Transport {
|
|
|
626
648
|
}
|
|
627
649
|
/** The status a late answer's body failed with, or undefined when it is an
|
|
628
650
|
* answer. The body is the error the API would have sent as its status. */
|
|
651
|
+
const said = new Set();
|
|
652
|
+
/** CLOUD.md section 4: a call under a renamed product word is answered with a
|
|
653
|
+
* Warning naming the new word. It is printed once per process, to stderr, so
|
|
654
|
+
* a loop does not drown its own output and stdout stays the caller's. */
|
|
655
|
+
export function sayRenamed(header, say = console.warn) {
|
|
656
|
+
const text = warningText(header);
|
|
657
|
+
if (text === undefined || said.has(text))
|
|
658
|
+
return;
|
|
659
|
+
said.add(text);
|
|
660
|
+
say(`Runtime: ${text}`);
|
|
661
|
+
}
|
|
629
662
|
function lateFailure(text) {
|
|
630
663
|
let body;
|
|
631
664
|
try {
|
|
@@ -686,6 +719,28 @@ export function missingKey() {
|
|
|
686
719
|
hint: "Run `npx -y withruntime login` (a browser approval; nothing to copy), set RUNTIME_API_KEY to a key from https://withruntime.com/account/keys, or pass { apiKey }.",
|
|
687
720
|
});
|
|
688
721
|
}
|
|
722
|
+
/** Error codes of a connection that never opened (Node's and Bun's), so no
|
|
723
|
+
* byte of the request left this machine. */
|
|
724
|
+
const NEVER_OPENED = new Set([
|
|
725
|
+
"ECONNREFUSED",
|
|
726
|
+
"ENOENT",
|
|
727
|
+
"EHOSTUNREACH",
|
|
728
|
+
"ENETUNREACH",
|
|
729
|
+
"EADDRNOTAVAIL",
|
|
730
|
+
"ConnectionRefused",
|
|
731
|
+
"FailedToOpenSocket",
|
|
732
|
+
]);
|
|
733
|
+
/** Whether a fetch failure is a connection that never opened: its code, or
|
|
734
|
+
* one of its causes', says so. A timeout or a reset never counts. */
|
|
735
|
+
export function neverSent(cause) {
|
|
736
|
+
for (let at = cause, depth = 0; at && depth < 5; depth++) {
|
|
737
|
+
const code = at.code;
|
|
738
|
+
if (typeof code === "string" && NEVER_OPENED.has(code))
|
|
739
|
+
return true;
|
|
740
|
+
at = at.cause;
|
|
741
|
+
}
|
|
742
|
+
return false;
|
|
743
|
+
}
|
|
689
744
|
function backoff(attempt) {
|
|
690
745
|
return Math.min(8000, 250 * 2 ** attempt) * (0.5 + Math.random());
|
|
691
746
|
}
|
package/dist/tunnel.js
CHANGED
|
@@ -222,7 +222,7 @@ export class Tunnel {
|
|
|
222
222
|
message: `Nothing is listening on port ${port} in the sandbox.`,
|
|
223
223
|
code: "port_closed",
|
|
224
224
|
status: 0,
|
|
225
|
-
hint: "Start the server with spawn (`runtime
|
|
225
|
+
hint: "Start the server with spawn (`runtime sandboxes spawn <id> -- <command>`, sbx.spawn()), which keeps it running: a process started by exec ends with its command. Let it listen on 127.0.0.1, ::1 or every address.",
|
|
226
226
|
})
|
|
227
227
|
: error.message === "reserved"
|
|
228
228
|
? new RuntimeError({
|
package/dist/types.d.ts
CHANGED
|
@@ -33,7 +33,10 @@ export type SandboxInfo = {
|
|
|
33
33
|
persistent?: boolean;
|
|
34
34
|
/** The last exec, file, terminal, desktop or preview request, to within a minute. */
|
|
35
35
|
lastActiveAt?: string | null;
|
|
36
|
-
|
|
36
|
+
/** What happens when its time limit, credit or a spending limit ends it. */
|
|
37
|
+
onLeaseEnd: "pause" | "stop" | "delete";
|
|
38
|
+
/** onLeaseEnd's newer name (0381): the same value. */
|
|
39
|
+
onTimeout?: "pause" | "stop" | "delete";
|
|
37
40
|
createdAt: string;
|
|
38
41
|
readyAt: string | null;
|
|
39
42
|
/** Paid up to: a time ahead of now that moves on by itself while it runs.
|
|
@@ -79,13 +82,17 @@ export type SandboxInfo = {
|
|
|
79
82
|
};
|
|
80
83
|
export type CreateSandbox = {
|
|
81
84
|
name?: string;
|
|
85
|
+
/** What the end of an `await using` block does to it. By default the
|
|
86
|
+
* block deletes it; `keep: true` stops it instead, which keeps its disk
|
|
87
|
+
* (billed while it is kept). Not sent to the API. */
|
|
88
|
+
keep?: boolean;
|
|
82
89
|
labels?: Record<string, string>;
|
|
83
90
|
/** Environment variables for every command, process, terminal, SSH session
|
|
84
91
|
* and the image's start command in this sandbox, under each command's own
|
|
85
92
|
* `env`. At most 32 variables and 32 KiB. Values are never shown again;
|
|
86
93
|
* answers list only `envNames`. Copies made by fork() keep them. */
|
|
87
94
|
env?: Record<string, string>;
|
|
88
|
-
/** Omit to use the
|
|
95
|
+
/** Omit to use the included usage while it lasts, then prepaid credit. */
|
|
89
96
|
funding?: "trial" | "paid";
|
|
90
97
|
region?: string;
|
|
91
98
|
vcpu?: number;
|
|
@@ -93,14 +100,16 @@ export type CreateSandbox = {
|
|
|
93
100
|
diskMiB?: number;
|
|
94
101
|
cpu?: "shared" | "reserved";
|
|
95
102
|
cpuFloorMillis?: number;
|
|
96
|
-
/** A time limit, 60 to
|
|
97
|
-
* sandbox runs while it works and pauses when idle, until you
|
|
98
|
-
* credit runs out. */
|
|
103
|
+
/** A time limit, 60 to 86400 seconds (24 hours). Leave it out (or 0) for
|
|
104
|
+
* none: the sandbox runs while it works and pauses when idle, until you
|
|
105
|
+
* stop it or credit runs out. */
|
|
99
106
|
timeoutSeconds?: number;
|
|
100
107
|
/** @deprecated Ignored since 5 October 2026: every sandbox can pause. */
|
|
101
108
|
pausable?: boolean;
|
|
102
|
-
/** What happens when its time limit
|
|
103
|
-
|
|
109
|
+
/** What happens when its time limit, credit or a spending limit ends it:
|
|
110
|
+
* "pause" (default), "stop", or "delete" (when the time limit runs out,
|
|
111
|
+
* delete it and its files; credit or a spending limit only stops it). */
|
|
112
|
+
onLeaseEnd?: "pause" | "stop" | "delete";
|
|
104
113
|
/** Pause after this many seconds in which nothing happens in it: no
|
|
105
114
|
* request, no command or terminal running, no open connection, no network
|
|
106
115
|
* traffic and no CPU use. Default 60 unless persistent; 0 never;
|
|
@@ -148,6 +157,18 @@ export type CreateSandbox = {
|
|
|
148
157
|
tags?: string[];
|
|
149
158
|
};
|
|
150
159
|
};
|
|
160
|
+
/** Present on a command the sandbox's out-of-memory killer ended (the
|
|
161
|
+
* program, or anything it started): a bare exit -9, or 137 from a shell,
|
|
162
|
+
* does not say why. */
|
|
163
|
+
export type OutOfMemory = {
|
|
164
|
+
code: "out_of_memory";
|
|
165
|
+
processesKilled: number;
|
|
166
|
+
/** The sandbox's memory size; null if it could not be read. */
|
|
167
|
+
memoryMiB: number | null;
|
|
168
|
+
message: string;
|
|
169
|
+
/** What to do: a larger memoryMiB, or a program that uses less. */
|
|
170
|
+
hint: string;
|
|
171
|
+
};
|
|
151
172
|
export type CommandResult = {
|
|
152
173
|
exitCode: number | null;
|
|
153
174
|
stdout: string;
|
|
@@ -158,6 +179,7 @@ export type CommandResult = {
|
|
|
158
179
|
durationMs?: number | null;
|
|
159
180
|
processId?: string;
|
|
160
181
|
replayed?: boolean;
|
|
182
|
+
outOfMemory?: OutOfMemory;
|
|
161
183
|
};
|
|
162
184
|
export type ExecOptions = {
|
|
163
185
|
cwd?: string;
|
|
@@ -191,6 +213,7 @@ export type ProcessInfo = {
|
|
|
191
213
|
timeoutMs: number | null;
|
|
192
214
|
outputBytes: number;
|
|
193
215
|
firstOffset: number;
|
|
216
|
+
outOfMemory?: OutOfMemory;
|
|
194
217
|
};
|
|
195
218
|
export type OutputEvent = {
|
|
196
219
|
type: "start";
|
|
@@ -207,6 +230,7 @@ export type OutputEvent = {
|
|
|
207
230
|
state: string;
|
|
208
231
|
timedOut: boolean;
|
|
209
232
|
durationMs?: number;
|
|
233
|
+
outOfMemory?: OutOfMemory;
|
|
210
234
|
} | {
|
|
211
235
|
type: "truncated";
|
|
212
236
|
droppedBytes: number;
|
|
@@ -260,13 +284,85 @@ export type Usage = {
|
|
|
260
284
|
available: string;
|
|
261
285
|
/** The part of spent that refunds and disputes took. */
|
|
262
286
|
takenBack: string;
|
|
287
|
+
/** Machine time the account can still run without credit, in
|
|
288
|
+
* milliseconds, or null when it has none. `totalMs` and `usedMs` count free
|
|
289
|
+
* hours given before 5 October 2026 (0 for an account given none);
|
|
290
|
+
* `availableMs` is the larger of those hours left and this month's included
|
|
291
|
+
* usage, as time at 2 vCPU and 4 GiB. The field keeps its older name. */
|
|
263
292
|
trial: {
|
|
264
293
|
totalMs: number;
|
|
265
294
|
usedMs: number;
|
|
266
295
|
/** @deprecated Read `availableMs`. Still sent for older clients. */
|
|
267
296
|
reservedMs: number;
|
|
268
297
|
availableMs: number;
|
|
298
|
+
/** `monthly`: the included usage every month only. `hours`: free hours
|
|
299
|
+
* given before 5 October 2026, kept, beside the included usage. Absent
|
|
300
|
+
* from an API older than 5 October 2026. */
|
|
301
|
+
offer?: "monthly" | "hours";
|
|
302
|
+
/** When the included usage renews: the 1st of next month, 00:00 UTC. */
|
|
303
|
+
renewsAt?: string;
|
|
304
|
+
} | null;
|
|
305
|
+
/** What the account uses free this calendar month (UTC), one row per
|
|
306
|
+
* product, drawn before credit and never charged
|
|
307
|
+
* (https://withruntime.com/docs/included-usage). */
|
|
308
|
+
allowances?: Array<{
|
|
309
|
+
/** machine-memory, machine-cpu, saved-copies or disks. */
|
|
310
|
+
pool: string;
|
|
311
|
+
/** GiB-hour, vCPU-hour or GB-month. */
|
|
312
|
+
unit: string;
|
|
313
|
+
quantity: number;
|
|
314
|
+
used: number;
|
|
315
|
+
/** Held for what is running now; given back unless used. */
|
|
316
|
+
reserved: number;
|
|
317
|
+
left: number;
|
|
318
|
+
/** The month's first day, YYYY-MM-DD. */
|
|
319
|
+
month: string;
|
|
320
|
+
renewsAt: string;
|
|
321
|
+
}>;
|
|
322
|
+
/** What Runtime for Startups includes (https://withruntime.com/startups).
|
|
323
|
+
* Startup hours are given once, used after this month's included usage
|
|
324
|
+
* and before credit, never renewed, and gone after 12 months. Storage is
|
|
325
|
+
* GB kept free each month for those 12 months. Empty unless the account
|
|
326
|
+
* was accepted to the program or given it; absent from an older API. */
|
|
327
|
+
startupIncluded?: Array<{
|
|
328
|
+
/** machine-cpu, machine-memory, saved-copies (snapshots, images and
|
|
329
|
+
* backups) or disks (volumes). */
|
|
330
|
+
pool: string;
|
|
331
|
+
/** vCPU-hour or GiB-hour for startup hours given `once`, GB for `month` storage. */
|
|
332
|
+
unit: string;
|
|
333
|
+
/** `once`: given once and used up by what runs. `month`: `quantity` GB
|
|
334
|
+
* added to each month's included storage until `expiresAt`, never used
|
|
335
|
+
* up; storage past it bills at the published rate. Absent from an API
|
|
336
|
+
* before startup storage (7 October 2026): `once`. */
|
|
337
|
+
period?: "once" | "month";
|
|
338
|
+
quantity: number;
|
|
339
|
+
/** Null for monthly storage. */
|
|
340
|
+
used: number | null;
|
|
341
|
+
/** Held for what is running now; given back unless used. Null for
|
|
342
|
+
* monthly storage. */
|
|
343
|
+
reserved: number | null;
|
|
344
|
+
/** Null for monthly storage. */
|
|
345
|
+
left: number | null;
|
|
346
|
+
/** Storage GB kept now; null for startup hours given `once`. */
|
|
347
|
+
keptGB?: number | null;
|
|
348
|
+
/** `startup`. */
|
|
349
|
+
source: string;
|
|
350
|
+
grantedAt: string;
|
|
351
|
+
/** 12 months after `grantedAt`: what is left then is gone. */
|
|
352
|
+
expiresAt?: string;
|
|
353
|
+
}>;
|
|
354
|
+
/** What Runtime for Startups includes at once for its 12 months:
|
|
355
|
+
* image builds, and sandboxes (past it, a create answers quota_exceeded).
|
|
356
|
+
* Null without one or after them, when the account's own limits apply;
|
|
357
|
+
* absent from an API older than 7 October 2026. */
|
|
358
|
+
startupLimits?: {
|
|
359
|
+
buildsAtOnce: number;
|
|
360
|
+
sandboxesAtOnce: number;
|
|
269
361
|
} | null;
|
|
362
|
+
/** @deprecated Renamed `startupIncluded`; works for 30 days after the rename, with a warning. */
|
|
363
|
+
readonly pot?: Usage["startupIncluded"];
|
|
364
|
+
/** @deprecated Renamed `startupLimits`; works for 30 days after the rename, with a warning. */
|
|
365
|
+
readonly potLimits?: Usage["startupLimits"];
|
|
270
366
|
/** Outbound traffic this calendar month, UTC: the first `allowanceBytes` an
|
|
271
367
|
* account sends are free, and the rest is charged at the rate in the pricing
|
|
272
368
|
* guide (https://withruntime.com/docs/pricing#network-products). */
|
|
@@ -282,7 +378,9 @@ export type Usage = {
|
|
|
282
378
|
} | null;
|
|
283
379
|
/** The account's pilot while it serves its sandboxes, a free run agreed
|
|
284
380
|
* with Runtime: `hours` sandbox-hours of running time, `usedMs` and
|
|
285
|
-
* `leftMs` of it used and left
|
|
381
|
+
* `leftMs` of it used and left, and `running`, its sandboxes running now:
|
|
382
|
+
* `leftMs / running` is how long the hours last at this rate. Null on every
|
|
383
|
+
* other account. */
|
|
286
384
|
pilot?: {
|
|
287
385
|
id: string;
|
|
288
386
|
sandboxes: number;
|
|
@@ -296,7 +394,17 @@ export type Usage = {
|
|
|
296
394
|
hours: number;
|
|
297
395
|
usedMs: number;
|
|
298
396
|
leftMs: number;
|
|
397
|
+
running?: number;
|
|
299
398
|
} | null;
|
|
399
|
+
/** Everything this key acts for, a row a kind, past the hundred newest
|
|
400
|
+
* `resources` lists: how many, and what was charged and is held, in
|
|
401
|
+
* integer microdollars as strings. Absent from an API before 6 October 2026. */
|
|
402
|
+
kinds?: Array<{
|
|
403
|
+
kind: string;
|
|
404
|
+
resources: number;
|
|
405
|
+
chargedMicros: string;
|
|
406
|
+
heldMicros: string;
|
|
407
|
+
}>;
|
|
300
408
|
resources: Array<Record<string, unknown>>;
|
|
301
409
|
[key: string]: unknown;
|
|
302
410
|
};
|
package/dist/vercel/sandbox.d.ts
CHANGED
|
@@ -147,8 +147,7 @@ export declare class Sandbox {
|
|
|
147
147
|
/** Creates a sandbox and waits until it runs. Vercel's defaults: 2 vCPUs,
|
|
148
148
|
* 2048 MiB per vCPU, persistent. With no `timeout` it has no time limit: it
|
|
149
149
|
* runs while it works and pauses when idle. A `timeout` is kept as given. Funding is left to
|
|
150
|
-
* Runtime: the
|
|
151
|
-
* credit, exactly as withruntime's own create. */
|
|
150
|
+
* Runtime: the included usage first, then prepaid credit, exactly as withruntime's own create. */
|
|
152
151
|
static create(params?: CreateSandboxParams): Promise<Sandbox & AsyncDisposable>;
|
|
153
152
|
/** A sandbox by name (or Runtime id), woken if it is paused unless
|
|
154
153
|
* `resume: false`. */
|
package/dist/vercel/sandbox.js
CHANGED
|
@@ -2,7 +2,7 @@ import { extensionSeconds, LeaseKeeper, LEASE_MAX_SECONDS } from "../compat/leas
|
|
|
2
2
|
import { RuntimeError } from "../errors.js";
|
|
3
3
|
import { clientFor, signalOf, } from "./client.js";
|
|
4
4
|
import { Command, CommandFinished, exitCodeOf } from "./command.js";
|
|
5
|
-
import { APIError, guard, NotSupportedError, translate } from "./errors.js";
|
|
5
|
+
import { APIError, guard, NotSupportedError, StreamError, translate } from "./errors.js";
|
|
6
6
|
import { FileSystem } from "./filesystem.js";
|
|
7
7
|
import { rootOrThrow, SandboxUser, SandboxUserAlreadyExistsError, validateName, } from "./sandbox-user.js";
|
|
8
8
|
import { Snapshot } from "./snapshot.js";
|
|
@@ -105,7 +105,7 @@ async function resolveImage(client, params) {
|
|
|
105
105
|
const found = page.data[0];
|
|
106
106
|
if (found)
|
|
107
107
|
return { image: found.id };
|
|
108
|
-
throw new NotSupportedError(`The image ${image}, which is not a Runtime image`, `Build it as a Runtime image with that name and this call starts from it: \`npx withruntime
|
|
108
|
+
throw new NotSupportedError(`The image ${image}, which is not a Runtime image`, `Build it as a Runtime image with that name and this call starts from it: \`npx withruntime images build --dockerfile Dockerfile --name ${image}\`, or runtime.images.build({ name: "${image}", image: "<registry reference>" }).`);
|
|
109
109
|
}
|
|
110
110
|
/** Runtime's state as Vercel's status: a paused sandbox is a stopped
|
|
111
111
|
* persistent one. */
|
|
@@ -260,8 +260,7 @@ export class Sandbox {
|
|
|
260
260
|
/** Creates a sandbox and waits until it runs. Vercel's defaults: 2 vCPUs,
|
|
261
261
|
* 2048 MiB per vCPU, persistent. With no `timeout` it has no time limit: it
|
|
262
262
|
* runs while it works and pauses when idle. A `timeout` is kept as given. Funding is left to
|
|
263
|
-
* Runtime: the
|
|
264
|
-
* credit, exactly as withruntime's own create. */
|
|
263
|
+
* Runtime: the included usage first, then prepaid credit, exactly as withruntime's own create. */
|
|
265
264
|
static async create(params = {}) {
|
|
266
265
|
refuseCreate(params);
|
|
267
266
|
const client = clientFor(params);
|
|
@@ -521,6 +520,8 @@ export class Sandbox {
|
|
|
521
520
|
onStdout: record("stdout", params.stdout),
|
|
522
521
|
onStderr: record("stderr", params.stderr),
|
|
523
522
|
}), params);
|
|
523
|
+
if (result.stdoutTruncated || result.stderrTruncated)
|
|
524
|
+
throw new StreamError("output_truncated", "Some command output is no longer available.", result.processId ?? this.#rt.id);
|
|
524
525
|
return new CommandFinished({
|
|
525
526
|
id: result.processId ?? `cmd_${startedAt}`,
|
|
526
527
|
cwd: vercelCwd,
|
|
@@ -776,7 +777,7 @@ export class Sandbox {
|
|
|
776
777
|
* Runtime's terminal opens with the account key, which must not leave the
|
|
777
778
|
* server. */
|
|
778
779
|
openInteractive() {
|
|
779
|
-
return Promise.reject(new NotSupportedError("Vercel's interactive shell (openInteractive)", "Use `await sandbox.withruntime.terminal({ cols, rows, onData })`, or `npx withruntime
|
|
780
|
+
return Promise.reject(new NotSupportedError("Vercel's interactive shell (openInteractive)", "Use `await sandbox.withruntime.terminal({ cols, rows, onData })`, or `npx withruntime sandboxes shell <id>`."));
|
|
780
781
|
}
|
|
781
782
|
/** The user commands run as, `runtime`, and its group. */
|
|
782
783
|
getDefaultUser(_opts = {}) {
|
package/dist/vercel/snapshot.js
CHANGED
|
@@ -7,6 +7,14 @@ function statusOf(state) {
|
|
|
7
7
|
return "deleted";
|
|
8
8
|
return "created";
|
|
9
9
|
}
|
|
10
|
+
/** Vercel's snapshots always expire. Runtime's has no end date while it is kept
|
|
11
|
+
* for as long as the account has credit; it is then taken at the longest a
|
|
12
|
+
* snapshot is kept, a year from when it was made. */
|
|
13
|
+
function expiresAtOf(snapshot) {
|
|
14
|
+
return snapshot.expiresAt === null
|
|
15
|
+
? Date.parse(snapshot.createdAt) + 365 * 86_400_000
|
|
16
|
+
: Date.parse(snapshot.expiresAt);
|
|
17
|
+
}
|
|
10
18
|
function metadataOf(snapshot) {
|
|
11
19
|
return {
|
|
12
20
|
id: snapshot.id,
|
|
@@ -17,7 +25,7 @@ function metadataOf(snapshot) {
|
|
|
17
25
|
sizeBytes: snapshot.storedBytes ?? 0,
|
|
18
26
|
createdAt: Date.parse(snapshot.createdAt),
|
|
19
27
|
updatedAt: Date.parse(snapshot.readyAt ?? snapshot.createdAt),
|
|
20
|
-
expiresAt:
|
|
28
|
+
expiresAt: expiresAtOf(snapshot),
|
|
21
29
|
};
|
|
22
30
|
}
|
|
23
31
|
/** A saved filesystem, as Vercel's Snapshot, over a Runtime disk snapshot.
|
|
@@ -52,7 +60,7 @@ export class Snapshot {
|
|
|
52
60
|
return new Date(this.#snapshot.readyAt ?? this.#snapshot.createdAt);
|
|
53
61
|
}
|
|
54
62
|
get expiresAt() {
|
|
55
|
-
return new Date(this.#snapshot
|
|
63
|
+
return new Date(expiresAtOf(this.#snapshot));
|
|
56
64
|
}
|
|
57
65
|
static async get(params) {
|
|
58
66
|
const client = clientFor(params);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** `withruntime/volumes`: Volumes alone. Persistent disks to attach to sandboxes.
|
|
2
|
+
*
|
|
3
|
+
* import { volumes } from "withruntime/volumes";
|
|
4
|
+
* const client = volumes(); // RUNTIME_API_KEY, or this machine's saved connection
|
|
5
|
+
*/
|
|
6
|
+
import { Runtime, type RuntimeOptions } from "../client.js";
|
|
7
|
+
export type * from "../products/volumes.js";
|
|
8
|
+
/** `runtime.volumes` of a client made with `options`. */
|
|
9
|
+
export declare function volumes(options?: RuntimeOptions): Runtime["volumes"];
|