withruntime 0.8.4 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BLAXEL.md +4 -4
- package/COMPATIBILITY.md +145 -0
- package/DAYTONA.md +13 -7
- package/E2B.md +34 -20
- package/README.md +22 -11
- package/README.src.md +22 -11
- package/VERCEL.md +13 -3
- package/compatibility-lock.json +357 -0
- package/dist/ai-harness/index.js +2 -2
- package/dist/api-defaults.d.ts +17 -0
- package/dist/api-defaults.js +22 -0
- 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 +3 -2
- package/dist/blaxel/preview.js +16 -14
- package/dist/blaxel/process.d.ts +1 -1
- package/dist/blaxel/process.js +66 -11
- 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-words.d.ts +27 -0
- package/dist/cli-words.js +135 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +351 -85
- package/dist/client.d.ts +33 -4
- package/dist/client.js +47 -12
- package/dist/cloudflare/identity.d.ts +7 -0
- package/dist/cloudflare/identity.js +13 -0
- package/dist/cloudflare/index.d.ts +303 -0
- package/dist/cloudflare/index.js +592 -0
- package/dist/cloudflare/worker.d.ts +419 -0
- package/dist/cloudflare/worker.js +447 -0
- package/dist/codesandbox/guest-service.d.ts +31 -0
- package/dist/codesandbox/guest-service.js +490 -0
- package/dist/codesandbox/index.d.ts +386 -0
- package/dist/codesandbox/index.js +1347 -0
- package/dist/compat/core.d.ts +40 -0
- package/dist/compat/core.js +238 -0
- package/dist/compat/files.d.ts +26 -0
- package/dist/compat/files.js +133 -0
- package/dist/compat/shell.d.ts +4 -0
- package/dist/compat/shell.js +165 -0
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +107 -38
- package/dist/daytona/context.js +2 -1
- package/dist/daytona/daytona.js +11 -4
- package/dist/daytona/filesystem.d.ts +17 -4
- package/dist/daytona/filesystem.js +121 -38
- package/dist/daytona/index.d.ts +1 -1
- package/dist/daytona/process.d.ts +1 -1
- package/dist/daytona/process.js +27 -4
- package/dist/daytona/sandbox.d.ts +1 -1
- package/dist/daytona/sandbox.js +16 -7
- package/dist/e2b/client.js +1 -1
- package/dist/e2b/code-interpreter.d.ts +4 -5
- package/dist/e2b/code-interpreter.js +54 -56
- package/dist/e2b/commands.d.ts +35 -12
- package/dist/e2b/commands.js +169 -73
- package/dist/e2b/errors.js +1 -1
- package/dist/e2b/filesystem.d.ts +8 -6
- package/dist/e2b/filesystem.js +127 -28
- package/dist/e2b/index.d.ts +1 -0
- package/dist/e2b/index.js +1 -0
- package/dist/e2b/pty.d.ts +24 -0
- package/dist/e2b/pty.js +80 -0
- package/dist/e2b/sandbox.d.ts +6 -4
- package/dist/e2b/sandbox.js +59 -25
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +15 -2
- package/dist/file-source.d.ts +16 -0
- package/dist/file-source.js +162 -0
- package/dist/freestyle/index.d.ts +309 -0
- package/dist/freestyle/index.js +343 -0
- package/dist/index.d.ts +3 -1
- package/dist/login.js +16 -10
- package/dist/mcp.js +2 -2
- package/dist/modal/index.d.ts +205 -0
- package/dist/modal/index.js +486 -0
- package/dist/network-cli.js +112 -44
- package/dist/openai-agents/index.js +18 -71
- package/dist/page.d.ts +1 -1
- package/dist/page.js +2 -2
- package/dist/products/audit.d.ts +3 -0
- package/dist/products/index.d.ts +14 -0
- package/dist/products/index.js +12 -0
- package/dist/products/interpreter.d.ts +11 -4
- package/dist/products/interpreter.js +33 -9
- package/dist/products/jobs.js +3 -2
- package/dist/products/limits.d.ts +10 -0
- package/dist/products/observability.d.ts +44 -0
- package/dist/products/observability.js +6 -0
- package/dist/products/previews.d.ts +18 -4
- package/dist/products/previews.js +14 -5
- package/dist/products/tailscale.d.ts +57 -0
- package/dist/products/tailscale.js +17 -0
- package/dist/products/volumes.d.ts +42 -0
- package/dist/products/volumes.js +36 -0
- package/dist/products/watch.d.ts +25 -4
- package/dist/products/watch.js +132 -18
- package/dist/proxy.js +3 -1
- package/dist/runloop/index.d.ts +326 -0
- package/dist/runloop/index.js +535 -0
- package/dist/runloop/pagination.d.ts +46 -0
- package/dist/runloop/pagination.js +82 -0
- package/dist/runloop/snapshots.d.ts +52 -0
- package/dist/runloop/snapshots.js +244 -0
- package/dist/sandbox.d.ts +76 -16
- package/dist/sandbox.js +696 -135
- package/dist/snapshots.d.ts +20 -5
- package/dist/snapshots.js +11 -1
- package/dist/sprites/index.d.ts +251 -0
- package/dist/sprites/index.js +588 -0
- package/dist/tar.d.ts +10 -1
- package/dist/tar.js +311 -35
- package/dist/tools/index.js +2 -1
- package/dist/transport.d.ts +23 -8
- package/dist/transport.js +247 -127
- package/dist/types.d.ts +52 -3
- package/dist/vercel/command.d.ts +1 -1
- package/dist/vercel/command.js +15 -3
- package/dist/vercel/errors.d.ts +2 -2
- package/dist/vercel/errors.js +19 -2
- package/dist/vercel/filesystem.d.ts +21 -18
- package/dist/vercel/filesystem.js +95 -48
- package/dist/vercel/sandbox.d.ts +8 -8
- package/dist/vercel/sandbox.js +159 -64
- package/dist/vercel/snapshot.d.ts +3 -2
- package/dist/vercel/snapshot.js +9 -5
- package/package.json +46 -3
package/dist/e2b/filesystem.d.ts
CHANGED
|
@@ -14,9 +14,9 @@ export interface EntryInfo extends WriteInfo {
|
|
|
14
14
|
size: number;
|
|
15
15
|
mode: number;
|
|
16
16
|
permissions: string;
|
|
17
|
-
/**
|
|
17
|
+
/** File owner when returned by the native guest. */
|
|
18
18
|
owner: string;
|
|
19
|
-
/**
|
|
19
|
+
/** File group when returned by the native guest. */
|
|
20
20
|
group: string;
|
|
21
21
|
modifiedTime?: Date;
|
|
22
22
|
symlinkTarget?: string;
|
|
@@ -32,11 +32,14 @@ export interface FilesystemEvent {
|
|
|
32
32
|
/** Relative to the watched directory. */
|
|
33
33
|
name: string;
|
|
34
34
|
type: FilesystemEventType;
|
|
35
|
+
entry?: EntryInfo;
|
|
35
36
|
}
|
|
36
37
|
export interface WatchOpts extends FilesystemRequestOpts {
|
|
37
|
-
/** How long the
|
|
38
|
+
/** How long the subscription runs; 0 has no subscription deadline. Default 60000. */
|
|
38
39
|
timeoutMs?: number;
|
|
39
40
|
recursive?: boolean;
|
|
41
|
+
includeEntry?: boolean;
|
|
42
|
+
allowNetworkMounts?: boolean;
|
|
40
43
|
}
|
|
41
44
|
export interface E2BWatchHandle {
|
|
42
45
|
stop(): Promise<void>;
|
|
@@ -98,9 +101,8 @@ export declare class Filesystem {
|
|
|
98
101
|
remove(path: string, opts?: FilesystemRequestOpts): Promise<void>;
|
|
99
102
|
exists(path: string, opts?: FilesystemRequestOpts): Promise<boolean>;
|
|
100
103
|
getInfo(path: string, opts?: FilesystemRequestOpts): Promise<EntryInfo>;
|
|
101
|
-
/** E2B's watchDir on Runtime's file watch
|
|
102
|
-
*
|
|
103
|
-
* with `handle.stop()`. `timeoutMs` 0 is Runtime's 24-hour maximum. */
|
|
104
|
+
/** E2B's watchDir on Runtime's file watch. A local deadline preserves
|
|
105
|
+
* subsecond subscriptions; 0 runs until stopped or the sandbox ends. */
|
|
104
106
|
watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, opts?: WatchOpts & {
|
|
105
107
|
onExit?: (err?: Error) => void | Promise<void>;
|
|
106
108
|
}): Promise<E2BWatchHandle>;
|
package/dist/e2b/filesystem.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { request } from "./client.js";
|
|
2
|
-
import { FileNotFoundError, guard, NotSupportedError } from "./errors.js";
|
|
2
|
+
import { FileNotFoundError, guard, InvalidArgumentError, NotSupportedError, TimeoutError, } from "./errors.js";
|
|
3
3
|
export var FileType;
|
|
4
4
|
(function (FileType) {
|
|
5
5
|
FileType["FILE"] = "file";
|
|
@@ -42,8 +42,9 @@ function entryInfo(entry) {
|
|
|
42
42
|
size: entry.size,
|
|
43
43
|
mode,
|
|
44
44
|
permissions: PERMISSIONS[(bits >> 6) & 7] + PERMISSIONS[(bits >> 3) & 7] + PERMISSIONS[bits & 7],
|
|
45
|
-
owner: "",
|
|
46
|
-
group: "",
|
|
45
|
+
owner: entry.owner ?? "",
|
|
46
|
+
group: entry.group ?? "",
|
|
47
|
+
...(entry.symlinkTarget ? { symlinkTarget: entry.symlinkTarget } : {}),
|
|
47
48
|
modifiedTime: new Date(entry.modifiedAt),
|
|
48
49
|
};
|
|
49
50
|
}
|
|
@@ -73,8 +74,10 @@ export class Filesystem {
|
|
|
73
74
|
return this.#ctx.runtime.files;
|
|
74
75
|
}
|
|
75
76
|
async #path(path, opts) {
|
|
77
|
+
opts.signal?.throwIfAborted();
|
|
76
78
|
refuse(opts);
|
|
77
79
|
await this.#ctx.ensureHome(path);
|
|
80
|
+
opts.signal?.throwIfAborted();
|
|
78
81
|
return absolute(path);
|
|
79
82
|
}
|
|
80
83
|
async read(path, opts = {}) {
|
|
@@ -98,6 +101,7 @@ export class Filesystem {
|
|
|
98
101
|
return this.#writeOne(pathOrFiles, dataOrOpts, maybeOpts ?? {});
|
|
99
102
|
}
|
|
100
103
|
async writeFiles(files, opts = {}) {
|
|
104
|
+
opts.signal?.throwIfAborted();
|
|
101
105
|
const written = [];
|
|
102
106
|
for (const file of files)
|
|
103
107
|
written.push(await this.#writeOne(file.path, file.data, opts));
|
|
@@ -112,61 +116,156 @@ export class Filesystem {
|
|
|
112
116
|
/** A directory's entries, hidden ones included; `depth` goes deeper. */
|
|
113
117
|
async list(path, opts = {}) {
|
|
114
118
|
const dir = await this.#path(path, opts);
|
|
115
|
-
const entries = await guard("file", () => this.#files.list(dir, { depth: opts.depth ?? 1, hidden: true }));
|
|
119
|
+
const entries = await guard("file", () => this.#files.list(dir, { depth: opts.depth ?? 1, hidden: true, ...request(opts) }));
|
|
116
120
|
return entries.map(entryInfo);
|
|
117
121
|
}
|
|
118
122
|
/** Makes a directory and its parents. False when it already existed. */
|
|
119
123
|
async makeDir(path, opts = {}) {
|
|
120
124
|
const dir = await this.#path(path, opts);
|
|
121
|
-
if (await guard("file", () => this.#files.exists(dir)))
|
|
125
|
+
if (await guard("file", () => this.#files.exists(dir, request(opts))))
|
|
122
126
|
return false;
|
|
123
|
-
await guard("file", () => this.#files.mkdir(dir, { parents: true }));
|
|
127
|
+
await guard("file", () => this.#files.mkdir(dir, { parents: true, ...request(opts) }));
|
|
124
128
|
return true;
|
|
125
129
|
}
|
|
126
130
|
/** Moves a file or directory, replacing a file at the new path, as E2B does. */
|
|
127
131
|
async rename(oldPath, newPath, opts = {}) {
|
|
128
132
|
const from = await this.#path(oldPath, opts);
|
|
129
133
|
const to = await this.#path(newPath, opts);
|
|
130
|
-
await guard("file", () => this.#files.rename(from, to, { overwrite: true }));
|
|
134
|
+
await guard("file", () => this.#files.rename(from, to, { overwrite: true, ...request(opts) }));
|
|
131
135
|
return this.getInfo(to, opts);
|
|
132
136
|
}
|
|
133
137
|
/** Removes a file, or a directory with everything in it. */
|
|
134
138
|
async remove(path, opts = {}) {
|
|
135
139
|
const target = await this.#path(path, opts);
|
|
136
|
-
await guard("file", () => this.#files.remove(target, { recursive: true }));
|
|
140
|
+
await guard("file", () => this.#files.remove(target, { recursive: true, ...request(opts) }));
|
|
137
141
|
}
|
|
138
142
|
async exists(path, opts = {}) {
|
|
139
143
|
const target = await this.#path(path, opts);
|
|
140
|
-
return guard("file", () => this.#files.exists(target));
|
|
144
|
+
return guard("file", () => this.#files.exists(target, request(opts)));
|
|
141
145
|
}
|
|
142
146
|
async getInfo(path, opts = {}) {
|
|
143
147
|
const target = await this.#path(path, opts);
|
|
144
|
-
const stat = await guard("file", () => this.#files.stat(target));
|
|
148
|
+
const stat = await guard("file", () => this.#files.stat(target, request(opts)));
|
|
145
149
|
if (!stat.exists)
|
|
146
150
|
throw new FileNotFoundError(`${target} does not exist.`);
|
|
147
151
|
return entryInfo(stat);
|
|
148
152
|
}
|
|
149
|
-
/** E2B's watchDir on Runtime's file watch
|
|
150
|
-
*
|
|
151
|
-
* with `handle.stop()`. `timeoutMs` 0 is Runtime's 24-hour maximum. */
|
|
153
|
+
/** E2B's watchDir on Runtime's file watch. A local deadline preserves
|
|
154
|
+
* subsecond subscriptions; 0 runs until stopped or the sandbox ends. */
|
|
152
155
|
async watchDir(path, onEvent, opts = {}) {
|
|
156
|
+
opts.signal?.throwIfAborted();
|
|
157
|
+
if (opts.allowNetworkMounts)
|
|
158
|
+
throw new NotSupportedError("Watching network mounts", "Watch a local sandbox directory instead.");
|
|
159
|
+
const lifetime = opts.timeoutMs ?? 60000;
|
|
160
|
+
if (!Number.isFinite(lifetime) || lifetime < 0)
|
|
161
|
+
throw new InvalidArgumentError("timeoutMs must be a nonnegative finite number.");
|
|
153
162
|
const target = await this.#path(path, opts);
|
|
154
163
|
const prefix = target.endsWith("/") ? target : `${target}/`;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
let exited = false;
|
|
165
|
+
let native;
|
|
166
|
+
let stopping;
|
|
167
|
+
let timer;
|
|
168
|
+
const lifetimeAbort = new AbortController();
|
|
169
|
+
const signal = opts.signal
|
|
170
|
+
? AbortSignal.any([opts.signal, lifetimeAbort.signal])
|
|
171
|
+
: lifetimeAbort.signal;
|
|
172
|
+
const exit = async (error) => {
|
|
173
|
+
if (exited)
|
|
174
|
+
return;
|
|
175
|
+
exited = true;
|
|
176
|
+
if (timer !== undefined)
|
|
177
|
+
clearTimeout(timer);
|
|
178
|
+
opts.signal?.removeEventListener("abort", onAbort);
|
|
179
|
+
try {
|
|
180
|
+
await opts.onExit?.(error);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
/* Upstream treats a throwing terminal callback as handled. */
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const stopRemote = () => {
|
|
187
|
+
if (!native)
|
|
188
|
+
return Promise.resolve();
|
|
189
|
+
return (stopping ??= native.stop());
|
|
190
|
+
};
|
|
191
|
+
const close = async (error) => {
|
|
192
|
+
const callback = exit(error);
|
|
193
|
+
try {
|
|
194
|
+
await stopRemote();
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
await callback;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
const onAbort = () => {
|
|
201
|
+
const error = opts.signal?.reason instanceof Error
|
|
202
|
+
? opts.signal.reason
|
|
203
|
+
: new Error("The watch was aborted.");
|
|
204
|
+
void close(error).catch(() => undefined);
|
|
205
|
+
};
|
|
206
|
+
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
207
|
+
if (opts.signal?.aborted)
|
|
208
|
+
onAbort();
|
|
209
|
+
if (lifetime > 0) {
|
|
210
|
+
const deadline = Date.now() + lifetime;
|
|
211
|
+
const schedule = () => {
|
|
212
|
+
timer = setTimeout(() => {
|
|
213
|
+
if (exited)
|
|
214
|
+
return;
|
|
215
|
+
if (Date.now() < deadline) {
|
|
216
|
+
schedule();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const error = new TimeoutError("Filesystem watch timed out.");
|
|
220
|
+
// Mark the terminal result before native cancellation can report a
|
|
221
|
+
// clean end. The same signal also cancels creation still in flight.
|
|
222
|
+
void close(error).catch(() => undefined);
|
|
223
|
+
lifetimeAbort.abort(error);
|
|
224
|
+
}, Math.min(2147483647, Math.max(0, deadline - Date.now())));
|
|
225
|
+
timer.unref?.();
|
|
226
|
+
};
|
|
227
|
+
schedule();
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
const watch = await guard("file", () => this.#files.watch(target, async (event) => {
|
|
231
|
+
if (exited)
|
|
164
232
|
return;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
233
|
+
let entry;
|
|
234
|
+
if (opts.includeEntry) {
|
|
235
|
+
try {
|
|
236
|
+
entry = await this.getInfo(event.path, { ...opts, signal });
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
if (!(error instanceof FileNotFoundError))
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (!exited)
|
|
244
|
+
await onEvent({
|
|
245
|
+
name: event.path.startsWith(prefix) ? event.path.slice(prefix.length) : event.path,
|
|
246
|
+
type: event.type,
|
|
247
|
+
...(entry ? { entry } : {}),
|
|
248
|
+
});
|
|
249
|
+
}, {
|
|
250
|
+
recursive: opts.recursive === true,
|
|
251
|
+
timeoutMs: 0,
|
|
252
|
+
signal,
|
|
253
|
+
onExit: (reason) => {
|
|
254
|
+
void exit(reason === "timeout" ? new TimeoutError("Filesystem watch timed out.") : undefined);
|
|
255
|
+
},
|
|
256
|
+
onNotice: (notice) => {
|
|
257
|
+
void close(new Error(`Filesystem events were lost (${notice.k}); rescan the directory and start a new watch.`)).catch(() => undefined);
|
|
258
|
+
},
|
|
259
|
+
}));
|
|
260
|
+
native = watch;
|
|
261
|
+
if (exited)
|
|
262
|
+
await stopRemote();
|
|
263
|
+
void watch.done?.then(() => exit(), (error) => close(error instanceof Error ? error : new Error(String(error))).catch(() => undefined));
|
|
264
|
+
return { stop: () => close() };
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
await close(error instanceof Error ? error : new Error(String(error))).catch(() => undefined);
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
171
270
|
}
|
|
172
271
|
}
|
package/dist/e2b/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { Commands, CommandHandle, pidOf, type CommandStartOpts, type CommandConn
|
|
|
12
12
|
export { Filesystem, FileType, type EntryInfo, type WriteInfo, type WriteEntry, type FilesystemRequestOpts, type FilesystemReadOpts, type FilesystemWriteOpts, type FilesystemListOpts, FilesystemEventType, type FilesystemEvent, type WatchOpts, type E2BWatchHandle as WatchHandle, } from "./filesystem.js";
|
|
13
13
|
export { SandboxError, TimeoutError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, FileNotFoundError, SandboxNotFoundError, TemplateError, RateLimitError, AuthenticationError, ServiceBusyError, CommandExitError, NotSupportedError, type CommandResult, } from "./errors.js";
|
|
14
14
|
export type { ConnectionOpts, RuntimeOpts } from "./client.js";
|
|
15
|
+
export { Pty, type PtyCreateOpts, type PtyConnectOpts } from "./pty.js";
|
|
15
16
|
export { Template, TemplateBase, Volume, Secret, waitForPort, waitForURL, waitForProcess, waitForFile, waitForTimeout, } from "./unsupported.js";
|
|
16
17
|
export default Sandbox;
|
|
17
18
|
/** E2B's client with bound options: `new E2B({ apiKey }).Sandbox.create()`. */
|
package/dist/e2b/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { Sandbox, SandboxPaginator, DEFAULT_SHAPE, DEFAULT_TIMEOUT_MS, } from ".
|
|
|
4
4
|
export { Commands, CommandHandle, pidOf, } from "./commands.js";
|
|
5
5
|
export { Filesystem, FileType, FilesystemEventType, } from "./filesystem.js";
|
|
6
6
|
export { SandboxError, TimeoutError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, FileNotFoundError, SandboxNotFoundError, TemplateError, RateLimitError, AuthenticationError, ServiceBusyError, CommandExitError, NotSupportedError, } from "./errors.js";
|
|
7
|
+
export { Pty } from "./pty.js";
|
|
7
8
|
export { Template, TemplateBase, Volume, Secret, waitForPort, waitForURL, waitForProcess, waitForFile, waitForTimeout, } from "./unsupported.js";
|
|
8
9
|
export default Sandbox;
|
|
9
10
|
/** E2B's client with bound options: `new E2B({ apiKey }).Sandbox.create()`. */
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CommandHandle, type CommandRequestOpts, type SandboxContext, type Username } from "./commands.js";
|
|
2
|
+
export interface PtyCreateOpts extends CommandRequestOpts {
|
|
3
|
+
cols: number;
|
|
4
|
+
rows: number;
|
|
5
|
+
onData: (data: Uint8Array) => void | Promise<void>;
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
user?: Username;
|
|
8
|
+
envs?: Record<string, string>;
|
|
9
|
+
cwd?: string;
|
|
10
|
+
}
|
|
11
|
+
export type PtyConnectOpts = CommandRequestOpts & Pick<PtyCreateOpts, "onData" | "timeoutMs">;
|
|
12
|
+
/** E2B's PTY methods over native terminal processes with lossless output. */
|
|
13
|
+
export declare class Pty {
|
|
14
|
+
private readonly ctx;
|
|
15
|
+
constructor(ctx: SandboxContext);
|
|
16
|
+
create(opts: PtyCreateOpts): Promise<CommandHandle>;
|
|
17
|
+
connect(pid: number, opts?: PtyConnectOpts): Promise<CommandHandle>;
|
|
18
|
+
sendInput(pid: number, data: Uint8Array, opts?: CommandRequestOpts): Promise<void>;
|
|
19
|
+
resize(pid: number, size: {
|
|
20
|
+
cols: number;
|
|
21
|
+
rows: number;
|
|
22
|
+
}, opts?: CommandRequestOpts): Promise<void>;
|
|
23
|
+
kill(pid: number, opts?: CommandRequestOpts): Promise<boolean>;
|
|
24
|
+
}
|
package/dist/e2b/pty.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { CommandHandle, commandRequest, connectionRequest, killProcess, refuseUser, resolveProcess, } from "./commands.js";
|
|
2
|
+
import { guard, InvalidArgumentError, NotSupportedError } from "./errors.js";
|
|
3
|
+
function dimensions(size) {
|
|
4
|
+
for (const value of [size.cols, size.rows])
|
|
5
|
+
if (!Number.isSafeInteger(value) || value <= 0)
|
|
6
|
+
throw new InvalidArgumentError("PTY rows and columns must be positive whole numbers.");
|
|
7
|
+
return { cols: size.cols, rows: size.rows };
|
|
8
|
+
}
|
|
9
|
+
/** E2B's PTY methods over native terminal processes with lossless output. */
|
|
10
|
+
export class Pty {
|
|
11
|
+
ctx;
|
|
12
|
+
constructor(ctx) {
|
|
13
|
+
this.ctx = ctx;
|
|
14
|
+
}
|
|
15
|
+
async create(opts) {
|
|
16
|
+
refuseUser(opts.user);
|
|
17
|
+
const pty = dimensions(opts);
|
|
18
|
+
const opening = connectionRequest(opts, this.ctx.requestTimeoutMs);
|
|
19
|
+
if (typeof opts.onData !== "function")
|
|
20
|
+
throw new InvalidArgumentError("onData must be a function.");
|
|
21
|
+
const env = { TERM: "xterm-256color", LANG: "C.UTF-8", LC_ALL: "C.UTF-8", ...opts.envs };
|
|
22
|
+
const process = await guard("sandbox", async () => {
|
|
23
|
+
await this.ctx.ensureHome(opts.cwd, opening.request);
|
|
24
|
+
opening.request.signal?.throwIfAborted();
|
|
25
|
+
return this.ctx.runtime.spawn(["/bin/bash", "-i", "-l"], {
|
|
26
|
+
pty,
|
|
27
|
+
stdin: "pipe",
|
|
28
|
+
outputEncoding: "base64",
|
|
29
|
+
env,
|
|
30
|
+
...(opts.cwd === undefined ? {} : { cwd: opts.cwd }),
|
|
31
|
+
request: opening.request,
|
|
32
|
+
});
|
|
33
|
+
}).catch(opening.failure);
|
|
34
|
+
return new CommandHandle(process, {
|
|
35
|
+
stdin: false,
|
|
36
|
+
pty: true,
|
|
37
|
+
onData: opts.onData,
|
|
38
|
+
timeoutMs: opening.timeoutMs,
|
|
39
|
+
deadline: opening.deadline,
|
|
40
|
+
signal: opts.signal,
|
|
41
|
+
requestTimeoutMs: this.ctx.requestTimeoutMs,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async connect(pid, opts) {
|
|
45
|
+
const opening = connectionRequest(opts ?? {}, this.ctx.requestTimeoutMs);
|
|
46
|
+
const process = await resolveProcess(this.ctx, pid, opening.request).catch(opening.failure);
|
|
47
|
+
if (!process.info.pty || process.info.outputEncoding !== "base64")
|
|
48
|
+
throw new NotSupportedError("Connecting to a legacy text-output PTY", "Create the PTY through sandbox.pty.create first.");
|
|
49
|
+
return new CommandHandle(process, {
|
|
50
|
+
stdin: false,
|
|
51
|
+
pty: true,
|
|
52
|
+
onData: opts?.onData,
|
|
53
|
+
timeoutMs: opening.timeoutMs,
|
|
54
|
+
deadline: opening.deadline,
|
|
55
|
+
cursor: process.info.outputBytes,
|
|
56
|
+
signal: opts?.signal,
|
|
57
|
+
requestTimeoutMs: this.ctx.requestTimeoutMs,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async sendInput(pid, data, opts = {}) {
|
|
61
|
+
const request = commandRequest(opts, this.ctx.requestTimeoutMs);
|
|
62
|
+
const process = await resolveProcess(this.ctx, pid, request);
|
|
63
|
+
if (!process.info.pty)
|
|
64
|
+
throw new InvalidArgumentError(`The process with pid ${pid} is not a PTY.`);
|
|
65
|
+
request.signal?.throwIfAborted();
|
|
66
|
+
await guard("sandbox", () => process.write(data, request));
|
|
67
|
+
}
|
|
68
|
+
async resize(pid, size, opts = {}) {
|
|
69
|
+
const pty = dimensions(size);
|
|
70
|
+
const request = commandRequest(opts, this.ctx.requestTimeoutMs);
|
|
71
|
+
const process = await resolveProcess(this.ctx, pid, request);
|
|
72
|
+
if (!process.info.pty)
|
|
73
|
+
throw new InvalidArgumentError(`The process with pid ${pid} is not a PTY.`);
|
|
74
|
+
request.signal?.throwIfAborted();
|
|
75
|
+
await guard("sandbox", () => process.resize(pty.cols, pty.rows, request));
|
|
76
|
+
}
|
|
77
|
+
kill(pid, opts = {}) {
|
|
78
|
+
return killProcess(this.ctx, pid, commandRequest(opts, this.ctx.requestTimeoutMs));
|
|
79
|
+
}
|
|
80
|
+
}
|
package/dist/e2b/sandbox.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Runtime } from "../client.js";
|
|
|
2
2
|
import { type ConnectionOpts, type RuntimeOpts, type RuntimeSandbox } from "./client.js";
|
|
3
3
|
import { Commands } from "./commands.js";
|
|
4
4
|
import { Filesystem } from "./filesystem.js";
|
|
5
|
+
import { Pty } from "./pty.js";
|
|
5
6
|
/** E2B's default machine: 2 vCPU and 512 MiB (docs.e2b.dev/billing, checked
|
|
6
7
|
* 23 September 2026). Pass `runtime: { create: { memoryMiB } }` for another. */
|
|
7
8
|
export declare const DEFAULT_SHAPE: {
|
|
@@ -26,7 +27,8 @@ export interface SandboxOpts extends ConnectionOpts {
|
|
|
26
27
|
template?: string;
|
|
27
28
|
/** Stored as the sandbox's labels (at most 32, values up to 256 characters). */
|
|
28
29
|
metadata?: Record<string, string>;
|
|
29
|
-
/**
|
|
30
|
+
/** The sandbox's own environment: every command, terminal and code run in it
|
|
31
|
+
* gets these, whoever connects. Values are never shown again. */
|
|
30
32
|
envs?: Record<string, string>;
|
|
31
33
|
/** Default 300 000. Runtime's leases run 60 s to 1 hour; shorter rounds up
|
|
32
34
|
* to 60 s (with a warning), longer is refused. */
|
|
@@ -88,17 +90,18 @@ export type SandboxListOpts = SandboxApiOpts & {
|
|
|
88
90
|
};
|
|
89
91
|
export declare class Sandbox {
|
|
90
92
|
#private;
|
|
93
|
+
protected readonly requestTimeoutMs: number;
|
|
91
94
|
protected static readonly defaultTemplate: string;
|
|
92
95
|
readonly files: Filesystem;
|
|
93
96
|
readonly commands: Commands;
|
|
97
|
+
readonly pty: Pty;
|
|
94
98
|
/** Use Sandbox.create or Sandbox.connect. */
|
|
95
|
-
constructor(runtime: RuntimeSandbox, client: Runtime,
|
|
99
|
+
constructor(runtime: RuntimeSandbox, client: Runtime, requestTimeoutMs?: number);
|
|
96
100
|
get sandboxId(): string;
|
|
97
101
|
/** The Runtime sandbox underneath: previews, network, desktop, interpreter,
|
|
98
102
|
* processes, terminal and the rest of Runtime's SDK. */
|
|
99
103
|
get runtime(): RuntimeSandbox;
|
|
100
104
|
protected get client(): Runtime;
|
|
101
|
-
protected get envs(): Record<string, string>;
|
|
102
105
|
/** Creates a sandbox from `template` (default "base", Runtime's stock image)
|
|
103
106
|
* with E2B's default machine, 2 vCPU and 512 MiB, and waits until it runs.
|
|
104
107
|
* Funding is left to Runtime: the free trial while the account has trial
|
|
@@ -166,7 +169,6 @@ export declare class Sandbox {
|
|
|
166
169
|
* its host, `<port>-<id>.<domain>`, once the share has landed. Anyone with
|
|
167
170
|
* the address can reach it; a browser sees a one-time page naming Runtime. */
|
|
168
171
|
getPublicHost(port: number): Promise<string>;
|
|
169
|
-
get pty(): never;
|
|
170
172
|
get git(): never;
|
|
171
173
|
/** E2B's metrics, from Runtime's measured readings (`sbx.metrics()`): CPU
|
|
172
174
|
* as a percent of the sandbox's vCPUs and resident memory, one entry per
|
package/dist/e2b/sandbox.js
CHANGED
|
@@ -2,6 +2,7 @@ import { clientFor, request, } from "./client.js";
|
|
|
2
2
|
import { Commands } from "./commands.js";
|
|
3
3
|
import { guard, InvalidArgumentError, NotSupportedError, SandboxError, SandboxNotFoundError, TemplateError, } from "./errors.js";
|
|
4
4
|
import { Filesystem } from "./filesystem.js";
|
|
5
|
+
import { Pty } from "./pty.js";
|
|
5
6
|
/* E2B's Sandbox over Runtime's. Every call is one or a few calls of the
|
|
6
7
|
withruntime SDK; nothing here speaks HTTP. What Runtime cannot do the same
|
|
7
8
|
way throws NotSupportedError before anything happens. */
|
|
@@ -65,12 +66,13 @@ function refuseCreate(opts) {
|
|
|
65
66
|
}
|
|
66
67
|
/** Where a template sends the create: the stock image, a Runtime image by
|
|
67
68
|
* name or id, or a Runtime snapshot by id. */
|
|
68
|
-
async function resolveTemplate(client, template) {
|
|
69
|
+
async function resolveTemplate(client, template, options) {
|
|
70
|
+
options.signal?.throwIfAborted();
|
|
69
71
|
if (STOCK_TEMPLATES.has(template))
|
|
70
72
|
return {};
|
|
71
73
|
if (UUID.test(template)) {
|
|
72
74
|
try {
|
|
73
|
-
await client.images.get(template);
|
|
75
|
+
await client.images.get(template, options);
|
|
74
76
|
return { image: template };
|
|
75
77
|
}
|
|
76
78
|
catch (error) {
|
|
@@ -79,7 +81,7 @@ async function resolveTemplate(client, template) {
|
|
|
79
81
|
}
|
|
80
82
|
return { snapshot: template };
|
|
81
83
|
}
|
|
82
|
-
const page = await client.images.list({ name: template, state: "ready", limit: 1 });
|
|
84
|
+
const page = await client.images.list({ name: template, state: "ready", limit: 1 }, options);
|
|
83
85
|
const image = page.data[0];
|
|
84
86
|
if (image)
|
|
85
87
|
return { image: image.id };
|
|
@@ -131,28 +133,30 @@ function unsupported(feature, alternative) {
|
|
|
131
133
|
/** Where Runtime serves previews; getHost names a host under it. */
|
|
132
134
|
const PREVIEW_DOMAIN = "runtimehost.com";
|
|
133
135
|
export class Sandbox {
|
|
136
|
+
requestTimeoutMs;
|
|
134
137
|
static defaultTemplate = "base";
|
|
135
138
|
files;
|
|
136
139
|
commands;
|
|
140
|
+
pty;
|
|
137
141
|
#client;
|
|
138
142
|
#runtime;
|
|
139
|
-
#envs;
|
|
140
143
|
#home;
|
|
141
144
|
/** Ports shared as public previews, by port: the one share each asked for. */
|
|
142
145
|
#shares = new Map();
|
|
143
146
|
/** Use Sandbox.create or Sandbox.connect. */
|
|
144
|
-
constructor(runtime, client,
|
|
147
|
+
constructor(runtime, client, requestTimeoutMs = 60_000) {
|
|
148
|
+
this.requestTimeoutMs = requestTimeoutMs;
|
|
145
149
|
this.#runtime = runtime;
|
|
146
150
|
this.#client = client;
|
|
147
|
-
this.#envs = envs;
|
|
148
151
|
const ctx = {
|
|
149
|
-
|
|
150
|
-
|
|
152
|
+
ensureHome: (text, options) => this.#ensureHome(text, options),
|
|
153
|
+
requestTimeoutMs: this.requestTimeoutMs,
|
|
151
154
|
};
|
|
152
155
|
// A getter, so the modules see the sandbox as it is after each refresh.
|
|
153
156
|
Object.defineProperty(ctx, "runtime", { get: () => this.#runtime });
|
|
154
157
|
this.files = new Filesystem(ctx);
|
|
155
158
|
this.commands = new Commands(ctx);
|
|
159
|
+
this.pty = new Pty(ctx);
|
|
156
160
|
}
|
|
157
161
|
get sandboxId() {
|
|
158
162
|
return this.#runtime.id;
|
|
@@ -165,27 +169,50 @@ export class Sandbox {
|
|
|
165
169
|
get client() {
|
|
166
170
|
return this.#client;
|
|
167
171
|
}
|
|
168
|
-
get envs() {
|
|
169
|
-
return this.#envs;
|
|
170
|
-
}
|
|
171
172
|
/** E2B's home is /home/user and Runtime's is /workspace. The first time a
|
|
172
173
|
* path or command names /home/user, it is made a link to /workspace (unless
|
|
173
174
|
* something is already there), so paths written for E2B work. */
|
|
174
|
-
#ensureHome(text) {
|
|
175
|
+
#ensureHome(text, options = {}) {
|
|
176
|
+
const signal = options.signal;
|
|
177
|
+
signal?.throwIfAborted();
|
|
178
|
+
const wait = (pending) => {
|
|
179
|
+
if (!signal)
|
|
180
|
+
return pending;
|
|
181
|
+
return new Promise((resolve, reject) => {
|
|
182
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- rejects with the caller's abort reason as is, as the upstream SDK does
|
|
183
|
+
const abort = () => reject(signal.reason);
|
|
184
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
185
|
+
pending.then(() => {
|
|
186
|
+
signal.removeEventListener("abort", abort);
|
|
187
|
+
resolve();
|
|
188
|
+
}, (error) => {
|
|
189
|
+
signal.removeEventListener("abort", abort);
|
|
190
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- passes the pending call's own failure through unchanged
|
|
191
|
+
reject(error);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
};
|
|
175
195
|
if (this.#home || !text?.includes("/home/user"))
|
|
176
|
-
return this.#home ?? Promise.resolve();
|
|
177
|
-
|
|
178
|
-
const result = await guard("sandbox", () => this.#runtime.exec("[ -e /home/user ] || sudo ln -s /workspace /home/user"));
|
|
196
|
+
return wait(this.#home ?? Promise.resolve());
|
|
197
|
+
const pending = (async () => {
|
|
198
|
+
const result = await guard("sandbox", () => this.#runtime.exec("[ -e /home/user ] || sudo ln -s /workspace /home/user", { signal }));
|
|
179
199
|
if (result.exitCode !== 0 && typeof process !== "undefined")
|
|
180
200
|
process.emitWarning(`Could not link /home/user to /workspace: ${result.stderr.trim()}`, {
|
|
181
201
|
code: "RUNTIME_E2B_HOME",
|
|
182
202
|
});
|
|
183
203
|
})();
|
|
184
|
-
|
|
204
|
+
this.#home = pending;
|
|
205
|
+
pending.catch(() => {
|
|
206
|
+
if (this.#home === pending)
|
|
207
|
+
this.#home = undefined;
|
|
208
|
+
});
|
|
209
|
+
return wait(pending);
|
|
185
210
|
}
|
|
186
211
|
static async create(templateOrOpts, maybeOpts) {
|
|
187
212
|
const opts = (typeof templateOrOpts === "string" ? maybeOpts : templateOrOpts) ?? {};
|
|
188
213
|
const template = (typeof templateOrOpts === "string" ? templateOrOpts : opts.template) ?? this.defaultTemplate;
|
|
214
|
+
const options = request(opts);
|
|
215
|
+
options.signal?.throwIfAborted();
|
|
189
216
|
refuseCreate(opts);
|
|
190
217
|
const client = clientFor(opts);
|
|
191
218
|
const input = {
|
|
@@ -195,9 +222,13 @@ export class Sandbox {
|
|
|
195
222
|
// asked (autoResume); Runtime's automatic wake is the same thing (0093).
|
|
196
223
|
...(opts.lifecycle ? { autoWake: opts.lifecycle.autoResume === true } : {}),
|
|
197
224
|
...(opts.metadata && Object.keys(opts.metadata).length ? { labels: opts.metadata } : {}),
|
|
225
|
+
// Runtime keeps them with the sandbox: every command, terminal and
|
|
226
|
+
// interpreter in it gets them, from this client or any other.
|
|
227
|
+
...(opts.envs && Object.keys(opts.envs).length ? { env: opts.envs } : {}),
|
|
198
228
|
...(opts.allowInternetAccess === false ? { network: { internet: false } } : {}),
|
|
199
229
|
};
|
|
200
|
-
const source = await guard("other", () => resolveTemplate(client, template));
|
|
230
|
+
const source = await guard("other", () => resolveTemplate(client, template, options));
|
|
231
|
+
options.signal?.throwIfAborted();
|
|
201
232
|
const create = {
|
|
202
233
|
// A snapshot carries its own machine; everything else gets E2B's shape.
|
|
203
234
|
...(source.snapshot ? {} : DEFAULT_SHAPE),
|
|
@@ -205,8 +236,8 @@ export class Sandbox {
|
|
|
205
236
|
...source,
|
|
206
237
|
...opts.runtime?.create,
|
|
207
238
|
};
|
|
208
|
-
const runtime = await guard("sandbox", () => client.sandboxes.create(create,
|
|
209
|
-
return new this(runtime, client,
|
|
239
|
+
const runtime = await guard("sandbox", () => client.sandboxes.create(create, options));
|
|
240
|
+
return new this(runtime, client, opts.requestTimeoutMs);
|
|
210
241
|
}
|
|
211
242
|
/** Connects to a sandbox by id, waking it if it is paused, as E2B does. A
|
|
212
243
|
* `timeoutMs` moves a running sandbox's end later, never earlier. */
|
|
@@ -214,7 +245,7 @@ export class Sandbox {
|
|
|
214
245
|
const client = clientFor(opts);
|
|
215
246
|
const runtime = await guard("sandbox", () => client.sandboxes.get(sandboxId, request(opts)));
|
|
216
247
|
await resume(runtime, opts);
|
|
217
|
-
return new this(runtime, client);
|
|
248
|
+
return new this(runtime, client, opts.requestTimeoutMs);
|
|
218
249
|
}
|
|
219
250
|
/** Wakes this sandbox if it is paused. */
|
|
220
251
|
async connect(opts = {}) {
|
|
@@ -309,8 +340,9 @@ export class Sandbox {
|
|
|
309
340
|
// honoured after the forks exist, so this is refused before any are made.
|
|
310
341
|
throw new NotSupportedError("A timeout for forks (fork timeoutMs)", "Fork without it, then call setTimeout(ms) on each fork.");
|
|
311
342
|
const copies = await guard("sandbox", () => this.#runtime.fork({ count: opts.count ?? 1, ...request(opts) }));
|
|
343
|
+
// Copies keep the source's environment on Runtime's side.
|
|
312
344
|
const Kind = this.constructor;
|
|
313
|
-
return copies.map((copy) => new Kind(copy, this.#client
|
|
345
|
+
return copies.map((copy) => new Kind(copy, this.#client));
|
|
314
346
|
}
|
|
315
347
|
/** Keeps the sandbox's whole machine as a Runtime snapshot; start from it
|
|
316
348
|
* with Sandbox.create(snapshotId). */
|
|
@@ -369,9 +401,6 @@ export class Sandbox {
|
|
|
369
401
|
return share;
|
|
370
402
|
}
|
|
371
403
|
// ---- what Runtime does differently -----------------------------------
|
|
372
|
-
get pty() {
|
|
373
|
-
throw new NotSupportedError("E2B's pty module", "Use `await sandbox.runtime.terminal({ cols, rows, onData })` for an interactive terminal, or runtime.spawn(cmd, { pty: {} }).");
|
|
374
|
-
}
|
|
375
404
|
get git() {
|
|
376
405
|
throw new NotSupportedError("E2B's git module (deprecated by E2B too)", "Run git with sandbox.commands.run('git ...'); git is installed.");
|
|
377
406
|
}
|
|
@@ -454,11 +483,13 @@ const PAUSED = ["pausing", "paused"];
|
|
|
454
483
|
/** E2B's paginator: `while (p.hasNext) items.push(...(await p.nextItems()))`. */
|
|
455
484
|
export class SandboxPaginator {
|
|
456
485
|
#client;
|
|
486
|
+
#request;
|
|
457
487
|
#filter;
|
|
458
488
|
#page;
|
|
459
489
|
#hasNext = true;
|
|
460
490
|
constructor(client, opts) {
|
|
461
491
|
this.#client = client;
|
|
492
|
+
this.#request = request(opts);
|
|
462
493
|
const query = opts.query ?? {};
|
|
463
494
|
if (query.template !== undefined && !STOCK_TEMPLATES.has(query.template))
|
|
464
495
|
throw new NotSupportedError("Listing by template", "Filter by metadata instead: give sandboxes a metadata key when you create them.");
|
|
@@ -482,10 +513,13 @@ export class SandboxPaginator {
|
|
|
482
513
|
return this.#page?.nextCursor ?? undefined;
|
|
483
514
|
}
|
|
484
515
|
async nextItems() {
|
|
516
|
+
this.#request.signal?.throwIfAborted();
|
|
485
517
|
if (!this.#hasNext)
|
|
486
518
|
throw new SandboxError("No more items to fetch.");
|
|
487
519
|
const previous = this.#page;
|
|
488
|
-
const page = await guard("other", async () => previous
|
|
520
|
+
const page = await guard("other", async () => previous
|
|
521
|
+
? await previous.next()
|
|
522
|
+
: await this.#client.sandboxes.list(this.#filter, this.#request));
|
|
489
523
|
this.#page = page ?? undefined;
|
|
490
524
|
this.#hasNext = Boolean(page?.hasMore);
|
|
491
525
|
return (page?.data ?? []).map(infoOf);
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/** Every failure the SDK raises. `code` is stable and machine-readable,
|
|
2
|
+
* `hint` says what to do next, and `requestId` is what to quote in a report
|
|
3
|
+
* (runtime.feedback.submit, `runtime feedback`, or support). */
|
|
4
|
+
/** A product switched off on this deployment, or paused on purpose: the API
|
|
5
|
+
* answers these 503s in fixed words (`serverFault` "off" in
|
|
6
|
+
* packages/cloud/src/api/respond.ts) and retrying cannot change them.
|
|
7
|
+
* host_unavailable and busy pass, and are retried. */
|
|
8
|
+
export declare const DELIBERATE: ReadonlySet<string>;
|
|
1
9
|
/** Refusals of a create that clear when a sandbox stops or pauses, or a host
|
|
2
10
|
* frees room: the trial's slots, an email domain's trial slots, the account's
|
|
3
11
|
* quota and the region's capacity. `sandboxes.create` waits them out, retrying
|