withruntime 0.3.0 → 0.4.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/E2B.md +146 -0
- package/README.md +41 -5
- package/dist/cli.js +43 -7
- package/dist/client.d.ts +5 -0
- package/dist/e2b/client.d.ts +58 -0
- package/dist/e2b/client.js +66 -0
- package/dist/e2b/code-interpreter.d.ts +144 -0
- package/dist/e2b/code-interpreter.js +244 -0
- package/dist/e2b/commands.d.ts +100 -0
- package/dist/e2b/commands.js +268 -0
- package/dist/e2b/errors.d.ts +72 -0
- package/dist/e2b/errors.js +151 -0
- package/dist/e2b/filesystem.d.ts +82 -0
- package/dist/e2b/filesystem.js +143 -0
- package/dist/e2b/index.d.ts +28 -0
- package/dist/e2b/index.js +61 -0
- package/dist/e2b/sandbox.d.ts +183 -0
- package/dist/e2b/sandbox.js +458 -0
- package/dist/e2b/unsupported.d.ts +19 -0
- package/dist/e2b/unsupported.js +27 -0
- package/dist/index.d.ts +1 -0
- package/dist/login.js +13 -4
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +4 -3
- package/dist/products/index.d.ts +2 -0
- package/dist/products/index.js +2 -1
- package/dist/products/limits.d.ts +25 -0
- package/dist/products/limits.js +10 -0
- package/dist/products/previews.d.ts +3 -0
- package/dist/proxy.d.ts +30 -0
- package/dist/proxy.js +178 -0
- package/dist/sandbox.d.ts +4 -1
- package/dist/transport.d.ts +1 -1
- package/dist/transport.js +46 -13
- package/package.json +16 -3
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { RuntimeError } from "../errors.js";
|
|
2
|
+
function attach(error, detail) {
|
|
3
|
+
const target = error;
|
|
4
|
+
if (detail.code !== undefined)
|
|
5
|
+
target.code = detail.code;
|
|
6
|
+
if (detail.hint !== undefined)
|
|
7
|
+
target.hint = detail.hint;
|
|
8
|
+
if (detail.requestId !== undefined)
|
|
9
|
+
target.requestId = detail.requestId;
|
|
10
|
+
if (detail.cause !== undefined)
|
|
11
|
+
target.cause = detail.cause;
|
|
12
|
+
}
|
|
13
|
+
/** Base class for E2B's sandbox errors. */
|
|
14
|
+
export class SandboxError extends Error {
|
|
15
|
+
statusCode;
|
|
16
|
+
code;
|
|
17
|
+
hint;
|
|
18
|
+
requestId;
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = new.target.name;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class TimeoutError extends SandboxError {
|
|
25
|
+
}
|
|
26
|
+
export class InvalidArgumentError extends SandboxError {
|
|
27
|
+
}
|
|
28
|
+
export class NotEnoughSpaceError extends SandboxError {
|
|
29
|
+
}
|
|
30
|
+
export class NotFoundError extends SandboxError {
|
|
31
|
+
}
|
|
32
|
+
export class FileNotFoundError extends NotFoundError {
|
|
33
|
+
}
|
|
34
|
+
export class SandboxNotFoundError extends NotFoundError {
|
|
35
|
+
}
|
|
36
|
+
export class TemplateError extends SandboxError {
|
|
37
|
+
}
|
|
38
|
+
export class RateLimitError extends SandboxError {
|
|
39
|
+
}
|
|
40
|
+
/** E2B's AuthenticationError extends Error, not SandboxError. */
|
|
41
|
+
export class AuthenticationError extends Error {
|
|
42
|
+
code;
|
|
43
|
+
hint;
|
|
44
|
+
requestId;
|
|
45
|
+
constructor(message) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.name = new.target.name;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** E2B's ServiceBusyError extends Error, not SandboxError. */
|
|
51
|
+
export class ServiceBusyError extends Error {
|
|
52
|
+
statusCode = 503;
|
|
53
|
+
code;
|
|
54
|
+
hint;
|
|
55
|
+
requestId;
|
|
56
|
+
constructor(message) {
|
|
57
|
+
super(message);
|
|
58
|
+
this.name = new.target.name;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** A call that E2B supports and Runtime does not, or not in the same way.
|
|
62
|
+
* Thrown before anything is done, never after doing something different.
|
|
63
|
+
* `feature` names what was asked for; `alternative` says what to use on
|
|
64
|
+
* Runtime instead. */
|
|
65
|
+
export class NotSupportedError extends SandboxError {
|
|
66
|
+
feature;
|
|
67
|
+
alternative;
|
|
68
|
+
constructor(feature, alternative, message) {
|
|
69
|
+
super(message ?? `${feature} is not supported on Runtime. ${alternative}`);
|
|
70
|
+
this.feature = feature;
|
|
71
|
+
this.alternative = alternative;
|
|
72
|
+
this.code = "not_supported";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Thrown by `commands.run` and `CommandHandle.wait` when the command exits
|
|
76
|
+
* with a code other than 0. It carries the result, as in E2B. */
|
|
77
|
+
export class CommandExitError extends SandboxError {
|
|
78
|
+
#result;
|
|
79
|
+
constructor(result) {
|
|
80
|
+
super(`Command exited with code ${result.exitCode} and error:\n${result.stderr}`);
|
|
81
|
+
this.#result = result;
|
|
82
|
+
}
|
|
83
|
+
get exitCode() {
|
|
84
|
+
return this.#result.exitCode;
|
|
85
|
+
}
|
|
86
|
+
get error() {
|
|
87
|
+
return this.#result.error;
|
|
88
|
+
}
|
|
89
|
+
get stdout() {
|
|
90
|
+
return this.#result.stdout;
|
|
91
|
+
}
|
|
92
|
+
get stderr() {
|
|
93
|
+
return this.#result.stderr;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Turns a Runtime SDK error into the E2B error a caller written for E2B
|
|
97
|
+
* expects. Anything that is not a Runtime error passes through unchanged. */
|
|
98
|
+
export function translate(error, subject = "other") {
|
|
99
|
+
if (!(error instanceof RuntimeError))
|
|
100
|
+
return error;
|
|
101
|
+
const message = [
|
|
102
|
+
error.message,
|
|
103
|
+
error.hint ? `Hint: ${error.hint}` : "",
|
|
104
|
+
error.requestId ? `Request: ${error.requestId}` : "",
|
|
105
|
+
]
|
|
106
|
+
.filter(Boolean)
|
|
107
|
+
.join("\n");
|
|
108
|
+
let out;
|
|
109
|
+
if (error.status === 503 && error.code.endsWith("_unavailable"))
|
|
110
|
+
// A product switched off on purpose (forks, previews): Runtime's own words
|
|
111
|
+
// say what is off and what to use meanwhile.
|
|
112
|
+
out = new NotSupportedError(error.code.replace(/_unavailable$/, ""), error.hint ?? "", message);
|
|
113
|
+
else if (error.status === 401 || error.status === 403)
|
|
114
|
+
out = new AuthenticationError(message);
|
|
115
|
+
else if (error.code === "file_not_found" || (error.status === 404 && subject === "file"))
|
|
116
|
+
out = new FileNotFoundError(message);
|
|
117
|
+
else if (error.status === 404 && subject === "sandbox")
|
|
118
|
+
out = new SandboxNotFoundError(message);
|
|
119
|
+
else if (error.status === 404)
|
|
120
|
+
out = new NotFoundError(message);
|
|
121
|
+
else if (error.status === 429)
|
|
122
|
+
out = new RateLimitError(message);
|
|
123
|
+
else if (/space|disk_full|no_room/.test(error.code))
|
|
124
|
+
out = new NotEnoughSpaceError(message);
|
|
125
|
+
else if (error.status === 400 || error.status === 413 || error.status === 422)
|
|
126
|
+
out = new InvalidArgumentError(message);
|
|
127
|
+
else if (error.status === 503)
|
|
128
|
+
out = new ServiceBusyError(message);
|
|
129
|
+
else if (error.code === "command_timeout")
|
|
130
|
+
out = new TimeoutError(message);
|
|
131
|
+
else
|
|
132
|
+
out = new SandboxError(message);
|
|
133
|
+
if (out instanceof SandboxError && error.status)
|
|
134
|
+
out.statusCode = error.status;
|
|
135
|
+
attach(out, {
|
|
136
|
+
code: error.code,
|
|
137
|
+
...(error.hint ? { hint: error.hint } : {}),
|
|
138
|
+
...(error.requestId ? { requestId: error.requestId } : {}),
|
|
139
|
+
cause: error,
|
|
140
|
+
});
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
/** Runs `work`, turning any Runtime error into its E2B counterpart. */
|
|
144
|
+
export async function guard(subject, work) {
|
|
145
|
+
try {
|
|
146
|
+
return await work();
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
throw translate(error, subject);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { SandboxContext, Username } from "./commands.js";
|
|
2
|
+
export declare enum FileType {
|
|
3
|
+
FILE = "file",
|
|
4
|
+
DIR = "dir",
|
|
5
|
+
SYMLINK = "symlink"
|
|
6
|
+
}
|
|
7
|
+
export interface WriteInfo {
|
|
8
|
+
name: string;
|
|
9
|
+
type?: FileType;
|
|
10
|
+
path: string;
|
|
11
|
+
metadata?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
export interface EntryInfo extends WriteInfo {
|
|
14
|
+
size: number;
|
|
15
|
+
mode: number;
|
|
16
|
+
permissions: string;
|
|
17
|
+
/** Runtime's listing does not say who owns a file: always "". */
|
|
18
|
+
owner: string;
|
|
19
|
+
/** Runtime's listing does not say a file's group: always "". */
|
|
20
|
+
group: string;
|
|
21
|
+
modifiedTime?: Date;
|
|
22
|
+
symlinkTarget?: string;
|
|
23
|
+
}
|
|
24
|
+
export type WriteEntry = {
|
|
25
|
+
path: string;
|
|
26
|
+
data: string | ArrayBuffer | Blob | ReadableStream;
|
|
27
|
+
};
|
|
28
|
+
export interface FilesystemRequestOpts {
|
|
29
|
+
requestTimeoutMs?: number;
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
/** Only the default user; see CommandStartOpts.user. */
|
|
32
|
+
user?: Username;
|
|
33
|
+
}
|
|
34
|
+
export interface FilesystemReadOpts extends FilesystemRequestOpts {
|
|
35
|
+
/** Accepted; Runtime's transfer is already compressed where it helps. */
|
|
36
|
+
gzip?: boolean;
|
|
37
|
+
streamIdleTimeoutMs?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface FilesystemWriteOpts extends FilesystemRequestOpts {
|
|
40
|
+
/** Accepted; Runtime chooses the transfer. */
|
|
41
|
+
gzip?: boolean;
|
|
42
|
+
useOctetStream?: boolean;
|
|
43
|
+
/** Refused: Runtime does not keep metadata on files. */
|
|
44
|
+
metadata?: Record<string, string>;
|
|
45
|
+
}
|
|
46
|
+
export interface FilesystemListOpts extends FilesystemRequestOpts {
|
|
47
|
+
depth?: number;
|
|
48
|
+
}
|
|
49
|
+
/** `sandbox.files`: E2B's filesystem module over Runtime's files API. Relative
|
|
50
|
+
* paths resolve against the home directory, as in E2B (Runtime's is
|
|
51
|
+
* /workspace). */
|
|
52
|
+
export declare class Filesystem {
|
|
53
|
+
#private;
|
|
54
|
+
constructor(ctx: SandboxContext);
|
|
55
|
+
read(path: string, opts?: FilesystemReadOpts & {
|
|
56
|
+
format?: "text";
|
|
57
|
+
}): Promise<string>;
|
|
58
|
+
read(path: string, opts: FilesystemReadOpts & {
|
|
59
|
+
format: "bytes";
|
|
60
|
+
}): Promise<Uint8Array>;
|
|
61
|
+
read(path: string, opts: FilesystemReadOpts & {
|
|
62
|
+
format: "blob";
|
|
63
|
+
}): Promise<Blob>;
|
|
64
|
+
read(path: string, opts: FilesystemReadOpts & {
|
|
65
|
+
format: "stream";
|
|
66
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
67
|
+
/** Writes a file, making its directories, and overwrites one that exists. */
|
|
68
|
+
write(path: string, data: string | ArrayBuffer | Blob | ReadableStream, opts?: FilesystemWriteOpts): Promise<WriteInfo>;
|
|
69
|
+
write(files: WriteEntry[], opts?: FilesystemWriteOpts): Promise<WriteInfo[]>;
|
|
70
|
+
writeFiles(files: WriteEntry[], opts?: FilesystemWriteOpts): Promise<WriteInfo[]>;
|
|
71
|
+
/** A directory's entries, hidden ones included; `depth` goes deeper. */
|
|
72
|
+
list(path: string, opts?: FilesystemListOpts): Promise<EntryInfo[]>;
|
|
73
|
+
/** Makes a directory and its parents. False when it already existed. */
|
|
74
|
+
makeDir(path: string, opts?: FilesystemRequestOpts): Promise<boolean>;
|
|
75
|
+
/** Moves a file or directory, replacing a file at the new path, as E2B does. */
|
|
76
|
+
rename(oldPath: string, newPath: string, opts?: FilesystemRequestOpts): Promise<EntryInfo>;
|
|
77
|
+
/** Removes a file, or a directory with everything in it. */
|
|
78
|
+
remove(path: string, opts?: FilesystemRequestOpts): Promise<void>;
|
|
79
|
+
exists(path: string, opts?: FilesystemRequestOpts): Promise<boolean>;
|
|
80
|
+
getInfo(path: string, opts?: FilesystemRequestOpts): Promise<EntryInfo>;
|
|
81
|
+
watchDir(): Promise<never>;
|
|
82
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { request } from "./client.js";
|
|
2
|
+
import { FileNotFoundError, guard, NotSupportedError } from "./errors.js";
|
|
3
|
+
export var FileType;
|
|
4
|
+
(function (FileType) {
|
|
5
|
+
FileType["FILE"] = "file";
|
|
6
|
+
FileType["DIR"] = "dir";
|
|
7
|
+
FileType["SYMLINK"] = "symlink";
|
|
8
|
+
})(FileType || (FileType = {}));
|
|
9
|
+
/** Runtime's home, where E2B's relative paths land. */
|
|
10
|
+
const HOME = "/workspace";
|
|
11
|
+
function absolute(path) {
|
|
12
|
+
return path.startsWith("/") ? path : `${HOME}/${path.replace(/^\.\//, "")}`;
|
|
13
|
+
}
|
|
14
|
+
function refuse(opts) {
|
|
15
|
+
if (opts.user !== undefined && opts.user !== "user")
|
|
16
|
+
throw new NotSupportedError(`File access as the user "${opts.user}"`, "Runtime's file calls act as the sandbox owner; use commands.run('sudo ...') for root-owned paths.");
|
|
17
|
+
if (opts.metadata && Object.keys(opts.metadata).length)
|
|
18
|
+
throw new NotSupportedError("File metadata (user.e2b.* extended attributes)", "Keep the metadata beside the file, for example in a JSON file.");
|
|
19
|
+
}
|
|
20
|
+
const PERMISSIONS = ["---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"];
|
|
21
|
+
function entryInfo(entry) {
|
|
22
|
+
const mode = parseInt(entry.mode, 8) || 0;
|
|
23
|
+
const bits = mode & 0o777;
|
|
24
|
+
return {
|
|
25
|
+
name: entry.name,
|
|
26
|
+
path: entry.path,
|
|
27
|
+
...(entry.type === "file"
|
|
28
|
+
? { type: FileType.FILE }
|
|
29
|
+
: entry.type === "directory"
|
|
30
|
+
? { type: FileType.DIR }
|
|
31
|
+
: entry.type === "symlink"
|
|
32
|
+
? { type: FileType.SYMLINK }
|
|
33
|
+
: {}),
|
|
34
|
+
size: entry.size,
|
|
35
|
+
mode,
|
|
36
|
+
permissions: PERMISSIONS[(bits >> 6) & 7] + PERMISSIONS[(bits >> 3) & 7] + PERMISSIONS[bits & 7],
|
|
37
|
+
owner: "",
|
|
38
|
+
group: "",
|
|
39
|
+
modifiedTime: new Date(entry.modifiedAt),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async function bytesOf(data) {
|
|
43
|
+
if (typeof data === "string")
|
|
44
|
+
return new TextEncoder().encode(data);
|
|
45
|
+
if (data instanceof ArrayBuffer)
|
|
46
|
+
return new Uint8Array(data);
|
|
47
|
+
if (ArrayBuffer.isView(data)) {
|
|
48
|
+
const view = data;
|
|
49
|
+
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
50
|
+
}
|
|
51
|
+
if (typeof Blob !== "undefined" && data instanceof Blob)
|
|
52
|
+
return new Uint8Array(await data.arrayBuffer());
|
|
53
|
+
return new Uint8Array(await new Response(data).arrayBuffer());
|
|
54
|
+
}
|
|
55
|
+
const basename = (path) => path.split("/").filter(Boolean).pop() ?? path;
|
|
56
|
+
/** `sandbox.files`: E2B's filesystem module over Runtime's files API. Relative
|
|
57
|
+
* paths resolve against the home directory, as in E2B (Runtime's is
|
|
58
|
+
* /workspace). */
|
|
59
|
+
export class Filesystem {
|
|
60
|
+
#ctx;
|
|
61
|
+
constructor(ctx) {
|
|
62
|
+
this.#ctx = ctx;
|
|
63
|
+
}
|
|
64
|
+
get #files() {
|
|
65
|
+
return this.#ctx.runtime.files;
|
|
66
|
+
}
|
|
67
|
+
async #path(path, opts) {
|
|
68
|
+
refuse(opts);
|
|
69
|
+
await this.#ctx.ensureHome(path);
|
|
70
|
+
return absolute(path);
|
|
71
|
+
}
|
|
72
|
+
async read(path, opts = {}) {
|
|
73
|
+
const file = await this.#path(path, opts);
|
|
74
|
+
const bytes = await guard("file", () => this.#files.read(file, request(opts)));
|
|
75
|
+
switch (opts.format) {
|
|
76
|
+
case "bytes":
|
|
77
|
+
return bytes;
|
|
78
|
+
case "blob":
|
|
79
|
+
return new Blob([bytes]);
|
|
80
|
+
case "stream":
|
|
81
|
+
return new Blob([bytes]).stream();
|
|
82
|
+
default:
|
|
83
|
+
return new TextDecoder().decode(bytes);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async write(pathOrFiles, dataOrOpts, maybeOpts) {
|
|
87
|
+
if (Array.isArray(pathOrFiles))
|
|
88
|
+
return this.writeFiles(pathOrFiles, (dataOrOpts ?? {}));
|
|
89
|
+
return this.#writeOne(pathOrFiles, dataOrOpts, maybeOpts ?? {});
|
|
90
|
+
}
|
|
91
|
+
async writeFiles(files, opts = {}) {
|
|
92
|
+
const written = [];
|
|
93
|
+
for (const file of files)
|
|
94
|
+
written.push(await this.#writeOne(file.path, file.data, opts));
|
|
95
|
+
return written;
|
|
96
|
+
}
|
|
97
|
+
async #writeOne(path, data, opts) {
|
|
98
|
+
const file = await this.#path(path, opts);
|
|
99
|
+
const bytes = await bytesOf(data);
|
|
100
|
+
await guard("file", () => this.#files.write(file, bytes, request(opts)));
|
|
101
|
+
return { name: basename(file), type: FileType.FILE, path: file };
|
|
102
|
+
}
|
|
103
|
+
/** A directory's entries, hidden ones included; `depth` goes deeper. */
|
|
104
|
+
async list(path, opts = {}) {
|
|
105
|
+
const dir = await this.#path(path, opts);
|
|
106
|
+
const entries = await guard("file", () => this.#files.list(dir, { depth: opts.depth ?? 1, hidden: true }));
|
|
107
|
+
return entries.map(entryInfo);
|
|
108
|
+
}
|
|
109
|
+
/** Makes a directory and its parents. False when it already existed. */
|
|
110
|
+
async makeDir(path, opts = {}) {
|
|
111
|
+
const dir = await this.#path(path, opts);
|
|
112
|
+
if (await guard("file", () => this.#files.exists(dir)))
|
|
113
|
+
return false;
|
|
114
|
+
await guard("file", () => this.#files.mkdir(dir, { parents: true }));
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
/** Moves a file or directory, replacing a file at the new path, as E2B does. */
|
|
118
|
+
async rename(oldPath, newPath, opts = {}) {
|
|
119
|
+
const from = await this.#path(oldPath, opts);
|
|
120
|
+
const to = await this.#path(newPath, opts);
|
|
121
|
+
await guard("file", () => this.#files.rename(from, to, { overwrite: true }));
|
|
122
|
+
return this.getInfo(to, opts);
|
|
123
|
+
}
|
|
124
|
+
/** Removes a file, or a directory with everything in it. */
|
|
125
|
+
async remove(path, opts = {}) {
|
|
126
|
+
const target = await this.#path(path, opts);
|
|
127
|
+
await guard("file", () => this.#files.remove(target, { recursive: true }));
|
|
128
|
+
}
|
|
129
|
+
async exists(path, opts = {}) {
|
|
130
|
+
const target = await this.#path(path, opts);
|
|
131
|
+
return guard("file", () => this.#files.exists(target));
|
|
132
|
+
}
|
|
133
|
+
async getInfo(path, opts = {}) {
|
|
134
|
+
const target = await this.#path(path, opts);
|
|
135
|
+
const stat = await guard("file", () => this.#files.stat(target));
|
|
136
|
+
if (!stat.exists)
|
|
137
|
+
throw new FileNotFoundError(`${target} does not exist.`);
|
|
138
|
+
return entryInfo(stat);
|
|
139
|
+
}
|
|
140
|
+
watchDir() {
|
|
141
|
+
return Promise.reject(new NotSupportedError("Watching a directory (files.watchDir)", "Poll with files.list(path), or run your own watcher with commands.run(..., { background: true })."));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Code written for E2B's SDK, on Runtime Cloud. Change the import:
|
|
2
|
+
*
|
|
3
|
+
* import { Sandbox } from "withruntime/e2b"; // was: from "e2b"
|
|
4
|
+
*
|
|
5
|
+
* and set RUNTIME_API_KEY (or put a Runtime key in E2B_API_KEY). What Runtime
|
|
6
|
+
* cannot do the way E2B does throws NotSupportedError, naming what to use. */
|
|
7
|
+
import type { Runtime } from "../client.js";
|
|
8
|
+
import { type ConnectionOpts } from "./client.js";
|
|
9
|
+
import { Sandbox } from "./sandbox.js";
|
|
10
|
+
export { Sandbox, SandboxPaginator, DEFAULT_SHAPE, DEFAULT_TIMEOUT_MS, type SandboxOpts, type SandboxConnectOpts, type SandboxApiOpts, type SandboxInfo, type SandboxListOpts, type SandboxState, type SandboxLifecycle, type SandboxOnTimeout, type SnapshotInfo, } from "./sandbox.js";
|
|
11
|
+
export { Commands, CommandHandle, pidOf, type CommandStartOpts, type CommandConnectOpts, type CommandRequestOpts, type ProcessInfo, type Username, } from "./commands.js";
|
|
12
|
+
export { Filesystem, FileType, type EntryInfo, type WriteInfo, type WriteEntry, type FilesystemRequestOpts, type FilesystemReadOpts, type FilesystemWriteOpts, type FilesystemListOpts, } from "./filesystem.js";
|
|
13
|
+
export { SandboxError, TimeoutError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, FileNotFoundError, SandboxNotFoundError, TemplateError, RateLimitError, AuthenticationError, ServiceBusyError, CommandExitError, NotSupportedError, type CommandResult, } from "./errors.js";
|
|
14
|
+
export type { ConnectionOpts, RuntimeOpts } from "./client.js";
|
|
15
|
+
export { Template, TemplateBase, Volume, Secret, waitForPort, waitForURL, waitForProcess, waitForFile, waitForTimeout, } from "./unsupported.js";
|
|
16
|
+
export default Sandbox;
|
|
17
|
+
/** E2B's client with bound options: `new E2B({ apiKey }).Sandbox.create()`. */
|
|
18
|
+
export declare class E2B {
|
|
19
|
+
readonly Sandbox: typeof Sandbox;
|
|
20
|
+
constructor(opts?: Omit<ConnectionOpts, "signal"> & {
|
|
21
|
+
client?: Runtime;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/** A subclass whose static calls use `opts`'s key or client unless a call
|
|
25
|
+
* names its own. */
|
|
26
|
+
export declare function bind<S extends typeof Sandbox>(Base: S, opts: Omit<ConnectionOpts, "signal"> & {
|
|
27
|
+
client?: Runtime;
|
|
28
|
+
}): S;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { clientFor } from "./client.js";
|
|
2
|
+
import { Sandbox } from "./sandbox.js";
|
|
3
|
+
export { Sandbox, SandboxPaginator, DEFAULT_SHAPE, DEFAULT_TIMEOUT_MS, } from "./sandbox.js";
|
|
4
|
+
export { Commands, CommandHandle, pidOf, } from "./commands.js";
|
|
5
|
+
export { Filesystem, FileType, } from "./filesystem.js";
|
|
6
|
+
export { SandboxError, TimeoutError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, FileNotFoundError, SandboxNotFoundError, TemplateError, RateLimitError, AuthenticationError, ServiceBusyError, CommandExitError, NotSupportedError, } from "./errors.js";
|
|
7
|
+
export { Template, TemplateBase, Volume, Secret, waitForPort, waitForURL, waitForProcess, waitForFile, waitForTimeout, } from "./unsupported.js";
|
|
8
|
+
export default Sandbox;
|
|
9
|
+
/** E2B's client with bound options: `new E2B({ apiKey }).Sandbox.create()`. */
|
|
10
|
+
export class E2B {
|
|
11
|
+
Sandbox;
|
|
12
|
+
constructor(opts = {}) {
|
|
13
|
+
this.Sandbox = bind(Sandbox, opts);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** A subclass whose static calls use `opts`'s key or client unless a call
|
|
17
|
+
* names its own. */
|
|
18
|
+
export function bind(Base, opts) {
|
|
19
|
+
const client = clientFor({
|
|
20
|
+
...opts,
|
|
21
|
+
...(opts.client ? { runtime: { client: opts.client } } : {}),
|
|
22
|
+
});
|
|
23
|
+
const withClient = (given) => ({
|
|
24
|
+
...given,
|
|
25
|
+
runtime: { ...given?.runtime, client: given?.runtime?.client ?? client },
|
|
26
|
+
});
|
|
27
|
+
const Bound = class extends Base {
|
|
28
|
+
};
|
|
29
|
+
const create = Reflect.get(Base, "create");
|
|
30
|
+
const statics = {
|
|
31
|
+
create(first, second) {
|
|
32
|
+
return typeof first === "string"
|
|
33
|
+
? create.call(this, first, withClient(second))
|
|
34
|
+
: create.call(this, withClient(first));
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
// The calls that take (id, opts) or (id, x, opts): the options come last.
|
|
38
|
+
for (const name of [
|
|
39
|
+
"connect",
|
|
40
|
+
"list",
|
|
41
|
+
"kill",
|
|
42
|
+
"getInfo",
|
|
43
|
+
"setTimeout",
|
|
44
|
+
"pause",
|
|
45
|
+
"betaPause",
|
|
46
|
+
"fork",
|
|
47
|
+
"createSnapshot",
|
|
48
|
+
"deleteSnapshot",
|
|
49
|
+
]) {
|
|
50
|
+
const original = Reflect.get(Base, name);
|
|
51
|
+
const arity = name === "list" ? 1 : name === "setTimeout" ? 3 : 2;
|
|
52
|
+
statics[name] = function (...args) {
|
|
53
|
+
const padded = [...args];
|
|
54
|
+
padded[arity - 1] = withClient(padded[arity - 1]);
|
|
55
|
+
return original.apply(this, padded);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
for (const [name, value] of Object.entries(statics))
|
|
59
|
+
Object.defineProperty(Bound, name, { value, writable: true, configurable: true });
|
|
60
|
+
return Bound;
|
|
61
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { Runtime } from "../client.js";
|
|
2
|
+
import { type ConnectionOpts, type RuntimeOpts, type RuntimeSandbox } from "./client.js";
|
|
3
|
+
import { Commands } from "./commands.js";
|
|
4
|
+
import { Filesystem } from "./filesystem.js";
|
|
5
|
+
/** E2B's default machine: 2 vCPU and 512 MiB (docs.e2b.dev/billing, checked
|
|
6
|
+
* 23 September 2026). Pass `runtime: { create: { memoryMiB } }` for another. */
|
|
7
|
+
export declare const DEFAULT_SHAPE: {
|
|
8
|
+
readonly vcpu: 2;
|
|
9
|
+
readonly memoryMiB: 512;
|
|
10
|
+
};
|
|
11
|
+
/** E2B's default sandbox timeout, 300 s. */
|
|
12
|
+
export declare const DEFAULT_TIMEOUT_MS = 300000;
|
|
13
|
+
export type SandboxState = "running" | "paused";
|
|
14
|
+
export type SandboxOnTimeout = "pause" | "kill" | {
|
|
15
|
+
action: "pause" | "kill";
|
|
16
|
+
keepMemory?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type SandboxLifecycle = {
|
|
19
|
+
onTimeout: SandboxOnTimeout;
|
|
20
|
+
autoResume?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export interface SandboxOpts extends ConnectionOpts {
|
|
23
|
+
/** An E2B template name. "base" (the default) is Runtime's stock image; any
|
|
24
|
+
* other name must be a ready Runtime image of that name, and a UUID a
|
|
25
|
+
* Runtime image or snapshot id. */
|
|
26
|
+
template?: string;
|
|
27
|
+
/** Stored as the sandbox's labels (at most 32, values up to 256 characters). */
|
|
28
|
+
metadata?: Record<string, string>;
|
|
29
|
+
/** Given to every command and code run through this object. */
|
|
30
|
+
envs?: Record<string, string>;
|
|
31
|
+
/** Default 300 000. Runtime's leases run 60 s to 1 hour; shorter rounds up
|
|
32
|
+
* to 60 s (with a warning), longer is refused. */
|
|
33
|
+
timeoutMs?: number;
|
|
34
|
+
/** Accepted and ignored, as E2B ignores it. */
|
|
35
|
+
secure?: boolean;
|
|
36
|
+
/** false: no network at all. */
|
|
37
|
+
allowInternetAccess?: boolean;
|
|
38
|
+
/** What happens when the timeout ends: "kill" (E2B's default, Runtime stops
|
|
39
|
+
* the sandbox) or "pause". */
|
|
40
|
+
lifecycle?: SandboxLifecycle;
|
|
41
|
+
mcp?: unknown;
|
|
42
|
+
network?: unknown;
|
|
43
|
+
iam?: unknown;
|
|
44
|
+
volumeMounts?: unknown;
|
|
45
|
+
/** Runtime-only: an explicit client, or fields for the create. */
|
|
46
|
+
runtime?: RuntimeOpts;
|
|
47
|
+
}
|
|
48
|
+
export type SandboxConnectOpts = ConnectionOpts & {
|
|
49
|
+
timeoutMs?: number;
|
|
50
|
+
onResume?: "restore" | "reboot";
|
|
51
|
+
runtime?: RuntimeOpts;
|
|
52
|
+
};
|
|
53
|
+
export type SandboxApiOpts = Pick<ConnectionOpts, "apiKey" | "requestTimeoutMs" | "signal"> & {
|
|
54
|
+
runtime?: RuntimeOpts;
|
|
55
|
+
};
|
|
56
|
+
export interface SandboxInfo {
|
|
57
|
+
sandboxId: string;
|
|
58
|
+
/** "base" for Runtime's stock image, else the image or snapshot id. */
|
|
59
|
+
templateId: string;
|
|
60
|
+
name?: string;
|
|
61
|
+
metadata: Record<string, string>;
|
|
62
|
+
startedAt: Date;
|
|
63
|
+
endAt: Date;
|
|
64
|
+
state: SandboxState;
|
|
65
|
+
cpuCount: number;
|
|
66
|
+
memoryMB: number;
|
|
67
|
+
/** Runtime has no envd: "runtime". */
|
|
68
|
+
envdVersion: string;
|
|
69
|
+
lifecycle?: {
|
|
70
|
+
onTimeout: "pause" | "kill";
|
|
71
|
+
autoResume: boolean;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export interface SnapshotInfo {
|
|
75
|
+
snapshotId: string;
|
|
76
|
+
names: string[];
|
|
77
|
+
}
|
|
78
|
+
export type SandboxListOpts = SandboxApiOpts & {
|
|
79
|
+
query?: {
|
|
80
|
+
metadata?: Record<string, string>;
|
|
81
|
+
state?: SandboxState[];
|
|
82
|
+
startedAfter?: Date;
|
|
83
|
+
template?: string;
|
|
84
|
+
};
|
|
85
|
+
order?: "asc" | "desc";
|
|
86
|
+
limit?: number;
|
|
87
|
+
nextToken?: string;
|
|
88
|
+
};
|
|
89
|
+
/** A sandbox, with E2B's methods. `sandbox.runtime` is the Runtime sandbox
|
|
90
|
+
* underneath, for anything E2B has no name for. */
|
|
91
|
+
export declare class Sandbox {
|
|
92
|
+
#private;
|
|
93
|
+
protected static readonly defaultTemplate: string;
|
|
94
|
+
readonly files: Filesystem;
|
|
95
|
+
readonly commands: Commands;
|
|
96
|
+
/** Use Sandbox.create or Sandbox.connect. */
|
|
97
|
+
constructor(runtime: RuntimeSandbox, client: Runtime, envs?: Record<string, string>);
|
|
98
|
+
get sandboxId(): string;
|
|
99
|
+
/** The Runtime sandbox underneath: previews, network, desktop, interpreter,
|
|
100
|
+
* processes, terminal and the rest of Runtime's SDK. */
|
|
101
|
+
get runtime(): RuntimeSandbox;
|
|
102
|
+
protected get client(): Runtime;
|
|
103
|
+
protected get envs(): Record<string, string>;
|
|
104
|
+
/** Creates a sandbox from `template` (default "base", Runtime's stock image)
|
|
105
|
+
* with E2B's default machine, 2 vCPU and 512 MiB, and waits until it runs.
|
|
106
|
+
* Funding is left to Runtime: the free trial while the account has trial
|
|
107
|
+
* time, then prepaid credit, exactly as withruntime's own create. */
|
|
108
|
+
static create<S extends typeof Sandbox>(this: S, opts?: SandboxOpts): Promise<InstanceType<S>>;
|
|
109
|
+
static create<S extends typeof Sandbox>(this: S, template: string, opts?: SandboxOpts): Promise<InstanceType<S>>;
|
|
110
|
+
/** Connects to a sandbox by id, waking it if it is paused, as E2B does. A
|
|
111
|
+
* `timeoutMs` moves a running sandbox's end later, never earlier. */
|
|
112
|
+
static connect<S extends typeof Sandbox>(this: S, sandboxId: string, opts?: SandboxConnectOpts): Promise<InstanceType<S>>;
|
|
113
|
+
/** Wakes this sandbox if it is paused. */
|
|
114
|
+
connect(opts?: SandboxConnectOpts): Promise<this>;
|
|
115
|
+
/** Running and paused sandboxes, a page at a time, as E2B's paginator. */
|
|
116
|
+
static list(opts?: SandboxListOpts): SandboxPaginator;
|
|
117
|
+
/** Stops the sandbox. False when it was not found or had already ended. */
|
|
118
|
+
static kill(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean>;
|
|
119
|
+
kill(opts?: Pick<ConnectionOpts, "requestTimeoutMs" | "signal">): Promise<boolean>;
|
|
120
|
+
/** Sets the sandbox to end `timeoutMs` from now. Runtime leases only move
|
|
121
|
+
* later: a shorter timeout than the one it has is refused. */
|
|
122
|
+
static setTimeout(sandboxId: string, timeoutMs: number, opts?: SandboxApiOpts): Promise<void>;
|
|
123
|
+
setTimeout(timeoutMs: number, opts?: Pick<ConnectionOpts, "requestTimeoutMs" | "signal">): Promise<void>;
|
|
124
|
+
static getInfo(sandboxId: string, opts?: SandboxApiOpts): Promise<SandboxInfo>;
|
|
125
|
+
getInfo(opts?: Pick<ConnectionOpts, "requestTimeoutMs" | "signal">): Promise<SandboxInfo>;
|
|
126
|
+
isRunning(opts?: Pick<ConnectionOpts, "requestTimeoutMs" | "signal">): Promise<boolean>;
|
|
127
|
+
/** Pauses the sandbox, keeping memory and files. False when it was paused. */
|
|
128
|
+
static pause(sandboxId: string, opts?: SandboxApiOpts & {
|
|
129
|
+
keepMemory?: boolean;
|
|
130
|
+
}): Promise<boolean>;
|
|
131
|
+
static betaPause(sandboxId: string, opts?: SandboxApiOpts & {
|
|
132
|
+
keepMemory?: boolean;
|
|
133
|
+
}): Promise<boolean>;
|
|
134
|
+
pause(opts?: SandboxApiOpts & {
|
|
135
|
+
keepMemory?: boolean;
|
|
136
|
+
}): Promise<boolean>;
|
|
137
|
+
betaPause(opts?: SandboxApiOpts & {
|
|
138
|
+
keepMemory?: boolean;
|
|
139
|
+
}): Promise<boolean>;
|
|
140
|
+
/** Copies of this sandbox, memory and all. While Runtime's forks are
|
|
141
|
+
* switched off this throws NotSupportedError with Runtime's own words. */
|
|
142
|
+
static fork<S extends typeof Sandbox>(this: S, sandboxId: string, opts?: SandboxApiOpts & {
|
|
143
|
+
count?: number;
|
|
144
|
+
timeoutMs?: number;
|
|
145
|
+
}): Promise<Array<InstanceType<S> | Error>>;
|
|
146
|
+
fork(opts?: SandboxApiOpts & {
|
|
147
|
+
count?: number;
|
|
148
|
+
timeoutMs?: number;
|
|
149
|
+
}): Promise<Array<this | Error>>;
|
|
150
|
+
/** Keeps the sandbox's whole machine as a Runtime snapshot; start from it
|
|
151
|
+
* with Sandbox.create(snapshotId). */
|
|
152
|
+
createSnapshot(opts?: SandboxApiOpts & {
|
|
153
|
+
name?: string;
|
|
154
|
+
}): Promise<SnapshotInfo>;
|
|
155
|
+
static createSnapshot(sandboxId: string, opts?: SandboxApiOpts & {
|
|
156
|
+
name?: string;
|
|
157
|
+
}): Promise<SnapshotInfo>;
|
|
158
|
+
static deleteSnapshot(snapshotId: string, opts?: SandboxApiOpts): Promise<boolean>;
|
|
159
|
+
/** Refused: E2B answers getHost without a call, and a Runtime port becomes
|
|
160
|
+
* reachable only once it is shared. Use getPublicHost. */
|
|
161
|
+
getHost(port: number): string;
|
|
162
|
+
/** Shares `port` at a public HTTPS address (a Runtime preview) and returns
|
|
163
|
+
* its host, `<port>-<id>.<domain>`, like E2B's getHost. Anyone with the
|
|
164
|
+
* address can reach it; a browser sees a one-time page naming Runtime. */
|
|
165
|
+
getPublicHost(port: number): Promise<string>;
|
|
166
|
+
get pty(): never;
|
|
167
|
+
get git(): never;
|
|
168
|
+
getMetrics(): Promise<never>;
|
|
169
|
+
static getMetrics(): Promise<never>;
|
|
170
|
+
updateNetwork(): Promise<never>;
|
|
171
|
+
uploadUrl(): Promise<never>;
|
|
172
|
+
downloadUrl(): Promise<never>;
|
|
173
|
+
getMcpUrl(): never;
|
|
174
|
+
getMcpToken(): Promise<never>;
|
|
175
|
+
}
|
|
176
|
+
/** E2B's paginator: `while (p.hasNext) items.push(...(await p.nextItems()))`. */
|
|
177
|
+
export declare class SandboxPaginator {
|
|
178
|
+
#private;
|
|
179
|
+
constructor(client: Runtime, opts: SandboxListOpts);
|
|
180
|
+
get hasNext(): boolean;
|
|
181
|
+
get nextToken(): string | undefined;
|
|
182
|
+
nextItems(): Promise<SandboxInfo[]>;
|
|
183
|
+
}
|