withruntime 0.3.1 → 0.5.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.
Files changed (105) hide show
  1. package/DAYTONA.md +129 -0
  2. package/E2B.md +146 -0
  3. package/README.md +84 -12
  4. package/VERCEL.md +127 -0
  5. package/dist/ai/index.d.ts +33 -0
  6. package/dist/ai/index.js +38 -0
  7. package/dist/claude-agent-sdk/index.d.ts +7 -0
  8. package/dist/claude-agent-sdk/index.js +65 -0
  9. package/dist/cli.d.ts +6 -0
  10. package/dist/cli.js +949 -105
  11. package/dist/client.d.ts +25 -2
  12. package/dist/client.js +14 -1
  13. package/dist/credentials.d.ts +10 -0
  14. package/dist/credentials.js +56 -1
  15. package/dist/daytona/client.d.ts +44 -0
  16. package/dist/daytona/client.js +40 -0
  17. package/dist/daytona/context.d.ts +26 -0
  18. package/dist/daytona/context.js +22 -0
  19. package/dist/daytona/daytona.d.ts +185 -0
  20. package/dist/daytona/daytona.js +416 -0
  21. package/dist/daytona/errors.d.ts +106 -0
  22. package/dist/daytona/errors.js +182 -0
  23. package/dist/daytona/filesystem.d.ts +84 -0
  24. package/dist/daytona/filesystem.js +206 -0
  25. package/dist/daytona/git.d.ts +33 -0
  26. package/dist/daytona/git.js +128 -0
  27. package/dist/daytona/image.d.ts +45 -0
  28. package/dist/daytona/image.js +140 -0
  29. package/dist/daytona/index.d.ts +50 -0
  30. package/dist/daytona/index.js +50 -0
  31. package/dist/daytona/process.d.ts +86 -0
  32. package/dist/daytona/process.js +339 -0
  33. package/dist/daytona/sandbox.d.ts +196 -0
  34. package/dist/daytona/sandbox.js +448 -0
  35. package/dist/e2b/client.d.ts +58 -0
  36. package/dist/e2b/client.js +66 -0
  37. package/dist/e2b/code-interpreter.d.ts +144 -0
  38. package/dist/e2b/code-interpreter.js +244 -0
  39. package/dist/e2b/commands.d.ts +100 -0
  40. package/dist/e2b/commands.js +268 -0
  41. package/dist/e2b/errors.d.ts +72 -0
  42. package/dist/e2b/errors.js +151 -0
  43. package/dist/e2b/filesystem.d.ts +82 -0
  44. package/dist/e2b/filesystem.js +143 -0
  45. package/dist/e2b/index.d.ts +28 -0
  46. package/dist/e2b/index.js +61 -0
  47. package/dist/e2b/sandbox.d.ts +203 -0
  48. package/dist/e2b/sandbox.js +490 -0
  49. package/dist/e2b/unsupported.d.ts +19 -0
  50. package/dist/e2b/unsupported.js +27 -0
  51. package/dist/errors.d.ts +10 -4
  52. package/dist/errors.js +26 -6
  53. package/dist/image-context.d.ts +39 -0
  54. package/dist/image-context.js +176 -0
  55. package/dist/index.d.ts +19 -2
  56. package/dist/index.js +17 -2
  57. package/dist/keys.d.ts +43 -0
  58. package/dist/keys.js +196 -0
  59. package/dist/login.js +27 -6
  60. package/dist/mcp.d.ts +2 -2
  61. package/dist/mcp.js +4 -3
  62. package/dist/openai-agents/index.d.ts +132 -0
  63. package/dist/openai-agents/index.js +791 -0
  64. package/dist/products/audit.d.ts +48 -0
  65. package/dist/products/audit.js +10 -0
  66. package/dist/products/images.d.ts +113 -7
  67. package/dist/products/images.js +186 -27
  68. package/dist/products/index.d.ts +11 -0
  69. package/dist/products/index.js +17 -1
  70. package/dist/products/observability.d.ts +186 -0
  71. package/dist/products/observability.js +117 -0
  72. package/dist/products/secrets.d.ts +40 -0
  73. package/dist/products/secrets.js +24 -0
  74. package/dist/products/switching.d.ts +89 -0
  75. package/dist/products/switching.js +25 -0
  76. package/dist/proxy.d.ts +30 -0
  77. package/dist/proxy.js +178 -0
  78. package/dist/sandbox.d.ts +30 -2
  79. package/dist/sandbox.js +101 -1
  80. package/dist/ssh.d.ts +21 -0
  81. package/dist/ssh.js +312 -0
  82. package/dist/tar.d.ts +1 -0
  83. package/dist/tar.js +4 -4
  84. package/dist/tools/index.d.ts +62 -0
  85. package/dist/tools/index.js +180 -0
  86. package/dist/transport.d.ts +12 -2
  87. package/dist/transport.js +76 -16
  88. package/dist/tunnel.d.ts +67 -0
  89. package/dist/tunnel.js +311 -0
  90. package/dist/types.d.ts +57 -1
  91. package/dist/vercel/client.d.ts +40 -0
  92. package/dist/vercel/client.js +39 -0
  93. package/dist/vercel/command.d.ts +70 -0
  94. package/dist/vercel/command.js +148 -0
  95. package/dist/vercel/errors.d.ts +53 -0
  96. package/dist/vercel/errors.js +113 -0
  97. package/dist/vercel/filesystem.d.ts +150 -0
  98. package/dist/vercel/filesystem.js +248 -0
  99. package/dist/vercel/index.d.ts +30 -0
  100. package/dist/vercel/index.js +38 -0
  101. package/dist/vercel/sandbox.d.ts +317 -0
  102. package/dist/vercel/sandbox.js +726 -0
  103. package/dist/vercel/snapshot.d.ts +93 -0
  104. package/dist/vercel/snapshot.js +123 -0
  105. package/package.json +69 -5
