@mastra/e2b 0.5.1 → 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/dist/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export { E2BProcessManager } from './sandbox/process-manager.js';
3
3
  export { createDefaultMountableTemplate, type TemplateSpec, type MountableTemplateResult } from './utils/template.js';
4
4
  export { type E2BS3MountConfig, type E2BGCSMountConfig, type E2BAzureBlobMountConfig, type E2BMountConfig, } from './sandbox/mounts/index.js';
5
5
  export { e2bSandboxProvider } from './provider.js';
6
+ export { E2BCodeModeTransport } from './code-mode/transport.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,KAAK,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AACnH,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,KAAK,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AACnH,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { SandboxProcessManager, MastraSandbox, SandboxNotReadyError, ProcessHandle } from '@mastra/core/workspace';
2
2
  import { Template, Sandbox } from 'e2b';
3
- import { createHash } from 'crypto';
3
+ import { createHash, randomBytes } from 'crypto';
4
+ import { buildProgramModule, buildRunner, FRAME_PREFIX } from '@mastra/core/tools';
5
+ import { transformSync } from 'esbuild';
4
6
 
5
7
  // src/sandbox/index.ts
6
8
  var MOUNTABLE_TEMPLATE_VERSION = "v1";
@@ -1212,7 +1214,168 @@ var e2bSandboxProvider = {
1212
1214
  },
1213
1215
  createSandbox: (config) => new E2BSandbox(config)
1214
1216
  };
