noumen 0.4.0 → 0.6.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/README.md +63 -8
- package/dist/a2a/index.d.ts +6 -4
- package/dist/acp/index.d.ts +7 -5
- package/dist/{agent-1nFVUP9E.d.ts → agent-DWE4_P5X.d.ts} +169 -485
- package/dist/{cache-DsRqxx6v.d.ts → cache-BlBwXXPS.d.ts} +1 -1
- package/dist/{chunk-4HW6LN6D.js → chunk-6MMYCGJQ.js} +366 -1227
- package/dist/chunk-6MMYCGJQ.js.map +1 -0
- package/dist/{chunk-5JN4SPI7.js → chunk-7IQCQI2G.js} +1 -1
- package/dist/{chunk-L3L3FG5T.js → chunk-CCM2AXZG.js} +1 -1
- package/dist/{chunk-L3L3FG5T.js.map → chunk-CCM2AXZG.js.map} +1 -1
- package/dist/{chunk-CS6WNDCF.js → chunk-I3JTUFPK.js} +2 -2
- package/dist/chunk-I3JTUFPK.js.map +1 -0
- package/dist/chunk-I5SBSOS6.js +40 -0
- package/dist/chunk-I5SBSOS6.js.map +1 -0
- package/dist/{chunk-HL6JCRZJ.js → chunk-XZN4QZLK.js} +4 -4
- package/dist/{chunk-EKOGVTBT.js → chunk-ZXSDKBYB.js} +4 -2
- package/dist/chunk-ZXSDKBYB.js.map +1 -0
- package/dist/cli/index.js +11 -11
- package/dist/client/index.d.ts +1 -1
- package/dist/computer-BPdxSo6X.d.ts +88 -0
- package/dist/docker.d.ts +129 -0
- package/dist/docker.js +401 -0
- package/dist/docker.js.map +1 -0
- package/dist/e2b.d.ts +157 -0
- package/dist/e2b.js +202 -0
- package/dist/e2b.js.map +1 -0
- package/dist/freestyle.d.ts +174 -0
- package/dist/freestyle.js +240 -0
- package/dist/freestyle.js.map +1 -0
- package/dist/index.d.ts +19 -204
- package/dist/index.js +38 -48
- package/dist/lsp/index.d.ts +4 -3
- package/dist/mcp/index.d.ts +5 -4
- package/dist/mcp/index.js +2 -2
- package/dist/{provider-factory-KCLIF34X.js → provider-factory-TUHU3DIG.js} +2 -2
- package/dist/providers/anthropic.d.ts +3 -3
- package/dist/providers/anthropic.js +4 -3
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/bedrock.d.ts +3 -3
- package/dist/providers/bedrock.js +2 -2
- package/dist/providers/bedrock.js.map +1 -1
- package/dist/providers/gemini.d.ts +2 -2
- package/dist/providers/gemini.js +1 -1
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/ollama.d.ts +1 -1
- package/dist/providers/ollama.js +2 -2
- package/dist/providers/openai.d.ts +2 -2
- package/dist/providers/openai.js +2 -2
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/openrouter.js +2 -2
- package/dist/providers/vertex.d.ts +3 -3
- package/dist/providers/vertex.js +4 -3
- package/dist/providers/vertex.js.map +1 -1
- package/dist/{resolve-4JA2BBDA.js → resolve-6KUZNEYW.js} +2 -2
- package/dist/sandbox-9qeMTNrD.d.ts +126 -0
- package/dist/server/index.d.ts +6 -4
- package/dist/{server-CHMxuWKq.d.ts → server-BzNGKTP6.d.ts} +1 -1
- package/dist/sprites.d.ts +136 -0
- package/dist/sprites.js +334 -0
- package/dist/sprites.js.map +1 -0
- package/dist/ssh.d.ts +187 -0
- package/dist/ssh.js +392 -0
- package/dist/ssh.js.map +1 -0
- package/dist/{types-RPKUTu1k.d.ts → types-DhXwOQwD.d.ts} +3 -89
- package/dist/{types-LrU4LRmX.d.ts → types-kiGBF35b.d.ts} +40 -2
- package/package.json +25 -1
- package/dist/chunk-4HW6LN6D.js.map +0 -1
- package/dist/chunk-CS6WNDCF.js.map +0 -1
- package/dist/chunk-EKOGVTBT.js.map +0 -1
- /package/dist/{chunk-5JN4SPI7.js.map → chunk-7IQCQI2G.js.map} +0 -0
- /package/dist/{chunk-HL6JCRZJ.js.map → chunk-XZN4QZLK.js.map} +0 -0
- /package/dist/{provider-factory-KCLIF34X.js.map → provider-factory-TUHU3DIG.js.map} +0 -0
- /package/dist/{resolve-4JA2BBDA.js.map → resolve-6KUZNEYW.js.map} +0 -0
package/dist/docker.js
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createComputerProxy,
|
|
3
|
+
createFsProxy
|
|
4
|
+
} from "./chunk-I5SBSOS6.js";
|
|
5
|
+
import "./chunk-DGUM43GV.js";
|
|
6
|
+
|
|
7
|
+
// src/virtual/docker-fs.ts
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
var DockerFs = class {
|
|
10
|
+
container;
|
|
11
|
+
workingDir;
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
this.container = opts.container;
|
|
14
|
+
this.workingDir = opts.workingDir ?? "/";
|
|
15
|
+
}
|
|
16
|
+
resolvePath(p) {
|
|
17
|
+
if (p.includes("\0")) {
|
|
18
|
+
throw new Error("Path contains null bytes");
|
|
19
|
+
}
|
|
20
|
+
const normalizedBase = this.workingDir.endsWith("/") ? this.workingDir : this.workingDir + "/";
|
|
21
|
+
if (p.startsWith("/")) {
|
|
22
|
+
const normalized = path.normalize(p);
|
|
23
|
+
if (normalized !== this.workingDir && !normalized.startsWith(normalizedBase)) {
|
|
24
|
+
throw new Error(`Absolute path "${p}" is outside working directory "${this.workingDir}"`);
|
|
25
|
+
}
|
|
26
|
+
return normalized;
|
|
27
|
+
}
|
|
28
|
+
const resolved = path.resolve(this.workingDir, p);
|
|
29
|
+
if (resolved !== this.workingDir && !resolved.startsWith(normalizedBase)) {
|
|
30
|
+
throw new Error(`Path "${p}" escapes working directory "${this.workingDir}"`);
|
|
31
|
+
}
|
|
32
|
+
return resolved;
|
|
33
|
+
}
|
|
34
|
+
async exec(cmd) {
|
|
35
|
+
const execInstance = await this.container.exec({
|
|
36
|
+
Cmd: cmd,
|
|
37
|
+
AttachStdout: true,
|
|
38
|
+
AttachStderr: true,
|
|
39
|
+
Tty: false
|
|
40
|
+
});
|
|
41
|
+
const stream = await execInstance.start({ hijack: true, stdin: false });
|
|
42
|
+
const result = await collectExecStream(stream);
|
|
43
|
+
const inspection = await execInstance.inspect();
|
|
44
|
+
return { exitCode: inspection.ExitCode, ...result };
|
|
45
|
+
}
|
|
46
|
+
async readFile(path2, _opts) {
|
|
47
|
+
const resolved = this.resolvePath(path2);
|
|
48
|
+
const { exitCode, stdout, stderr } = await this.exec([
|
|
49
|
+
"cat",
|
|
50
|
+
resolved
|
|
51
|
+
]);
|
|
52
|
+
if (exitCode !== 0) {
|
|
53
|
+
throw new Error(`DockerFs readFile failed: ${stderr.trim() || `exit code ${exitCode}`}`);
|
|
54
|
+
}
|
|
55
|
+
return stdout;
|
|
56
|
+
}
|
|
57
|
+
async readFileBytes(path2, maxBytes) {
|
|
58
|
+
const resolved = this.resolvePath(path2);
|
|
59
|
+
const cmd = maxBytes !== void 0 ? ["head", "-c", String(maxBytes), resolved] : ["cat", resolved];
|
|
60
|
+
const { exitCode, stdout, stderr } = await this.exec([
|
|
61
|
+
"bash",
|
|
62
|
+
"-c",
|
|
63
|
+
`${cmd.map(shellEscape).join(" ")} | base64`
|
|
64
|
+
]);
|
|
65
|
+
if (exitCode !== 0) {
|
|
66
|
+
throw new Error(`DockerFs readFileBytes failed: ${stderr.trim() || `exit code ${exitCode}`}`);
|
|
67
|
+
}
|
|
68
|
+
return Buffer.from(stdout.trim(), "base64");
|
|
69
|
+
}
|
|
70
|
+
async writeFile(path2, content) {
|
|
71
|
+
const resolved = this.resolvePath(path2);
|
|
72
|
+
const dir = resolved.substring(0, resolved.lastIndexOf("/"));
|
|
73
|
+
if (dir) {
|
|
74
|
+
await this.exec(["mkdir", "-p", dir]);
|
|
75
|
+
}
|
|
76
|
+
const encoded = Buffer.from(content, "utf-8").toString("base64");
|
|
77
|
+
const MAX_INLINE_LEN = 1e5;
|
|
78
|
+
if (encoded.length <= MAX_INLINE_LEN) {
|
|
79
|
+
const { exitCode, stderr } = await this.exec([
|
|
80
|
+
"bash",
|
|
81
|
+
"-c",
|
|
82
|
+
`echo ${shellEscape(encoded)} | base64 -d > ${shellEscape(resolved)}`
|
|
83
|
+
]);
|
|
84
|
+
if (exitCode !== 0) {
|
|
85
|
+
throw new Error(`DockerFs writeFile failed: ${stderr.trim()}`);
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
const execInstance = await this.container.exec({
|
|
89
|
+
Cmd: ["bash", "-c", `base64 -d > ${shellEscape(resolved)}`],
|
|
90
|
+
AttachStdout: true,
|
|
91
|
+
AttachStderr: true,
|
|
92
|
+
AttachStdin: true,
|
|
93
|
+
Tty: false
|
|
94
|
+
});
|
|
95
|
+
const stream = await execInstance.start({ hijack: true, stdin: true });
|
|
96
|
+
const writable = stream;
|
|
97
|
+
writable.write(encoded);
|
|
98
|
+
writable.end();
|
|
99
|
+
const result = await collectExecStream(stream);
|
|
100
|
+
const inspection = await execInstance.inspect();
|
|
101
|
+
if (inspection.ExitCode !== 0) {
|
|
102
|
+
throw new Error(`DockerFs writeFile failed: ${result.stderr.trim()}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async appendFile(path2, content) {
|
|
107
|
+
const resolved = this.resolvePath(path2);
|
|
108
|
+
const dir = resolved.substring(0, resolved.lastIndexOf("/"));
|
|
109
|
+
if (dir) {
|
|
110
|
+
await this.exec(["mkdir", "-p", dir]);
|
|
111
|
+
}
|
|
112
|
+
const encoded = Buffer.from(content, "utf-8").toString("base64");
|
|
113
|
+
const { exitCode, stderr } = await this.exec([
|
|
114
|
+
"bash",
|
|
115
|
+
"-c",
|
|
116
|
+
`echo ${shellEscape(encoded)} | base64 -d >> ${shellEscape(resolved)}`
|
|
117
|
+
]);
|
|
118
|
+
if (exitCode !== 0) {
|
|
119
|
+
throw new Error(`DockerFs appendFile failed: ${stderr.trim()}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async deleteFile(path2, opts) {
|
|
123
|
+
const resolved = this.resolvePath(path2);
|
|
124
|
+
const args = opts?.recursive ? ["rm", "-rf", resolved] : ["rm", "-f", resolved];
|
|
125
|
+
await this.exec(args);
|
|
126
|
+
}
|
|
127
|
+
async mkdir(path2, opts) {
|
|
128
|
+
const resolved = this.resolvePath(path2);
|
|
129
|
+
const args = opts?.recursive ? ["mkdir", "-p", resolved] : ["mkdir", resolved];
|
|
130
|
+
await this.exec(args);
|
|
131
|
+
}
|
|
132
|
+
async readdir(path2, _opts) {
|
|
133
|
+
const resolved = this.resolvePath(path2);
|
|
134
|
+
const { exitCode, stdout, stderr } = await this.exec([
|
|
135
|
+
"bash",
|
|
136
|
+
"-c",
|
|
137
|
+
`find ${shellEscape(resolved)} -maxdepth 1 -mindepth 1 -printf '%y %p\\n' 2>/dev/null`
|
|
138
|
+
]);
|
|
139
|
+
if (exitCode !== 0 && stderr.trim()) {
|
|
140
|
+
throw new Error(`DockerFs readdir failed: ${stderr.trim()}`);
|
|
141
|
+
}
|
|
142
|
+
const entries = [];
|
|
143
|
+
for (const line of stdout.trim().split("\n")) {
|
|
144
|
+
if (!line) continue;
|
|
145
|
+
const spaceIdx = line.indexOf(" ");
|
|
146
|
+
const type = line.substring(0, spaceIdx);
|
|
147
|
+
const fullPath = line.substring(spaceIdx + 1);
|
|
148
|
+
const name = fullPath.substring(fullPath.lastIndexOf("/") + 1);
|
|
149
|
+
entries.push({
|
|
150
|
+
name,
|
|
151
|
+
path: fullPath,
|
|
152
|
+
isDirectory: type === "d",
|
|
153
|
+
isFile: type === "f"
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return entries;
|
|
157
|
+
}
|
|
158
|
+
async exists(path2) {
|
|
159
|
+
const resolved = this.resolvePath(path2);
|
|
160
|
+
const { exitCode } = await this.exec(["test", "-e", resolved]);
|
|
161
|
+
return exitCode === 0;
|
|
162
|
+
}
|
|
163
|
+
async stat(path2) {
|
|
164
|
+
const resolved = this.resolvePath(path2);
|
|
165
|
+
const { exitCode, stdout, stderr } = await this.exec([
|
|
166
|
+
"stat",
|
|
167
|
+
"-c",
|
|
168
|
+
"%s %F %W %Y",
|
|
169
|
+
resolved
|
|
170
|
+
]);
|
|
171
|
+
if (exitCode !== 0) {
|
|
172
|
+
throw new Error(`DockerFs stat failed: ${stderr.trim() || `exit code ${exitCode}`}`);
|
|
173
|
+
}
|
|
174
|
+
const parts = stdout.trim().split(" ");
|
|
175
|
+
const size = parseInt(parts[0], 10);
|
|
176
|
+
const fileType = parts[1];
|
|
177
|
+
const createdEpoch = parseInt(parts[2], 10);
|
|
178
|
+
const modifiedEpoch = parseInt(parts[3], 10);
|
|
179
|
+
return {
|
|
180
|
+
size,
|
|
181
|
+
isDirectory: fileType === "directory",
|
|
182
|
+
isFile: fileType.startsWith("regular"),
|
|
183
|
+
createdAt: createdEpoch > 0 ? new Date(createdEpoch * 1e3) : void 0,
|
|
184
|
+
modifiedAt: modifiedEpoch > 0 ? new Date(modifiedEpoch * 1e3) : void 0
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
function shellEscape(s) {
|
|
189
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
190
|
+
}
|
|
191
|
+
function collectExecStream(stream) {
|
|
192
|
+
return new Promise((resolve2, reject) => {
|
|
193
|
+
const stdoutBufs = [];
|
|
194
|
+
const stderrBufs = [];
|
|
195
|
+
let pending = Buffer.alloc(0);
|
|
196
|
+
stream.on("data", (chunk) => {
|
|
197
|
+
let buf = pending.length > 0 ? Buffer.concat([pending, chunk]) : chunk;
|
|
198
|
+
let offset = 0;
|
|
199
|
+
while (offset + 8 <= buf.length) {
|
|
200
|
+
const payloadLen = buf.readUInt32BE(offset + 4);
|
|
201
|
+
if (offset + 8 + payloadLen > buf.length) break;
|
|
202
|
+
const streamType = buf[offset];
|
|
203
|
+
const payload = buf.subarray(offset + 8, offset + 8 + payloadLen);
|
|
204
|
+
if (streamType === 2) {
|
|
205
|
+
stderrBufs.push(payload);
|
|
206
|
+
} else {
|
|
207
|
+
stdoutBufs.push(payload);
|
|
208
|
+
}
|
|
209
|
+
offset += 8 + payloadLen;
|
|
210
|
+
}
|
|
211
|
+
pending = offset < buf.length ? buf.subarray(offset) : Buffer.alloc(0);
|
|
212
|
+
});
|
|
213
|
+
stream.on("end", () => {
|
|
214
|
+
resolve2({
|
|
215
|
+
stdout: Buffer.concat(stdoutBufs).toString("utf-8"),
|
|
216
|
+
stderr: Buffer.concat(stderrBufs).toString("utf-8")
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
stream.on("error", (err) => reject(err));
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/virtual/docker-computer.ts
|
|
224
|
+
var DockerComputer = class {
|
|
225
|
+
container;
|
|
226
|
+
defaultCwd;
|
|
227
|
+
defaultTimeout;
|
|
228
|
+
constructor(opts) {
|
|
229
|
+
this.container = opts.container;
|
|
230
|
+
this.defaultCwd = opts.defaultCwd ?? "/";
|
|
231
|
+
this.defaultTimeout = opts.defaultTimeout ?? 3e4;
|
|
232
|
+
}
|
|
233
|
+
async executeCommand(command, opts) {
|
|
234
|
+
const cwd = opts?.cwd ?? this.defaultCwd;
|
|
235
|
+
const timeout = opts?.timeout ?? this.defaultTimeout;
|
|
236
|
+
const execOpts = {
|
|
237
|
+
Cmd: ["bash", "-c", `cd ${shellEscape2(cwd)} && ${command}`],
|
|
238
|
+
AttachStdout: true,
|
|
239
|
+
AttachStderr: true,
|
|
240
|
+
Tty: false
|
|
241
|
+
};
|
|
242
|
+
if (opts?.env) {
|
|
243
|
+
execOpts.Env = Object.entries(opts.env).map(
|
|
244
|
+
([k, v]) => `${k}=${v}`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
const exec = await this.container.exec(execOpts);
|
|
248
|
+
const stream = await exec.start({ hijack: true, stdin: false });
|
|
249
|
+
const { stdout, stderr } = await collectStream(stream, timeout);
|
|
250
|
+
const inspection = await exec.inspect();
|
|
251
|
+
return {
|
|
252
|
+
exitCode: inspection.ExitCode,
|
|
253
|
+
stdout,
|
|
254
|
+
stderr
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
function shellEscape2(s) {
|
|
259
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
260
|
+
}
|
|
261
|
+
function collectStream(stream, timeout) {
|
|
262
|
+
return new Promise((resolve2, reject) => {
|
|
263
|
+
const stdoutBufs = [];
|
|
264
|
+
const stderrBufs = [];
|
|
265
|
+
let pending = Buffer.alloc(0);
|
|
266
|
+
const timer = setTimeout(() => {
|
|
267
|
+
stream.destroy?.();
|
|
268
|
+
resolve2({
|
|
269
|
+
stdout: Buffer.concat(stdoutBufs).toString("utf-8"),
|
|
270
|
+
stderr: Buffer.concat(stderrBufs).toString("utf-8") + "\n[timeout after " + timeout + "ms]"
|
|
271
|
+
});
|
|
272
|
+
}, timeout);
|
|
273
|
+
stream.on("data", (chunk) => {
|
|
274
|
+
let buf = pending.length > 0 ? Buffer.concat([pending, chunk]) : chunk;
|
|
275
|
+
let offset = 0;
|
|
276
|
+
while (offset + 8 <= buf.length) {
|
|
277
|
+
const payloadLen = buf.readUInt32BE(offset + 4);
|
|
278
|
+
if (offset + 8 + payloadLen > buf.length) break;
|
|
279
|
+
const streamType = buf[offset];
|
|
280
|
+
const payload = buf.subarray(offset + 8, offset + 8 + payloadLen);
|
|
281
|
+
if (streamType === 2) {
|
|
282
|
+
stderrBufs.push(payload);
|
|
283
|
+
} else {
|
|
284
|
+
stdoutBufs.push(payload);
|
|
285
|
+
}
|
|
286
|
+
offset += 8 + payloadLen;
|
|
287
|
+
}
|
|
288
|
+
pending = offset < buf.length ? buf.subarray(offset) : Buffer.alloc(0);
|
|
289
|
+
});
|
|
290
|
+
stream.on("end", () => {
|
|
291
|
+
clearTimeout(timer);
|
|
292
|
+
resolve2({
|
|
293
|
+
stdout: Buffer.concat(stdoutBufs).toString("utf-8"),
|
|
294
|
+
stderr: Buffer.concat(stderrBufs).toString("utf-8")
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
stream.on("error", (err) => {
|
|
298
|
+
clearTimeout(timer);
|
|
299
|
+
reject(err);
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// src/virtual/docker-sandbox.ts
|
|
305
|
+
function DockerSandbox(opts) {
|
|
306
|
+
if (opts.container) {
|
|
307
|
+
const c = opts.container;
|
|
308
|
+
return {
|
|
309
|
+
fs: new DockerFs({ container: c, workingDir: opts.cwd }),
|
|
310
|
+
computer: new DockerComputer({
|
|
311
|
+
container: c,
|
|
312
|
+
defaultCwd: opts.cwd,
|
|
313
|
+
defaultTimeout: opts.defaultTimeout
|
|
314
|
+
}),
|
|
315
|
+
sandboxId: () => c.id
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
if (!opts.image) {
|
|
319
|
+
throw new Error("DockerSandbox requires either `container` or `image`");
|
|
320
|
+
}
|
|
321
|
+
const fsProxy = createFsProxy();
|
|
322
|
+
const computerProxy = createComputerProxy();
|
|
323
|
+
let containerId;
|
|
324
|
+
let containerRef;
|
|
325
|
+
let autoCreated = false;
|
|
326
|
+
let initPromise = null;
|
|
327
|
+
async function doInit(reconnectId) {
|
|
328
|
+
const Docker = (await import("dockerode")).default;
|
|
329
|
+
const docker = new Docker();
|
|
330
|
+
let container;
|
|
331
|
+
if (reconnectId) {
|
|
332
|
+
container = docker.getContainer(reconnectId);
|
|
333
|
+
try {
|
|
334
|
+
await container.inspect();
|
|
335
|
+
} catch {
|
|
336
|
+
container = await docker.createContainer({
|
|
337
|
+
Image: opts.image,
|
|
338
|
+
Cmd: opts.cmd ?? ["sleep", "infinity"],
|
|
339
|
+
Env: opts.env,
|
|
340
|
+
Tty: false,
|
|
341
|
+
...opts.dockerOptions
|
|
342
|
+
});
|
|
343
|
+
await container.start();
|
|
344
|
+
autoCreated = true;
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
container = await docker.createContainer({
|
|
348
|
+
Image: opts.image,
|
|
349
|
+
Cmd: opts.cmd ?? ["sleep", "infinity"],
|
|
350
|
+
Env: opts.env,
|
|
351
|
+
Tty: false,
|
|
352
|
+
...opts.dockerOptions
|
|
353
|
+
});
|
|
354
|
+
await container.start();
|
|
355
|
+
autoCreated = true;
|
|
356
|
+
}
|
|
357
|
+
containerRef = container;
|
|
358
|
+
containerId = container.id;
|
|
359
|
+
fsProxy.setTarget(new DockerFs({ container, workingDir: opts.cwd }));
|
|
360
|
+
computerProxy.setTarget(new DockerComputer({
|
|
361
|
+
container,
|
|
362
|
+
defaultCwd: opts.cwd,
|
|
363
|
+
defaultTimeout: opts.defaultTimeout
|
|
364
|
+
}));
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
fs: fsProxy,
|
|
368
|
+
computer: computerProxy,
|
|
369
|
+
sandboxId: () => containerId,
|
|
370
|
+
init(sandboxId) {
|
|
371
|
+
if (!initPromise) {
|
|
372
|
+
initPromise = doInit(sandboxId).catch((err) => {
|
|
373
|
+
initPromise = null;
|
|
374
|
+
throw err;
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
return initPromise;
|
|
378
|
+
},
|
|
379
|
+
async dispose() {
|
|
380
|
+
if (initPromise) {
|
|
381
|
+
await initPromise.catch(() => {
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
if (!autoCreated || !containerRef) return;
|
|
385
|
+
try {
|
|
386
|
+
await containerRef.stop();
|
|
387
|
+
} catch {
|
|
388
|
+
}
|
|
389
|
+
try {
|
|
390
|
+
await containerRef.remove();
|
|
391
|
+
} catch {
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
export {
|
|
397
|
+
DockerComputer,
|
|
398
|
+
DockerFs,
|
|
399
|
+
DockerSandbox
|
|
400
|
+
};
|
|
401
|
+
//# sourceMappingURL=docker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/virtual/docker-fs.ts","../src/virtual/docker-computer.ts","../src/virtual/docker-sandbox.ts"],"sourcesContent":["import * as path from \"node:path\";\nimport type { VirtualFs, FileEntry, FileStat, ReadOptions } from \"./fs.js\";\nimport type { DockerContainer } from \"./docker-computer.js\";\n\nexport interface DockerFsOptions {\n /** A dockerode Container instance for the target container. */\n container: DockerContainer;\n /** Working directory for relative path resolution (default: /). */\n workingDir?: string;\n}\n\n/**\n * VirtualFs backed by file operations inside a Docker container.\n *\n * Uses `container.exec()` to run filesystem commands (cat, tee, rm, mkdir,\n * stat, etc.) inside the container. File writes use exec + tee to avoid\n * tar archive overhead for text content.\n *\n * Requires `dockerode` as an optional peer dependency.\n * The user is responsible for container lifecycle.\n */\nexport class DockerFs implements VirtualFs {\n private container: DockerContainer;\n private workingDir: string;\n\n constructor(opts: DockerFsOptions) {\n this.container = opts.container;\n this.workingDir = opts.workingDir ?? \"/\";\n }\n\n private resolvePath(p: string): string {\n if (p.includes(\"\\0\")) {\n throw new Error(\"Path contains null bytes\");\n }\n const normalizedBase = this.workingDir.endsWith(\"/\") ? this.workingDir : this.workingDir + \"/\";\n if (p.startsWith(\"/\")) {\n const normalized = path.normalize(p);\n if (normalized !== this.workingDir && !normalized.startsWith(normalizedBase)) {\n throw new Error(`Absolute path \"${p}\" is outside working directory \"${this.workingDir}\"`);\n }\n return normalized;\n }\n const resolved = path.resolve(this.workingDir, p);\n if (resolved !== this.workingDir && !resolved.startsWith(normalizedBase)) {\n throw new Error(`Path \"${p}\" escapes working directory \"${this.workingDir}\"`);\n }\n return resolved;\n }\n\n private async exec(\n cmd: string[],\n ): Promise<{ exitCode: number; stdout: string; stderr: string }> {\n const execInstance = await this.container.exec({\n Cmd: cmd,\n AttachStdout: true,\n AttachStderr: true,\n Tty: false,\n });\n const stream = await execInstance.start({ hijack: true, stdin: false });\n const result = await collectExecStream(stream);\n const inspection = await execInstance.inspect();\n return { exitCode: inspection.ExitCode, ...result };\n }\n\n async readFile(path: string, _opts?: ReadOptions): Promise<string> {\n const resolved = this.resolvePath(path);\n const { exitCode, stdout, stderr } = await this.exec([\n \"cat\",\n resolved,\n ]);\n if (exitCode !== 0) {\n throw new Error(`DockerFs readFile failed: ${stderr.trim() || `exit code ${exitCode}`}`);\n }\n return stdout;\n }\n\n async readFileBytes(path: string, maxBytes?: number): Promise<Buffer> {\n const resolved = this.resolvePath(path);\n const cmd = maxBytes !== undefined\n ? [\"head\", \"-c\", String(maxBytes), resolved]\n : [\"cat\", resolved];\n const { exitCode, stdout, stderr } = await this.exec([\n \"bash\", \"-c\",\n `${cmd.map(shellEscape).join(\" \")} | base64`,\n ]);\n if (exitCode !== 0) {\n throw new Error(`DockerFs readFileBytes failed: ${stderr.trim() || `exit code ${exitCode}`}`);\n }\n return Buffer.from(stdout.trim(), \"base64\");\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n const resolved = this.resolvePath(path);\n const dir = resolved.substring(0, resolved.lastIndexOf(\"/\"));\n if (dir) {\n await this.exec([\"mkdir\", \"-p\", dir]);\n }\n\n const encoded = Buffer.from(content, \"utf-8\").toString(\"base64\");\n\n const MAX_INLINE_LEN = 100_000;\n if (encoded.length <= MAX_INLINE_LEN) {\n const { exitCode, stderr } = await this.exec([\n \"bash\",\n \"-c\",\n `echo ${shellEscape(encoded)} | base64 -d > ${shellEscape(resolved)}`,\n ]);\n if (exitCode !== 0) {\n throw new Error(`DockerFs writeFile failed: ${stderr.trim()}`);\n }\n } else {\n const execInstance = await this.container.exec({\n Cmd: [\"bash\", \"-c\", `base64 -d > ${shellEscape(resolved)}`],\n AttachStdout: true,\n AttachStderr: true,\n AttachStdin: true,\n Tty: false,\n });\n const stream = await execInstance.start({ hijack: true, stdin: true });\n const writable = stream as unknown as NodeJS.WritableStream;\n writable.write(encoded);\n writable.end();\n const result = await collectExecStream(stream as unknown as NodeJS.ReadableStream);\n const inspection = await execInstance.inspect();\n if (inspection.ExitCode !== 0) {\n throw new Error(`DockerFs writeFile failed: ${result.stderr.trim()}`);\n }\n }\n }\n\n async appendFile(path: string, content: string): Promise<void> {\n const resolved = this.resolvePath(path);\n const dir = resolved.substring(0, resolved.lastIndexOf(\"/\"));\n if (dir) {\n await this.exec([\"mkdir\", \"-p\", dir]);\n }\n const encoded = Buffer.from(content, \"utf-8\").toString(\"base64\");\n const { exitCode, stderr } = await this.exec([\n \"bash\",\n \"-c\",\n `echo ${shellEscape(encoded)} | base64 -d >> ${shellEscape(resolved)}`,\n ]);\n if (exitCode !== 0) {\n throw new Error(`DockerFs appendFile failed: ${stderr.trim()}`);\n }\n }\n\n async deleteFile(\n path: string,\n opts?: { recursive?: boolean },\n ): Promise<void> {\n const resolved = this.resolvePath(path);\n const args = opts?.recursive ? [\"rm\", \"-rf\", resolved] : [\"rm\", \"-f\", resolved];\n await this.exec(args);\n }\n\n async mkdir(path: string, opts?: { recursive?: boolean }): Promise<void> {\n const resolved = this.resolvePath(path);\n const args = opts?.recursive\n ? [\"mkdir\", \"-p\", resolved]\n : [\"mkdir\", resolved];\n await this.exec(args);\n }\n\n async readdir(\n path: string,\n _opts?: { recursive?: boolean },\n ): Promise<FileEntry[]> {\n const resolved = this.resolvePath(path);\n const { exitCode, stdout, stderr } = await this.exec([\n \"bash\",\n \"-c\",\n `find ${shellEscape(resolved)} -maxdepth 1 -mindepth 1 -printf '%y %p\\\\n' 2>/dev/null`,\n ]);\n if (exitCode !== 0 && stderr.trim()) {\n throw new Error(`DockerFs readdir failed: ${stderr.trim()}`);\n }\n\n const entries: FileEntry[] = [];\n for (const line of stdout.trim().split(\"\\n\")) {\n if (!line) continue;\n const spaceIdx = line.indexOf(\" \");\n const type = line.substring(0, spaceIdx);\n const fullPath = line.substring(spaceIdx + 1);\n const name = fullPath.substring(fullPath.lastIndexOf(\"/\") + 1);\n entries.push({\n name,\n path: fullPath,\n isDirectory: type === \"d\",\n isFile: type === \"f\",\n });\n }\n return entries;\n }\n\n async exists(path: string): Promise<boolean> {\n const resolved = this.resolvePath(path);\n const { exitCode } = await this.exec([\"test\", \"-e\", resolved]);\n return exitCode === 0;\n }\n\n async stat(path: string): Promise<FileStat> {\n const resolved = this.resolvePath(path);\n const { exitCode, stdout, stderr } = await this.exec([\n \"stat\",\n \"-c\",\n \"%s\\t%F\\t%W\\t%Y\",\n resolved,\n ]);\n if (exitCode !== 0) {\n throw new Error(`DockerFs stat failed: ${stderr.trim() || `exit code ${exitCode}`}`);\n }\n\n const parts = stdout.trim().split(\"\\t\");\n const size = parseInt(parts[0], 10);\n const fileType = parts[1];\n const createdEpoch = parseInt(parts[2], 10);\n const modifiedEpoch = parseInt(parts[3], 10);\n\n return {\n size,\n isDirectory: fileType === \"directory\",\n isFile: fileType.startsWith(\"regular\"),\n createdAt: createdEpoch > 0 ? new Date(createdEpoch * 1000) : undefined,\n modifiedAt: modifiedEpoch > 0 ? new Date(modifiedEpoch * 1000) : undefined,\n };\n }\n}\n\nfunction shellEscape(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nfunction collectExecStream(\n stream: NodeJS.ReadableStream,\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n const stdoutBufs: Buffer[] = [];\n const stderrBufs: Buffer[] = [];\n let pending: Buffer = Buffer.alloc(0);\n\n stream.on(\"data\", (chunk: Buffer) => {\n let buf = pending.length > 0 ? Buffer.concat([pending, chunk]) : chunk;\n let offset = 0;\n while (offset + 8 <= buf.length) {\n const payloadLen = buf.readUInt32BE(offset + 4);\n if (offset + 8 + payloadLen > buf.length) break;\n const streamType = buf[offset];\n const payload = buf.subarray(offset + 8, offset + 8 + payloadLen);\n if (streamType === 2) {\n stderrBufs.push(payload);\n } else {\n stdoutBufs.push(payload);\n }\n offset += 8 + payloadLen;\n }\n pending = offset < buf.length ? buf.subarray(offset) : Buffer.alloc(0);\n });\n\n stream.on(\"end\", () => {\n resolve({\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr: Buffer.concat(stderrBufs).toString(\"utf-8\"),\n });\n });\n\n stream.on(\"error\", (err: Error) => reject(err));\n });\n}\n","import type { VirtualComputer, ExecOptions, CommandResult } from \"./computer.js\";\n\n/**\n * Minimal subset of the dockerode Container interface used by DockerComputer.\n * Avoids a hard import of dockerode at the module level.\n */\nexport interface DockerContainer {\n exec(\n options: Record<string, unknown>,\n ): Promise<{ start(opts?: Record<string, unknown>): Promise<NodeJS.ReadableStream>; inspect(): Promise<{ ExitCode: number }> }>;\n}\n\nexport interface DockerComputerOptions {\n /** A dockerode Container instance for the target container. */\n container: DockerContainer;\n /** Default working directory for commands (default: /). */\n defaultCwd?: string;\n /** Default timeout in ms for commands (default: 30000). */\n defaultTimeout?: number;\n}\n\n/**\n * VirtualComputer backed by command execution inside a Docker container.\n *\n * Requires `dockerode` as an optional peer dependency.\n * The user is responsible for container lifecycle (create, start, stop).\n */\nexport class DockerComputer implements VirtualComputer {\n private container: DockerContainer;\n private defaultCwd: string;\n private defaultTimeout: number;\n\n constructor(opts: DockerComputerOptions) {\n this.container = opts.container;\n this.defaultCwd = opts.defaultCwd ?? \"/\";\n this.defaultTimeout = opts.defaultTimeout ?? 30_000;\n }\n\n async executeCommand(\n command: string,\n opts?: ExecOptions,\n ): Promise<CommandResult> {\n const cwd = opts?.cwd ?? this.defaultCwd;\n const timeout = opts?.timeout ?? this.defaultTimeout;\n\n const execOpts: Record<string, unknown> = {\n Cmd: [\"bash\", \"-c\", `cd ${shellEscape(cwd)} && ${command}`],\n AttachStdout: true,\n AttachStderr: true,\n Tty: false,\n };\n if (opts?.env) {\n execOpts.Env = Object.entries(opts.env).map(\n ([k, v]) => `${k}=${v}`,\n );\n }\n\n const exec = await this.container.exec(execOpts);\n const stream = await exec.start({ hijack: true, stdin: false });\n\n const { stdout, stderr } = await collectStream(stream, timeout);\n const inspection = await exec.inspect();\n\n return {\n exitCode: inspection.ExitCode,\n stdout,\n stderr,\n };\n }\n}\n\nfunction shellEscape(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nfunction collectStream(\n stream: NodeJS.ReadableStream,\n timeout: number,\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n const stdoutBufs: Buffer[] = [];\n const stderrBufs: Buffer[] = [];\n let pending: Buffer = Buffer.alloc(0);\n\n const timer = setTimeout(() => {\n (stream as unknown as { destroy?: () => void }).destroy?.();\n resolve({\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr: Buffer.concat(stderrBufs).toString(\"utf-8\") +\n \"\\n[timeout after \" + timeout + \"ms]\",\n });\n }, timeout);\n\n stream.on(\"data\", (chunk: Buffer) => {\n let buf = pending.length > 0 ? Buffer.concat([pending, chunk]) : chunk;\n let offset = 0;\n while (offset + 8 <= buf.length) {\n const payloadLen = buf.readUInt32BE(offset + 4);\n if (offset + 8 + payloadLen > buf.length) break;\n const streamType = buf[offset];\n const payload = buf.subarray(offset + 8, offset + 8 + payloadLen);\n if (streamType === 2) {\n stderrBufs.push(payload);\n } else {\n stdoutBufs.push(payload);\n }\n offset += 8 + payloadLen;\n }\n pending = offset < buf.length ? buf.subarray(offset) : Buffer.alloc(0);\n });\n\n stream.on(\"end\", () => {\n clearTimeout(timer);\n resolve({\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr: Buffer.concat(stderrBufs).toString(\"utf-8\"),\n });\n });\n\n stream.on(\"error\", (err: Error) => {\n clearTimeout(timer);\n reject(err);\n });\n });\n}\n","import type { Sandbox } from \"./sandbox.js\";\nimport { DockerFs } from \"./docker-fs.js\";\nimport { DockerComputer, type DockerContainer } from \"./docker-computer.js\";\nimport { createFsProxy, createComputerProxy } from \"./proxy.js\";\n\nexport interface DockerSandboxOptions {\n /**\n * A pre-existing dockerode Container instance. When provided the sandbox\n * attaches to this container directly — no auto-creation occurs and\n * `dispose()` will **not** stop or remove it.\n *\n * When omitted, a new container is created from `image` on the first\n * `init()` call via a dynamic import of `dockerode`. The auto-created\n * container is stopped and removed when `dispose()` is called.\n */\n container?: DockerContainer;\n /**\n * Docker image to use for auto-creation (e.g. `\"ubuntu:22.04\"`).\n * Required when `container` is omitted; ignored when `container` is provided.\n */\n image?: string;\n /** Command to run in the auto-created container (default: `[\"sleep\", \"infinity\"]`). */\n cmd?: string[];\n /** Environment variables for the auto-created container. */\n env?: string[];\n /** Extra options passed to dockerode `createContainer`. */\n dockerOptions?: Record<string, unknown>;\n /** Working directory inside the container. */\n cwd?: string;\n /** Default timeout (ms) for shell commands. */\n defaultTimeout?: number;\n}\n\n/**\n * Create a `Sandbox` backed by a Docker container.\n * Requires `dockerode` as an optional peer dependency.\n *\n * **Auto-creation:** When `container` is omitted and `image` is provided,\n * the container is created and started lazily on the first `init()` call.\n * The container ID is available through `sandboxId()` for session\n * persistence. Pass the stored ID back through `init(storedId)` to\n * reattach to an existing container on resume.\n *\n * **Explicit container:** When `container` is provided, `init()` binds\n * it immediately. `dispose()` is a no-op — the caller owns the\n * container's lifecycle.\n *\n * @example\n * ```ts\n * // Auto-create from image\n * const sandbox = DockerSandbox({ image: \"ubuntu:22.04\", cwd: \"/workspace\" });\n *\n * // Explicit container (lifecycle managed externally)\n * const sandbox = DockerSandbox({ container: myDockerodeContainer });\n * ```\n */\nexport function DockerSandbox(opts: DockerSandboxOptions): Sandbox {\n if (opts.container) {\n const c = opts.container;\n return {\n fs: new DockerFs({ container: c, workingDir: opts.cwd }),\n computer: new DockerComputer({\n container: c,\n defaultCwd: opts.cwd,\n defaultTimeout: opts.defaultTimeout,\n }),\n sandboxId: () => (c as any).id as string | undefined,\n };\n }\n\n if (!opts.image) {\n throw new Error(\"DockerSandbox requires either `container` or `image`\");\n }\n\n const fsProxy = createFsProxy();\n const computerProxy = createComputerProxy();\n let containerId: string | undefined;\n let containerRef: any;\n let autoCreated = false;\n let initPromise: Promise<void> | null = null;\n\n async function doInit(reconnectId?: string): Promise<void> {\n const Docker = (await import(\"dockerode\")).default;\n const docker = new Docker();\n\n let container: any;\n if (reconnectId) {\n container = docker.getContainer(reconnectId);\n try {\n await container.inspect();\n } catch {\n container = await docker.createContainer({\n Image: opts.image!,\n Cmd: opts.cmd ?? [\"sleep\", \"infinity\"],\n Env: opts.env,\n Tty: false,\n ...opts.dockerOptions,\n });\n await container.start();\n autoCreated = true;\n }\n } else {\n container = await docker.createContainer({\n Image: opts.image!,\n Cmd: opts.cmd ?? [\"sleep\", \"infinity\"],\n Env: opts.env,\n Tty: false,\n ...opts.dockerOptions,\n });\n await container.start();\n autoCreated = true;\n }\n\n containerRef = container;\n containerId = container.id;\n fsProxy.setTarget(new DockerFs({ container, workingDir: opts.cwd }));\n computerProxy.setTarget(new DockerComputer({\n container,\n defaultCwd: opts.cwd,\n defaultTimeout: opts.defaultTimeout,\n }));\n }\n\n return {\n fs: fsProxy,\n computer: computerProxy,\n sandboxId: () => containerId,\n\n init(sandboxId?: string): Promise<void> {\n if (!initPromise) {\n initPromise = doInit(sandboxId).catch((err) => {\n initPromise = null;\n throw err;\n });\n }\n return initPromise;\n },\n\n async dispose(): Promise<void> {\n if (initPromise) {\n await initPromise.catch(() => {});\n }\n if (!autoCreated || !containerRef) return;\n try { await containerRef.stop(); } catch { /* may already be stopped */ }\n try { await containerRef.remove(); } catch { /* best-effort */ }\n },\n };\n}\n"],"mappings":"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","names":["path","resolve","shellEscape","resolve"]}
|
package/dist/e2b.d.ts
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { S as Sandbox } from './sandbox-9qeMTNrD.js';
|
|
2
|
+
import { V as VirtualComputer, E as ExecOptions, C as CommandResult, a as VirtualFs, R as ReadOptions, F as FileEntry, b as FileStat } from './computer-BPdxSo6X.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Minimal subset of the E2B Sandbox interface used by E2BComputer and E2BFs.
|
|
6
|
+
* Avoids a hard import of `e2b` at the module level.
|
|
7
|
+
*/
|
|
8
|
+
interface E2BSandboxInstance {
|
|
9
|
+
commands: {
|
|
10
|
+
run(cmd: string, opts?: {
|
|
11
|
+
cwd?: string;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
envs?: Record<string, string>;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
exitCode: number;
|
|
16
|
+
stdout: string;
|
|
17
|
+
stderr: string;
|
|
18
|
+
}>;
|
|
19
|
+
};
|
|
20
|
+
files: {
|
|
21
|
+
read(path: string, opts?: {
|
|
22
|
+
format?: string;
|
|
23
|
+
}): Promise<string>;
|
|
24
|
+
write(path: string, data: string): Promise<unknown>;
|
|
25
|
+
remove(path: string): Promise<void>;
|
|
26
|
+
makeDir(path: string): Promise<unknown>;
|
|
27
|
+
list(path: string): Promise<Array<{
|
|
28
|
+
name: string;
|
|
29
|
+
path: string;
|
|
30
|
+
type?: string;
|
|
31
|
+
size?: number;
|
|
32
|
+
modifiedTime?: Date;
|
|
33
|
+
}>>;
|
|
34
|
+
exists(path: string): Promise<boolean>;
|
|
35
|
+
getInfo(path: string): Promise<{
|
|
36
|
+
name: string;
|
|
37
|
+
path: string;
|
|
38
|
+
type?: string;
|
|
39
|
+
size?: number;
|
|
40
|
+
modifiedTime?: Date;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
interface E2BComputerOptions {
|
|
45
|
+
/** An E2B Sandbox instance created via `Sandbox.create()`. */
|
|
46
|
+
sandbox: E2BSandboxInstance;
|
|
47
|
+
/** Default working directory for commands. */
|
|
48
|
+
defaultCwd?: string;
|
|
49
|
+
/** Default timeout in ms for commands (default: 30000). */
|
|
50
|
+
defaultTimeout?: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* VirtualComputer backed by command execution in an E2B cloud sandbox.
|
|
54
|
+
*
|
|
55
|
+
* Requires `e2b` as an optional peer dependency.
|
|
56
|
+
* The user is responsible for sandbox lifecycle (create, close).
|
|
57
|
+
*/
|
|
58
|
+
declare class E2BComputer implements VirtualComputer {
|
|
59
|
+
private sandbox;
|
|
60
|
+
private defaultCwd;
|
|
61
|
+
private defaultTimeout;
|
|
62
|
+
constructor(opts: E2BComputerOptions);
|
|
63
|
+
executeCommand(command: string, opts?: ExecOptions): Promise<CommandResult>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface E2BSandboxOptions {
|
|
67
|
+
/**
|
|
68
|
+
* A pre-existing E2B Sandbox instance (e.g. from `Sandbox.create()`).
|
|
69
|
+
* When provided the sandbox attaches to this instance — no auto-creation
|
|
70
|
+
* occurs and `dispose()` will **not** kill it.
|
|
71
|
+
*
|
|
72
|
+
* When omitted, a new E2B sandbox is created on the first `init()` call
|
|
73
|
+
* via a dynamic import of the `e2b` package. The auto-created sandbox
|
|
74
|
+
* is killed when `dispose()` is called.
|
|
75
|
+
*/
|
|
76
|
+
sandbox?: E2BSandboxInstance;
|
|
77
|
+
/**
|
|
78
|
+
* E2B template to use for auto-creation (default: `"base"`).
|
|
79
|
+
* Only used when `sandbox` is omitted.
|
|
80
|
+
*/
|
|
81
|
+
template?: string;
|
|
82
|
+
/**
|
|
83
|
+
* E2B API key. Falls back to the `E2B_API_KEY` environment variable
|
|
84
|
+
* when omitted. Only used during auto-creation.
|
|
85
|
+
*/
|
|
86
|
+
apiKey?: string;
|
|
87
|
+
/** Timeout (ms) for the auto-created E2B sandbox (default: E2B SDK default). */
|
|
88
|
+
timeoutMs?: number;
|
|
89
|
+
/** Working directory inside the sandbox. */
|
|
90
|
+
cwd?: string;
|
|
91
|
+
/** Default timeout (ms) for shell commands. */
|
|
92
|
+
defaultTimeout?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create a `Sandbox` backed by an E2B cloud sandbox.
|
|
96
|
+
* Requires `e2b` as an optional peer dependency.
|
|
97
|
+
*
|
|
98
|
+
* **Auto-creation:** When `sandbox` is omitted the E2B sandbox is
|
|
99
|
+
* provisioned lazily on the first `init()` call via the E2B SDK.
|
|
100
|
+
* The sandbox ID is available through `sandboxId()` for session
|
|
101
|
+
* persistence. Pass the stored ID back through `init(storedId)` to
|
|
102
|
+
* reconnect to the same sandbox on resume (via `Sandbox.connect()`).
|
|
103
|
+
*
|
|
104
|
+
* **Explicit instance:** When `sandbox` is provided, `init()` binds
|
|
105
|
+
* it immediately. `dispose()` is a no-op — the caller owns the
|
|
106
|
+
* sandbox's lifecycle.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* // Auto-create — sandbox provisioned on first init()
|
|
111
|
+
* const sandbox = E2BSandbox({ template: "base" });
|
|
112
|
+
*
|
|
113
|
+
* // Explicit — attach to pre-existing instance
|
|
114
|
+
* const sandbox = E2BSandbox({ sandbox: await E2BSdk.Sandbox.create() });
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
declare function E2BSandbox(opts: E2BSandboxOptions): Sandbox;
|
|
118
|
+
|
|
119
|
+
interface E2BFsOptions {
|
|
120
|
+
/** An E2B Sandbox instance created via `Sandbox.create()`. */
|
|
121
|
+
sandbox: E2BSandboxInstance;
|
|
122
|
+
/** Working directory for relative path resolution. */
|
|
123
|
+
workingDir?: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* VirtualFs backed by the E2B cloud sandbox filesystem.
|
|
127
|
+
*
|
|
128
|
+
* Requires `e2b` as an optional peer dependency.
|
|
129
|
+
* The user is responsible for sandbox lifecycle (create, close).
|
|
130
|
+
*/
|
|
131
|
+
declare class E2BFs implements VirtualFs {
|
|
132
|
+
private sandbox;
|
|
133
|
+
private workingDir;
|
|
134
|
+
constructor(opts: E2BFsOptions);
|
|
135
|
+
private resolvePath;
|
|
136
|
+
readFile(path: string, _opts?: ReadOptions): Promise<string>;
|
|
137
|
+
readFileBytes(path: string, maxBytes?: number): Promise<Buffer>;
|
|
138
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* @warning Not atomic. Concurrent appends may lose data due to
|
|
141
|
+
* read-then-write TOCTOU. The E2B SDK does not expose an append primitive.
|
|
142
|
+
*/
|
|
143
|
+
appendFile(path: string, content: string): Promise<void>;
|
|
144
|
+
deleteFile(path: string, _opts?: {
|
|
145
|
+
recursive?: boolean;
|
|
146
|
+
}): Promise<void>;
|
|
147
|
+
mkdir(path: string, _opts?: {
|
|
148
|
+
recursive?: boolean;
|
|
149
|
+
}): Promise<void>;
|
|
150
|
+
readdir(path: string, _opts?: {
|
|
151
|
+
recursive?: boolean;
|
|
152
|
+
}): Promise<FileEntry[]>;
|
|
153
|
+
exists(path: string): Promise<boolean>;
|
|
154
|
+
stat(path: string): Promise<FileStat>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export { E2BComputer, type E2BComputerOptions, E2BFs, type E2BFsOptions, E2BSandbox, type E2BSandboxInstance, type E2BSandboxOptions };
|