@molecule/api-code-sandbox-e2b 1.0.0 → 1.0.2
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/README.md +12 -3
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +86 -7
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
|
3
3
|
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
4
|
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
5
|
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
-
Generated: 2026-08-
|
|
6
|
+
Generated: 2026-08-11T00:53:00.606Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-code-sandbox-e2b
|
|
@@ -88,7 +88,13 @@ Subset of the SDK's `Commands` the bond uses.
|
|
|
88
88
|
interface E2BCommandsLike {
|
|
89
89
|
run(
|
|
90
90
|
cmd: string,
|
|
91
|
-
opts?: {
|
|
91
|
+
opts?: {
|
|
92
|
+
cwd?: string
|
|
93
|
+
timeoutMs?: number
|
|
94
|
+
envs?: Record<string, string>
|
|
95
|
+
/** Fire-and-forget: returns immediately without waiting for exit. */
|
|
96
|
+
background?: boolean
|
|
97
|
+
},
|
|
92
98
|
): Promise<E2BCommandResultLike>
|
|
93
99
|
}
|
|
94
100
|
```
|
|
@@ -143,7 +149,10 @@ Subset of the SDK's `Filesystem` the bond uses.
|
|
|
143
149
|
```typescript
|
|
144
150
|
interface E2BFilesystemLike {
|
|
145
151
|
read(path: string): Promise<string>
|
|
146
|
-
|
|
152
|
+
/** Binary read (`format: 'bytes'`) — used by `exportFiles` to stream a tar out. */
|
|
153
|
+
read(path: string, opts: { format: 'bytes' }): Promise<Uint8Array>
|
|
154
|
+
/** Accepts text or binary; `importFiles` writes a tar blob in. */
|
|
155
|
+
write(path: string, data: string | Uint8Array | ArrayBuffer | Blob): Promise<unknown>
|
|
147
156
|
list(path: string): Promise<Array<{ name: string; type?: string; size?: number }>>
|
|
148
157
|
remove(path: string): Promise<void>
|
|
149
158
|
}
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAEV,aAAa,EAKb,OAAO,EACP,aAAa,EACb,eAAe,EAChB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAkB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAEV,aAAa,EAKb,OAAO,EACP,aAAa,EACb,eAAe,EAChB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAkB,MAAM,YAAY,CAAA;AAsWjF;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,YAAW,eAAe;IACxD,QAAQ,CAAC,IAAI,SAAQ;IAErB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0D;IACjF,OAAO,CAAC,aAAa,CAA6C;IAClE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAsB;IAEtD;;;;;OAKG;gBACS,MAAM,GAAE,SAAc,EAAE,cAAc,CAAC,EAAE,oBAAoB;IAYzE;;;;OAIG;YACW,MAAM;IASpB;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBrD;;;;;OAKG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAgB9C;;;;;OAKG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAY/C;;;;OAIG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxC;;;;;;;;;;;OAWG;IACG,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC;CAyD7C;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,MAAM,GAAE,SAAc,EACtB,cAAc,CAAC,EAAE,oBAAoB,GACpC,kBAAkB,CAEpB;AAED,kEAAkE;AAClE,eAAO,MAAM,QAAQ,EAAE,eAAkC,CAAA"}
|
package/dist/provider.js
CHANGED
|
@@ -166,17 +166,49 @@ class E2BSandbox {
|
|
|
166
166
|
/**
|
|
167
167
|
* Run a command to completion in the sandbox.
|
|
168
168
|
*
|
|
169
|
+
* The core contract is RETURN, not throw: a non-zero exit is data
|
|
170
|
+
* (`exitCode`), not an error — control-plane code reads `exitCode`/`stdout`
|
|
171
|
+
* to decide (install sentinels, health probes, existence checks). E2B's
|
|
172
|
+
* `commands.run` throws `CommandExitError` on non-zero, so we catch it and
|
|
173
|
+
* map its `.result` back to an {@link ExecResult}. Only a genuine
|
|
174
|
+
* infrastructure failure (no `.result`) rethrows.
|
|
175
|
+
*
|
|
169
176
|
* @param command - The shell command to run.
|
|
170
177
|
* @param opts - Working directory, timeout (ms), and env vars.
|
|
171
|
-
* @returns stdout, stderr and the exit code.
|
|
178
|
+
* @returns stdout, stderr and the exit code (even when non-zero).
|
|
172
179
|
*/
|
|
173
180
|
async exec(command, opts) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
181
|
+
// A shell-backgrounded command (`… &` / `… & true`) must NOT block exec —
|
|
182
|
+
// that is the whole point of `&`. E2B's `commands.run` waits for the process
|
|
183
|
+
// group anyway (a detached `nohup`/`setsid` dev-server launch times out the
|
|
184
|
+
// request), so route backgrounded commands through the SDK's native
|
|
185
|
+
// `background: true`, which returns immediately. The control plane launches
|
|
186
|
+
// every dev server this way (`nohup sh -c '…' >log 2>&1 & true`), so this
|
|
187
|
+
// makes the provider-agnostic launch code work unchanged on E2B.
|
|
188
|
+
if (/&\s*(?:true\s*)?$/.test(command)) {
|
|
189
|
+
await this.sbx.commands.run(command, {
|
|
190
|
+
cwd: opts?.cwd,
|
|
191
|
+
envs: opts?.env,
|
|
192
|
+
background: true,
|
|
193
|
+
});
|
|
194
|
+
return { stdout: '', stderr: '', exitCode: 0 };
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const r = await this.sbx.commands.run(command, {
|
|
198
|
+
cwd: opts?.cwd,
|
|
199
|
+
timeoutMs: opts?.timeout,
|
|
200
|
+
envs: opts?.env,
|
|
201
|
+
});
|
|
202
|
+
return { stdout: r.stdout, stderr: r.stderr, exitCode: r.exitCode };
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
const res = error
|
|
206
|
+
?.result;
|
|
207
|
+
if (res && typeof res.exitCode === 'number') {
|
|
208
|
+
return { stdout: res.stdout ?? '', stderr: res.stderr ?? '', exitCode: res.exitCode };
|
|
209
|
+
}
|
|
210
|
+
throw error;
|
|
211
|
+
}
|
|
180
212
|
}
|
|
181
213
|
/**
|
|
182
214
|
* Read a file's contents as text.
|
|
@@ -234,6 +266,53 @@ class E2BSandbox {
|
|
|
234
266
|
// Returning a no-op unsubscribe keeps callers that register-and-forget safe.
|
|
235
267
|
return () => { };
|
|
236
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* Extract a POSIX tar stream into the sandbox at `path`.
|
|
271
|
+
*
|
|
272
|
+
* The transfer primitive the scaffold path uses to copy a project tree in.
|
|
273
|
+
* Buffers the stream, writes it as one blob, and `tar x`-tracts it.
|
|
274
|
+
* `--no-same-owner --no-same-permissions` enforces the contract that a
|
|
275
|
+
* caller/tenant-authored archive's ownership + setuid/setgid bits are NOT
|
|
276
|
+
* restored (they arrive owned by the sandbox user, no privilege bits).
|
|
277
|
+
*
|
|
278
|
+
* @param path - Absolute destination directory inside the sandbox.
|
|
279
|
+
* @param archive - POSIX tar byte stream to extract there.
|
|
280
|
+
*/
|
|
281
|
+
async importFiles(path, archive) {
|
|
282
|
+
const chunks = [];
|
|
283
|
+
for await (const chunk of archive)
|
|
284
|
+
chunks.push(chunk);
|
|
285
|
+
const tarPath = `/tmp/mol-import-${Date.now().toString(36)}.tar`;
|
|
286
|
+
await this.sbx.files.write(tarPath, new Blob([Buffer.concat(chunks)]));
|
|
287
|
+
const r = await this.sbx.commands.run(`mkdir -p ${path} && tar xf ${tarPath} -C ${path} --no-same-owner --no-same-permissions && rm -f ${tarPath}`, { timeoutMs: 300_000 });
|
|
288
|
+
if (r.exitCode !== 0) {
|
|
289
|
+
throw new Error(`importFiles: tar extract failed (${r.exitCode}): ${r.stderr.slice(0, 300)}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Stream a directory tree out of the sandbox as a POSIX tar archive.
|
|
294
|
+
*
|
|
295
|
+
* Tars the tree in-sandbox, reads it back as bytes, and yields it as a single
|
|
296
|
+
* chunk. Sufficient for archive/migrate (whole-workspace capture); not a
|
|
297
|
+
* chunked pipe.
|
|
298
|
+
*
|
|
299
|
+
* @param path - Absolute path inside the sandbox to archive.
|
|
300
|
+
* @returns A POSIX tar byte stream of that path's contents.
|
|
301
|
+
*/
|
|
302
|
+
async exportFiles(path) {
|
|
303
|
+
const tarPath = `/tmp/mol-export-${Date.now().toString(36)}.tar`;
|
|
304
|
+
const r = await this.sbx.commands.run(`tar cf ${tarPath} -C ${path} .`, { timeoutMs: 300_000 });
|
|
305
|
+
if (r.exitCode !== 0) {
|
|
306
|
+
throw new Error(`exportFiles: tar create failed (${r.exitCode}): ${r.stderr.slice(0, 300)}`);
|
|
307
|
+
}
|
|
308
|
+
const bytes = await this.sbx.files.read(tarPath, { format: 'bytes' });
|
|
309
|
+
await this.sbx.commands.run(`rm -f ${tarPath}`, { timeoutMs: 20_000 }).catch((_error) => {
|
|
310
|
+
// intentional noop — leftover /tmp tar is harmless; the sandbox is ephemeral.
|
|
311
|
+
});
|
|
312
|
+
return (async function* () {
|
|
313
|
+
yield bytes;
|
|
314
|
+
})();
|
|
315
|
+
}
|
|
237
316
|
/**
|
|
238
317
|
* Extend the sandbox's auto-pause deadline (heartbeat).
|
|
239
318
|
*
|
package/dist/types.d.ts
CHANGED
|
@@ -55,7 +55,12 @@ export interface E2BCommandResultLike {
|
|
|
55
55
|
/** Subset of the SDK's `Filesystem` the bond uses. */
|
|
56
56
|
export interface E2BFilesystemLike {
|
|
57
57
|
read(path: string): Promise<string>;
|
|
58
|
-
|
|
58
|
+
/** Binary read (`format: 'bytes'`) — used by `exportFiles` to stream a tar out. */
|
|
59
|
+
read(path: string, opts: {
|
|
60
|
+
format: 'bytes';
|
|
61
|
+
}): Promise<Uint8Array>;
|
|
62
|
+
/** Accepts text or binary; `importFiles` writes a tar blob in. */
|
|
63
|
+
write(path: string, data: string | Uint8Array | ArrayBuffer | Blob): Promise<unknown>;
|
|
59
64
|
list(path: string): Promise<Array<{
|
|
60
65
|
name: string;
|
|
61
66
|
type?: string;
|
|
@@ -69,6 +74,8 @@ export interface E2BCommandsLike {
|
|
|
69
74
|
cwd?: string;
|
|
70
75
|
timeoutMs?: number;
|
|
71
76
|
envs?: Record<string, string>;
|
|
77
|
+
/** Fire-and-forget: returns immediately without waiting for exit. */
|
|
78
|
+
background?: boolean;
|
|
72
79
|
}): Promise<E2BCommandResultLike>;
|
|
73
80
|
}
|
|
74
81
|
/** Subset of the SDK's `Sandbox` instance the bond uses. */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,qFAAqF;AACrF,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED