@molecule/api-code-sandbox-e2b 1.2.4 → 1.2.5
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 +8 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/provider.d.ts +16 -0
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +44 -4
- package/package.json +2 -2
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-10-
|
|
6
|
+
Generated: 2026-10-04T09:45:27.540Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-code-sandbox-e2b
|
|
@@ -603,5 +603,12 @@ default is `onTimeout: 'kill'`, so a sandbox nothing touched for its lifetime
|
|
|
603
603
|
would be destroyed with its files. This bond creates every sandbox with
|
|
604
604
|
`lifecycle: { onTimeout: { action: 'pause', keepMemory: true } }`; the memory
|
|
605
605
|
snapshot is what lets `resume()` truthfully report `processesPreserved: true`.
|
|
606
|
+
The one exception is the throwaway `verifyEgress()` probe, created with
|
|
607
|
+
`lifecycle: { onTimeout: 'kill' }`: a pause writes a full snapshot to the
|
|
608
|
+
host's disk, and nobody resumes a probe. Every pause and every
|
|
609
|
+
`commitTemplate()` is a new snapshot build on a self-hosted box's disk, so
|
|
610
|
+
a pause-on-timeout sandbox you do not need back is disk you pay for — keep a
|
|
611
|
+
sandbox you intend to keep warm alive with `keepAlive(ms)`, and destroy one
|
|
612
|
+
you are done with rather than letting it time out.
|
|
606
613
|
Extending the deadline is `keepAlive(ms)` — call it from a real activity
|
|
607
614
|
signal (an open editor's heartbeat), never as a side effect of polling.
|
package/dist/index.d.ts
CHANGED
|
@@ -144,6 +144,13 @@
|
|
|
144
144
|
* would be destroyed with its files. This bond creates every sandbox with
|
|
145
145
|
* `lifecycle: { onTimeout: { action: 'pause', keepMemory: true } }`; the memory
|
|
146
146
|
* snapshot is what lets `resume()` truthfully report `processesPreserved: true`.
|
|
147
|
+
* The one exception is the throwaway `verifyEgress()` probe, created with
|
|
148
|
+
* `lifecycle: { onTimeout: 'kill' }`: a pause writes a full snapshot to the
|
|
149
|
+
* host's disk, and nobody resumes a probe. Every pause and every
|
|
150
|
+
* `commitTemplate()` is a new snapshot build on a self-hosted box's disk, so
|
|
151
|
+
* a pause-on-timeout sandbox you do not need back is disk you pay for — keep a
|
|
152
|
+
* sandbox you intend to keep warm alive with `keepAlive(ms)`, and destroy one
|
|
153
|
+
* you are done with rather than letting it time out.
|
|
147
154
|
* Extending the deadline is `keepAlive(ms)` — call it from a real activity
|
|
148
155
|
* signal (an open editor's heartbeat), never as a side effect of polling.
|
|
149
156
|
*
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6JG;AAEH,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -144,6 +144,13 @@
|
|
|
144
144
|
* would be destroyed with its files. This bond creates every sandbox with
|
|
145
145
|
* `lifecycle: { onTimeout: { action: 'pause', keepMemory: true } }`; the memory
|
|
146
146
|
* snapshot is what lets `resume()` truthfully report `processesPreserved: true`.
|
|
147
|
+
* The one exception is the throwaway `verifyEgress()` probe, created with
|
|
148
|
+
* `lifecycle: { onTimeout: 'kill' }`: a pause writes a full snapshot to the
|
|
149
|
+
* host's disk, and nobody resumes a probe. Every pause and every
|
|
150
|
+
* `commitTemplate()` is a new snapshot build on a self-hosted box's disk, so
|
|
151
|
+
* a pause-on-timeout sandbox you do not need back is disk you pay for — keep a
|
|
152
|
+
* sandbox you intend to keep warm alive with `keepAlive(ms)`, and destroy one
|
|
153
|
+
* you are done with rather than letting it time out.
|
|
147
154
|
* Extending the deadline is `keepAlive(ms)` — call it from a real activity
|
|
148
155
|
* signal (an open editor's heartbeat), never as a side effect of polling.
|
|
149
156
|
*
|
package/dist/provider.d.ts
CHANGED
|
@@ -64,6 +64,22 @@ export declare class E2BSandboxProvider implements SandboxProvider {
|
|
|
64
64
|
* @returns A live sandbox handle.
|
|
65
65
|
*/
|
|
66
66
|
create(config: SandboxConfig): Promise<Sandbox>;
|
|
67
|
+
/**
|
|
68
|
+
* {@link create} with the sandbox's timeout action chosen by the caller.
|
|
69
|
+
*
|
|
70
|
+
* `'pause'` is E2B's `lifecycle: { onTimeout: { action: 'pause', keepMemory:
|
|
71
|
+
* true } }` — the data-safe default for anything that may hold a project
|
|
72
|
+
* (see {@link create}). `'kill'` is `lifecycle: { onTimeout: 'kill' }` — for a
|
|
73
|
+
* THROWAWAY sandbox this bond destroys itself (the egress probe): pausing one
|
|
74
|
+
* at its deadline would write a full memory + filesystem snapshot to the
|
|
75
|
+
* host's disk for a sandbox nobody will ever resume. E2B cannot change a
|
|
76
|
+
* sandbox's `onTimeout` after create, so the choice is made here, once.
|
|
77
|
+
*
|
|
78
|
+
* @param config - As for {@link create}.
|
|
79
|
+
* @param onTimeout - What E2B does at the sandbox's deadline.
|
|
80
|
+
* @returns A live sandbox handle.
|
|
81
|
+
*/
|
|
82
|
+
private createSandbox;
|
|
67
83
|
/**
|
|
68
84
|
* Resolve an existing sandbox by id.
|
|
69
85
|
*
|
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,EACV,qBAAqB,EAErB,aAAa,EAKb,oBAAoB,EACpB,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,eAAe,EAGf,UAAU,EACX,MAAM,4BAA4B,CAAA;AAEnC,OAAO,KAAK,EAGV,SAAS,EACT,oBAAoB,EAMrB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/provider.js
CHANGED
|
@@ -551,6 +551,25 @@ class E2BSandbox {
|
|
|
551
551
|
async writeFile(path, content) {
|
|
552
552
|
await this.sbx.files.write(path, content);
|
|
553
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* Read a file's exact bytes through envd's file API (never command stdout,
|
|
556
|
+
* which envd truncates for large outputs).
|
|
557
|
+
*
|
|
558
|
+
* @param path - Absolute path inside the sandbox.
|
|
559
|
+
* @returns The file's bytes.
|
|
560
|
+
*/
|
|
561
|
+
async readFileBytes(path) {
|
|
562
|
+
return this.sbx.files.read(path, { format: 'bytes' });
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Write exact bytes to a file through envd's file API, replacing it.
|
|
566
|
+
*
|
|
567
|
+
* @param path - Absolute path inside the sandbox.
|
|
568
|
+
* @param data - The bytes to write.
|
|
569
|
+
*/
|
|
570
|
+
async writeFileBytes(path, data) {
|
|
571
|
+
await this.sbx.files.write(path, data);
|
|
572
|
+
}
|
|
554
573
|
/**
|
|
555
574
|
* List a directory. Throws when the path does not exist (an empty array
|
|
556
575
|
* means "exists and is empty", never "missing").
|
|
@@ -777,6 +796,24 @@ export class E2BSandboxProvider {
|
|
|
777
796
|
* @returns A live sandbox handle.
|
|
778
797
|
*/
|
|
779
798
|
async create(config) {
|
|
799
|
+
return this.createSandbox(config, 'pause');
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* {@link create} with the sandbox's timeout action chosen by the caller.
|
|
803
|
+
*
|
|
804
|
+
* `'pause'` is E2B's `lifecycle: { onTimeout: { action: 'pause', keepMemory:
|
|
805
|
+
* true } }` — the data-safe default for anything that may hold a project
|
|
806
|
+
* (see {@link create}). `'kill'` is `lifecycle: { onTimeout: 'kill' }` — for a
|
|
807
|
+
* THROWAWAY sandbox this bond destroys itself (the egress probe): pausing one
|
|
808
|
+
* at its deadline would write a full memory + filesystem snapshot to the
|
|
809
|
+
* host's disk for a sandbox nobody will ever resume. E2B cannot change a
|
|
810
|
+
* sandbox's `onTimeout` after create, so the choice is made here, once.
|
|
811
|
+
*
|
|
812
|
+
* @param config - As for {@link create}.
|
|
813
|
+
* @param onTimeout - What E2B does at the sandbox's deadline.
|
|
814
|
+
* @returns A live sandbox handle.
|
|
815
|
+
*/
|
|
816
|
+
async createSandbox(config, onTimeout) {
|
|
780
817
|
const client = await this.client();
|
|
781
818
|
const templateId = config.templateId ?? this.config.templateId;
|
|
782
819
|
if (config.volumeName && !config.volumeMountPath) {
|
|
@@ -789,7 +826,9 @@ export class E2BSandboxProvider {
|
|
|
789
826
|
timeoutMs: this.config.defaultTimeoutMs,
|
|
790
827
|
envs: config.env ?? {},
|
|
791
828
|
metadata: { projectId: config.projectId, ...(config.labels ?? {}) },
|
|
792
|
-
lifecycle:
|
|
829
|
+
lifecycle: onTimeout === 'kill'
|
|
830
|
+
? { onTimeout: 'kill' }
|
|
831
|
+
: { onTimeout: { action: 'pause', keepMemory: true } },
|
|
793
832
|
...(config.volumeName
|
|
794
833
|
? { volumeMounts: { [config.volumeMountPath]: config.volumeName } }
|
|
795
834
|
: {}),
|
|
@@ -1193,7 +1232,9 @@ export class E2BSandboxProvider {
|
|
|
1193
1232
|
async verifyEgress() {
|
|
1194
1233
|
let handle;
|
|
1195
1234
|
try {
|
|
1196
|
-
|
|
1235
|
+
// Kill, not pause, at its deadline: a leaked probe must not leave a
|
|
1236
|
+
// snapshot on the host's disk (see createSandbox).
|
|
1237
|
+
handle = await this.createSandbox({ projectId: `egress-probe-${Date.now()}`, env: {} }, 'kill');
|
|
1197
1238
|
}
|
|
1198
1239
|
catch (error) {
|
|
1199
1240
|
return {
|
|
@@ -1205,8 +1246,7 @@ export class E2BSandboxProvider {
|
|
|
1205
1246
|
const verdict = await this.probeEgress(handle);
|
|
1206
1247
|
// The probe sandbox is destroyed on EVERY path. A failed destroy is retried,
|
|
1207
1248
|
// and one that still fails is reported in the verdict's detail: the sandbox
|
|
1208
|
-
//
|
|
1209
|
-
// storage forever.
|
|
1249
|
+
// is killed at its own deadline, but until then it runs metered.
|
|
1210
1250
|
const leaked = await this.destroyProbe(handle.id);
|
|
1211
1251
|
return leaked ? { ...verdict, detail: `${verdict.detail} ${leaked}` } : verdict;
|
|
1212
1252
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/api-code-sandbox-e2b",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "E2B (e2b.dev) code sandbox provider — Firecracker microVMs with golden templates, fork, and pause/resume",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"license": "Apache-2.0",
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@molecule/api-bond": "1.0.2",
|
|
33
|
-
"@molecule/api-code-sandbox": "1.
|
|
33
|
+
"@molecule/api-code-sandbox": "1.3.0",
|
|
34
34
|
"@types/node": "26.1.2",
|
|
35
35
|
"typescript": "6.0.3",
|
|
36
36
|
"vitest": "4.1.11"
|