@mastra/platform-workspace 1.3.0 → 1.4.0-alpha.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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @mastra/platform
2
2
 
3
+ ## 1.4.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added provider-selectable Platform Workspace routing through `SANDBOX_PROVIDER`, with direct E2B command execution and snapshot restore support. ([#21991](https://github.com/mastra-ai/mastra/pull/21991))
8
+
9
+ Set `SANDBOX_PROVIDER=e2b` before constructing `PlatformSandbox` or `PlatformFilesystem` to use provider-prefixed E2B routes. Set it to `railway` for provider-prefixed Railway routes, or leave it unset to preserve the legacy `/v1/projects/...` Railway API.
10
+
3
11
  ## 1.3.0
4
12
 
5
13
  ### Minor Changes
package/dist/client.d.ts CHANGED
@@ -20,12 +20,15 @@ export interface PlatformClientOptions {
20
20
  export interface PlatformRequestOptions extends RequestInit {
21
21
  query?: Record<string, string | number | boolean | undefined>;
22
22
  }
23
+ export type SandboxProvider = 'railway' | 'e2b';
23
24
  export declare function requireOption(value: string | undefined, name: string): string;
24
25
  export declare function resolvePlatformOptions(options: PlatformClientOptions): {
25
26
  accessToken: string;
26
27
  projectId: string;
27
28
  actingUserId: string | undefined;
28
29
  proxyUrl: string;
30
+ sandboxProvider: SandboxProvider;
31
+ useLegacyRoutes: boolean;
29
32
  sessionId: string | undefined;
30
33
  threadId: string | undefined;
31
34
  fetch: typeof fetch;
@@ -55,6 +58,8 @@ export declare class PlatformClient {
55
58
  readonly projectId: string;
56
59
  readonly actingUserId: string | undefined;
57
60
  readonly proxyUrl: string;
61
+ readonly sandboxProvider: SandboxProvider;
62
+ private readonly useLegacyRoutes;
58
63
  /** Advisory session correlation id — see {@link PlatformClientOptions.sessionId}. */
59
64
  readonly sessionId: string | undefined;
60
65
  /** Advisory thread correlation id — see {@link PlatformClientOptions.threadId}. */
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;CAC/D;AAWD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7E;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,qBAAqB;;;;;;;;EAUpE;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAC;CACd;AAkBD,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2HAA2H;IAC3H,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,yGAAyG;IACzG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE9B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAUzC;AAED,qBAAa,cAAc;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,qFAAqF;IACrF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;gBAEjB,OAAO,EAAE,qBAAqB;IAWpC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,QAAQ,CAAC;CA2BrF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;CAC/D;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,KAAK,CAAC;AAWhD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7E;AAUD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,qBAAqB;;;;;;;;;;EAcpE;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAC;CACd;AAkBD,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2HAA2H;IAC3H,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,yGAAyG;IACzG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE9B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAUzC;AAED,qBAAa,cAAc;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;IAC1C,qFAAqF;IACrF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;gBAEjB,OAAO,EAAE,qBAAqB;IAapC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,QAAQ,CAAC;CA4BrF"}
@@ -36,7 +36,7 @@ export interface DirectExecWebSocket {
36
36
  * (the package's minimum) and in the browser. Tests inject a fake here.
37
37
  */
38
38
  export type DirectExecWebSocketFactory = (endpoint: string, subprotocols: string[]) => DirectExecWebSocket;
39
- /** Lease payload returned by `POST /v1/projects/:projectId/sandbox/:sandboxId/exec-lease`. */
39
+ /** Lease payload returned by `POST /v1/:provider/projects/:projectId/sandbox/:sandboxId/exec-lease`. */
40
40
  export interface ExecLease {
41
41
  jwt: string;
42
42
  wsEndpoint: string;
@@ -1 +1 @@
1
- {"version":3,"file":"direct-exec.d.ts","sourceRoot":"","sources":["../src/direct-exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAeH;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,GAAG,aAAa,CAAC;IACnC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACvD,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACpE,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,mBAAmB,CAAC;AAE3G,8FAA8F;AAC9F,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,uFAAuF;AACvF,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;CAC/C;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAcD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyJpG"}
1
+ {"version":3,"file":"direct-exec.d.ts","sourceRoot":"","sources":["../src/direct-exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAeH;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,GAAG,aAAa,CAAC;IACnC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACvD,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACpE,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,mBAAmB,CAAC;AAE3G,wGAAwG;AACxG,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,uFAAuF;AACvF,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;CAC/C;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAcD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyJpG"}
@@ -0,0 +1,7 @@
1
+ import type { DirectExecOptions, DirectExecResult, ExecLease } from './direct-exec.js';
2
+ export interface E2BExecLease extends ExecLease {
3
+ sandboxId: string;
4
+ }
5
+ export type E2BExecRunner = (lease: E2BExecLease, options: DirectExecOptions) => Promise<DirectExecResult>;
6
+ export declare const execViaE2BLease: E2BExecRunner;
7
+ //# sourceMappingURL=e2b-exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e2b-exec.d.ts","sourceRoot":"","sources":["../src/e2b-exec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAIvF,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE3G,eAAO,MAAM,eAAe,EAAE,aAwD7B,CAAC"}
package/dist/index.cjs CHANGED
@@ -25,6 +25,7 @@ let buffer = require("buffer");
25
25
  let path = require("path");
26
26
  path = __toESM(path, 1);
27
27
  let _mastra_core_workspace = require("@mastra/core/workspace");
28
+ let e2b = require("e2b");
28
29
  //#region src/client.ts
29
30
  const DEFAULT_PROXY_URL = "https://workspaces.mastra.ai";
30
31
  /**
@@ -37,12 +38,20 @@ function requireOption(value, name) {
37
38
  if (!value) throw new Error(`${name} is required`);
38
39
  return value;
39
40
  }
41
+ function resolveSandboxProvider(value) {
42
+ const provider = value?.trim() || "railway";
43
+ if (provider !== "railway" && provider !== "e2b") throw new Error("SANDBOX_PROVIDER must be either \"railway\" or \"e2b\"");
44
+ return provider;
45
+ }
40
46
  function resolvePlatformOptions(options) {
47
+ const configuredSandboxProvider = process.env.SANDBOX_PROVIDER?.trim();
41
48
  return {
42
49
  accessToken: requireOption(options.accessToken ?? process.env.MASTRA_PLATFORM_ACCESS_TOKEN, "accessToken"),
43
50
  projectId: requireOption(options.projectId ?? process.env.MASTRA_PROJECT_ID, "projectId"),
44
51
  actingUserId: options.actingUserId?.trim() || void 0,
45
52
  proxyUrl: (process.env.MASTRA_WORKSPACE_PROXY_URL ?? DEFAULT_PROXY_URL).replace(/\/$/, ""),
53
+ sandboxProvider: resolveSandboxProvider(configuredSandboxProvider),
54
+ useLegacyRoutes: !configuredSandboxProvider,
46
55
  sessionId: options.sessionId,
47
56
  threadId: options.threadId,
48
57
  fetch: options.fetch ?? fetch
@@ -89,6 +98,8 @@ var PlatformClient = class {
89
98
  projectId;
90
99
  actingUserId;
91
100
  proxyUrl;
101
+ sandboxProvider;
102
+ useLegacyRoutes;
92
103
  /** Advisory session correlation id — see {@link PlatformClientOptions.sessionId}. */
93
104
  sessionId;
94
105
  /** Advisory thread correlation id — see {@link PlatformClientOptions.threadId}. */
@@ -100,12 +111,15 @@ var PlatformClient = class {
100
111
  this.projectId = resolved.projectId;
101
112
  this.actingUserId = resolved.actingUserId;
102
113
  this.proxyUrl = resolved.proxyUrl;
114
+ this.sandboxProvider = resolved.sandboxProvider;
115
+ this.useLegacyRoutes = resolved.useLegacyRoutes;
103
116
  this.sessionId = resolved.sessionId;
104
117
  this.threadId = resolved.threadId;
105
118
  this.fetch = resolved.fetch;
106
119
  }
107
120
  async request(path, options = {}) {
108
- const url = new URL(`${this.proxyUrl}/v1/projects/${encodeURIComponent(this.projectId)}${path}`);
121
+ const providerPath = this.useLegacyRoutes ? "" : `/${this.sandboxProvider}`;
122
+ const url = new URL(`${this.proxyUrl}/v1${providerPath}/projects/${encodeURIComponent(this.projectId)}${path}`);
109
123
  for (const [key, value] of Object.entries(options.query ?? {})) if (value !== void 0) url.searchParams.set(key, String(value));
110
124
  const headers = new Headers(options.headers);
111
125
  headers.set("authorization", `Bearer ${this.accessToken}`);
@@ -526,6 +540,62 @@ function execViaLease(lease, options) {
526
540
  });
527
541
  }
528
542
  //#endregion
543
+ //#region src/e2b-exec.ts
544
+ const E2B_ENVD_VERSION = "0.4.0";
545
+ const execViaE2BLease = async (lease, options) => {
546
+ const stdoutChunks = [];
547
+ const stderrChunks = [];
548
+ const onStdout = (data) => {
549
+ stdoutChunks.push(data);
550
+ options.onStdout?.(data);
551
+ };
552
+ const onStderr = (data) => {
553
+ stderrChunks.push(data);
554
+ options.onStderr?.(data);
555
+ };
556
+ try {
557
+ const result = await new e2b.Sandbox({
558
+ sandboxId: lease.sandboxId,
559
+ envdVersion: E2B_ENVD_VERSION,
560
+ envdAccessToken: lease.jwt,
561
+ sandboxUrl: lease.wsEndpoint,
562
+ validateApiKey: false
563
+ }).commands.run(options.command, {
564
+ cwd: options.cwd,
565
+ envs: options.env,
566
+ timeoutMs: options.timeoutMs,
567
+ onStdout,
568
+ onStderr
569
+ });
570
+ return {
571
+ exitCode: result.exitCode,
572
+ stdout: result.stdout,
573
+ stderr: result.stderr,
574
+ truncated: false,
575
+ timedOut: false,
576
+ opened: true
577
+ };
578
+ } catch (error) {
579
+ if (error instanceof e2b.CommandExitError) return {
580
+ exitCode: error.exitCode,
581
+ stdout: error.stdout,
582
+ stderr: error.stderr,
583
+ truncated: false,
584
+ timedOut: false,
585
+ opened: true
586
+ };
587
+ return {
588
+ exitCode: null,
589
+ stdout: stdoutChunks.join(""),
590
+ stderr: stderrChunks.join(""),
591
+ truncated: false,
592
+ timedOut: error instanceof e2b.TimeoutError,
593
+ closeReason: error instanceof Error ? error.message : String(error),
594
+ opened: true
595
+ };
596
+ }
597
+ };
598
+ //#endregion
529
599
  //#region src/private-net-exec.ts
530
600
  /**
531
601
  * Thrown by {@link execViaPrivateNetwork} when the sidecar returns a non-2xx
@@ -867,6 +937,7 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
867
937
  _instructionsOverride;
868
938
  _createdAt = null;
869
939
  _webSocketFactory;
940
+ _e2bExecRunner;
870
941
  _privateNetFetch;
871
942
  /**
872
943
  * Registry that maps `sandboxId → instanceUrl` for the private-network
@@ -964,6 +1035,7 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
964
1035
  this._timeout = options.timeout;
965
1036
  this._instructionsOverride = options.instructions;
966
1037
  this._webSocketFactory = options.webSocketFactory;
1038
+ this._e2bExecRunner = options.e2bExecRunner ?? execViaE2BLease;
967
1039
  this._privateNetFetch = options.privateNetFetch;
968
1040
  this._addressRegistry = options.addressRegistry;
969
1041
  }
@@ -984,6 +1056,7 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
984
1056
  */
985
1057
  clone(options = {}) {
986
1058
  const id = options.id ?? options.checkpointName;
1059
+ const seedCheckpointName = options.seedCheckpointName ?? (this._client.sandboxProvider === "e2b" ? options.checkpointName : void 0) ?? this._seedCheckpointName;
987
1060
  return new PlatformSandbox({
988
1061
  ...id !== void 0 && { id },
989
1062
  accessToken: this._client.accessToken,
@@ -994,13 +1067,14 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
994
1067
  fetch: this._client.fetch,
995
1068
  environmentId: this._environmentId,
996
1069
  ...options.sandboxId !== void 0 && { sandboxId: options.sandboxId },
997
- ...(options.seedCheckpointName ?? this._seedCheckpointName) !== void 0 && { seedCheckpointName: options.seedCheckpointName ?? this._seedCheckpointName },
1070
+ ...seedCheckpointName !== void 0 && { seedCheckpointName },
998
1071
  idleTimeoutMinutes: options.idleTimeoutMinutes ?? this._idleTimeoutMinutes,
999
1072
  ...this._networkIsolation !== void 0 && { networkIsolation: this._networkIsolation },
1000
1073
  env: options.env ?? this._env,
1001
1074
  ...this._timeout !== void 0 && { timeout: this._timeout },
1002
1075
  ...this._instructionsOverride !== void 0 && { instructions: this._instructionsOverride },
1003
1076
  ...this._webSocketFactory !== void 0 && { webSocketFactory: this._webSocketFactory },
1077
+ e2bExecRunner: this._e2bExecRunner,
1004
1078
  ...this._privateNetFetch !== void 0 && { privateNetFetch: this._privateNetFetch },
1005
1079
  ...this._addressRegistry !== void 0 && { addressRegistry: this._addressRegistry }
1006
1080
  });
@@ -1201,7 +1275,7 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
1201
1275
  * it. Any in-flight capture is awaited first so the preserved checkpoint
1202
1276
  * reflects the latest disk state we asked for.
1203
1277
  *
1204
- * Corresponds to `DELETE /v1/projects/:pid/sandbox/:sandboxId` on
1278
+ * Corresponds to `DELETE /v1/:provider/projects/:pid/sandbox/:sandboxId` on
1205
1279
  * workspace-proxy, which by contract does not touch the checkpoint. Use
1206
1280
  * {@link destroy} when you want the checkpoint released too.
1207
1281
  */
@@ -1222,15 +1296,15 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
1222
1296
  * transient proxy error must not leave the caller with a half-torn-down
1223
1297
  * sandbox they can't safely retry.
1224
1298
  *
1225
- * Requires the caller to have constructed with a recovery `id` (there is
1226
- * no checkpoint to delete otherwise); callers without one skip the
1227
- * checkpoint DELETE and behave identically to {@link stop}.
1299
+ * Railway requires a caller-supplied recovery `id` before it can have a
1300
+ * checkpoint to delete. E2B also permits capture with the automatic id, so
1301
+ * destroy releases that named snapshot even when no recovery id was supplied.
1228
1302
  */
1229
1303
  async destroy() {
1230
1304
  if (!this._sandboxId) return;
1231
1305
  const destroyedSandboxId = this._sandboxId;
1232
1306
  this._captureInFlight = null;
1233
- if (this._hasRecoveryKey) try {
1307
+ if (this._hasRecoveryKey || this._client.sandboxProvider === "e2b") try {
1234
1308
  await this._client.request(`/sandbox/${encodeURIComponent(destroyedSandboxId)}/checkpoint`, {
1235
1309
  method: "DELETE",
1236
1310
  headers: { "content-type": "application/json" },
@@ -1313,7 +1387,7 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
1313
1387
  * to a skip as described above.
1314
1388
  */
1315
1389
  async captureCheckpoint() {
1316
- if (!this._hasRecoveryKey) {
1390
+ if (!this._hasRecoveryKey && this._client.sandboxProvider !== "e2b") {
1317
1391
  this.logger.debug(`captureCheckpoint skipped: no recovery key configured for sandbox ${this._sandboxId ?? "(unstarted)"}`);
1318
1392
  return {
1319
1393
  status: "skipped",
@@ -1496,13 +1570,14 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
1496
1570
  }
1497
1571
  lastLease = lease;
1498
1572
  attemptsMade = attempt + 1;
1499
- const result = await execViaLease(lease, {
1573
+ const execOptions = {
1500
1574
  command: fullCommand,
1501
1575
  ...options?.cwd !== void 0 && { cwd: options.cwd },
1502
1576
  ...filteredEnv !== void 0 && { env: filteredEnv },
1503
1577
  ...effectiveTimeout != null && effectiveTimeout > 0 && { timeoutMs: effectiveTimeout },
1504
1578
  ...this._webSocketFactory && { webSocketFactory: this._webSocketFactory }
1505
- });
1579
+ };
1580
+ const result = lease.provider === "e2b" ? await this._e2bExecRunner(lease, execOptions) : await execViaLease(lease, execOptions);
1506
1581
  lastResult = result;
1507
1582
  if (result.exitCode !== null || result.timedOut) return result;
1508
1583
  }
@@ -1585,6 +1660,9 @@ var PlatformSandbox = class PlatformSandbox extends _mastra_core_workspace.Mastr
1585
1660
  const json = await (await this._client.request(`/sandbox/${encodeURIComponent(sandboxId)}/exec-lease`, { method: "POST" })).json();
1586
1661
  const expiresAtMs = json.expiresAt ? Date.parse(json.expiresAt) : null;
1587
1662
  const lease = {
1663
+ provider: json.provider,
1664
+ sandboxId: json.sandboxId,
1665
+ providerResourceId: json.providerResourceId,
1588
1666
  jwt: json.jwt,
1589
1667
  wsEndpoint: json.wsEndpoint,
1590
1668
  subprotocol: json.subprotocol,