withruntime 0.9.0 → 0.11.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 +52 -40
- package/E2B.md +65 -62
- package/README.md +15 -7
- package/README.src.md +15 -7
- package/VERCEL.md +34 -22
- package/compatibility-lock.json +16 -16
- 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 +262 -56
- package/dist/client.d.ts +41 -3
- package/dist/client.js +67 -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/compat/lease.d.ts +36 -0
- package/dist/compat/lease.js +87 -0
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +107 -38
- package/dist/daytona/computer-use.d.ts +162 -0
- package/dist/daytona/computer-use.js +324 -0
- package/dist/daytona/context.d.ts +10 -0
- package/dist/daytona/context.js +24 -0
- package/dist/daytona/daytona.d.ts +20 -0
- package/dist/daytona/daytona.js +134 -20
- package/dist/daytona/filesystem.d.ts +17 -4
- package/dist/daytona/filesystem.js +129 -38
- package/dist/daytona/index.d.ts +3 -27
- package/dist/daytona/index.js +2 -7
- package/dist/daytona/process.d.ts +63 -6
- package/dist/daytona/process.js +224 -23
- package/dist/daytona/sandbox.d.ts +20 -6
- package/dist/daytona/sandbox.js +55 -32
- package/dist/e2b/client.d.ts +5 -0
- package/dist/e2b/client.js +6 -2
- package/dist/e2b/commands.d.ts +43 -12
- package/dist/e2b/commands.js +217 -64
- package/dist/e2b/errors.d.ts +7 -0
- package/dist/e2b/errors.js +20 -0
- package/dist/e2b/filesystem.d.ts +2 -1
- package/dist/e2b/filesystem.js +43 -6
- package/dist/e2b/index.d.ts +3 -2
- package/dist/e2b/index.js +2 -1
- package/dist/e2b/pty.d.ts +24 -0
- package/dist/e2b/pty.js +83 -0
- package/dist/e2b/sandbox.d.ts +17 -6
- package/dist/e2b/sandbox.js +239 -43
- package/dist/e2b/users.d.ts +30 -0
- package/dist/e2b/users.js +185 -0
- 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 +3 -1
- package/dist/login.js +16 -10
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.js +6 -1
- package/dist/modal/index.js +2 -1
- package/dist/network-cli.js +139 -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/browser.d.ts +60 -0
- package/dist/products/browser.js +37 -0
- package/dist/products/desktop.d.ts +2 -2
- package/dist/products/desktop.js +2 -2
- package/dist/products/images.d.ts +3 -1
- package/dist/products/images.js +14 -2
- package/dist/products/index.d.ts +14 -0
- package/dist/products/index.js +12 -0
- package/dist/products/network-products.d.ts +7 -0
- package/dist/products/network-products.js +3 -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/private-network.d.ts +22 -0
- package/dist/products/private-network.js +10 -0
- 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 +59 -8
- package/dist/sandbox.js +479 -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/types.d.ts +5 -2
- 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/index.d.ts +1 -7
- package/dist/vercel/index.js +1 -3
- package/dist/vercel/sandbox-user.d.ts +70 -0
- package/dist/vercel/sandbox-user.js +206 -0
- package/dist/vercel/sandbox.d.ts +55 -20
- package/dist/vercel/sandbox.js +353 -99
- package/dist/vercel/snapshot.d.ts +3 -2
- package/dist/vercel/snapshot.js +9 -5
- package/package.json +2 -1
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
2
|
+
/* Vercel's multi-user helpers over Runtime's sandbox owner, who has
|
|
3
|
+
passwordless sudo: a user is a real Linux user made with `sudo useradd`,
|
|
4
|
+
and every call as that user is `sudo -u <user>`, exactly as Vercel's own
|
|
5
|
+
SDK does it (checked against @vercel/sandbox 3.5.1). */
|
|
6
|
+
const VALID_NAME = /^[a-z_][a-z0-9_-]*$/;
|
|
7
|
+
const MAX_NAME_LENGTH = 32;
|
|
8
|
+
/** A Linux user or group name Vercel accepts, which is also safe to pass to
|
|
9
|
+
* useradd, groupadd and sudo. */
|
|
10
|
+
export function validateName(name, kind) {
|
|
11
|
+
if (!name)
|
|
12
|
+
throw new Error(`Invalid ${kind}: must not be empty`);
|
|
13
|
+
if (name.length > MAX_NAME_LENGTH)
|
|
14
|
+
throw new Error(`Invalid ${kind} "${name}": must be at most ${MAX_NAME_LENGTH} characters`);
|
|
15
|
+
if (!VALID_NAME.test(name))
|
|
16
|
+
throw new Error(`Invalid ${kind} "${name}": must match ${VALID_NAME} (lowercase letters, digits, hyphens, underscores)`);
|
|
17
|
+
}
|
|
18
|
+
/** Thrown when `sandbox.createUser` is called for an existing username. */
|
|
19
|
+
export class SandboxUserAlreadyExistsError extends Error {
|
|
20
|
+
username;
|
|
21
|
+
constructor(username) {
|
|
22
|
+
super(`Failed to create user "${username}": user already exists`);
|
|
23
|
+
this.name = "SandboxUserAlreadyExistsError";
|
|
24
|
+
this.username = username;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** A user in a sandbox, made with `sandbox.createUser` or found with
|
|
28
|
+
* `sandbox.asUser`. Commands and file calls run as this user. */
|
|
29
|
+
export class SandboxUser {
|
|
30
|
+
username;
|
|
31
|
+
/** `/root` for root, else `/home/<username>`. */
|
|
32
|
+
homeDir;
|
|
33
|
+
#sandbox;
|
|
34
|
+
#primaryGroup;
|
|
35
|
+
/** Use sandbox.createUser or sandbox.asUser. */
|
|
36
|
+
constructor({ sandbox, username }) {
|
|
37
|
+
this.#sandbox = sandbox;
|
|
38
|
+
this.username = username;
|
|
39
|
+
this.homeDir = username === "root" ? "/root" : `/home/${username}`;
|
|
40
|
+
}
|
|
41
|
+
/** `sudo -u <user>`, in `cwd` (the user's home by default), with `env`
|
|
42
|
+
* given through `env` so it survives sudo. */
|
|
43
|
+
#wrap(params) {
|
|
44
|
+
const env = Object.entries(params.env ?? {}).map(([key, value]) => `${key}=${value}`);
|
|
45
|
+
return {
|
|
46
|
+
cmd: "sudo",
|
|
47
|
+
args: [
|
|
48
|
+
"-u",
|
|
49
|
+
this.username,
|
|
50
|
+
"--",
|
|
51
|
+
"bash",
|
|
52
|
+
"-c",
|
|
53
|
+
'cd "$1" || exit 1; shift; exec "$@"',
|
|
54
|
+
"bash",
|
|
55
|
+
params.cwd ?? this.homeDir,
|
|
56
|
+
...(env.length ? ["env", ...env] : []),
|
|
57
|
+
params.cmd,
|
|
58
|
+
...(params.args ?? []),
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
#resolve(path) {
|
|
63
|
+
return path.startsWith("/") ? path : `${this.homeDir}/${path}`;
|
|
64
|
+
}
|
|
65
|
+
runCommand(commandOrParams, args, opts = {}) {
|
|
66
|
+
if (typeof commandOrParams === "string")
|
|
67
|
+
return this.#sandbox.runCommand({
|
|
68
|
+
...this.#wrap({ cmd: commandOrParams, ...(args ? { args } : {}) }),
|
|
69
|
+
...(opts.signal ? { signal: opts.signal } : {}),
|
|
70
|
+
...(opts.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {}),
|
|
71
|
+
});
|
|
72
|
+
const params = commandOrParams;
|
|
73
|
+
if (params.sudo)
|
|
74
|
+
return this.#sandbox.runCommand({ ...params });
|
|
75
|
+
const wrapped = this.#wrap(params);
|
|
76
|
+
return this.#sandbox.runCommand({
|
|
77
|
+
cmd: wrapped.cmd,
|
|
78
|
+
args: wrapped.args,
|
|
79
|
+
...(params.detached ? { detached: true } : {}),
|
|
80
|
+
...(params.stdout ? { stdout: params.stdout } : {}),
|
|
81
|
+
...(params.stderr ? { stderr: params.stderr } : {}),
|
|
82
|
+
...(params.signal ? { signal: params.signal } : {}),
|
|
83
|
+
...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs } : {}),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** Writes files into this user's home (or absolute paths), then gives them
|
|
87
|
+
* and the directories made for them to this user. */
|
|
88
|
+
async writeFiles(files, opts = {}) {
|
|
89
|
+
const absolute = files.map((file) => ({ ...file, path: this.#resolve(file.path) }));
|
|
90
|
+
await this.#sandbox.writeFiles(absolute, opts);
|
|
91
|
+
const paths = absolute.map((file) => file.path);
|
|
92
|
+
if (!paths.length)
|
|
93
|
+
return;
|
|
94
|
+
await this.#chown(paths, `${this.username}:${await this.#group(opts.signal)}`, opts.signal);
|
|
95
|
+
const dirs = this.#ancestorsUnderHome(paths);
|
|
96
|
+
if (dirs.length) {
|
|
97
|
+
const { group } = await this.#sandbox.getDefaultUser(opts);
|
|
98
|
+
await this.#chown(dirs, `${this.username}:${group}`, opts.signal);
|
|
99
|
+
await this.#chmod(dirs, "770", opts.signal);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** The file as this user may read it, as a stream; null when missing. */
|
|
103
|
+
async readFile(file, opts = {}) {
|
|
104
|
+
const buffer = await this.#cat(file, opts);
|
|
105
|
+
if (buffer === null)
|
|
106
|
+
return null;
|
|
107
|
+
const { Readable } = await import("node:stream");
|
|
108
|
+
return Readable.from([buffer]);
|
|
109
|
+
}
|
|
110
|
+
/** The file as this user may read it; null when missing. */
|
|
111
|
+
readFileToBuffer(file, opts = {}) {
|
|
112
|
+
return this.#cat(file, opts);
|
|
113
|
+
}
|
|
114
|
+
/** Copies a file this user may read to the local disk; null when missing. */
|
|
115
|
+
async downloadFile(src, dst, opts = {}) {
|
|
116
|
+
const buffer = await this.#cat(src, opts);
|
|
117
|
+
if (buffer === null)
|
|
118
|
+
return null;
|
|
119
|
+
const { mkdir, writeFile } = await import("node:fs/promises");
|
|
120
|
+
const target = resolve(dst.cwd ?? "", dst.path);
|
|
121
|
+
if (opts.mkdirRecursive)
|
|
122
|
+
await mkdir(dirname(target), { recursive: true });
|
|
123
|
+
await writeFile(target, buffer, opts.signal ? { signal: opts.signal } : {});
|
|
124
|
+
return target;
|
|
125
|
+
}
|
|
126
|
+
/** Reads as this user with `base64`, so the user's own permissions apply
|
|
127
|
+
* and binary files arrive whole. */
|
|
128
|
+
async #cat(file, opts) {
|
|
129
|
+
const path = file.path.startsWith("/") ? file.path : `${file.cwd ?? this.homeDir}/${file.path}`;
|
|
130
|
+
const result = await this.runCommand({
|
|
131
|
+
cmd: "base64",
|
|
132
|
+
args: [path],
|
|
133
|
+
...(opts.signal ? { signal: opts.signal } : {}),
|
|
134
|
+
});
|
|
135
|
+
if (result.exitCode !== 0) {
|
|
136
|
+
const stderr = await result.stderr();
|
|
137
|
+
if (/No such file or directory/i.test(stderr))
|
|
138
|
+
return null;
|
|
139
|
+
throw new Error(`Failed to read ${path}: ${stderr}`);
|
|
140
|
+
}
|
|
141
|
+
return Buffer.from(await result.stdout(), "base64");
|
|
142
|
+
}
|
|
143
|
+
/** Makes a directory owned by this user. */
|
|
144
|
+
async mkDir(path, opts = {}) {
|
|
145
|
+
const absolute = this.#resolve(path);
|
|
146
|
+
await this.#sandbox.mkDir(absolute, opts);
|
|
147
|
+
const dirs = [absolute, ...this.#ancestorsUnderHome([absolute])];
|
|
148
|
+
const { group } = await this.#sandbox.getDefaultUser(opts);
|
|
149
|
+
await this.#chown(dirs, `${this.username}:${group}`, opts.signal);
|
|
150
|
+
await this.#chmod(dirs, "770", opts.signal);
|
|
151
|
+
}
|
|
152
|
+
async addToGroup(groupname, opts = {}) {
|
|
153
|
+
validateName(groupname, "group name");
|
|
154
|
+
await this.#sandbox.addUserToGroup(this.username, groupname, opts);
|
|
155
|
+
}
|
|
156
|
+
async removeFromGroup(groupname, opts = {}) {
|
|
157
|
+
validateName(groupname, "group name");
|
|
158
|
+
await this.#sandbox.removeUserFromGroup(this.username, groupname, opts);
|
|
159
|
+
}
|
|
160
|
+
/** The user's primary group, read from the sandbox once. */
|
|
161
|
+
#group(signal) {
|
|
162
|
+
this.#primaryGroup ??= (async () => {
|
|
163
|
+
const result = await this.#sandbox.runCommand({
|
|
164
|
+
cmd: "id",
|
|
165
|
+
args: ["-gn", this.username],
|
|
166
|
+
...(signal ? { signal } : {}),
|
|
167
|
+
});
|
|
168
|
+
if (result.exitCode !== 0)
|
|
169
|
+
throw new Error(`Failed to resolve the primary group of "${this.username}": ${await result.stderr()}`);
|
|
170
|
+
const group = (await result.stdout()).trim();
|
|
171
|
+
if (!group)
|
|
172
|
+
throw new Error(`Failed to resolve the primary group of "${this.username}"`);
|
|
173
|
+
return group;
|
|
174
|
+
})().catch((error) => {
|
|
175
|
+
this.#primaryGroup = undefined;
|
|
176
|
+
throw error;
|
|
177
|
+
});
|
|
178
|
+
return this.#primaryGroup;
|
|
179
|
+
}
|
|
180
|
+
async #chown(paths, owner, signal) {
|
|
181
|
+
await rootOrThrow(this.#sandbox, "chown", [owner, ...paths], signal, () => `Failed to set ownership on ${paths.join(", ")}`);
|
|
182
|
+
}
|
|
183
|
+
async #chmod(paths, mode, signal) {
|
|
184
|
+
await rootOrThrow(this.#sandbox, "chmod", [mode, ...paths], signal, () => `Failed to set permissions on ${paths.join(", ")}`);
|
|
185
|
+
}
|
|
186
|
+
/** The directories strictly between this user's home and each path. */
|
|
187
|
+
#ancestorsUnderHome(paths) {
|
|
188
|
+
const dirs = new Set();
|
|
189
|
+
const prefix = `${this.homeDir}/`;
|
|
190
|
+
for (const path of paths) {
|
|
191
|
+
let dir = path.slice(0, path.lastIndexOf("/"));
|
|
192
|
+
while (dir.length > this.homeDir.length && dir.startsWith(prefix)) {
|
|
193
|
+
dirs.add(dir);
|
|
194
|
+
dir = dir.slice(0, dir.lastIndexOf("/"));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return [...dirs];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/** Runs `cmd args` under sudo; a non-zero exit throws `what(): <stderr>`. */
|
|
201
|
+
export async function rootOrThrow(sandbox, cmd, args, signal, what) {
|
|
202
|
+
const result = await sandbox.runCommand({ cmd, args, sudo: true, ...(signal ? { signal } : {}) });
|
|
203
|
+
if (result.exitCode !== 0)
|
|
204
|
+
throw new Error(`${what()}: ${await result.stderr()}`);
|
|
205
|
+
return result;
|
|
206
|
+
}
|
package/dist/vercel/sandbox.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Runtime } from "../client.js";
|
|
|
3
3
|
import { type Credentials, type RuntimeCreate, type RuntimeSandbox, type WithRuntime } from "./client.js";
|
|
4
4
|
import { Command, CommandFinished } from "./command.js";
|
|
5
5
|
import { FileSystem } from "./filesystem.js";
|
|
6
|
+
import { SandboxUser } from "./sandbox-user.js";
|
|
6
7
|
import { Snapshot } from "./snapshot.js";
|
|
7
8
|
/** Vercel's default machine: 2 vCPUs with 2048 MB each (checked 23 September
|
|
8
9
|
* 2026). Runtime gives 2 vCPU and 4096 MiB. */
|
|
@@ -39,7 +40,9 @@ export interface CreateSandboxParams extends Credentials {
|
|
|
39
40
|
/** Shared at public HTTPS addresses (Runtime previews); `domain(port)`
|
|
40
41
|
* answers from them. */
|
|
41
42
|
ports?: number[];
|
|
42
|
-
/** Milliseconds. Default 300 000
|
|
43
|
+
/** Milliseconds. Default 300 000, at least 60 s. Over an hour, the
|
|
44
|
+
* sandbox's hour-long lease is extended while this object lives, up to the
|
|
45
|
+
* timeout (`sandbox.timeout`). */
|
|
43
46
|
timeout?: number;
|
|
44
47
|
resources?: {
|
|
45
48
|
vcpus: number;
|
|
@@ -60,7 +63,7 @@ export interface CreateSandboxParams extends Credentials {
|
|
|
60
63
|
/** Milliseconds a stopped persistent sandbox is kept, as Runtime's
|
|
61
64
|
* retention (whole days, 1 to 365; 0 is 365). */
|
|
62
65
|
snapshotExpiration?: number;
|
|
63
|
-
/**
|
|
66
|
+
/** Refused: Runtime does not enforce snapshot count or eviction policies. */
|
|
64
67
|
keepLastSnapshots?: {
|
|
65
68
|
count: number;
|
|
66
69
|
expiration?: number;
|
|
@@ -131,7 +134,8 @@ export declare class Sandbox {
|
|
|
131
134
|
get updatedAt(): Date;
|
|
132
135
|
get cwd(): string;
|
|
133
136
|
get status(): "pending" | "running" | "stopping" | "stopped";
|
|
134
|
-
/** Milliseconds
|
|
137
|
+
/** Milliseconds from the start of the session: the timeout given at
|
|
138
|
+
* create, with every extension, or the lease of a sandbox found by name. */
|
|
135
139
|
get timeout(): number;
|
|
136
140
|
get expiresAt(): Date;
|
|
137
141
|
get tags(): Record<string, string>;
|
|
@@ -162,14 +166,23 @@ export declare class Sandbox {
|
|
|
162
166
|
sourceSandbox: string;
|
|
163
167
|
}): Promise<Sandbox & AsyncDisposable>;
|
|
164
168
|
/** Running and stopped (paused) sandboxes, oldest first, with Vercel's
|
|
165
|
-
* paginator: `for await (const s of await Sandbox.list())`.
|
|
169
|
+
* paginator: `for await (const s of await Sandbox.list())`. A name prefix,
|
|
170
|
+
* creation-time bounds (`since`, `until`, epoch ms), `sortBy` and
|
|
171
|
+
* `sortOrder`, and a `cursor` from an earlier page are applied here, over
|
|
172
|
+
* every sandbox the key sees. */
|
|
166
173
|
static list(params?: {
|
|
167
174
|
tags?: Record<string, string>;
|
|
168
175
|
limit?: number;
|
|
176
|
+
namePrefix?: string;
|
|
177
|
+
sortBy?: "createdAt" | "name" | "statusUpdatedAt";
|
|
178
|
+
sortOrder?: "asc" | "desc";
|
|
179
|
+
cursor?: string;
|
|
180
|
+
since?: number | Date;
|
|
181
|
+
until?: number | Date;
|
|
169
182
|
signal?: AbortSignal;
|
|
170
183
|
} & Credentials & {
|
|
171
184
|
withruntime?: WithRuntime;
|
|
172
|
-
}
|
|
185
|
+
}): Promise<{
|
|
173
186
|
sandboxes: ListItem[];
|
|
174
187
|
pagination: {
|
|
175
188
|
count: number;
|
|
@@ -198,10 +211,10 @@ export declare class Sandbox {
|
|
|
198
211
|
}): Promise<Command>;
|
|
199
212
|
runCommand(params: RunCommandParams): Promise<CommandFinished>;
|
|
200
213
|
/** A command started earlier, by its cmdId. */
|
|
201
|
-
getCommand(cmdId: string,
|
|
214
|
+
getCommand(cmdId: string, opts?: {
|
|
202
215
|
signal?: AbortSignal;
|
|
203
216
|
}): Promise<Command>;
|
|
204
|
-
mkDir(path: string,
|
|
217
|
+
mkDir(path: string, opts?: {
|
|
205
218
|
signal?: AbortSignal;
|
|
206
219
|
}): Promise<void>;
|
|
207
220
|
/** The file's bytes as a Node stream, or null when there is no file. */
|
|
@@ -235,7 +248,7 @@ export declare class Sandbox {
|
|
|
235
248
|
path: string;
|
|
236
249
|
content: string | Uint8Array;
|
|
237
250
|
mode?: number;
|
|
238
|
-
}[],
|
|
251
|
+
}[], opts?: {
|
|
239
252
|
signal?: AbortSignal;
|
|
240
253
|
}): Promise<void>;
|
|
241
254
|
/** The public address of a port listed in `ports`, such as
|
|
@@ -256,13 +269,14 @@ export declare class Sandbox {
|
|
|
256
269
|
signal?: AbortSignal;
|
|
257
270
|
}): Promise<void>;
|
|
258
271
|
[Symbol.asyncDispose](): Promise<void>;
|
|
259
|
-
/** Moves the end `duration` milliseconds later
|
|
260
|
-
*
|
|
272
|
+
/** Moves the end `duration` milliseconds later. The lease moves at once
|
|
273
|
+
* as far as it may (an hour ahead of now); past that it is extended while
|
|
274
|
+
* this object lives. */
|
|
261
275
|
extendTimeout(duration: number, opts?: {
|
|
262
276
|
signal?: AbortSignal;
|
|
263
277
|
}): Promise<void>;
|
|
264
278
|
/** Replaces the network rules; returns the policy given. */
|
|
265
|
-
updateNetworkPolicy(networkPolicy: NetworkPolicy,
|
|
279
|
+
updateNetworkPolicy(networkPolicy: NetworkPolicy, opts?: {
|
|
266
280
|
signal?: AbortSignal;
|
|
267
281
|
}): Promise<NetworkPolicy>;
|
|
268
282
|
/** Changes what Runtime can change on a sandbox: `timeout`, `ports`,
|
|
@@ -273,26 +287,47 @@ export declare class Sandbox {
|
|
|
273
287
|
ports?: number[];
|
|
274
288
|
networkPolicy?: NetworkPolicy;
|
|
275
289
|
snapshotExpiration?: number;
|
|
276
|
-
} & Record<string, unknown>,
|
|
290
|
+
} & Record<string, unknown>, opts?: {
|
|
277
291
|
signal?: AbortSignal;
|
|
278
292
|
}): Promise<void>;
|
|
279
|
-
/** Keeps the sandbox's
|
|
280
|
-
*
|
|
293
|
+
/** Keeps the sandbox's filesystem as a disk-only snapshot, then stops
|
|
294
|
+
* the source. Restoring it starts fresh processes, as Vercel does. Start
|
|
281
295
|
* from it with `Sandbox.create({ source: { type: "snapshot", snapshotId } })`. */
|
|
282
296
|
snapshot(opts?: {
|
|
283
297
|
expiration?: number;
|
|
284
298
|
signal?: AbortSignal;
|
|
285
299
|
}): Promise<Snapshot>;
|
|
300
|
+
/** Refused: Vercel hands back a token scoped to this one shell, and
|
|
301
|
+
* Runtime's terminal opens with the account key, which must not leave the
|
|
302
|
+
* server. */
|
|
286
303
|
openInteractive(): Promise<never>;
|
|
287
|
-
|
|
304
|
+
/** The user commands run as, `runtime`, and its group. */
|
|
305
|
+
getDefaultUser(_opts?: {
|
|
306
|
+
signal?: AbortSignal;
|
|
307
|
+
}): Promise<{
|
|
288
308
|
username: string;
|
|
289
309
|
group: string;
|
|
290
310
|
}>;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
311
|
+
/** Makes a Linux user with its own home, as Vercel does: `useradd -m`,
|
|
312
|
+
* then the home given to the user and the sandbox's group, mode 770. */
|
|
313
|
+
createUser(username: string, opts?: {
|
|
314
|
+
signal?: AbortSignal;
|
|
315
|
+
}): Promise<SandboxUser>;
|
|
316
|
+
/** A handle for an existing user, such as `root`. */
|
|
317
|
+
asUser(username: "root" | (string & {})): SandboxUser;
|
|
318
|
+
/** Makes a group and its shared directory, `/shared/<group>`, setgid 2770. */
|
|
319
|
+
createGroup(groupname: string, opts?: {
|
|
320
|
+
signal?: AbortSignal;
|
|
321
|
+
}): Promise<{
|
|
322
|
+
groupname: string;
|
|
323
|
+
sharedDir: string;
|
|
324
|
+
}>;
|
|
325
|
+
addUserToGroup(username: string, groupname: string, opts?: {
|
|
326
|
+
signal?: AbortSignal;
|
|
327
|
+
}): Promise<void>;
|
|
328
|
+
removeUserFromGroup(username: string, groupname: string, opts?: {
|
|
329
|
+
signal?: AbortSignal;
|
|
330
|
+
}): Promise<void>;
|
|
296
331
|
currentSession(): never;
|
|
297
332
|
listSessions(): Promise<never>;
|
|
298
333
|
listSnapshots(): Promise<never>;
|