1217
+ var SANDBOX_TMP = "/home/user/mastra-code-mode";
1218
+ function sanitize(id) {
1219
+ const cleaned = id.replace(/[^A-Za-z0-9_$]/g, "_");
1220
+ return /^[A-Za-z_$]/.test(cleaned) ? cleaned : `_${cleaned}`;
1221
+ }
1222
+ var E2BCodeModeTransport = class {
1223
+ async run(opts) {
1224
+ const { sandbox, program, toolIds, dispatch, timeout, abortSignal, onExternalCall, onExternalResult } = opts;
1225
+ if (!(sandbox instanceof E2BSandbox)) {
1226
+ throw new Error("E2BCodeModeTransport requires an E2BSandbox");
1227
+ }
1228
+ if (!sandbox.processes) {
1229
+ throw new Error("Sandbox has no process manager");
1230
+ }
1231
+ if (sandbox.status !== "running") {
1232
+ await sandbox.start();
1233
+ }
1234
+ const e2b = sandbox.e2b;
1235
+ const externals = toolIds.map((toolId) => ({ toolId, externalName: sanitize(toolId) }));
1236
+ const allowList = new Set(toolIds);
1237
+ const suffix = randomBytes(4).toString("hex");
1238
+ const dir = `${SANDBOX_TMP}/${suffix}`;
1239
+ const programPath = `${dir}/program-${suffix}.mjs`;
1240
+ const runnerPath = `${dir}/runner-${suffix}.mjs`;
1241
+ const programSource = transformSync(buildProgramModule(program), { loader: "ts", target: "es2022" }).code;
1242
+ const runnerSource = buildRunner({ programModule: `file://${programPath}`, externals });
1243
+ const logs = [];
1244
+ let stderr = "";
1245
+ let done;
1246
+ let stdoutBuffer = "";
1247
+ let resolveDone;
1248
+ const donePromise = new Promise((resolve) => {
1249
+ resolveDone = resolve;
1250
+ });
1251
+ const notifyCall = (tool, args) => {
1252
+ try {
1253
+ onExternalCall?.(tool, args);
1254
+ } catch {
1255
+ }
1256
+ };
1257
+ const notifyResult = (tool, durationMs, error) => {
1258
+ try {
1259
+ onExternalResult?.(tool, durationMs, error);
1260
+ } catch {
1261
+ }
1262
+ };
1263
+ try {
1264
+ await e2b.files.makeDir(dir);
1265
+ await e2b.files.write(programPath, programSource);
1266
+ await e2b.files.write(runnerPath, runnerSource);
1267
+ let handle;
1268
+ const respond = async (id, ok, result, error) => {
1269
+ await handle.sendStdin(JSON.stringify({ type: "rpc-result", id, ok, result, error }) + "\n");
1270
+ };
1271
+ const serveRpc = async (id, tool, args) => {
1272
+ const started = Date.now();
1273
+ notifyCall(tool, args);
1274
+ if (!allowList.has(tool)) {
1275
+ notifyResult(tool, Date.now() - started, new Error("not allowed"));
1276
+ await respond(id, false, void 0, {
1277
+ message: `Tool "${tool}" is not available in Code Mode`,
1278
+ name: "NotAllowedError"
1279
+ });
1280
+ return;
1281
+ }
1282
+ try {
1283
+ const result = await dispatch(tool, args);
1284
+ notifyResult(tool, Date.now() - started);
1285
+ await respond(id, true, result);
1286
+ } catch (error) {
1287
+ const err = error;
1288
+ notifyResult(tool, Date.now() - started, error instanceof Error ? error : new Error(String(error)));
1289
+ await respond(id, false, void 0, {
1290
+ message: err?.message ?? String(error),
1291
+ name: err?.name
1292
+ });
1293
+ }
1294
+ };
1295
+ const handleFrame = (frame) => {
1296
+ switch (frame.type) {
1297
+ case "log":
1298
+ logs.push(frame.message);
1299
+ return;
1300
+ case "done":
1301
+ done = frame.ok ? { success: true, result: frame.result, logs } : { success: false, error: frame.error, logs };
1302
+ resolveDone();
1303
+ return;
1304
+ case "rpc":
1305
+ void serveRpc(frame.id, frame.tool, frame.args).catch(() => {
1306
+ });
1307
+ return;
1308
+ }
1309
+ };
1310
+ handle = await sandbox.processes.spawn(`node ${runnerPath}`, {
1311
+ cwd: dir,
1312
+ abortSignal,
1313
+ // E2B failures are otherwise silent, which makes them painful to debug.
1314
+ // Capture stderr and surface it in Timeout/NoResult errors below.
1315
+ onStderr: (chunk) => {
1316
+ stderr += chunk;
1317
+ },
1318
+ onStdout: (chunk) => {
1319
+ stdoutBuffer += chunk;
1320
+ let idx;
1321
+ while ((idx = stdoutBuffer.indexOf("\n")) >= 0) {
1322
+ const line = stdoutBuffer.slice(0, idx);
1323
+ stdoutBuffer = stdoutBuffer.slice(idx + 1);
1324
+ if (!line.startsWith(FRAME_PREFIX)) continue;
1325
+ let frame;
1326
+ try {
1327
+ frame = JSON.parse(line.slice(FRAME_PREFIX.length));
1328
+ } catch {
1329
+ continue;
1330
+ }
1331
+ handleFrame(frame);
1332
+ }
1333
+ }
1334
+ });
1335
+ let timer;
1336
+ const timeoutPromise = new Promise((resolve) => {
1337
+ timer = setTimeout(() => resolve("timeout"), timeout);
1338
+ });
1339
+ const exitPromise = handle.wait().then(() => "exited");
1340
+ const outcome = await Promise.race([
1341
+ donePromise.then(() => "done"),
1342
+ exitPromise.catch(() => "exited"),
1343
+ timeoutPromise
1344
+ ]);
1345
+ if (timer) clearTimeout(timer);
1346
+ if (outcome === "timeout") {
1347
+ await handle.kill().catch(() => {
1348
+ });
1349
+ return {
1350
+ success: false,
1351
+ logs,
1352
+ error: {
1353
+ message: `Code Mode execution timed out after ${timeout}ms${stderr ? `
1354
+ stderr: ${stderr}` : ""}`,
1355
+ name: "TimeoutError"
1356
+ }
1357
+ };
1358
+ }
1359
+ if (!done) {
1360
+ await exitPromise.catch(() => {
1361
+ });
1362
+ }
1363
+ return done ?? {
1364
+ success: false,
1365
+ logs,
1366
+ error: {
1367
+ message: `Program exited without returning a result${stderr ? `
1368
+ stderr: ${stderr}` : ""}`,
1369
+ name: "NoResultError"
1370
+ }
1371
+ };
1372
+ } finally {
1373
+ await e2b.files.remove(dir).catch(() => {
1374
+ });
1375
+ }
1376
+ }
1377
+ };
1215
1378
 
1216
- export { E2BProcessManager, E2BSandbox, createDefaultMountableTemplate, e2bSandboxProvider };
1379
+ export { E2BCodeModeTransport, E2BProcessManager, E2BSandbox, createDefaultMountableTemplate, e2bSandboxProvider };
1217
1380
  //# sourceMappingURL=index.js.map
1218
1381
  //# sourceMappingURL=index.js.map