@@ -0,0 +1,58 @@
1
+ import { Runtime } from "../client.js";
2
+ /** The Runtime sandbox the adapter drives. */
3
+ export type RuntimeSandbox = Awaited<ReturnType<Runtime["sandboxes"]["create"]>>;
4
+ /** What `Sandbox.create` sends to Runtime. */
5
+ export type RuntimeCreate = NonNullable<Parameters<Runtime["sandboxes"]["create"]>[0]>;
6
+ /** E2B's connection options, as far as they mean anything on Runtime. */
7
+ export interface ConnectionOpts {
8
+ /** A Runtime key. Default: RUNTIME_API_KEY, then E2B_API_KEY if it holds a
9
+ * Runtime key, then the key `npx withruntime login` saved. An E2B key
10
+ * (`e2b_...`) is never sent anywhere. */
11
+ apiKey?: string;
12
+ /** Per call, retries included. */
13
+ requestTimeoutMs?: number;
14
+ signal?: AbortSignal;
15
+ /** Accepted and ignored, as E2B ignores them. */
16
+ validateApiKey?: boolean;
17
+ /** Accepted and ignored: Runtime's SDK retries by itself. */
18
+ retries?: number;
19
+ /** Accepted and ignored: Runtime's SDK does not take a logger. */
20
+ logger?: unknown;
21
+ /** E2B endpoints. Refused: this package only talks to Runtime. */
22
+ domain?: string;
23
+ apiUrl?: string;
24
+ sandboxUrl?: string;
25
+ debug?: boolean;
26
+ headers?: Record<string, string>;
27
+ apiHeaders?: Record<string, string>;
28
+ proxy?: string;
29
+ }
30
+ /** Runtime-only options, for code that has been through the switch. */
31
+ export interface RuntimeOpts {
32
+ /** A Runtime client to use instead of one made from the key. */
33
+ client?: Runtime;
34
+ /** Fields sent as they are with the create, over the adapter's own: for
35
+ * example `{ funding: "trial" }`, `{ memoryMiB: 4096 }` or `{ region }`. */
36
+ create?: Partial<RuntimeCreate>;
37
+ }
38
+ /** Refuses the E2B-only connection options: they point at E2B, and quietly
39
+ * dropping one would send the call somewhere its author did not mean. */
40
+ export declare function refuseE2BConnection(opts?: ConnectionOpts): void;
41
+ /** The Runtime client for these options: an explicit client, else one per key,
42
+ * made once and reused so its connections stay open. */
43
+ export declare function clientFor(opts?: ConnectionOpts & {
44
+ runtime?: RuntimeOpts;
45
+ }): Runtime;
46
+ /** Explicit key, then RUNTIME_API_KEY, then E2B_API_KEY when it holds a
47
+ * Runtime key; undefined lets the Runtime SDK find the saved login. */
48
+ export declare function pickKey(explicit?: string): string | undefined;
49
+ /** Test hook: forget the cached clients. */
50
+ export declare function resetClients(): void;
51
+ /** Request options for a Runtime call from E2B's. */
52
+ export declare function request(opts?: {
53
+ requestTimeoutMs?: number;
54
+ signal?: AbortSignal;
55
+ }): {
56
+ signal?: AbortSignal | undefined;
57
+ timeoutMs?: number | undefined;
58
+ };
@@ -0,0 +1,66 @@
1
+ import { Runtime } from "../client.js";
2
+ import { AuthenticationError, NotSupportedError } from "./errors.js";
3
+ const env = (name) => typeof process === "undefined" ? undefined : process.env[name];
4
+ const isE2BKey = (key) => key.startsWith("e2b_");
5
+ /** Refuses the E2B-only connection options: they point at E2B, and quietly
6
+ * dropping one would send the call somewhere its author did not mean. */
7
+ export function refuseE2BConnection(opts = {}) {
8
+ for (const field of [
9
+ "domain",
10
+ "apiUrl",
11
+ "sandboxUrl",
12
+ "headers",
13
+ "apiHeaders",
14
+ "proxy",
15
+ ]) {
16
+ if (opts[field] !== undefined)
17
+ throw new NotSupportedError(`The E2B connection option "${field}"`, field === "proxy"
18
+ ? "Set HTTPS_PROXY in the environment instead; Runtime's SDK reads it."
19
+ : "Remove it: this package talks only to Runtime (RUNTIME_API_URL overrides the API origin).");
20
+ }
21
+ if (opts.debug)
22
+ throw new NotSupportedError("E2B's debug mode (a local envd)", "Remove debug: true; there is no local Runtime guest to connect to.");
23
+ }
24
+ const clients = new Map();
25
+ /** The Runtime client for these options: an explicit client, else one per key,
26
+ * made once and reused so its connections stay open. */
27
+ export function clientFor(opts = {}) {
28
+ refuseE2BConnection(opts);
29
+ if (opts.runtime?.client)
30
+ return opts.runtime.client;
31
+ const key = pickKey(opts.apiKey);
32
+ const cacheKey = key ?? "";
33
+ let client = clients.get(cacheKey);
34
+ if (!client) {
35
+ client = new Runtime(key ? { apiKey: key } : {});
36
+ clients.set(cacheKey, client);
37
+ }
38
+ return client;
39
+ }
40
+ /** Explicit key, then RUNTIME_API_KEY, then E2B_API_KEY when it holds a
41
+ * Runtime key; undefined lets the Runtime SDK find the saved login. */
42
+ export function pickKey(explicit) {
43
+ const runtimeKey = env("RUNTIME_API_KEY");
44
+ if (explicit !== undefined && !isE2BKey(explicit))
45
+ return explicit;
46
+ if (runtimeKey)
47
+ return runtimeKey;
48
+ if (explicit !== undefined)
49
+ throw new AuthenticationError("The apiKey passed is an E2B API key (e2b_...), and it was not sent. Set RUNTIME_API_KEY to a Runtime key " +
50
+ "(https://withruntime.com/account/keys, or run `npx withruntime login`), or pass the Runtime key as apiKey.");
51
+ // An E2B key left in E2B_API_KEY is skipped, never sent: the Runtime SDK
52
+ // then uses the key `npx withruntime login` saved, or says none was found.
53
+ const e2bVariable = env("E2B_API_KEY");
54
+ return e2bVariable && !isE2BKey(e2bVariable) ? e2bVariable : undefined;
55
+ }
56
+ /** Test hook: forget the cached clients. */
57
+ export function resetClients() {
58
+ clients.clear();
59
+ }
60
+ /** Request options for a Runtime call from E2B's. */
61
+ export function request(opts = {}) {
62
+ return {
63
+ ...(opts.requestTimeoutMs ? { timeoutMs: opts.requestTimeoutMs } : {}),
64
+ ...(opts.signal ? { signal: opts.signal } : {}),
65
+ };
66
+ }
@@ -0,0 +1,144 @@
1
+ /** `@e2b/code-interpreter`, on Runtime. Change the import:
2
+ *
3
+ * import { Sandbox } from "withruntime/e2b/code-interpreter";
4
+ *
5
+ * runCode runs in Runtime's interpreter (sandbox.runtime.interpreter):
6
+ * stateful Python and JavaScript contexts, as in E2B. Other languages throw
7
+ * NotSupportedError. */
8
+ import type { Runtime } from "../client.js";
9
+ import type { ConnectionOpts } from "./client.js";
10
+ import { Sandbox as BaseSandbox } from "./sandbox.js";
11
+ export * from "./index.js";
12
+ export type RunCodeLanguage = "python" | "javascript" | "typescript" | "r" | "java" | "bash" | (string & {});
13
+ /** A line of output, as E2B's callbacks receive it. */
14
+ export declare class OutputMessage {
15
+ readonly line: string;
16
+ /** Unix epoch in nanoseconds (from the client's clock). */
17
+ readonly timestamp: number;
18
+ readonly error: boolean;
19
+ constructor(line: string,
20
+ /** Unix epoch in nanoseconds (from the client's clock). */
21
+ timestamp: number, error: boolean);
22
+ toString(): string;
23
+ }
24
+ export declare class ExecutionError {
25
+ name: string;
26
+ value: string;
27
+ traceback: string;
28
+ constructor(name: string, value: string, traceback: string);
29
+ }
30
+ export type MIMEType = string;
31
+ export type RawData = {
32
+ [key: MIMEType]: unknown;
33
+ };
34
+ type ResultFields = {
35
+ text?: string;
36
+ html?: string;
37
+ markdown?: string;
38
+ svg?: string;
39
+ png?: string;
40
+ jpeg?: string;
41
+ pdf?: string;
42
+ latex?: string;
43
+ json?: string;
44
+ javascript?: string;
45
+ };
46
+ /** One rich result, as E2B's: text, html, png (base64) and the rest. `chart`
47
+ * and E2B's `data` (its own DataFrame format) are never set on Runtime; a
48
+ * DataFrame arrives in `extra` under application/vnd.runtime.table+json. */
49
+ export declare class Result implements ResultFields {
50
+ readonly isMainResult: boolean;
51
+ readonly text?: string;
52
+ readonly html?: string;
53
+ readonly markdown?: string;
54
+ readonly svg?: string;
55
+ readonly png?: string;
56
+ readonly jpeg?: string;
57
+ readonly pdf?: string;
58
+ readonly latex?: string;
59
+ readonly json?: string;
60
+ readonly javascript?: string;
61
+ readonly data?: Record<string, unknown>;
62
+ readonly chart?: undefined;
63
+ readonly extra?: Record<string, unknown>;
64
+ readonly raw: RawData;
65
+ constructor(rawData: RawData, isMainResult: boolean);
66
+ formats(): string[];
67
+ toJSON(): {
68
+ extra?: Record<string, unknown> | undefined;
69
+ text: string | undefined;
70
+ html: string | undefined;
71
+ markdown: string | undefined;
72
+ svg: string | undefined;
73
+ png: string | undefined;
74
+ jpeg: string | undefined;
75
+ pdf: string | undefined;
76
+ latex: string | undefined;
77
+ json: string | undefined;
78
+ javascript: string | undefined;
79
+ };
80
+ }
81
+ export type Logs = {
82
+ stdout: string[];
83
+ stderr: string[];
84
+ };
85
+ export declare class Execution {
86
+ results: Result[];
87
+ logs: Logs;
88
+ error?: ExecutionError | undefined;
89
+ executionCount?: number | undefined;
90
+ constructor(results?: Result[], logs?: Logs, error?: ExecutionError | undefined, executionCount?: number | undefined);
91
+ /** The main result's text. */
92
+ get text(): string | undefined;
93
+ toJSON(): {
94
+ results: Result[];
95
+ logs: Logs;
96
+ error: ExecutionError | undefined;
97
+ };
98
+ }
99
+ export type Context = {
100
+ id: string;
101
+ language: string;
102
+ cwd: string;
103
+ };
104
+ export interface RunCodeOpts {
105
+ onStdout?: (output: OutputMessage) => unknown;
106
+ onStderr?: (output: OutputMessage) => unknown;
107
+ onResult?: (data: Result) => unknown;
108
+ onError?: (error: ExecutionError) => unknown;
109
+ /** Refused when set: Runtime's contexts take their environment when made. */
110
+ envs?: Record<string, string>;
111
+ /** Default 60 000, as in E2B. */
112
+ timeoutMs?: number;
113
+ /** Accepted and ignored: Runtime's SDK allows the run its timeout plus a minute. */
114
+ requestTimeoutMs?: number;
115
+ }
116
+ export interface CreateCodeContextOpts {
117
+ cwd?: string;
118
+ language?: RunCodeLanguage;
119
+ requestTimeoutMs?: number;
120
+ }
121
+ /** The code interpreter sandbox: everything the base Sandbox has, plus runCode
122
+ * and code contexts. */
123
+ export declare class Sandbox extends BaseSandbox {
124
+ #private;
125
+ protected static readonly defaultTemplate: string;
126
+ /** Runs code in a stateful context. Errors in the code come back in
127
+ * `execution.error`, as in E2B; a run past `timeoutMs` throws TimeoutError. */
128
+ runCode(code: string, opts?: RunCodeOpts & {
129
+ language?: RunCodeLanguage;
130
+ context?: Context;
131
+ }): Promise<Execution>;
132
+ createCodeContext(opts?: CreateCodeContextOpts): Promise<Context>;
133
+ removeCodeContext(context: Context | string): Promise<void>;
134
+ listCodeContexts(): Promise<Context[]>;
135
+ restartCodeContext(context: Context | string): Promise<void>;
136
+ }
137
+ export default Sandbox;
138
+ /** E2B's client with bound options, for the code interpreter. */
139
+ export declare class E2B {
140
+ readonly Sandbox: typeof Sandbox;
141
+ constructor(opts?: Omit<ConnectionOpts, "signal"> & {
142
+ client?: Runtime;
143
+ });
144
+ }
@@ -0,0 +1,244 @@
1
+ import { guard, NotSupportedError, SandboxError, TimeoutError } from "./errors.js";
2
+ import { bind } from "./index.js";
3
+ import { Sandbox as BaseSandbox } from "./sandbox.js";
4
+ export * from "./index.js";
5
+ /** A line of output, as E2B's callbacks receive it. */
6
+ export class OutputMessage {
7
+ line;
8
+ timestamp;
9
+ error;
10
+ constructor(line,
11
+ /** Unix epoch in nanoseconds (from the client's clock). */
12
+ timestamp, error) {
13
+ this.line = line;
14
+ this.timestamp = timestamp;
15
+ this.error = error;
16
+ }
17
+ toString() {
18
+ return this.line;
19
+ }
20
+ }
21
+ export class ExecutionError {
22
+ name;
23
+ value;
24
+ traceback;
25
+ constructor(name, value, traceback) {
26
+ this.name = name;
27
+ this.value = value;
28
+ this.traceback = traceback;
29
+ }
30
+ }
31
+ const FORMATS = {
32
+ "text/plain": "text",
33
+ "text/html": "html",
34
+ "text/markdown": "markdown",
35
+ "image/svg+xml": "svg",
36
+ "image/png": "png",
37
+ "image/jpeg": "jpeg",
38
+ "application/pdf": "pdf",
39
+ "text/latex": "latex",
40
+ "application/json": "json",
41
+ "application/javascript": "javascript",
42
+ };
43
+ /** One rich result, as E2B's: text, html, png (base64) and the rest. `chart`
44
+ * and E2B's `data` (its own DataFrame format) are never set on Runtime; a
45
+ * DataFrame arrives in `extra` under application/vnd.runtime.table+json. */
46
+ export class Result {
47
+ isMainResult;
48
+ text;
49
+ html;
50
+ markdown;
51
+ svg;
52
+ png;
53
+ jpeg;
54
+ pdf;
55
+ latex;
56
+ json;
57
+ javascript;
58
+ data;
59
+ chart;
60
+ extra;
61
+ raw;
62
+ constructor(rawData, isMainResult) {
63
+ this.raw = rawData;
64
+ this.isMainResult = isMainResult;
65
+ const extra = {};
66
+ const fields = {};
67
+ for (const [mime, value] of Object.entries(rawData)) {
68
+ const field = FORMATS[mime];
69
+ if (field)
70
+ fields[field] = value;
71
+ else
72
+ extra[mime] = value;
73
+ }
74
+ Object.assign(this, fields);
75
+ if (Object.keys(extra).length)
76
+ this.extra = extra;
77
+ }
78
+ formats() {
79
+ return [
80
+ ...Object.values(FORMATS).filter((field) => this[field] !== undefined),
81
+ ...Object.keys(this.extra ?? {}),
82
+ ];
83
+ }
84
+ toJSON() {
85
+ return {
86
+ text: this.text,
87
+ html: this.html,
88
+ markdown: this.markdown,
89
+ svg: this.svg,
90
+ png: this.png,
91
+ jpeg: this.jpeg,
92
+ pdf: this.pdf,
93
+ latex: this.latex,
94
+ json: this.json,
95
+ javascript: this.javascript,
96
+ ...(this.extra ? { extra: this.extra } : {}),
97
+ };
98
+ }
99
+ }
100
+ export class Execution {
101
+ results;
102
+ logs;
103
+ error;
104
+ executionCount;
105
+ constructor(results = [], logs = { stdout: [], stderr: [] }, error, executionCount) {
106
+ this.results = results;
107
+ this.logs = logs;
108
+ this.error = error;
109
+ this.executionCount = executionCount;
110
+ }
111
+ /** The main result's text. */
112
+ get text() {
113
+ return this.results.find((result) => result.isMainResult)?.text;
114
+ }
115
+ toJSON() {
116
+ return { results: this.results, logs: this.logs, error: this.error };
117
+ }
118
+ }
119
+ const TEXT_MIME = /^text\/|json|javascript|svg|latex/;
120
+ /** Output as E2B's logs: one entry per line, each keeping its newline. */
121
+ function lines(text) {
122
+ return text.match(/[^\n]*\n|[^\n]+$/g) ?? [];
123
+ }
124
+ function language(requested) {
125
+ if (requested === undefined || requested === "python")
126
+ return "python";
127
+ if (requested === "javascript" || requested === "js")
128
+ return "javascript";
129
+ throw new NotSupportedError(`Running ${requested} code in the interpreter`, requested === "bash"
130
+ ? "Use sandbox.commands.run(code)."
131
+ : "Runtime's interpreter runs Python and JavaScript; install the language and run it with sandbox.commands.run(...).");
132
+ }
133
+ /** The code interpreter sandbox: everything the base Sandbox has, plus runCode
134
+ * and code contexts. */
135
+ export class Sandbox extends BaseSandbox {
136
+ static defaultTemplate = "code-interpreter-v1";
137
+ /** Contexts made to carry the sandbox's envs, one per language. */
138
+ #envContexts = new Map();
139
+ get #interpreter() {
140
+ return this.runtime.interpreter;
141
+ }
142
+ /** The context a run goes to: the one asked for; else, when the sandbox has
143
+ * envs, a context made once with them; else Runtime's default one. */
144
+ async #contextFor(lang, context) {
145
+ if (context)
146
+ return context.id;
147
+ if (!Object.keys(this.envs).length)
148
+ return undefined;
149
+ let id = this.#envContexts.get(lang);
150
+ if (!id) {
151
+ id = guard("sandbox", async () => {
152
+ const made = await this.#interpreter.contexts.create({
153
+ id: `e2b-${lang}`,
154
+ language: lang,
155
+ env: this.envs,
156
+ });
157
+ return made.id;
158
+ }).catch(async (error) => {
159
+ // Made already, by another object connected to this sandbox.
160
+ const existing = (await this.#interpreter.contexts.list()).find((one) => one.id === `e2b-${lang}`);
161
+ if (existing)
162
+ return existing.id;
163
+ throw error;
164
+ });
165
+ this.#envContexts.set(lang, id);
166
+ }
167
+ return id;
168
+ }
169
+ async #inline(result) {
170
+ const data = { ...result.data };
171
+ for (const [mime, ref] of Object.entries(result.refs ?? {})) {
172
+ if (data[mime] !== undefined)
173
+ continue;
174
+ const bytes = await guard("sandbox", () => this.#interpreter.result(ref));
175
+ data[mime] = TEXT_MIME.test(mime)
176
+ ? new TextDecoder().decode(bytes)
177
+ : Buffer.from(bytes).toString("base64");
178
+ }
179
+ return data;
180
+ }
181
+ /** Runs code in a stateful context. Errors in the code come back in
182
+ * `execution.error`, as in E2B; a run past `timeoutMs` throws TimeoutError. */
183
+ async runCode(code, opts = {}) {
184
+ if (opts.language !== undefined && opts.context !== undefined)
185
+ throw new SandboxError("Pass language or context, not both.");
186
+ if (opts.envs && Object.keys(opts.envs).length)
187
+ throw new NotSupportedError("Environment variables for one run (runCode envs)", "Make a context with them: sandbox.runtime.interpreter.contexts.create({ env }), then runCode(code, { context: { id } }).");
188
+ const lang = language(opts.context?.language ?? opts.language);
189
+ const context = await this.#contextFor(lang, opts.context);
190
+ const now = () => Date.now() * 1_000_000;
191
+ const streaming = opts.onStdout || opts.onStderr || opts.onResult || opts.onError;
192
+ const execution = await guard("sandbox", () => this.#interpreter.run(code, {
193
+ ...(context ? { context } : { language: lang }),
194
+ timeoutMs: opts.timeoutMs ?? 60_000,
195
+ ...(streaming
196
+ ? {
197
+ onStdout: (text) => void opts.onStdout?.(new OutputMessage(text, now(), false)),
198
+ onStderr: (text) => void opts.onStderr?.(new OutputMessage(text, now(), true)),
199
+ onError: (error) => void opts.onError?.(new ExecutionError(error.name, error.value, error.traceback)),
200
+ }
201
+ : {}),
202
+ }));
203
+ if (execution.status === "timeout")
204
+ throw new TimeoutError(`Execution timed out after ${opts.timeoutMs ?? 60_000} ms: pass a larger 'timeoutMs'.`);
205
+ if (execution.status === "lost")
206
+ throw new SandboxError("The interpreter lost this run (its context stopped); run it again.");
207
+ const results = await Promise.all(execution.results.map(async (result) => new Result(await this.#inline(result), result.main)));
208
+ if (opts.onResult)
209
+ for (const result of results)
210
+ await opts.onResult(result);
211
+ return new Execution(results, { stdout: lines(execution.stdout), stderr: lines(execution.stderr) }, execution.error
212
+ ? new ExecutionError(execution.error.name, execution.error.value, execution.error.traceback)
213
+ : undefined, execution.executionCount ?? undefined);
214
+ }
215
+ async createCodeContext(opts = {}) {
216
+ const lang = language(opts.language);
217
+ const made = await guard("sandbox", () => this.#interpreter.contexts.create({
218
+ language: lang,
219
+ ...(opts.cwd ? { cwd: opts.cwd } : {}),
220
+ ...(Object.keys(this.envs).length ? { env: this.envs } : {}),
221
+ }));
222
+ return { id: made.id, language: made.language, cwd: made.cwd };
223
+ }
224
+ async removeCodeContext(context) {
225
+ const id = typeof context === "string" ? context : context.id;
226
+ await guard("sandbox", () => this.#interpreter.contexts.remove(id));
227
+ }
228
+ async listCodeContexts() {
229
+ const contexts = await guard("sandbox", () => this.#interpreter.contexts.list());
230
+ return contexts.map((one) => ({ id: one.id, language: one.language, cwd: one.cwd }));
231
+ }
232
+ async restartCodeContext(context) {
233
+ const id = typeof context === "string" ? context : context.id;
234
+ await guard("sandbox", () => this.#interpreter.contexts.restart(id));
235
+ }
236
+ }
237
+ export default Sandbox;
238
+ /** E2B's client with bound options, for the code interpreter. */
239
+ export class E2B {
240
+ Sandbox;
241
+ constructor(opts = {}) {
242
+ this.Sandbox = bind(Sandbox, opts);
243
+ }
244
+ }
@@ -0,0 +1,100 @@
1
+ import type { Process } from "../sandbox.js";
2
+ import type { RuntimeSandbox } from "./client.js";
3
+ import { type CommandResult } from "./errors.js";
4
+ export type { CommandResult };
5
+ export type Username = "user" | "root" | (string & {});
6
+ export interface CommandRequestOpts {
7
+ requestTimeoutMs?: number;
8
+ signal?: AbortSignal;
9
+ }
10
+ export interface CommandStartOpts extends CommandRequestOpts {
11
+ background?: boolean;
12
+ cwd?: string;
13
+ /** Only the default user. Runtime runs commands as `runtime`, the sandbox's
14
+ * owner, with passwordless sudo; E2B's `root` is refused rather than
15
+ * silently run as someone else. */
16
+ user?: Username;
17
+ envs?: Record<string, string>;
18
+ onStdout?: (data: string) => void | Promise<void>;
19
+ onStderr?: (data: string) => void | Promise<void>;
20
+ stdin?: boolean;
21
+ /** Default 60 000, as in E2B. 0 is no limit (Runtime's longest, 24 hours). */
22
+ timeoutMs?: number;
23
+ }
24
+ export type CommandConnectOpts = Pick<CommandStartOpts, "onStderr" | "onStdout" | "timeoutMs"> & CommandRequestOpts;
25
+ /** A command as E2B lists it. `pid` is a number derived from Runtime's process
26
+ * id (stable for the life of the process), not the Linux pid. */
27
+ export interface ProcessInfo {
28
+ pid: number;
29
+ tag?: string;
30
+ cmd: string;
31
+ args: string[];
32
+ envs: Record<string, string>;
33
+ cwd?: string;
34
+ }
35
+ /** The shared state a sandbox's modules need: the Runtime sandbox, the
36
+ * environment given at create, and the one-time /home/user link. */
37
+ export interface SandboxContext {
38
+ readonly runtime: RuntimeSandbox;
39
+ readonly envs: Record<string, string>;
40
+ /** Makes /home/user (E2B's home) lead to /workspace (Runtime's), once, when
41
+ * something names it. */
42
+ ensureHome(text: string | undefined): Promise<void>;
43
+ }
44
+ /** E2B's pids are numbers; Runtime's process ids are strings. The number is a
45
+ * 31-bit FNV-1a hash of the id, so every client derives the same one. */
46
+ export declare function pidOf(processId: string): number;
47
+ /** `sandbox.commands`: E2B's command module over Runtime's exec and processes. */
48
+ export declare class Commands {
49
+ #private;
50
+ constructor(ctx: SandboxContext);
51
+ /** Runs a command. In the foreground it resolves with the result and throws
52
+ * CommandExitError on a non-zero exit and TimeoutError past `timeoutMs`; with
53
+ * `background: true` it resolves at once with a CommandHandle. */
54
+ run(cmd: string, opts?: CommandStartOpts & {
55
+ background?: false;
56
+ }): Promise<CommandResult>;
57
+ run(cmd: string, opts: CommandStartOpts & {
58
+ background: true;
59
+ }): Promise<CommandHandle>;
60
+ run(cmd: string, opts?: CommandStartOpts & {
61
+ background?: boolean;
62
+ }): Promise<CommandHandle | CommandResult>;
63
+ /** Running commands. */
64
+ list(_opts?: CommandRequestOpts): Promise<ProcessInfo[]>;
65
+ /** Kills a command with SIGKILL, as E2B does. False when there is none. */
66
+ kill(pid: number, _opts?: CommandRequestOpts): Promise<boolean>;
67
+ /** Sends input to a command started with `stdin: true`. */
68
+ sendStdin(pid: number, data: string | Uint8Array, _opts?: CommandRequestOpts): Promise<void>;
69
+ closeStdin(pid: number, _opts?: CommandRequestOpts): Promise<void>;
70
+ /** Attaches to a running command; output from now on reaches the handle. */
71
+ connect(pid: number, opts?: CommandConnectOpts): Promise<CommandHandle>;
72
+ }
73
+ /** A command started in the background: E2B's CommandHandle over a Runtime
74
+ * process. Output streams into `stdout`/`stderr` and the callbacks as it
75
+ * arrives. */
76
+ export declare class CommandHandle {
77
+ #private;
78
+ readonly pid: number;
79
+ constructor(process: Process, options: {
80
+ stdin: boolean;
81
+ timeoutMs: number;
82
+ cursor?: number;
83
+ onStdout?: (data: string) => void | Promise<void>;
84
+ onStderr?: (data: string) => void | Promise<void>;
85
+ });
86
+ /** The exit code, or undefined while the command runs. */
87
+ get exitCode(): number | undefined;
88
+ get error(): string | undefined;
89
+ get stdout(): string;
90
+ get stderr(): string;
91
+ /** Waits for the command to end. Throws CommandExitError on a non-zero exit,
92
+ * as E2B does. */
93
+ wait(): Promise<CommandResult>;
94
+ /** Stops receiving output; the command keeps running. */
95
+ disconnect(): Promise<void>;
96
+ /** Kills the command with SIGKILL. False when it had already ended. */
97
+ kill(): Promise<boolean>;
98
+ sendStdin(data: string | Uint8Array, _opts?: CommandRequestOpts): Promise<void>;
99
+ closeStdin(_opts?: CommandRequestOpts): Promise<void>;
100
+ }