@mastra/railway 0.2.1 → 0.3.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,45 @@
1
1
  # @mastra/railway
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added checkpoint-backed restart and reconnect support to `RailwaySandbox`. Pass `checkpointName` to save the sandbox filesystem before idle teardown and restore it when a sandbox must be recreated. ([#18725](https://github.com/mastra-ai/mastra/pull/18725))
8
+
9
+ ```ts
10
+ const sandbox = new RailwaySandbox({
11
+ checkpointName: 'mastra-workspace-cache',
12
+ idleTimeoutMinutes: 30,
13
+ });
14
+ ```
15
+
16
+ Added `restart()` and automatic retry for unavailable Railway sandboxes during command execution. Fixed checkpoint refresh scheduling, restart checkpoint flushing, teardown cleanup, and retry classification so checkpoint state is preserved without replaying commands after ambiguous transport failures.
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies [[`700619b`](https://github.com/mastra-ai/mastra/commit/700619b61d572e592cbaaf758121d168844ca4d2), [`0f69865`](https://github.com/mastra-ai/mastra/commit/0f69865aced225d98eac812e22699dc445ee18cb), [`9250acd`](https://github.com/mastra-ai/mastra/commit/9250acd1357f0f1f33d0dcca16f9655084c58eca), [`0c3d4bc`](https://github.com/mastra-ai/mastra/commit/0c3d4bcae13ea3699d379403e6f350d5cf4efe9f), [`cc440a3`](https://github.com/mastra-ai/mastra/commit/cc440a39400d8ce06655462b26c1666a1b3d4320), [`6a61846`](https://github.com/mastra-ai/mastra/commit/6a61846eeda29fb714549b70f1bee2bf6b141c44), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`17369b2`](https://github.com/mastra-ai/mastra/commit/17369b25250561e9ed994ae509be1d15bfb33bcb), [`c64c2a8`](https://github.com/mastra-ai/mastra/commit/c64c2a8503a50252f9ca6b8e8c54cadee31b92a2), [`bcae929`](https://github.com/mastra-ai/mastra/commit/bcae929945cbf265bd9f327cc715ecafa072b5b9), [`ea6327b`](https://github.com/mastra-ai/mastra/commit/ea6327ba2d63ca647804bc97b347e03a58617162), [`3439fa8`](https://github.com/mastra-ai/mastra/commit/3439fa836ecfcaa257b40c20b30ac2a8be22e9ea), [`85107f2`](https://github.com/mastra-ai/mastra/commit/85107f2758b527147fccbedff962961927c2d3b8), [`b33822e`](https://github.com/mastra-ai/mastra/commit/b33822e8d470884954b02f7b0745407ee4ef74b1), [`06e2680`](https://github.com/mastra-ai/mastra/commit/06e26806b51d2cbd858afdc66daa2b86ff3ba64a), [`06ff9e0`](https://github.com/mastra-ai/mastra/commit/06ff9e0befd1d642ab87ff749285ee4091205c7e), [`d5c11e3`](https://github.com/mastra-ai/mastra/commit/d5c11e3ba5045969caa7272a7bd1fd141c93ab6c), [`7f5e1ff`](https://github.com/mastra-ai/mastra/commit/7f5e1ff695a92f672bb3976363925d1e9136b54a), [`ff80671`](https://github.com/mastra-ai/mastra/commit/ff8067185e208b27198b4e5b71803013175c3643), [`b8375c1`](https://github.com/mastra-ai/mastra/commit/b8375c1f8fe905df8ae2ae9a893bb365f17aec4e), [`dab1257`](https://github.com/mastra-ai/mastra/commit/dab1257b64e4ed576dc5038bb7a3f7072338bc9f), [`1240f05`](https://github.com/mastra-ai/mastra/commit/1240f051c8e5371f1c014448bf37b1a1b9a05e47), [`705ff39`](https://github.com/mastra-ai/mastra/commit/705ff3969e57214ff2fdaf3815d751dd558886ed), [`e6fbd5b`](https://github.com/mastra-ai/mastra/commit/e6fbd5bfdc28e92c0c0433f29aa1bc152d3430f6), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`6f2026c`](https://github.com/mastra-ai/mastra/commit/6f2026cdf114ff1e21e49133ca774ec7d5085059), [`24c10d3`](https://github.com/mastra-ai/mastra/commit/24c10d333e6649ac06075903aeeee13a933db3b3), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`215f9b0`](https://github.com/mastra-ai/mastra/commit/215f9b0f3f3f6fc165edad360582dd4d3d7ea748), [`003f35d`](https://github.com/mastra-ai/mastra/commit/003f35d19e07b23b4bacc591c8bc0c59b42124ae), [`f890eda`](https://github.com/mastra-ai/mastra/commit/f890eda2c8a2ae83d9b30bc6d85842f93b6c266b), [`1340fb7`](https://github.com/mastra-ai/mastra/commit/1340fb76262a3ca062130aa71859f07257a0a5a4)]:
21
+ - @mastra/core@1.49.0
22
+
23
+ ## 0.3.0-alpha.0
24
+
25
+ ### Minor Changes
26
+
27
+ - Added checkpoint-backed restart and reconnect support to `RailwaySandbox`. Pass `checkpointName` to save the sandbox filesystem before idle teardown and restore it when a sandbox must be recreated. ([#18725](https://github.com/mastra-ai/mastra/pull/18725))
28
+
29
+ ```ts
30
+ const sandbox = new RailwaySandbox({
31
+ checkpointName: 'mastra-workspace-cache',
32
+ idleTimeoutMinutes: 30,
33
+ });
34
+ ```
35
+
36
+ Added `restart()` and automatic retry for unavailable Railway sandboxes during command execution. Fixed checkpoint refresh scheduling, restart checkpoint flushing, teardown cleanup, and retry classification so checkpoint state is preserved without replaying commands after ambiguous transport failures.
37
+
38
+ ### Patch Changes
39
+
40
+ - Updated dependencies [[`1340fb7`](https://github.com/mastra-ai/mastra/commit/1340fb76262a3ca062130aa71859f07257a0a5a4)]:
41
+ - @mastra/core@1.49.0-alpha.2
42
+
3
43
  ## 0.2.1
4
44
 
5
45
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -133,9 +133,12 @@ var RailwaySandbox = class _RailwaySandbox extends workspace.MastraSandbox {
133
133
  status = "pending";
134
134
  _sandbox = null;
135
135
  _createdAt = null;
136
+ _checkpointRefreshTimer = null;
137
+ _checkpointRefreshInFlight = null;
136
138
  _token;
137
139
  _environmentId;
138
140
  _sandboxId;
141
+ _checkpointName;
139
142
  _idleTimeoutMinutes;
140
143
  _networkIsolation;
141
144
  _env;
@@ -152,6 +155,7 @@ var RailwaySandbox = class _RailwaySandbox extends workspace.MastraSandbox {
152
155
  this._token = options.token ?? process.env.RAILWAY_API_TOKEN;
153
156
  this._environmentId = options.environmentId ?? process.env.RAILWAY_ENVIRONMENT_ID;
154
157
  this._sandboxId = options.sandboxId;
158
+ this._checkpointName = options.checkpointName;
155
159
  this._idleTimeoutMinutes = options.idleTimeoutMinutes;
156
160
  this._networkIsolation = options.networkIsolation;
157
161
  this._env = options.env ?? {};
@@ -186,29 +190,230 @@ var RailwaySandbox = class _RailwaySandbox extends workspace.MastraSandbox {
186
190
  if (this._sandbox) {
187
191
  return;
188
192
  }
189
- const clientConfig = {
193
+ await this._startRailwaySandbox({ reconnectSandboxId: this._sandboxId, fallbackToCreate: false });
194
+ }
195
+ async restart() {
196
+ const reconnectSandboxId = this._sandbox?.id ?? this._sandboxId;
197
+ this._cancelCheckpointRefresh();
198
+ await this._checkpointRefreshInFlight?.catch((error) => {
199
+ this.logger.warn(`${LOG_PREFIX} Failed to flush in-flight checkpoint before restart:`, error);
200
+ });
201
+ this._sandbox = null;
202
+ this._createdAt = null;
203
+ this.status = "starting";
204
+ try {
205
+ await this._startRailwaySandbox({ reconnectSandboxId, fallbackToCreate: true });
206
+ this.status = "running";
207
+ } catch (error) {
208
+ this.status = "error";
209
+ throw error;
210
+ }
211
+ }
212
+ async withRestartRetry(operation) {
213
+ await this.ensureRunning();
214
+ try {
215
+ return await operation();
216
+ } catch (error) {
217
+ if (!this.isSandboxUnavailableError(error)) {
218
+ throw error;
219
+ }
220
+ await this.restart();
221
+ return await operation();
222
+ } finally {
223
+ this._scheduleCheckpointRefresh();
224
+ }
225
+ }
226
+ async _startRailwaySandbox({
227
+ reconnectSandboxId,
228
+ fallbackToCreate
229
+ }) {
230
+ const clientConfig = this._clientConfig();
231
+ const createOptions = this._createOptions(clientConfig);
232
+ this._sandbox = reconnectSandboxId ? await this._reconnectSandbox(reconnectSandboxId, fallbackToCreate, clientConfig, createOptions) : await this._createNewSandbox(createOptions);
233
+ this._createdAt = this._sandbox.createdAt ? new Date(this._sandbox.createdAt) : /* @__PURE__ */ new Date();
234
+ this.logger.debug(`${LOG_PREFIX} Railway sandbox ${this._sandbox.id} ready for logical ID: ${this.id}`);
235
+ this._scheduleCheckpointRefresh();
236
+ }
237
+ /**
238
+ * Reconnect to an existing Railway sandbox, creating a fresh one when
239
+ * `fallbackToCreate` is set and the sandbox is unavailable or not running.
240
+ */
241
+ async _reconnectSandbox(reconnectSandboxId, fallbackToCreate, clientConfig, createOptions) {
242
+ this.logger.debug(`${LOG_PREFIX} Reconnecting to Railway sandbox ${reconnectSandboxId}...`);
243
+ let connectedSandbox;
244
+ try {
245
+ connectedSandbox = await railway.Sandbox.connect(reconnectSandboxId, clientConfig);
246
+ } catch (error) {
247
+ if (!fallbackToCreate || !this.isSandboxUnavailableError(error)) {
248
+ throw error;
249
+ }
250
+ return this._createNewSandbox(createOptions);
251
+ }
252
+ if (connectedSandbox.status === "RUNNING") {
253
+ return connectedSandbox;
254
+ }
255
+ if (!fallbackToCreate) {
256
+ throw new Error(`Railway sandbox ${reconnectSandboxId} is not running (status: ${connectedSandbox.status})`);
257
+ }
258
+ return this._createNewSandbox(createOptions);
259
+ }
260
+ _clientConfig() {
261
+ return {
190
262
  ...this._token !== void 0 && { token: this._token },
191
263
  ...this._environmentId !== void 0 && { environmentId: this._environmentId }
192
264
  };
193
- const createOptions = {
265
+ }
266
+ _createOptions(clientConfig) {
267
+ return {
194
268
  ...clientConfig,
195
269
  ...this._idleTimeoutMinutes !== void 0 && { idleTimeoutMinutes: this._idleTimeoutMinutes },
196
270
  ...this._networkIsolation !== void 0 && { networkIsolation: this._networkIsolation },
197
271
  ...Object.keys(this._env).length > 0 && { env: this._env }
198
272
  };
199
- if (this._sandboxId) {
200
- this.logger.debug(`${LOG_PREFIX} Reconnecting to Railway sandbox ${this._sandboxId}...`);
201
- this._sandbox = await railway.Sandbox.connect(this._sandboxId, clientConfig);
202
- } else if (this._templateOption) {
273
+ }
274
+ async _createNewSandbox(createOptions) {
275
+ const checkpointSandbox = await this._tryCreateFromCheckpoint(createOptions);
276
+ if (checkpointSandbox) {
277
+ return checkpointSandbox;
278
+ }
279
+ if (this._templateOption) {
203
280
  const template = this._resolveTemplate();
204
281
  this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from template for: ${this.id}`);
205
- this._sandbox = await railway.Sandbox.create(template, createOptions);
206
- } else {
207
- this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox for: ${this.id}`);
208
- this._sandbox = await railway.Sandbox.create(createOptions);
282
+ const sandbox2 = await railway.Sandbox.create(template, createOptions);
283
+ await this._checkpointSandbox(sandbox2);
284
+ return sandbox2;
285
+ }
286
+ this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox for: ${this.id}`);
287
+ const sandbox = await railway.Sandbox.create(createOptions);
288
+ await this._checkpointSandbox(sandbox);
289
+ return sandbox;
290
+ }
291
+ async _tryCreateFromCheckpoint(createOptions) {
292
+ if (!this._checkpointName) {
293
+ return void 0;
294
+ }
295
+ this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from checkpoint ${this._checkpointName} for: ${this.id}`);
296
+ try {
297
+ const sandbox = await railway.Sandbox.create(this._checkpointName, createOptions);
298
+ return sandbox;
299
+ } catch (error) {
300
+ if (!this.isCheckpointUnavailableError(error)) {
301
+ throw error;
302
+ }
303
+ return void 0;
304
+ }
305
+ }
306
+ async _checkpointSandbox(sandbox) {
307
+ if (!this._checkpointName) {
308
+ return;
309
+ }
310
+ try {
311
+ this.logger.debug(`${LOG_PREFIX} Capturing Railway sandbox checkpoint ${this._checkpointName} for: ${this.id}`);
312
+ await sandbox.checkpoint(this._checkpointName);
313
+ } catch (error) {
314
+ if (!this.isCheckpointAlreadyExistsError(error)) {
315
+ throw error;
316
+ }
317
+ await this._deleteCheckpointByName(this._checkpointName);
318
+ await sandbox.checkpoint(this._checkpointName);
209
319
  }
210
- this._createdAt = this._sandbox.createdAt ? new Date(this._sandbox.createdAt) : /* @__PURE__ */ new Date();
211
- this.logger.debug(`${LOG_PREFIX} Railway sandbox ${this._sandbox.id} ready for logical ID: ${this.id}`);
320
+ }
321
+ async _deleteCheckpointByName(name) {
322
+ try {
323
+ const checkpoint = (await railway.Sandbox.checkpoints(this._clientConfig())).find((checkpoint2) => checkpoint2.key === name);
324
+ if (!checkpoint) {
325
+ return;
326
+ }
327
+ await railway.Sandbox.deleteCheckpoint(checkpoint.id, this._clientConfig());
328
+ } catch (error) {
329
+ if (!this.isCheckpointUnavailableError(error)) {
330
+ throw error;
331
+ }
332
+ }
333
+ }
334
+ _scheduleCheckpointRefresh() {
335
+ if (!this._checkpointName || !this._sandbox) {
336
+ return;
337
+ }
338
+ const idleTimeoutMinutes = this._idleTimeoutMinutes ?? this._sandbox.idleTimeoutMinutes;
339
+ if (!idleTimeoutMinutes) {
340
+ return;
341
+ }
342
+ if (this._checkpointRefreshTimer) {
343
+ clearTimeout(this._checkpointRefreshTimer);
344
+ }
345
+ const delayMs = Math.max(1e3, idleTimeoutMinutes * 6e4 - 1e4);
346
+ this._checkpointRefreshTimer = setTimeout(() => {
347
+ this._checkpointRefreshTimer = null;
348
+ const sandbox = this._sandbox;
349
+ if (!sandbox) {
350
+ return;
351
+ }
352
+ const refresh = this._checkpointSandbox(sandbox).finally(() => {
353
+ if (this._checkpointRefreshInFlight === refresh) {
354
+ this._checkpointRefreshInFlight = null;
355
+ }
356
+ });
357
+ this._checkpointRefreshInFlight = refresh;
358
+ this._checkpointRefreshInFlight.catch((error) => {
359
+ this.logger.warn(`${LOG_PREFIX} Failed to refresh Railway sandbox checkpoint ${this._checkpointName}:`, error);
360
+ });
361
+ }, delayMs);
362
+ this._checkpointRefreshTimer.unref?.();
363
+ }
364
+ _cancelCheckpointRefresh() {
365
+ if (this._checkpointRefreshTimer) {
366
+ clearTimeout(this._checkpointRefreshTimer);
367
+ this._checkpointRefreshTimer = null;
368
+ }
369
+ }
370
+ async _flushCheckpointRefresh() {
371
+ this._cancelCheckpointRefresh();
372
+ if (this._checkpointRefreshInFlight) {
373
+ await this._checkpointRefreshInFlight;
374
+ return;
375
+ }
376
+ if (this._sandbox) {
377
+ await this._checkpointSandbox(this._sandbox);
378
+ }
379
+ }
380
+ isCheckpointUnavailableError(error) {
381
+ if (!(error instanceof Error)) {
382
+ return false;
383
+ }
384
+ const message = error.message.toLowerCase();
385
+ return message.includes("checkpoint") && ["not found", "does not exist", "missing", "unknown", "no checkpoint"].some((phrase) => message.includes(phrase));
386
+ }
387
+ isCheckpointAlreadyExistsError(error) {
388
+ if (!(error instanceof Error)) {
389
+ return false;
390
+ }
391
+ const message = error.message.toLowerCase();
392
+ return message.includes("checkpoint") && (["already exists", "must be unused", "unique"].some((phrase) => message.includes(phrase)) || message.includes("name") && message.includes("used"));
393
+ }
394
+ isSandboxUnavailableError(error, seen = /* @__PURE__ */ new Set()) {
395
+ if (error && typeof error === "object") {
396
+ if (seen.has(error)) return false;
397
+ seen.add(error);
398
+ }
399
+ if (error instanceof railway.SandboxNotFoundError || error instanceof railway.SandboxFailedError || error instanceof railway.SandboxTimeoutError && error.resource === "sandbox") {
400
+ return true;
401
+ }
402
+ if (error && typeof error === "object") {
403
+ const errorLike = error;
404
+ const name = typeof errorLike.name === "string" ? errorLike.name : "";
405
+ const message = typeof errorLike.message === "string" ? errorLike.message.toLowerCase() : "";
406
+ if (name === "SandboxNotFoundError" || name === "SandboxFailedError" || name === "SandboxTimeoutError" && errorLike.resource === "sandbox") {
407
+ return true;
408
+ }
409
+ if (message.includes("sandbox") && ["not found", "destroyed", "failed", "not running", "unavailable"].some((phrase) => message.includes(phrase))) {
410
+ return true;
411
+ }
412
+ if (errorLike.cause !== void 0) {
413
+ return this.isSandboxUnavailableError(errorLike.cause, seen);
414
+ }
415
+ }
416
+ return false;
212
417
  }
213
418
  /**
214
419
  * Stop the Railway sandbox.
@@ -227,9 +432,15 @@ var RailwaySandbox = class _RailwaySandbox extends workspace.MastraSandbox {
227
432
  }
228
433
  async _teardown() {
229
434
  if (!this._sandbox) {
435
+ this._cancelCheckpointRefresh();
230
436
  return;
231
437
  }
232
438
  const sandbox = this._sandbox;
439
+ try {
440
+ await this._flushCheckpointRefresh();
441
+ } catch (error) {
442
+ this.logger.warn(`${LOG_PREFIX} Failed to flush checkpoint before teardown:`, error);
443
+ }
233
444
  this._sandbox = null;
234
445
  try {
235
446
  await sandbox.destroy();
@@ -332,15 +543,30 @@ var RailwaySandbox = class _RailwaySandbox extends workspace.MastraSandbox {
332
543
  * Execute a command in the sandbox and return the result.
333
544
  */
334
545
  async executeCommand(command, args = [], options = {}) {
335
- await this.ensureRunning();
336
- const fullCommand = args.length > 0 ? `${command} ${args.map(shellQuote).join(" ")}` : command;
337
- const effectiveOptions = {
338
- ...options,
339
- timeout: options.timeout ?? this._timeout
340
- };
341
- const handle = await this.processes.spawn(fullCommand, effectiveOptions);
342
- const result = await handle.wait();
343
- return { ...result, command, args };
546
+ return this.withRestartRetry(async () => {
547
+ const fullCommand = args.length > 0 ? `${command} ${args.map(shellQuote).join(" ")}` : command;
548
+ const timeout = options.timeout ?? this._timeout;
549
+ const env = options.env ? Object.fromEntries(
550
+ Object.entries(options.env).filter((entry) => entry[1] !== void 0)
551
+ ) : void 0;
552
+ const startedAt = Date.now();
553
+ const result = await this.railway.exec(fullCommand, {
554
+ ...timeout !== void 0 && { timeoutSec: Math.ceil(timeout / 1e3) },
555
+ ...options.cwd !== void 0 && { cwd: options.cwd },
556
+ ...env !== void 0 && { env }
557
+ });
558
+ const exitCode = result.exitCode ?? -1;
559
+ return {
560
+ success: exitCode === 0,
561
+ exitCode,
562
+ stdout: result.stdout,
563
+ stderr: result.stderr,
564
+ executionTimeMs: Date.now() - startedAt,
565
+ command,
566
+ args,
567
+ timedOut: result.timedOut
568
+ };
569
+ });
344
570
  }
345
571
  };
346
572
 
@@ -379,6 +605,10 @@ var railwaySandboxProvider = {
379
605
  createSandbox: (config) => new RailwaySandbox(config)
380
606
  };
381
607
 
608
+ Object.defineProperty(exports, "SandboxFileNotFoundError", {
609
+ enumerable: true,
610
+ get: function () { return railway.SandboxFileNotFoundError; }
611
+ });
382
612
  exports.RailwayProcessManager = RailwayProcessManager;
383
613
  exports.RailwaySandbox = RailwaySandbox;
384
614
  exports.railwaySandboxProvider = railwaySandboxProvider;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/shell-quote.ts","../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../src/provider.ts"],"names":["ProcessHandle","SandboxProcessManager","MastraSandbox","SandboxNotReadyError","Sandbox"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Shell-quote a single argument for safe use in a command string.\n *\n * Arguments containing only safe characters are returned as-is.\n * All others are wrapped in single quotes with embedded single quotes escaped.\n */\nexport function shellQuote(arg: string): string {\n // Safe characters that don't need quoting\n if (/^[a-zA-Z0-9._\\-/@:=]+$/.test(arg)) return arg;\n // Wrap in single quotes, escaping any embedded single quotes\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n","/**\n * Railway Process Manager\n *\n * Implements SandboxProcessManager for Railway sandboxes.\n * Wraps the Railway SDK's `Sandbox.exec()` API.\n *\n * Railway's `exec(command, options)` accepts per-call `cwd` and `env` options\n * (since SDK v3.3.1) and returns an `ExecHandle` that runs the command\n * server-side, independently of the client. Each spawn() starts one exec.\n * The handle streams output via `onStdout`/`onStderr` callbacks wired to\n * `emitStdout`/`emitStderr`, exposes a durable `sessionName`, and can be\n * terminated with `kill(signal)`.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ExecHandle, ExecResult } from 'railway';\nimport type { RailwaySandbox } from './index';\n\nexport const LOG_PREFIX = '[RailwaySandbox]';\n\n// =============================================================================\n// Railway Process Handle\n// =============================================================================\n\n/**\n * Wraps a Railway ExecHandle to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n */\nclass RailwayProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _execHandle: ExecHandle;\n private readonly _startTime: number;\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _killed = false;\n\n constructor(pid: string, execHandle: ExecHandle, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._execHandle = execHandle;\n this._startTime = startTime;\n\n // Resolve exit code once the command completes so exitCode is available\n // without an explicit wait().\n void this._execHandle.then(\n (result: ExecResult) => {\n // -1 means terminated by a signal (e.g. after kill()).\n this._exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n },\n () => {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n },\n );\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n async wait(): Promise<CommandResult> {\n // Idempotent — cache the promise so repeated calls return the same result.\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n try {\n const result = await this._execHandle;\n const exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n this._exitCode = exitCode;\n\n // Railway captures output server-side; surface it through the base buffers\n // if streaming callbacks didn't already populate them.\n if (result.stdout && !this.stdout) this.emitStdout(result.stdout);\n if (result.stderr && !this.stderr) this.emitStderr(result.stderr);\n\n return {\n success: exitCode === 0,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n timedOut: result.timedOut,\n };\n } catch (error) {\n const exitCode = this._exitCode ?? 1;\n this._exitCode = exitCode;\n return {\n success: false,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr || (error instanceof Error ? error.message : String(error)),\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n };\n }\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n try {\n return await this._execHandle.kill('TERM');\n } catch {\n // Command may already be gone.\n return false;\n }\n }\n\n async sendStdin(_data: string): Promise<void> {\n // Railway's exec API does not expose stdin streaming.\n throw new Error(`${LOG_PREFIX} sending stdin is not supported by the Railway sandbox provider`);\n }\n}\n\n// =============================================================================\n// Railway Process Manager\n// =============================================================================\n\nexport interface RailwayProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Railway implementation of SandboxProcessManager.\n * Uses the Railway SDK's `Sandbox.exec()` with one exec per spawned process.\n */\nexport class RailwayProcessManager extends SandboxProcessManager<RailwaySandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: RailwayProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n const railway = this.sandbox.railway;\n\n // Merge default env with per-spawn env.\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n const pid = `railway-proc-${Date.now().toString(36)}-${(this._spawnCounter++).toString(36)}`;\n\n // Deferred reference — callbacks fire asynchronously after the handle is\n // assigned, so `handle` is always defined by the time they run.\n let handle: RailwayProcessHandle;\n\n const execHandle = railway.exec(command, {\n ...(options.timeout !== undefined && { timeoutSec: Math.ceil(options.timeout / 1000) }),\n ...(options.cwd !== undefined && { cwd: options.cwd }),\n ...(Object.keys(env).length > 0 && { env }),\n onStdout: (chunk: string) => handle.emitStdout(chunk),\n onStderr: (chunk: string) => handle.emitStderr(chunk),\n });\n\n handle = new RailwayProcessHandle(pid, execHandle, Date.now(), options);\n this._tracked.set(handle.pid, handle);\n return handle;\n }\n\n /**\n * List tracked processes.\n *\n * Railway has no API to enumerate running exec sessions by sandbox, so this\n * reports the processes this manager spawned.\n */\n async list(): Promise<ProcessInfo[]> {\n return Array.from(this._tracked.values()).map(handle => ({\n pid: handle.pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n ...(handle.exitCode !== undefined && { exitCode: handle.exitCode }),\n }));\n }\n}\n","/**\n * Railway Sandbox Provider\n *\n * A Railway sandbox implementation for Mastra workspaces. Provisions an\n * ephemeral, isolated Linux VM on Railway, runs commands in it via the\n * Railway TypeScript SDK, and destroys it on teardown.\n *\n * @see https://docs.railway.com/sandboxes\n */\n\nimport type {\n CommandResult,\n ExecuteCommandOptions,\n InstructionsOption,\n MastraSandboxOptions,\n ProviderStatus,\n SandboxInfo,\n} from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { Sandbox } from 'railway';\nimport type { SandboxNetworkIsolation, SandboxTemplate } from 'railway';\nimport { shellQuote } from '../utils/shell-quote';\nimport { LOG_PREFIX, RailwayProcessManager } from './process-manager';\n\n// =============================================================================\n// Railway Sandbox Options\n// =============================================================================\n\n/**\n * Railway sandbox provider configuration.\n */\nexport interface RailwaySandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance. */\n id?: string;\n /** Railway API token. Falls back to the RAILWAY_API_TOKEN env var. */\n token?: string;\n /** Railway environment ID. Falls back to the RAILWAY_ENVIRONMENT_ID env var. */\n environmentId?: string;\n /**\n * Reattach to an existing Railway sandbox by its Railway ID instead of\n * creating a new one. When set, `start()` calls `Sandbox.connect()`.\n */\n sandboxId?: string;\n /**\n * How long the sandbox can sit idle (no `exec` interaction) before Railway\n * destroys it automatically. Range depends on plan (1–120 minutes on\n * Hobby/Pro, 1–5 on Trial/Free). Defaults to the plan default when omitted.\n */\n idleTimeoutMinutes?: number;\n /**\n * Network isolation mode.\n * - `ISOLATED` (default): outbound internet only, no private network access.\n * - `PRIVATE`: joins the environment's private network.\n */\n networkIsolation?: SandboxNetworkIsolation;\n /** Environment variables baked into the sandbox, available to every command. */\n env?: Record<string, string>;\n /**\n * Provision the sandbox from a custom base image built with the Railway\n * template builder. Use this to pre-install packages or run setup steps so\n * every sandbox created from it starts ready.\n *\n * - Builder callback — receives the base `Sandbox.template()` and returns the\n * configured template. Railway builds the template when `Sandbox.create()`\n * runs during `start()`.\n * ```ts\n * template: t => t.withPackages('git', 'curl').run('npm i -g pnpm')\n * ```\n * - Pre-built `SandboxTemplate` — pass a template to reuse it across\n * sandboxes. Railway still builds the image during sandbox creation.\n *\n * Ignored when `sandboxId` is set (reattach) or when forking.\n */\n template?: SandboxTemplate | ((base: SandboxTemplate) => SandboxTemplate);\n /**\n * Default execution timeout in milliseconds applied to commands that don't\n * specify their own timeout. When omitted, commands run until they exit.\n */\n timeout?: number;\n /**\n * Custom instructions that override the default instructions returned by\n * `getInstructions()`.\n *\n * - `string` — Fully replaces the default instructions. Pass an empty string\n * to suppress instructions entirely.\n * - `(opts) => string` — Receives the default instructions and optional\n * request context so you can extend or customise per-request.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// Railway Sandbox Implementation\n// =============================================================================\n\n/**\n * Railway sandbox provider for Mastra workspaces.\n *\n * Features:\n * - Ephemeral, isolated Linux VM via the Railway TypeScript SDK\n * - Command execution with streaming output and timeouts\n * - Configurable idle timeout and network isolation\n * - Reattach to an existing sandbox by Railway ID\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { RailwaySandbox } from '@mastra/railway';\n *\n * const sandbox = new RailwaySandbox({\n * // token + environmentId read from RAILWAY_API_TOKEN / RAILWAY_ENVIRONMENT_ID\n * idleTimeoutMinutes: 30,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example Private networking\n * ```typescript\n * const sandbox = new RailwaySandbox({\n * networkIsolation: 'PRIVATE',\n * env: { NODE_ENV: 'production' },\n * });\n * ```\n */\nexport class RailwaySandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'RailwaySandbox';\n readonly provider = 'railway';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: RailwayProcessManager;\n\n private _sandbox: Sandbox | null = null;\n private _createdAt: Date | null = null;\n\n private readonly _token?: string;\n private readonly _environmentId?: string;\n private readonly _sandboxId?: string;\n private readonly _idleTimeoutMinutes?: number;\n private readonly _networkIsolation?: SandboxNetworkIsolation;\n private readonly _env: Record<string, string>;\n private readonly _timeout?: number;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _templateOption?: RailwaySandboxOptions['template'];\n\n constructor(options: RailwaySandboxOptions = {}) {\n super({\n ...options,\n name: 'RailwaySandbox',\n processes: new RailwayProcessManager({ env: options.env }),\n });\n\n this.id = options.id ?? this.generateId();\n this._token = options.token ?? process.env.RAILWAY_API_TOKEN;\n this._environmentId = options.environmentId ?? process.env.RAILWAY_ENVIRONMENT_ID;\n this._sandboxId = options.sandboxId;\n this._idleTimeoutMinutes = options.idleTimeoutMinutes;\n this._networkIsolation = options.networkIsolation;\n this._env = options.env ?? {};\n this._timeout = options.timeout;\n this._instructionsOverride = options.instructions;\n this._templateOption = options.template;\n }\n\n private generateId(): string {\n return `railway-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /**\n * Get the underlying Railway Sandbox instance for direct SDK access.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get railway(): Sandbox {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sandbox;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Start the Railway sandbox.\n *\n * Reattaches to an existing sandbox when `sandboxId` is configured,\n * otherwise provisions a new one. Resolves once the sandbox is RUNNING.\n */\n async start(): Promise<void> {\n if (this._sandbox) {\n return;\n }\n\n const clientConfig = {\n ...(this._token !== undefined && { token: this._token }),\n ...(this._environmentId !== undefined && { environmentId: this._environmentId }),\n };\n\n const createOptions = {\n ...clientConfig,\n ...(this._idleTimeoutMinutes !== undefined && { idleTimeoutMinutes: this._idleTimeoutMinutes }),\n ...(this._networkIsolation !== undefined && { networkIsolation: this._networkIsolation }),\n ...(Object.keys(this._env).length > 0 && { env: this._env }),\n };\n\n if (this._sandboxId) {\n this.logger.debug(`${LOG_PREFIX} Reconnecting to Railway sandbox ${this._sandboxId}...`);\n this._sandbox = await Sandbox.connect(this._sandboxId, clientConfig);\n } else if (this._templateOption) {\n const template = this._resolveTemplate();\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from template for: ${this.id}`);\n this._sandbox = await Sandbox.create(template, createOptions);\n } else {\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox for: ${this.id}`);\n this._sandbox = await Sandbox.create(createOptions);\n }\n\n this._createdAt = this._sandbox.createdAt ? new Date(this._sandbox.createdAt) : new Date();\n this.logger.debug(`${LOG_PREFIX} Railway sandbox ${this._sandbox.id} ready for logical ID: ${this.id}`);\n }\n\n /**\n * Stop the Railway sandbox.\n *\n * Railway sandboxes have no separate \"stopped\" state — they're either\n * running or destroyed — so stopping destroys the sandbox.\n */\n async stop(): Promise<void> {\n await this._teardown();\n }\n\n /**\n * Destroy the Railway sandbox and release its resources.\n */\n async destroy(): Promise<void> {\n await this._teardown();\n }\n\n private async _teardown(): Promise<void> {\n if (!this._sandbox) {\n return;\n }\n const sandbox = this._sandbox;\n this._sandbox = null;\n try {\n await sandbox.destroy();\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Failed to destroy Railway sandbox ${sandbox.id}:`, error);\n }\n }\n\n /**\n * Resolve the configured template into a `SandboxTemplate` that Railway\n * builds during `Sandbox.create()`. Accepts either a pre-built\n * `SandboxTemplate` or a builder callback over `Sandbox.template()`.\n */\n private _resolveTemplate(): SandboxTemplate {\n const option = this._templateOption!;\n return typeof option === 'function' ? option(Sandbox.template()) : option;\n }\n\n /**\n * Fork this running sandbox into a new, independent `RailwaySandbox`.\n *\n * Clones the filesystem (a fresh boot, not live processes) into the same\n * environment. The returned sandbox is already started and reattached to the\n * forked Railway sandbox; it inherits this sandbox's credentials and defaults\n * unless overridden via `options`.\n *\n * @throws {SandboxNotReadyError} If this sandbox has not been started.\n */\n async fork(\n options: Pick<RailwaySandboxOptions, 'id' | 'idleTimeoutMinutes' | 'networkIsolation' | 'env'> = {},\n ): Promise<RailwaySandbox> {\n const source = this.railway;\n const forked = await source.fork({\n ...(options.idleTimeoutMinutes !== undefined && { idleTimeoutMinutes: options.idleTimeoutMinutes }),\n ...(options.networkIsolation !== undefined && { networkIsolation: options.networkIsolation }),\n ...(options.env !== undefined && { env: options.env }),\n });\n\n const child = new RailwaySandbox({\n ...(options.id !== undefined && { id: options.id }),\n ...(this._token !== undefined && { token: this._token }),\n ...(this._environmentId !== undefined && { environmentId: this._environmentId }),\n sandboxId: forked.id,\n idleTimeoutMinutes: options.idleTimeoutMinutes ?? this._idleTimeoutMinutes,\n networkIsolation: options.networkIsolation ?? this._networkIsolation,\n env: options.env ?? this._env,\n timeout: this._timeout,\n });\n await child._start();\n return child;\n }\n\n // ---------------------------------------------------------------------------\n // Info & Instructions\n // ---------------------------------------------------------------------------\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n metadata: {\n ...(this._sandbox && {\n railwaySandboxId: this._sandbox.id,\n environmentId: this._sandbox.environmentId,\n region: this._sandbox.region,\n networkIsolation: this._sandbox.networkIsolation,\n ...(this._sandbox.idleTimeoutMinutes != null && {\n idleTimeoutMinutes: this._sandbox.idleTimeoutMinutes,\n }),\n }),\n },\n };\n }\n\n getInstructions(): string {\n const defaultInstructions = this._buildDefaultInstructions();\n\n if (typeof this._instructionsOverride === 'string') {\n return this._instructionsOverride;\n }\n if (typeof this._instructionsOverride === 'function') {\n return this._instructionsOverride({ defaultInstructions });\n }\n return defaultInstructions;\n }\n\n private _buildDefaultInstructions(): string {\n const parts: string[] = [];\n parts.push('Railway cloud sandbox: an isolated Debian Linux VM with outbound internet access.');\n\n if (this._networkIsolation === 'PRIVATE') {\n parts.push('Joined to the environment private network.');\n }\n\n if (this._timeout !== undefined) {\n parts.push(`Default command timeout: ${Math.ceil(this._timeout / 1000)}s.`);\n } else {\n parts.push('Commands run until they exit unless a timeout is set.');\n }\n\n if (this._idleTimeoutMinutes !== undefined) {\n parts.push(`Idle timeout: ${this._idleTimeoutMinutes} minute(s).`);\n }\n\n return parts.join(' ');\n }\n\n // ---------------------------------------------------------------------------\n // Command Execution\n // ---------------------------------------------------------------------------\n\n /**\n * Execute a command in the sandbox and return the result.\n */\n async executeCommand(\n command: string,\n args: string[] = [],\n options: ExecuteCommandOptions = {},\n ): Promise<CommandResult> {\n await this.ensureRunning();\n const fullCommand = args.length > 0 ? `${command} ${args.map(shellQuote).join(' ')}` : command;\n const effectiveOptions: ExecuteCommandOptions = {\n ...options,\n timeout: options.timeout ?? this._timeout,\n };\n const handle = await this.processes.spawn(fullCommand, effectiveOptions);\n const result = await handle.wait();\n return { ...result, command, args };\n }\n}\n","/**\n * Railway sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { railwaySandboxProvider } from '@mastra/railway';\n *\n * const editor = new MastraEditor({\n * sandboxes: { [railwaySandboxProvider.id]: railwaySandboxProvider },\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { RailwaySandbox } from './sandbox';\n\n/**\n * Serializable subset of RailwaySandboxOptions for editor storage.\n */\ninterface RailwayProviderConfig {\n token?: string;\n environmentId?: string;\n sandboxId?: string;\n idleTimeoutMinutes?: number;\n networkIsolation?: 'ISOLATED' | 'PRIVATE';\n env?: Record<string, string>;\n timeout?: number;\n}\n\nexport const railwaySandboxProvider: SandboxProvider<RailwayProviderConfig> = {\n id: 'railway',\n name: 'Railway Sandbox',\n description: 'Ephemeral, isolated Linux VM powered by Railway',\n configSchema: {\n type: 'object',\n properties: {\n token: { type: 'string', description: 'Railway API token (falls back to RAILWAY_API_TOKEN)' },\n environmentId: {\n type: 'string',\n description: 'Railway environment ID (falls back to RAILWAY_ENVIRONMENT_ID)',\n },\n sandboxId: { type: 'string', description: 'Reattach to an existing Railway sandbox by ID' },\n idleTimeoutMinutes: {\n type: 'number',\n description: 'Minutes a sandbox can sit idle before Railway destroys it',\n },\n networkIsolation: {\n type: 'string',\n description: 'Network isolation mode',\n enum: ['ISOLATED', 'PRIVATE'],\n default: 'ISOLATED',\n },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n timeout: { type: 'number', description: 'Default command timeout in ms' },\n },\n },\n createSandbox: config => new RailwaySandbox(config),\n};\n"]}
1
+ {"version":3,"sources":["../src/utils/shell-quote.ts","../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../src/provider.ts"],"names":["ProcessHandle","SandboxProcessManager","MastraSandbox","SandboxNotReadyError","Sandbox","sandbox","checkpoint","SandboxNotFoundError","SandboxFailedError","SandboxTimeoutError"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Shell-quote a single argument for safe use in a command string.\n *\n * Arguments containing only safe characters are returned as-is.\n * All others are wrapped in single quotes with embedded single quotes escaped.\n */\nexport function shellQuote(arg: string): string {\n // Safe characters that don't need quoting\n if (/^[a-zA-Z0-9._\\-/@:=]+$/.test(arg)) return arg;\n // Wrap in single quotes, escaping any embedded single quotes\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n","/**\n * Railway Process Manager\n *\n * Implements SandboxProcessManager for Railway sandboxes.\n * Wraps the Railway SDK's `Sandbox.exec()` API.\n *\n * Railway's `exec(command, options)` accepts per-call `cwd` and `env` options\n * (since SDK v3.3.1) and returns an `ExecHandle` that runs the command\n * server-side, independently of the client. Each spawn() starts one exec.\n * The handle streams output via `onStdout`/`onStderr` callbacks wired to\n * `emitStdout`/`emitStderr`, exposes a durable `sessionName`, and can be\n * terminated with `kill(signal)`.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ExecHandle, ExecResult } from 'railway';\nimport type { RailwaySandbox } from './index';\n\nexport const LOG_PREFIX = '[RailwaySandbox]';\n\n// =============================================================================\n// Railway Process Handle\n// =============================================================================\n\n/**\n * Wraps a Railway ExecHandle to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n */\nclass RailwayProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _execHandle: ExecHandle;\n private readonly _startTime: number;\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _killed = false;\n\n constructor(pid: string, execHandle: ExecHandle, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._execHandle = execHandle;\n this._startTime = startTime;\n\n // Resolve exit code once the command completes so exitCode is available\n // without an explicit wait().\n void this._execHandle.then(\n (result: ExecResult) => {\n // -1 means terminated by a signal (e.g. after kill()).\n this._exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n },\n () => {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n },\n );\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n async wait(): Promise<CommandResult> {\n // Idempotent — cache the promise so repeated calls return the same result.\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n try {\n const result = await this._execHandle;\n const exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n this._exitCode = exitCode;\n\n // Railway captures output server-side; surface it through the base buffers\n // if streaming callbacks didn't already populate them.\n if (result.stdout && !this.stdout) this.emitStdout(result.stdout);\n if (result.stderr && !this.stderr) this.emitStderr(result.stderr);\n\n return {\n success: exitCode === 0,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n timedOut: result.timedOut,\n };\n } catch (error) {\n const exitCode = this._exitCode ?? 1;\n this._exitCode = exitCode;\n return {\n success: false,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr || (error instanceof Error ? error.message : String(error)),\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n };\n }\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n try {\n return await this._execHandle.kill('TERM');\n } catch {\n // Command may already be gone.\n return false;\n }\n }\n\n async sendStdin(_data: string): Promise<void> {\n // Railway's exec API does not expose stdin streaming.\n throw new Error(`${LOG_PREFIX} sending stdin is not supported by the Railway sandbox provider`);\n }\n}\n\n// =============================================================================\n// Railway Process Manager\n// =============================================================================\n\nexport interface RailwayProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Railway implementation of SandboxProcessManager.\n * Uses the Railway SDK's `Sandbox.exec()` with one exec per spawned process.\n */\nexport class RailwayProcessManager extends SandboxProcessManager<RailwaySandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: RailwayProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n const railway = this.sandbox.railway;\n\n // Merge default env with per-spawn env.\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n const pid = `railway-proc-${Date.now().toString(36)}-${(this._spawnCounter++).toString(36)}`;\n\n // Deferred reference — callbacks fire asynchronously after the handle is\n // assigned, so `handle` is always defined by the time they run.\n let handle: RailwayProcessHandle;\n\n const execHandle = railway.exec(command, {\n ...(options.timeout !== undefined && { timeoutSec: Math.ceil(options.timeout / 1000) }),\n ...(options.cwd !== undefined && { cwd: options.cwd }),\n ...(Object.keys(env).length > 0 && { env }),\n onStdout: (chunk: string) => handle.emitStdout(chunk),\n onStderr: (chunk: string) => handle.emitStderr(chunk),\n });\n\n handle = new RailwayProcessHandle(pid, execHandle, Date.now(), options);\n this._tracked.set(handle.pid, handle);\n return handle;\n }\n\n /**\n * List tracked processes.\n *\n * Railway has no API to enumerate running exec sessions by sandbox, so this\n * reports the processes this manager spawned.\n */\n async list(): Promise<ProcessInfo[]> {\n return Array.from(this._tracked.values()).map(handle => ({\n pid: handle.pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n ...(handle.exitCode !== undefined && { exitCode: handle.exitCode }),\n }));\n }\n}\n","/**\n * Railway Sandbox Provider\n *\n * A Railway sandbox implementation for Mastra workspaces. Provisions an\n * ephemeral, isolated Linux VM on Railway, runs commands in it via the\n * Railway TypeScript SDK, and destroys it on teardown.\n *\n * @see https://docs.railway.com/sandboxes\n */\n\nimport type {\n CommandResult,\n ExecuteCommandOptions,\n InstructionsOption,\n MastraSandboxOptions,\n ProviderStatus,\n SandboxInfo,\n} from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { Sandbox, SandboxFailedError, SandboxNotFoundError, SandboxTimeoutError } from 'railway';\nimport type { SandboxNetworkIsolation, SandboxTemplate } from 'railway';\nimport { shellQuote } from '../utils/shell-quote';\nimport { LOG_PREFIX, RailwayProcessManager } from './process-manager';\n\n// =============================================================================\n// Railway Sandbox Options\n// =============================================================================\n\n/**\n * Railway sandbox provider configuration.\n */\nexport interface RailwaySandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance. */\n id?: string;\n /** Railway API token. Falls back to the RAILWAY_API_TOKEN env var. */\n token?: string;\n /** Railway environment ID. Falls back to the RAILWAY_ENVIRONMENT_ID env var. */\n environmentId?: string;\n /**\n * Reattach to an existing Railway sandbox by its Railway ID instead of\n * creating a new one. When set, `start()` calls `Sandbox.connect()`.\n */\n sandboxId?: string;\n /**\n * Reuse a saved Railway sandbox checkpoint as the baseline filesystem for\n * new sandboxes. When the named checkpoint is missing, the sandbox is created\n * normally and a checkpoint is captured after setup succeeds.\n */\n checkpointName?: string;\n /**\n * How long the sandbox can sit idle (no `exec` interaction) before Railway\n * destroys it automatically. Range depends on plan (1–120 minutes on\n * Hobby/Pro, 1–5 on Trial/Free). Defaults to the plan default when omitted.\n */\n idleTimeoutMinutes?: number;\n /**\n * Network isolation mode.\n * - `ISOLATED` (default): outbound internet only, no private network access.\n * - `PRIVATE`: joins the environment's private network.\n */\n networkIsolation?: SandboxNetworkIsolation;\n /** Environment variables baked into the sandbox, available to every command. */\n env?: Record<string, string>;\n /**\n * Provision the sandbox from a custom base image built with the Railway\n * template builder. Use this to pre-install packages or run setup steps so\n * every sandbox created from it starts ready.\n *\n * - Builder callback — receives the base `Sandbox.template()` and returns the\n * configured template. Railway builds the template when `Sandbox.create()`\n * runs during `start()`.\n * ```ts\n * template: t => t.withPackages('git', 'curl').run('npm i -g pnpm')\n * ```\n * - Pre-built `SandboxTemplate` — pass a template to reuse it across\n * sandboxes. Railway still builds the image during sandbox creation.\n *\n * Ignored when `sandboxId` is set (reattach) or when forking.\n */\n template?: SandboxTemplate | ((base: SandboxTemplate) => SandboxTemplate);\n /**\n * Default execution timeout in milliseconds applied to commands that don't\n * specify their own timeout. When omitted, commands run until they exit.\n */\n timeout?: number;\n /**\n * Custom instructions that override the default instructions returned by\n * `getInstructions()`.\n *\n * - `string` — Fully replaces the default instructions. Pass an empty string\n * to suppress instructions entirely.\n * - `(opts) => string` — Receives the default instructions and optional\n * request context so you can extend or customise per-request.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// Railway Sandbox Implementation\n// =============================================================================\n\n/**\n * Railway sandbox provider for Mastra workspaces.\n *\n * Features:\n * - Ephemeral, isolated Linux VM via the Railway TypeScript SDK\n * - Command execution with streaming output and timeouts\n * - Configurable idle timeout and network isolation\n * - Reattach to an existing sandbox by Railway ID\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { RailwaySandbox } from '@mastra/railway';\n *\n * const sandbox = new RailwaySandbox({\n * // token + environmentId read from RAILWAY_API_TOKEN / RAILWAY_ENVIRONMENT_ID\n * idleTimeoutMinutes: 30,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example Private networking\n * ```typescript\n * const sandbox = new RailwaySandbox({\n * networkIsolation: 'PRIVATE',\n * env: { NODE_ENV: 'production' },\n * });\n * ```\n */\nexport class RailwaySandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'RailwaySandbox';\n readonly provider = 'railway';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: RailwayProcessManager;\n\n private _sandbox: Sandbox | null = null;\n private _createdAt: Date | null = null;\n private _checkpointRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _checkpointRefreshInFlight: Promise<void> | null = null;\n\n private readonly _token?: string;\n private readonly _environmentId?: string;\n private readonly _sandboxId?: string;\n private readonly _checkpointName?: string;\n private readonly _idleTimeoutMinutes?: number;\n private readonly _networkIsolation?: SandboxNetworkIsolation;\n private readonly _env: Record<string, string>;\n private readonly _timeout?: number;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _templateOption?: RailwaySandboxOptions['template'];\n\n constructor(options: RailwaySandboxOptions = {}) {\n super({\n ...options,\n name: 'RailwaySandbox',\n processes: new RailwayProcessManager({ env: options.env }),\n });\n\n this.id = options.id ?? this.generateId();\n this._token = options.token ?? process.env.RAILWAY_API_TOKEN;\n this._environmentId = options.environmentId ?? process.env.RAILWAY_ENVIRONMENT_ID;\n this._sandboxId = options.sandboxId;\n this._checkpointName = options.checkpointName;\n this._idleTimeoutMinutes = options.idleTimeoutMinutes;\n this._networkIsolation = options.networkIsolation;\n this._env = options.env ?? {};\n this._timeout = options.timeout;\n this._instructionsOverride = options.instructions;\n this._templateOption = options.template;\n }\n\n private generateId(): string {\n return `railway-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /**\n * Get the underlying Railway Sandbox instance for direct SDK access.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get railway(): Sandbox {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sandbox;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Start the Railway sandbox.\n *\n * Reattaches to an existing sandbox when `sandboxId` is configured,\n * otherwise provisions a new one. Resolves once the sandbox is RUNNING.\n */\n async start(): Promise<void> {\n if (this._sandbox) {\n return;\n }\n\n await this._startRailwaySandbox({ reconnectSandboxId: this._sandboxId, fallbackToCreate: false });\n }\n\n async restart(): Promise<void> {\n const reconnectSandboxId = this._sandbox?.id ?? this._sandboxId;\n this._cancelCheckpointRefresh();\n await this._checkpointRefreshInFlight?.catch(error => {\n this.logger.warn(`${LOG_PREFIX} Failed to flush in-flight checkpoint before restart:`, error);\n });\n this._sandbox = null;\n this._createdAt = null;\n this.status = 'starting';\n\n try {\n await this._startRailwaySandbox({ reconnectSandboxId, fallbackToCreate: true });\n this.status = 'running';\n } catch (error) {\n this.status = 'error';\n throw error;\n }\n }\n\n async withRestartRetry<T>(operation: () => Promise<T>): Promise<T> {\n await this.ensureRunning();\n try {\n return await operation();\n } catch (error) {\n if (!this.isSandboxUnavailableError(error)) {\n throw error;\n }\n\n await this.restart();\n return await operation();\n } finally {\n this._scheduleCheckpointRefresh();\n }\n }\n\n private async _startRailwaySandbox({\n reconnectSandboxId,\n fallbackToCreate,\n }: {\n reconnectSandboxId?: string;\n fallbackToCreate: boolean;\n }): Promise<void> {\n const clientConfig = this._clientConfig();\n const createOptions = this._createOptions(clientConfig);\n\n this._sandbox = reconnectSandboxId\n ? await this._reconnectSandbox(reconnectSandboxId, fallbackToCreate, clientConfig, createOptions)\n : await this._createNewSandbox(createOptions);\n\n this._createdAt = this._sandbox.createdAt ? new Date(this._sandbox.createdAt) : new Date();\n this.logger.debug(`${LOG_PREFIX} Railway sandbox ${this._sandbox.id} ready for logical ID: ${this.id}`);\n this._scheduleCheckpointRefresh();\n }\n\n /**\n * Reconnect to an existing Railway sandbox, creating a fresh one when\n * `fallbackToCreate` is set and the sandbox is unavailable or not running.\n */\n private async _reconnectSandbox(\n reconnectSandboxId: string,\n fallbackToCreate: boolean,\n clientConfig: { token?: string; environmentId?: string },\n createOptions: ReturnType<RailwaySandbox['_createOptions']>,\n ): Promise<Sandbox> {\n this.logger.debug(`${LOG_PREFIX} Reconnecting to Railway sandbox ${reconnectSandboxId}...`);\n\n let connectedSandbox: Sandbox;\n try {\n connectedSandbox = await Sandbox.connect(reconnectSandboxId, clientConfig);\n } catch (error) {\n if (!fallbackToCreate || !this.isSandboxUnavailableError(error)) {\n throw error;\n }\n return this._createNewSandbox(createOptions);\n }\n\n if (connectedSandbox.status === 'RUNNING') {\n return connectedSandbox;\n }\n\n if (!fallbackToCreate) {\n throw new Error(`Railway sandbox ${reconnectSandboxId} is not running (status: ${connectedSandbox.status})`);\n }\n\n return this._createNewSandbox(createOptions);\n }\n\n private _clientConfig(): { token?: string; environmentId?: string } {\n return {\n ...(this._token !== undefined && { token: this._token }),\n ...(this._environmentId !== undefined && { environmentId: this._environmentId }),\n };\n }\n\n private _createOptions(clientConfig: { token?: string; environmentId?: string }) {\n return {\n ...clientConfig,\n ...(this._idleTimeoutMinutes !== undefined && { idleTimeoutMinutes: this._idleTimeoutMinutes }),\n ...(this._networkIsolation !== undefined && { networkIsolation: this._networkIsolation }),\n ...(Object.keys(this._env).length > 0 && { env: this._env }),\n };\n }\n\n private async _createNewSandbox(createOptions: ReturnType<RailwaySandbox['_createOptions']>): Promise<Sandbox> {\n const checkpointSandbox = await this._tryCreateFromCheckpoint(createOptions);\n if (checkpointSandbox) {\n return checkpointSandbox;\n }\n\n if (this._templateOption) {\n const template = this._resolveTemplate();\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from template for: ${this.id}`);\n const sandbox = await Sandbox.create(template, createOptions);\n await this._checkpointSandbox(sandbox);\n return sandbox;\n }\n\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox for: ${this.id}`);\n const sandbox = await Sandbox.create(createOptions);\n await this._checkpointSandbox(sandbox);\n return sandbox;\n }\n\n private async _tryCreateFromCheckpoint(\n createOptions: ReturnType<RailwaySandbox['_createOptions']>,\n ): Promise<Sandbox | undefined> {\n if (!this._checkpointName) {\n return undefined;\n }\n\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from checkpoint ${this._checkpointName} for: ${this.id}`);\n\n try {\n const sandbox = await Sandbox.create(this._checkpointName, createOptions);\n return sandbox;\n } catch (error) {\n if (!this.isCheckpointUnavailableError(error)) {\n throw error;\n }\n return undefined;\n }\n }\n\n private async _checkpointSandbox(sandbox: Sandbox): Promise<void> {\n if (!this._checkpointName) {\n return;\n }\n\n try {\n this.logger.debug(`${LOG_PREFIX} Capturing Railway sandbox checkpoint ${this._checkpointName} for: ${this.id}`);\n await sandbox.checkpoint(this._checkpointName);\n } catch (error) {\n if (!this.isCheckpointAlreadyExistsError(error)) {\n throw error;\n }\n\n await this._deleteCheckpointByName(this._checkpointName);\n await sandbox.checkpoint(this._checkpointName);\n }\n }\n\n private async _deleteCheckpointByName(name: string): Promise<void> {\n try {\n const checkpoint = (await Sandbox.checkpoints(this._clientConfig())).find(checkpoint => checkpoint.key === name);\n if (!checkpoint) {\n return;\n }\n\n await Sandbox.deleteCheckpoint(checkpoint.id, this._clientConfig());\n } catch (error) {\n if (!this.isCheckpointUnavailableError(error)) {\n throw error;\n }\n }\n }\n\n private _scheduleCheckpointRefresh(): void {\n if (!this._checkpointName || !this._sandbox) {\n return;\n }\n\n const idleTimeoutMinutes = this._idleTimeoutMinutes ?? this._sandbox.idleTimeoutMinutes;\n if (!idleTimeoutMinutes) {\n return;\n }\n\n if (this._checkpointRefreshTimer) {\n clearTimeout(this._checkpointRefreshTimer);\n }\n\n const delayMs = Math.max(1_000, idleTimeoutMinutes * 60_000 - 10_000);\n this._checkpointRefreshTimer = setTimeout(() => {\n this._checkpointRefreshTimer = null;\n const sandbox = this._sandbox;\n if (!sandbox) {\n return;\n }\n\n const refresh = this._checkpointSandbox(sandbox).finally(() => {\n if (this._checkpointRefreshInFlight === refresh) {\n this._checkpointRefreshInFlight = null;\n }\n });\n this._checkpointRefreshInFlight = refresh;\n this._checkpointRefreshInFlight.catch(error => {\n this.logger.warn(`${LOG_PREFIX} Failed to refresh Railway sandbox checkpoint ${this._checkpointName}:`, error);\n });\n }, delayMs);\n this._checkpointRefreshTimer.unref?.();\n }\n\n private _cancelCheckpointRefresh(): void {\n if (this._checkpointRefreshTimer) {\n clearTimeout(this._checkpointRefreshTimer);\n this._checkpointRefreshTimer = null;\n }\n }\n\n private async _flushCheckpointRefresh(): Promise<void> {\n this._cancelCheckpointRefresh();\n\n if (this._checkpointRefreshInFlight) {\n await this._checkpointRefreshInFlight;\n return;\n }\n\n if (this._sandbox) {\n await this._checkpointSandbox(this._sandbox);\n }\n }\n\n private isCheckpointUnavailableError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n const message = error.message.toLowerCase();\n return (\n message.includes('checkpoint') &&\n ['not found', 'does not exist', 'missing', 'unknown', 'no checkpoint'].some(phrase => message.includes(phrase))\n );\n }\n\n private isCheckpointAlreadyExistsError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n const message = error.message.toLowerCase();\n return (\n message.includes('checkpoint') &&\n (['already exists', 'must be unused', 'unique'].some(phrase => message.includes(phrase)) ||\n (message.includes('name') && message.includes('used')))\n );\n }\n\n private isSandboxUnavailableError(error: unknown, seen = new Set<unknown>()): boolean {\n if (error && typeof error === 'object') {\n if (seen.has(error)) return false;\n seen.add(error);\n }\n\n if (\n error instanceof SandboxNotFoundError ||\n error instanceof SandboxFailedError ||\n (error instanceof SandboxTimeoutError && error.resource === 'sandbox')\n ) {\n return true;\n }\n\n if (error && typeof error === 'object') {\n const errorLike = error as { name?: unknown; message?: unknown; resource?: unknown; cause?: unknown };\n const name = typeof errorLike.name === 'string' ? errorLike.name : '';\n const message = typeof errorLike.message === 'string' ? errorLike.message.toLowerCase() : '';\n\n if (\n name === 'SandboxNotFoundError' ||\n name === 'SandboxFailedError' ||\n (name === 'SandboxTimeoutError' && errorLike.resource === 'sandbox')\n ) {\n return true;\n }\n\n if (\n message.includes('sandbox') &&\n ['not found', 'destroyed', 'failed', 'not running', 'unavailable'].some(phrase => message.includes(phrase))\n ) {\n return true;\n }\n\n if (errorLike.cause !== undefined) {\n return this.isSandboxUnavailableError(errorLike.cause, seen);\n }\n }\n\n return false;\n }\n\n /**\n * Stop the Railway sandbox.\n *\n * Railway sandboxes have no separate \"stopped\" state — they're either\n * running or destroyed — so stopping destroys the sandbox.\n */\n async stop(): Promise<void> {\n await this._teardown();\n }\n\n /**\n * Destroy the Railway sandbox and release its resources.\n */\n async destroy(): Promise<void> {\n await this._teardown();\n }\n\n private async _teardown(): Promise<void> {\n if (!this._sandbox) {\n this._cancelCheckpointRefresh();\n return;\n }\n const sandbox = this._sandbox;\n try {\n await this._flushCheckpointRefresh();\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Failed to flush checkpoint before teardown:`, error);\n }\n this._sandbox = null;\n try {\n await sandbox.destroy();\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Failed to destroy Railway sandbox ${sandbox.id}:`, error);\n }\n }\n\n /**\n * Resolve the configured template into a `SandboxTemplate` that Railway\n * builds during `Sandbox.create()`. Accepts either a pre-built\n * `SandboxTemplate` or a builder callback over `Sandbox.template()`.\n */\n private _resolveTemplate(): SandboxTemplate {\n const option = this._templateOption!;\n return typeof option === 'function' ? option(Sandbox.template()) : option;\n }\n\n /**\n * Fork this running sandbox into a new, independent `RailwaySandbox`.\n *\n * Clones the filesystem (a fresh boot, not live processes) into the same\n * environment. The returned sandbox is already started and reattached to the\n * forked Railway sandbox; it inherits this sandbox's credentials and defaults\n * unless overridden via `options`.\n *\n * @throws {SandboxNotReadyError} If this sandbox has not been started.\n */\n async fork(\n options: Pick<RailwaySandboxOptions, 'id' | 'idleTimeoutMinutes' | 'networkIsolation' | 'env'> = {},\n ): Promise<RailwaySandbox> {\n const source = this.railway;\n const forked = await source.fork({\n ...(options.idleTimeoutMinutes !== undefined && { idleTimeoutMinutes: options.idleTimeoutMinutes }),\n ...(options.networkIsolation !== undefined && { networkIsolation: options.networkIsolation }),\n ...(options.env !== undefined && { env: options.env }),\n });\n\n const child = new RailwaySandbox({\n ...(options.id !== undefined && { id: options.id }),\n ...(this._token !== undefined && { token: this._token }),\n ...(this._environmentId !== undefined && { environmentId: this._environmentId }),\n sandboxId: forked.id,\n idleTimeoutMinutes: options.idleTimeoutMinutes ?? this._idleTimeoutMinutes,\n networkIsolation: options.networkIsolation ?? this._networkIsolation,\n env: options.env ?? this._env,\n timeout: this._timeout,\n });\n await child._start();\n return child;\n }\n\n // ---------------------------------------------------------------------------\n // Info & Instructions\n // ---------------------------------------------------------------------------\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n metadata: {\n ...(this._sandbox && {\n railwaySandboxId: this._sandbox.id,\n environmentId: this._sandbox.environmentId,\n region: this._sandbox.region,\n networkIsolation: this._sandbox.networkIsolation,\n ...(this._sandbox.idleTimeoutMinutes != null && {\n idleTimeoutMinutes: this._sandbox.idleTimeoutMinutes,\n }),\n }),\n },\n };\n }\n\n getInstructions(): string {\n const defaultInstructions = this._buildDefaultInstructions();\n\n if (typeof this._instructionsOverride === 'string') {\n return this._instructionsOverride;\n }\n if (typeof this._instructionsOverride === 'function') {\n return this._instructionsOverride({ defaultInstructions });\n }\n return defaultInstructions;\n }\n\n private _buildDefaultInstructions(): string {\n const parts: string[] = [];\n parts.push('Railway cloud sandbox: an isolated Debian Linux VM with outbound internet access.');\n\n if (this._networkIsolation === 'PRIVATE') {\n parts.push('Joined to the environment private network.');\n }\n\n if (this._timeout !== undefined) {\n parts.push(`Default command timeout: ${Math.ceil(this._timeout / 1000)}s.`);\n } else {\n parts.push('Commands run until they exit unless a timeout is set.');\n }\n\n if (this._idleTimeoutMinutes !== undefined) {\n parts.push(`Idle timeout: ${this._idleTimeoutMinutes} minute(s).`);\n }\n\n return parts.join(' ');\n }\n\n // ---------------------------------------------------------------------------\n // Command Execution\n // ---------------------------------------------------------------------------\n\n /**\n * Execute a command in the sandbox and return the result.\n */\n async executeCommand(\n command: string,\n args: string[] = [],\n options: ExecuteCommandOptions = {},\n ): Promise<CommandResult> {\n return this.withRestartRetry(async () => {\n const fullCommand = args.length > 0 ? `${command} ${args.map(shellQuote).join(' ')}` : command;\n const timeout = options.timeout ?? this._timeout;\n const env = options.env\n ? Object.fromEntries(\n Object.entries(options.env).filter((entry): entry is [string, string] => entry[1] !== undefined),\n )\n : undefined;\n const startedAt = Date.now();\n const result = await this.railway.exec(fullCommand, {\n ...(timeout !== undefined && { timeoutSec: Math.ceil(timeout / 1000) }),\n ...(options.cwd !== undefined && { cwd: options.cwd }),\n ...(env !== undefined && { env }),\n });\n const exitCode = result.exitCode ?? -1;\n return {\n success: exitCode === 0,\n exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n executionTimeMs: Date.now() - startedAt,\n command,\n args,\n timedOut: result.timedOut,\n };\n });\n }\n}\n","/**\n * Railway sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { railwaySandboxProvider } from '@mastra/railway';\n *\n * const editor = new MastraEditor({\n * sandboxes: { [railwaySandboxProvider.id]: railwaySandboxProvider },\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { RailwaySandbox } from './sandbox';\n\n/**\n * Serializable subset of RailwaySandboxOptions for editor storage.\n */\ninterface RailwayProviderConfig {\n token?: string;\n environmentId?: string;\n sandboxId?: string;\n idleTimeoutMinutes?: number;\n networkIsolation?: 'ISOLATED' | 'PRIVATE';\n env?: Record<string, string>;\n timeout?: number;\n}\n\nexport const railwaySandboxProvider: SandboxProvider<RailwayProviderConfig> = {\n id: 'railway',\n name: 'Railway Sandbox',\n description: 'Ephemeral, isolated Linux VM powered by Railway',\n configSchema: {\n type: 'object',\n properties: {\n token: { type: 'string', description: 'Railway API token (falls back to RAILWAY_API_TOKEN)' },\n environmentId: {\n type: 'string',\n description: 'Railway environment ID (falls back to RAILWAY_ENVIRONMENT_ID)',\n },\n sandboxId: { type: 'string', description: 'Reattach to an existing Railway sandbox by ID' },\n idleTimeoutMinutes: {\n type: 'number',\n description: 'Minutes a sandbox can sit idle before Railway destroys it',\n },\n networkIsolation: {\n type: 'string',\n description: 'Network isolation mode',\n enum: ['ISOLATED', 'PRIVATE'],\n default: 'ISOLATED',\n },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n timeout: { type: 'number', description: 'Default command timeout in ms' },\n },\n },\n createSandbox: config => new RailwaySandbox(config),\n};\n"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { RailwaySandbox, type RailwaySandboxOptions } from './sandbox/index.js';
2
2
  export { RailwayProcessManager, type RailwayProcessManagerOptions } from './sandbox/process-manager.js';
3
3
  export { railwaySandboxProvider } from './provider.js';
4
+ export { SandboxFileNotFoundError } from 'railway';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AACrG,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AACrG,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { SandboxProcessManager, MastraSandbox, SandboxNotReadyError, ProcessHandle } from '@mastra/core/workspace';
2
- import { Sandbox } from 'railway';
2
+ import { Sandbox, SandboxNotFoundError, SandboxFailedError, SandboxTimeoutError } from 'railway';
3
+ export { SandboxFileNotFoundError } from 'railway';
3
4
 
4
5
  // src/sandbox/index.ts
5
6
 
@@ -131,9 +132,12 @@ var RailwaySandbox = class _RailwaySandbox extends MastraSandbox {
131
132
  status = "pending";
132
133
  _sandbox = null;
133
134
  _createdAt = null;
135
+ _checkpointRefreshTimer = null;
136
+ _checkpointRefreshInFlight = null;
134
137
  _token;
135
138
  _environmentId;
136
139
  _sandboxId;
140
+ _checkpointName;
137
141
  _idleTimeoutMinutes;
138
142
  _networkIsolation;
139
143
  _env;
@@ -150,6 +154,7 @@ var RailwaySandbox = class _RailwaySandbox extends MastraSandbox {
150
154
  this._token = options.token ?? process.env.RAILWAY_API_TOKEN;
151
155
  this._environmentId = options.environmentId ?? process.env.RAILWAY_ENVIRONMENT_ID;
152
156
  this._sandboxId = options.sandboxId;
157
+ this._checkpointName = options.checkpointName;
153
158
  this._idleTimeoutMinutes = options.idleTimeoutMinutes;
154
159
  this._networkIsolation = options.networkIsolation;
155
160
  this._env = options.env ?? {};
@@ -184,29 +189,230 @@ var RailwaySandbox = class _RailwaySandbox extends MastraSandbox {
184
189
  if (this._sandbox) {
185
190
  return;
186
191
  }
187
- const clientConfig = {
192
+ await this._startRailwaySandbox({ reconnectSandboxId: this._sandboxId, fallbackToCreate: false });
193
+ }
194
+ async restart() {
195
+ const reconnectSandboxId = this._sandbox?.id ?? this._sandboxId;
196
+ this._cancelCheckpointRefresh();
197
+ await this._checkpointRefreshInFlight?.catch((error) => {
198
+ this.logger.warn(`${LOG_PREFIX} Failed to flush in-flight checkpoint before restart:`, error);
199
+ });
200
+ this._sandbox = null;
201
+ this._createdAt = null;
202
+ this.status = "starting";
203
+ try {
204
+ await this._startRailwaySandbox({ reconnectSandboxId, fallbackToCreate: true });
205
+ this.status = "running";
206
+ } catch (error) {
207
+ this.status = "error";
208
+ throw error;
209
+ }
210
+ }
211
+ async withRestartRetry(operation) {
212
+ await this.ensureRunning();
213
+ try {
214
+ return await operation();
215
+ } catch (error) {
216
+ if (!this.isSandboxUnavailableError(error)) {
217
+ throw error;
218
+ }
219
+ await this.restart();
220
+ return await operation();
221
+ } finally {
222
+ this._scheduleCheckpointRefresh();
223
+ }
224
+ }
225
+ async _startRailwaySandbox({
226
+ reconnectSandboxId,
227
+ fallbackToCreate
228
+ }) {
229
+ const clientConfig = this._clientConfig();
230
+ const createOptions = this._createOptions(clientConfig);
231
+ this._sandbox = reconnectSandboxId ? await this._reconnectSandbox(reconnectSandboxId, fallbackToCreate, clientConfig, createOptions) : await this._createNewSandbox(createOptions);
232
+ this._createdAt = this._sandbox.createdAt ? new Date(this._sandbox.createdAt) : /* @__PURE__ */ new Date();
233
+ this.logger.debug(`${LOG_PREFIX} Railway sandbox ${this._sandbox.id} ready for logical ID: ${this.id}`);
234
+ this._scheduleCheckpointRefresh();
235
+ }
236
+ /**
237
+ * Reconnect to an existing Railway sandbox, creating a fresh one when
238
+ * `fallbackToCreate` is set and the sandbox is unavailable or not running.
239
+ */
240
+ async _reconnectSandbox(reconnectSandboxId, fallbackToCreate, clientConfig, createOptions) {
241
+ this.logger.debug(`${LOG_PREFIX} Reconnecting to Railway sandbox ${reconnectSandboxId}...`);
242
+ let connectedSandbox;
243
+ try {
244
+ connectedSandbox = await Sandbox.connect(reconnectSandboxId, clientConfig);
245
+ } catch (error) {
246
+ if (!fallbackToCreate || !this.isSandboxUnavailableError(error)) {
247
+ throw error;
248
+ }
249
+ return this._createNewSandbox(createOptions);
250
+ }
251
+ if (connectedSandbox.status === "RUNNING") {
252
+ return connectedSandbox;
253
+ }
254
+ if (!fallbackToCreate) {
255
+ throw new Error(`Railway sandbox ${reconnectSandboxId} is not running (status: ${connectedSandbox.status})`);
256
+ }
257
+ return this._createNewSandbox(createOptions);
258
+ }
259
+ _clientConfig() {
260
+ return {
188
261
  ...this._token !== void 0 && { token: this._token },
189
262
  ...this._environmentId !== void 0 && { environmentId: this._environmentId }
190
263
  };
191
- const createOptions = {
264
+ }
265
+ _createOptions(clientConfig) {
266
+ return {
192
267
  ...clientConfig,
193
268
  ...this._idleTimeoutMinutes !== void 0 && { idleTimeoutMinutes: this._idleTimeoutMinutes },
194
269
  ...this._networkIsolation !== void 0 && { networkIsolation: this._networkIsolation },
195
270
  ...Object.keys(this._env).length > 0 && { env: this._env }
196
271
  };
197
- if (this._sandboxId) {
198
- this.logger.debug(`${LOG_PREFIX} Reconnecting to Railway sandbox ${this._sandboxId}...`);
199
- this._sandbox = await Sandbox.connect(this._sandboxId, clientConfig);
200
- } else if (this._templateOption) {
272
+ }
273
+ async _createNewSandbox(createOptions) {
274
+ const checkpointSandbox = await this._tryCreateFromCheckpoint(createOptions);
275
+ if (checkpointSandbox) {
276
+ return checkpointSandbox;
277
+ }
278
+ if (this._templateOption) {
201
279
  const template = this._resolveTemplate();
202
280
  this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from template for: ${this.id}`);
203
- this._sandbox = await Sandbox.create(template, createOptions);
204
- } else {
205
- this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox for: ${this.id}`);
206
- this._sandbox = await Sandbox.create(createOptions);
281
+ const sandbox2 = await Sandbox.create(template, createOptions);
282
+ await this._checkpointSandbox(sandbox2);
283
+ return sandbox2;
284
+ }
285
+ this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox for: ${this.id}`);
286
+ const sandbox = await Sandbox.create(createOptions);
287
+ await this._checkpointSandbox(sandbox);
288
+ return sandbox;
289
+ }
290
+ async _tryCreateFromCheckpoint(createOptions) {
291
+ if (!this._checkpointName) {
292
+ return void 0;
293
+ }
294
+ this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from checkpoint ${this._checkpointName} for: ${this.id}`);
295
+ try {
296
+ const sandbox = await Sandbox.create(this._checkpointName, createOptions);
297
+ return sandbox;
298
+ } catch (error) {
299
+ if (!this.isCheckpointUnavailableError(error)) {
300
+ throw error;
301
+ }
302
+ return void 0;
303
+ }
304
+ }
305
+ async _checkpointSandbox(sandbox) {
306
+ if (!this._checkpointName) {
307
+ return;
308
+ }
309
+ try {
310
+ this.logger.debug(`${LOG_PREFIX} Capturing Railway sandbox checkpoint ${this._checkpointName} for: ${this.id}`);
311
+ await sandbox.checkpoint(this._checkpointName);
312
+ } catch (error) {
313
+ if (!this.isCheckpointAlreadyExistsError(error)) {
314
+ throw error;
315
+ }
316
+ await this._deleteCheckpointByName(this._checkpointName);
317
+ await sandbox.checkpoint(this._checkpointName);
207
318
  }
208
- this._createdAt = this._sandbox.createdAt ? new Date(this._sandbox.createdAt) : /* @__PURE__ */ new Date();
209
- this.logger.debug(`${LOG_PREFIX} Railway sandbox ${this._sandbox.id} ready for logical ID: ${this.id}`);
319
+ }
320
+ async _deleteCheckpointByName(name) {
321
+ try {
322
+ const checkpoint = (await Sandbox.checkpoints(this._clientConfig())).find((checkpoint2) => checkpoint2.key === name);
323
+ if (!checkpoint) {
324
+ return;
325
+ }
326
+ await Sandbox.deleteCheckpoint(checkpoint.id, this._clientConfig());
327
+ } catch (error) {
328
+ if (!this.isCheckpointUnavailableError(error)) {
329
+ throw error;
330
+ }
331
+ }
332
+ }
333
+ _scheduleCheckpointRefresh() {
334
+ if (!this._checkpointName || !this._sandbox) {
335
+ return;
336
+ }
337
+ const idleTimeoutMinutes = this._idleTimeoutMinutes ?? this._sandbox.idleTimeoutMinutes;
338
+ if (!idleTimeoutMinutes) {
339
+ return;
340
+ }
341
+ if (this._checkpointRefreshTimer) {
342
+ clearTimeout(this._checkpointRefreshTimer);
343
+ }
344
+ const delayMs = Math.max(1e3, idleTimeoutMinutes * 6e4 - 1e4);
345
+ this._checkpointRefreshTimer = setTimeout(() => {
346
+ this._checkpointRefreshTimer = null;
347
+ const sandbox = this._sandbox;
348
+ if (!sandbox) {
349
+ return;
350
+ }
351
+ const refresh = this._checkpointSandbox(sandbox).finally(() => {
352
+ if (this._checkpointRefreshInFlight === refresh) {
353
+ this._checkpointRefreshInFlight = null;
354
+ }
355
+ });
356
+ this._checkpointRefreshInFlight = refresh;
357
+ this._checkpointRefreshInFlight.catch((error) => {
358
+ this.logger.warn(`${LOG_PREFIX} Failed to refresh Railway sandbox checkpoint ${this._checkpointName}:`, error);
359
+ });
360
+ }, delayMs);
361
+ this._checkpointRefreshTimer.unref?.();
362
+ }
363
+ _cancelCheckpointRefresh() {
364
+ if (this._checkpointRefreshTimer) {
365
+ clearTimeout(this._checkpointRefreshTimer);
366
+ this._checkpointRefreshTimer = null;
367
+ }
368
+ }
369
+ async _flushCheckpointRefresh() {
370
+ this._cancelCheckpointRefresh();
371
+ if (this._checkpointRefreshInFlight) {
372
+ await this._checkpointRefreshInFlight;
373
+ return;
374
+ }
375
+ if (this._sandbox) {
376
+ await this._checkpointSandbox(this._sandbox);
377
+ }
378
+ }
379
+ isCheckpointUnavailableError(error) {
380
+ if (!(error instanceof Error)) {
381
+ return false;
382
+ }
383
+ const message = error.message.toLowerCase();
384
+ return message.includes("checkpoint") && ["not found", "does not exist", "missing", "unknown", "no checkpoint"].some((phrase) => message.includes(phrase));
385
+ }
386
+ isCheckpointAlreadyExistsError(error) {
387
+ if (!(error instanceof Error)) {
388
+ return false;
389
+ }
390
+ const message = error.message.toLowerCase();
391
+ return message.includes("checkpoint") && (["already exists", "must be unused", "unique"].some((phrase) => message.includes(phrase)) || message.includes("name") && message.includes("used"));
392
+ }
393
+ isSandboxUnavailableError(error, seen = /* @__PURE__ */ new Set()) {
394
+ if (error && typeof error === "object") {
395
+ if (seen.has(error)) return false;
396
+ seen.add(error);
397
+ }
398
+ if (error instanceof SandboxNotFoundError || error instanceof SandboxFailedError || error instanceof SandboxTimeoutError && error.resource === "sandbox") {
399
+ return true;
400
+ }
401
+ if (error && typeof error === "object") {
402
+ const errorLike = error;
403
+ const name = typeof errorLike.name === "string" ? errorLike.name : "";
404
+ const message = typeof errorLike.message === "string" ? errorLike.message.toLowerCase() : "";
405
+ if (name === "SandboxNotFoundError" || name === "SandboxFailedError" || name === "SandboxTimeoutError" && errorLike.resource === "sandbox") {
406
+ return true;
407
+ }
408
+ if (message.includes("sandbox") && ["not found", "destroyed", "failed", "not running", "unavailable"].some((phrase) => message.includes(phrase))) {
409
+ return true;
410
+ }
411
+ if (errorLike.cause !== void 0) {
412
+ return this.isSandboxUnavailableError(errorLike.cause, seen);
413
+ }
414
+ }
415
+ return false;
210
416
  }
211
417
  /**
212
418
  * Stop the Railway sandbox.
@@ -225,9 +431,15 @@ var RailwaySandbox = class _RailwaySandbox extends MastraSandbox {
225
431
  }
226
432
  async _teardown() {
227
433
  if (!this._sandbox) {
434
+ this._cancelCheckpointRefresh();
228
435
  return;
229
436
  }
230
437
  const sandbox = this._sandbox;
438
+ try {
439
+ await this._flushCheckpointRefresh();
440
+ } catch (error) {
441
+ this.logger.warn(`${LOG_PREFIX} Failed to flush checkpoint before teardown:`, error);
442
+ }
231
443
  this._sandbox = null;
232
444
  try {
233
445
  await sandbox.destroy();
@@ -330,15 +542,30 @@ var RailwaySandbox = class _RailwaySandbox extends MastraSandbox {
330
542
  * Execute a command in the sandbox and return the result.
331
543
  */
332
544
  async executeCommand(command, args = [], options = {}) {
333
- await this.ensureRunning();
334
- const fullCommand = args.length > 0 ? `${command} ${args.map(shellQuote).join(" ")}` : command;
335
- const effectiveOptions = {
336
- ...options,
337
- timeout: options.timeout ?? this._timeout
338
- };
339
- const handle = await this.processes.spawn(fullCommand, effectiveOptions);
340
- const result = await handle.wait();
341
- return { ...result, command, args };
545
+ return this.withRestartRetry(async () => {
546
+ const fullCommand = args.length > 0 ? `${command} ${args.map(shellQuote).join(" ")}` : command;
547
+ const timeout = options.timeout ?? this._timeout;
548
+ const env = options.env ? Object.fromEntries(
549
+ Object.entries(options.env).filter((entry) => entry[1] !== void 0)
550
+ ) : void 0;
551
+ const startedAt = Date.now();
552
+ const result = await this.railway.exec(fullCommand, {
553
+ ...timeout !== void 0 && { timeoutSec: Math.ceil(timeout / 1e3) },
554
+ ...options.cwd !== void 0 && { cwd: options.cwd },
555
+ ...env !== void 0 && { env }
556
+ });
557
+ const exitCode = result.exitCode ?? -1;
558
+ return {
559
+ success: exitCode === 0,
560
+ exitCode,
561
+ stdout: result.stdout,
562
+ stderr: result.stderr,
563
+ executionTimeMs: Date.now() - startedAt,
564
+ command,
565
+ args,
566
+ timedOut: result.timedOut
567
+ };
568
+ });
342
569
  }
343
570
  };
344
571
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/shell-quote.ts","../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../src/provider.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Shell-quote a single argument for safe use in a command string.\n *\n * Arguments containing only safe characters are returned as-is.\n * All others are wrapped in single quotes with embedded single quotes escaped.\n */\nexport function shellQuote(arg: string): string {\n // Safe characters that don't need quoting\n if (/^[a-zA-Z0-9._\\-/@:=]+$/.test(arg)) return arg;\n // Wrap in single quotes, escaping any embedded single quotes\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n","/**\n * Railway Process Manager\n *\n * Implements SandboxProcessManager for Railway sandboxes.\n * Wraps the Railway SDK's `Sandbox.exec()` API.\n *\n * Railway's `exec(command, options)` accepts per-call `cwd` and `env` options\n * (since SDK v3.3.1) and returns an `ExecHandle` that runs the command\n * server-side, independently of the client. Each spawn() starts one exec.\n * The handle streams output via `onStdout`/`onStderr` callbacks wired to\n * `emitStdout`/`emitStderr`, exposes a durable `sessionName`, and can be\n * terminated with `kill(signal)`.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ExecHandle, ExecResult } from 'railway';\nimport type { RailwaySandbox } from './index';\n\nexport const LOG_PREFIX = '[RailwaySandbox]';\n\n// =============================================================================\n// Railway Process Handle\n// =============================================================================\n\n/**\n * Wraps a Railway ExecHandle to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n */\nclass RailwayProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _execHandle: ExecHandle;\n private readonly _startTime: number;\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _killed = false;\n\n constructor(pid: string, execHandle: ExecHandle, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._execHandle = execHandle;\n this._startTime = startTime;\n\n // Resolve exit code once the command completes so exitCode is available\n // without an explicit wait().\n void this._execHandle.then(\n (result: ExecResult) => {\n // -1 means terminated by a signal (e.g. after kill()).\n this._exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n },\n () => {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n },\n );\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n async wait(): Promise<CommandResult> {\n // Idempotent — cache the promise so repeated calls return the same result.\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n try {\n const result = await this._execHandle;\n const exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n this._exitCode = exitCode;\n\n // Railway captures output server-side; surface it through the base buffers\n // if streaming callbacks didn't already populate them.\n if (result.stdout && !this.stdout) this.emitStdout(result.stdout);\n if (result.stderr && !this.stderr) this.emitStderr(result.stderr);\n\n return {\n success: exitCode === 0,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n timedOut: result.timedOut,\n };\n } catch (error) {\n const exitCode = this._exitCode ?? 1;\n this._exitCode = exitCode;\n return {\n success: false,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr || (error instanceof Error ? error.message : String(error)),\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n };\n }\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n try {\n return await this._execHandle.kill('TERM');\n } catch {\n // Command may already be gone.\n return false;\n }\n }\n\n async sendStdin(_data: string): Promise<void> {\n // Railway's exec API does not expose stdin streaming.\n throw new Error(`${LOG_PREFIX} sending stdin is not supported by the Railway sandbox provider`);\n }\n}\n\n// =============================================================================\n// Railway Process Manager\n// =============================================================================\n\nexport interface RailwayProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Railway implementation of SandboxProcessManager.\n * Uses the Railway SDK's `Sandbox.exec()` with one exec per spawned process.\n */\nexport class RailwayProcessManager extends SandboxProcessManager<RailwaySandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: RailwayProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n const railway = this.sandbox.railway;\n\n // Merge default env with per-spawn env.\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n const pid = `railway-proc-${Date.now().toString(36)}-${(this._spawnCounter++).toString(36)}`;\n\n // Deferred reference — callbacks fire asynchronously after the handle is\n // assigned, so `handle` is always defined by the time they run.\n let handle: RailwayProcessHandle;\n\n const execHandle = railway.exec(command, {\n ...(options.timeout !== undefined && { timeoutSec: Math.ceil(options.timeout / 1000) }),\n ...(options.cwd !== undefined && { cwd: options.cwd }),\n ...(Object.keys(env).length > 0 && { env }),\n onStdout: (chunk: string) => handle.emitStdout(chunk),\n onStderr: (chunk: string) => handle.emitStderr(chunk),\n });\n\n handle = new RailwayProcessHandle(pid, execHandle, Date.now(), options);\n this._tracked.set(handle.pid, handle);\n return handle;\n }\n\n /**\n * List tracked processes.\n *\n * Railway has no API to enumerate running exec sessions by sandbox, so this\n * reports the processes this manager spawned.\n */\n async list(): Promise<ProcessInfo[]> {\n return Array.from(this._tracked.values()).map(handle => ({\n pid: handle.pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n ...(handle.exitCode !== undefined && { exitCode: handle.exitCode }),\n }));\n }\n}\n","/**\n * Railway Sandbox Provider\n *\n * A Railway sandbox implementation for Mastra workspaces. Provisions an\n * ephemeral, isolated Linux VM on Railway, runs commands in it via the\n * Railway TypeScript SDK, and destroys it on teardown.\n *\n * @see https://docs.railway.com/sandboxes\n */\n\nimport type {\n CommandResult,\n ExecuteCommandOptions,\n InstructionsOption,\n MastraSandboxOptions,\n ProviderStatus,\n SandboxInfo,\n} from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { Sandbox } from 'railway';\nimport type { SandboxNetworkIsolation, SandboxTemplate } from 'railway';\nimport { shellQuote } from '../utils/shell-quote';\nimport { LOG_PREFIX, RailwayProcessManager } from './process-manager';\n\n// =============================================================================\n// Railway Sandbox Options\n// =============================================================================\n\n/**\n * Railway sandbox provider configuration.\n */\nexport interface RailwaySandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance. */\n id?: string;\n /** Railway API token. Falls back to the RAILWAY_API_TOKEN env var. */\n token?: string;\n /** Railway environment ID. Falls back to the RAILWAY_ENVIRONMENT_ID env var. */\n environmentId?: string;\n /**\n * Reattach to an existing Railway sandbox by its Railway ID instead of\n * creating a new one. When set, `start()` calls `Sandbox.connect()`.\n */\n sandboxId?: string;\n /**\n * How long the sandbox can sit idle (no `exec` interaction) before Railway\n * destroys it automatically. Range depends on plan (1–120 minutes on\n * Hobby/Pro, 1–5 on Trial/Free). Defaults to the plan default when omitted.\n */\n idleTimeoutMinutes?: number;\n /**\n * Network isolation mode.\n * - `ISOLATED` (default): outbound internet only, no private network access.\n * - `PRIVATE`: joins the environment's private network.\n */\n networkIsolation?: SandboxNetworkIsolation;\n /** Environment variables baked into the sandbox, available to every command. */\n env?: Record<string, string>;\n /**\n * Provision the sandbox from a custom base image built with the Railway\n * template builder. Use this to pre-install packages or run setup steps so\n * every sandbox created from it starts ready.\n *\n * - Builder callback — receives the base `Sandbox.template()` and returns the\n * configured template. Railway builds the template when `Sandbox.create()`\n * runs during `start()`.\n * ```ts\n * template: t => t.withPackages('git', 'curl').run('npm i -g pnpm')\n * ```\n * - Pre-built `SandboxTemplate` — pass a template to reuse it across\n * sandboxes. Railway still builds the image during sandbox creation.\n *\n * Ignored when `sandboxId` is set (reattach) or when forking.\n */\n template?: SandboxTemplate | ((base: SandboxTemplate) => SandboxTemplate);\n /**\n * Default execution timeout in milliseconds applied to commands that don't\n * specify their own timeout. When omitted, commands run until they exit.\n */\n timeout?: number;\n /**\n * Custom instructions that override the default instructions returned by\n * `getInstructions()`.\n *\n * - `string` — Fully replaces the default instructions. Pass an empty string\n * to suppress instructions entirely.\n * - `(opts) => string` — Receives the default instructions and optional\n * request context so you can extend or customise per-request.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// Railway Sandbox Implementation\n// =============================================================================\n\n/**\n * Railway sandbox provider for Mastra workspaces.\n *\n * Features:\n * - Ephemeral, isolated Linux VM via the Railway TypeScript SDK\n * - Command execution with streaming output and timeouts\n * - Configurable idle timeout and network isolation\n * - Reattach to an existing sandbox by Railway ID\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { RailwaySandbox } from '@mastra/railway';\n *\n * const sandbox = new RailwaySandbox({\n * // token + environmentId read from RAILWAY_API_TOKEN / RAILWAY_ENVIRONMENT_ID\n * idleTimeoutMinutes: 30,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example Private networking\n * ```typescript\n * const sandbox = new RailwaySandbox({\n * networkIsolation: 'PRIVATE',\n * env: { NODE_ENV: 'production' },\n * });\n * ```\n */\nexport class RailwaySandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'RailwaySandbox';\n readonly provider = 'railway';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: RailwayProcessManager;\n\n private _sandbox: Sandbox | null = null;\n private _createdAt: Date | null = null;\n\n private readonly _token?: string;\n private readonly _environmentId?: string;\n private readonly _sandboxId?: string;\n private readonly _idleTimeoutMinutes?: number;\n private readonly _networkIsolation?: SandboxNetworkIsolation;\n private readonly _env: Record<string, string>;\n private readonly _timeout?: number;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _templateOption?: RailwaySandboxOptions['template'];\n\n constructor(options: RailwaySandboxOptions = {}) {\n super({\n ...options,\n name: 'RailwaySandbox',\n processes: new RailwayProcessManager({ env: options.env }),\n });\n\n this.id = options.id ?? this.generateId();\n this._token = options.token ?? process.env.RAILWAY_API_TOKEN;\n this._environmentId = options.environmentId ?? process.env.RAILWAY_ENVIRONMENT_ID;\n this._sandboxId = options.sandboxId;\n this._idleTimeoutMinutes = options.idleTimeoutMinutes;\n this._networkIsolation = options.networkIsolation;\n this._env = options.env ?? {};\n this._timeout = options.timeout;\n this._instructionsOverride = options.instructions;\n this._templateOption = options.template;\n }\n\n private generateId(): string {\n return `railway-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /**\n * Get the underlying Railway Sandbox instance for direct SDK access.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get railway(): Sandbox {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sandbox;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Start the Railway sandbox.\n *\n * Reattaches to an existing sandbox when `sandboxId` is configured,\n * otherwise provisions a new one. Resolves once the sandbox is RUNNING.\n */\n async start(): Promise<void> {\n if (this._sandbox) {\n return;\n }\n\n const clientConfig = {\n ...(this._token !== undefined && { token: this._token }),\n ...(this._environmentId !== undefined && { environmentId: this._environmentId }),\n };\n\n const createOptions = {\n ...clientConfig,\n ...(this._idleTimeoutMinutes !== undefined && { idleTimeoutMinutes: this._idleTimeoutMinutes }),\n ...(this._networkIsolation !== undefined && { networkIsolation: this._networkIsolation }),\n ...(Object.keys(this._env).length > 0 && { env: this._env }),\n };\n\n if (this._sandboxId) {\n this.logger.debug(`${LOG_PREFIX} Reconnecting to Railway sandbox ${this._sandboxId}...`);\n this._sandbox = await Sandbox.connect(this._sandboxId, clientConfig);\n } else if (this._templateOption) {\n const template = this._resolveTemplate();\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from template for: ${this.id}`);\n this._sandbox = await Sandbox.create(template, createOptions);\n } else {\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox for: ${this.id}`);\n this._sandbox = await Sandbox.create(createOptions);\n }\n\n this._createdAt = this._sandbox.createdAt ? new Date(this._sandbox.createdAt) : new Date();\n this.logger.debug(`${LOG_PREFIX} Railway sandbox ${this._sandbox.id} ready for logical ID: ${this.id}`);\n }\n\n /**\n * Stop the Railway sandbox.\n *\n * Railway sandboxes have no separate \"stopped\" state — they're either\n * running or destroyed — so stopping destroys the sandbox.\n */\n async stop(): Promise<void> {\n await this._teardown();\n }\n\n /**\n * Destroy the Railway sandbox and release its resources.\n */\n async destroy(): Promise<void> {\n await this._teardown();\n }\n\n private async _teardown(): Promise<void> {\n if (!this._sandbox) {\n return;\n }\n const sandbox = this._sandbox;\n this._sandbox = null;\n try {\n await sandbox.destroy();\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Failed to destroy Railway sandbox ${sandbox.id}:`, error);\n }\n }\n\n /**\n * Resolve the configured template into a `SandboxTemplate` that Railway\n * builds during `Sandbox.create()`. Accepts either a pre-built\n * `SandboxTemplate` or a builder callback over `Sandbox.template()`.\n */\n private _resolveTemplate(): SandboxTemplate {\n const option = this._templateOption!;\n return typeof option === 'function' ? option(Sandbox.template()) : option;\n }\n\n /**\n * Fork this running sandbox into a new, independent `RailwaySandbox`.\n *\n * Clones the filesystem (a fresh boot, not live processes) into the same\n * environment. The returned sandbox is already started and reattached to the\n * forked Railway sandbox; it inherits this sandbox's credentials and defaults\n * unless overridden via `options`.\n *\n * @throws {SandboxNotReadyError} If this sandbox has not been started.\n */\n async fork(\n options: Pick<RailwaySandboxOptions, 'id' | 'idleTimeoutMinutes' | 'networkIsolation' | 'env'> = {},\n ): Promise<RailwaySandbox> {\n const source = this.railway;\n const forked = await source.fork({\n ...(options.idleTimeoutMinutes !== undefined && { idleTimeoutMinutes: options.idleTimeoutMinutes }),\n ...(options.networkIsolation !== undefined && { networkIsolation: options.networkIsolation }),\n ...(options.env !== undefined && { env: options.env }),\n });\n\n const child = new RailwaySandbox({\n ...(options.id !== undefined && { id: options.id }),\n ...(this._token !== undefined && { token: this._token }),\n ...(this._environmentId !== undefined && { environmentId: this._environmentId }),\n sandboxId: forked.id,\n idleTimeoutMinutes: options.idleTimeoutMinutes ?? this._idleTimeoutMinutes,\n networkIsolation: options.networkIsolation ?? this._networkIsolation,\n env: options.env ?? this._env,\n timeout: this._timeout,\n });\n await child._start();\n return child;\n }\n\n // ---------------------------------------------------------------------------\n // Info & Instructions\n // ---------------------------------------------------------------------------\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n metadata: {\n ...(this._sandbox && {\n railwaySandboxId: this._sandbox.id,\n environmentId: this._sandbox.environmentId,\n region: this._sandbox.region,\n networkIsolation: this._sandbox.networkIsolation,\n ...(this._sandbox.idleTimeoutMinutes != null && {\n idleTimeoutMinutes: this._sandbox.idleTimeoutMinutes,\n }),\n }),\n },\n };\n }\n\n getInstructions(): string {\n const defaultInstructions = this._buildDefaultInstructions();\n\n if (typeof this._instructionsOverride === 'string') {\n return this._instructionsOverride;\n }\n if (typeof this._instructionsOverride === 'function') {\n return this._instructionsOverride({ defaultInstructions });\n }\n return defaultInstructions;\n }\n\n private _buildDefaultInstructions(): string {\n const parts: string[] = [];\n parts.push('Railway cloud sandbox: an isolated Debian Linux VM with outbound internet access.');\n\n if (this._networkIsolation === 'PRIVATE') {\n parts.push('Joined to the environment private network.');\n }\n\n if (this._timeout !== undefined) {\n parts.push(`Default command timeout: ${Math.ceil(this._timeout / 1000)}s.`);\n } else {\n parts.push('Commands run until they exit unless a timeout is set.');\n }\n\n if (this._idleTimeoutMinutes !== undefined) {\n parts.push(`Idle timeout: ${this._idleTimeoutMinutes} minute(s).`);\n }\n\n return parts.join(' ');\n }\n\n // ---------------------------------------------------------------------------\n // Command Execution\n // ---------------------------------------------------------------------------\n\n /**\n * Execute a command in the sandbox and return the result.\n */\n async executeCommand(\n command: string,\n args: string[] = [],\n options: ExecuteCommandOptions = {},\n ): Promise<CommandResult> {\n await this.ensureRunning();\n const fullCommand = args.length > 0 ? `${command} ${args.map(shellQuote).join(' ')}` : command;\n const effectiveOptions: ExecuteCommandOptions = {\n ...options,\n timeout: options.timeout ?? this._timeout,\n };\n const handle = await this.processes.spawn(fullCommand, effectiveOptions);\n const result = await handle.wait();\n return { ...result, command, args };\n }\n}\n","/**\n * Railway sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { railwaySandboxProvider } from '@mastra/railway';\n *\n * const editor = new MastraEditor({\n * sandboxes: { [railwaySandboxProvider.id]: railwaySandboxProvider },\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { RailwaySandbox } from './sandbox';\n\n/**\n * Serializable subset of RailwaySandboxOptions for editor storage.\n */\ninterface RailwayProviderConfig {\n token?: string;\n environmentId?: string;\n sandboxId?: string;\n idleTimeoutMinutes?: number;\n networkIsolation?: 'ISOLATED' | 'PRIVATE';\n env?: Record<string, string>;\n timeout?: number;\n}\n\nexport const railwaySandboxProvider: SandboxProvider<RailwayProviderConfig> = {\n id: 'railway',\n name: 'Railway Sandbox',\n description: 'Ephemeral, isolated Linux VM powered by Railway',\n configSchema: {\n type: 'object',\n properties: {\n token: { type: 'string', description: 'Railway API token (falls back to RAILWAY_API_TOKEN)' },\n environmentId: {\n type: 'string',\n description: 'Railway environment ID (falls back to RAILWAY_ENVIRONMENT_ID)',\n },\n sandboxId: { type: 'string', description: 'Reattach to an existing Railway sandbox by ID' },\n idleTimeoutMinutes: {\n type: 'number',\n description: 'Minutes a sandbox can sit idle before Railway destroys it',\n },\n networkIsolation: {\n type: 'string',\n description: 'Network isolation mode',\n enum: ['ISOLATED', 'PRIVATE'],\n default: 'ISOLATED',\n },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n timeout: { type: 'number', description: 'Default command timeout in ms' },\n },\n },\n createSandbox: config => new RailwaySandbox(config),\n};\n"]}
1
+ {"version":3,"sources":["../src/utils/shell-quote.ts","../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../src/provider.ts"],"names":["sandbox","checkpoint"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Shell-quote a single argument for safe use in a command string.\n *\n * Arguments containing only safe characters are returned as-is.\n * All others are wrapped in single quotes with embedded single quotes escaped.\n */\nexport function shellQuote(arg: string): string {\n // Safe characters that don't need quoting\n if (/^[a-zA-Z0-9._\\-/@:=]+$/.test(arg)) return arg;\n // Wrap in single quotes, escaping any embedded single quotes\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n","/**\n * Railway Process Manager\n *\n * Implements SandboxProcessManager for Railway sandboxes.\n * Wraps the Railway SDK's `Sandbox.exec()` API.\n *\n * Railway's `exec(command, options)` accepts per-call `cwd` and `env` options\n * (since SDK v3.3.1) and returns an `ExecHandle` that runs the command\n * server-side, independently of the client. Each spawn() starts one exec.\n * The handle streams output via `onStdout`/`onStderr` callbacks wired to\n * `emitStdout`/`emitStderr`, exposes a durable `sessionName`, and can be\n * terminated with `kill(signal)`.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ExecHandle, ExecResult } from 'railway';\nimport type { RailwaySandbox } from './index';\n\nexport const LOG_PREFIX = '[RailwaySandbox]';\n\n// =============================================================================\n// Railway Process Handle\n// =============================================================================\n\n/**\n * Wraps a Railway ExecHandle to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n */\nclass RailwayProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _execHandle: ExecHandle;\n private readonly _startTime: number;\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _killed = false;\n\n constructor(pid: string, execHandle: ExecHandle, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._execHandle = execHandle;\n this._startTime = startTime;\n\n // Resolve exit code once the command completes so exitCode is available\n // without an explicit wait().\n void this._execHandle.then(\n (result: ExecResult) => {\n // -1 means terminated by a signal (e.g. after kill()).\n this._exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n },\n () => {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n },\n );\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n async wait(): Promise<CommandResult> {\n // Idempotent — cache the promise so repeated calls return the same result.\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n try {\n const result = await this._execHandle;\n const exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n this._exitCode = exitCode;\n\n // Railway captures output server-side; surface it through the base buffers\n // if streaming callbacks didn't already populate them.\n if (result.stdout && !this.stdout) this.emitStdout(result.stdout);\n if (result.stderr && !this.stderr) this.emitStderr(result.stderr);\n\n return {\n success: exitCode === 0,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n timedOut: result.timedOut,\n };\n } catch (error) {\n const exitCode = this._exitCode ?? 1;\n this._exitCode = exitCode;\n return {\n success: false,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr || (error instanceof Error ? error.message : String(error)),\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n };\n }\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n try {\n return await this._execHandle.kill('TERM');\n } catch {\n // Command may already be gone.\n return false;\n }\n }\n\n async sendStdin(_data: string): Promise<void> {\n // Railway's exec API does not expose stdin streaming.\n throw new Error(`${LOG_PREFIX} sending stdin is not supported by the Railway sandbox provider`);\n }\n}\n\n// =============================================================================\n// Railway Process Manager\n// =============================================================================\n\nexport interface RailwayProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Railway implementation of SandboxProcessManager.\n * Uses the Railway SDK's `Sandbox.exec()` with one exec per spawned process.\n */\nexport class RailwayProcessManager extends SandboxProcessManager<RailwaySandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: RailwayProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n const railway = this.sandbox.railway;\n\n // Merge default env with per-spawn env.\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n const pid = `railway-proc-${Date.now().toString(36)}-${(this._spawnCounter++).toString(36)}`;\n\n // Deferred reference — callbacks fire asynchronously after the handle is\n // assigned, so `handle` is always defined by the time they run.\n let handle: RailwayProcessHandle;\n\n const execHandle = railway.exec(command, {\n ...(options.timeout !== undefined && { timeoutSec: Math.ceil(options.timeout / 1000) }),\n ...(options.cwd !== undefined && { cwd: options.cwd }),\n ...(Object.keys(env).length > 0 && { env }),\n onStdout: (chunk: string) => handle.emitStdout(chunk),\n onStderr: (chunk: string) => handle.emitStderr(chunk),\n });\n\n handle = new RailwayProcessHandle(pid, execHandle, Date.now(), options);\n this._tracked.set(handle.pid, handle);\n return handle;\n }\n\n /**\n * List tracked processes.\n *\n * Railway has no API to enumerate running exec sessions by sandbox, so this\n * reports the processes this manager spawned.\n */\n async list(): Promise<ProcessInfo[]> {\n return Array.from(this._tracked.values()).map(handle => ({\n pid: handle.pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n ...(handle.exitCode !== undefined && { exitCode: handle.exitCode }),\n }));\n }\n}\n","/**\n * Railway Sandbox Provider\n *\n * A Railway sandbox implementation for Mastra workspaces. Provisions an\n * ephemeral, isolated Linux VM on Railway, runs commands in it via the\n * Railway TypeScript SDK, and destroys it on teardown.\n *\n * @see https://docs.railway.com/sandboxes\n */\n\nimport type {\n CommandResult,\n ExecuteCommandOptions,\n InstructionsOption,\n MastraSandboxOptions,\n ProviderStatus,\n SandboxInfo,\n} from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { Sandbox, SandboxFailedError, SandboxNotFoundError, SandboxTimeoutError } from 'railway';\nimport type { SandboxNetworkIsolation, SandboxTemplate } from 'railway';\nimport { shellQuote } from '../utils/shell-quote';\nimport { LOG_PREFIX, RailwayProcessManager } from './process-manager';\n\n// =============================================================================\n// Railway Sandbox Options\n// =============================================================================\n\n/**\n * Railway sandbox provider configuration.\n */\nexport interface RailwaySandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance. */\n id?: string;\n /** Railway API token. Falls back to the RAILWAY_API_TOKEN env var. */\n token?: string;\n /** Railway environment ID. Falls back to the RAILWAY_ENVIRONMENT_ID env var. */\n environmentId?: string;\n /**\n * Reattach to an existing Railway sandbox by its Railway ID instead of\n * creating a new one. When set, `start()` calls `Sandbox.connect()`.\n */\n sandboxId?: string;\n /**\n * Reuse a saved Railway sandbox checkpoint as the baseline filesystem for\n * new sandboxes. When the named checkpoint is missing, the sandbox is created\n * normally and a checkpoint is captured after setup succeeds.\n */\n checkpointName?: string;\n /**\n * How long the sandbox can sit idle (no `exec` interaction) before Railway\n * destroys it automatically. Range depends on plan (1–120 minutes on\n * Hobby/Pro, 1–5 on Trial/Free). Defaults to the plan default when omitted.\n */\n idleTimeoutMinutes?: number;\n /**\n * Network isolation mode.\n * - `ISOLATED` (default): outbound internet only, no private network access.\n * - `PRIVATE`: joins the environment's private network.\n */\n networkIsolation?: SandboxNetworkIsolation;\n /** Environment variables baked into the sandbox, available to every command. */\n env?: Record<string, string>;\n /**\n * Provision the sandbox from a custom base image built with the Railway\n * template builder. Use this to pre-install packages or run setup steps so\n * every sandbox created from it starts ready.\n *\n * - Builder callback — receives the base `Sandbox.template()` and returns the\n * configured template. Railway builds the template when `Sandbox.create()`\n * runs during `start()`.\n * ```ts\n * template: t => t.withPackages('git', 'curl').run('npm i -g pnpm')\n * ```\n * - Pre-built `SandboxTemplate` — pass a template to reuse it across\n * sandboxes. Railway still builds the image during sandbox creation.\n *\n * Ignored when `sandboxId` is set (reattach) or when forking.\n */\n template?: SandboxTemplate | ((base: SandboxTemplate) => SandboxTemplate);\n /**\n * Default execution timeout in milliseconds applied to commands that don't\n * specify their own timeout. When omitted, commands run until they exit.\n */\n timeout?: number;\n /**\n * Custom instructions that override the default instructions returned by\n * `getInstructions()`.\n *\n * - `string` — Fully replaces the default instructions. Pass an empty string\n * to suppress instructions entirely.\n * - `(opts) => string` — Receives the default instructions and optional\n * request context so you can extend or customise per-request.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// Railway Sandbox Implementation\n// =============================================================================\n\n/**\n * Railway sandbox provider for Mastra workspaces.\n *\n * Features:\n * - Ephemeral, isolated Linux VM via the Railway TypeScript SDK\n * - Command execution with streaming output and timeouts\n * - Configurable idle timeout and network isolation\n * - Reattach to an existing sandbox by Railway ID\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { RailwaySandbox } from '@mastra/railway';\n *\n * const sandbox = new RailwaySandbox({\n * // token + environmentId read from RAILWAY_API_TOKEN / RAILWAY_ENVIRONMENT_ID\n * idleTimeoutMinutes: 30,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example Private networking\n * ```typescript\n * const sandbox = new RailwaySandbox({\n * networkIsolation: 'PRIVATE',\n * env: { NODE_ENV: 'production' },\n * });\n * ```\n */\nexport class RailwaySandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'RailwaySandbox';\n readonly provider = 'railway';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: RailwayProcessManager;\n\n private _sandbox: Sandbox | null = null;\n private _createdAt: Date | null = null;\n private _checkpointRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _checkpointRefreshInFlight: Promise<void> | null = null;\n\n private readonly _token?: string;\n private readonly _environmentId?: string;\n private readonly _sandboxId?: string;\n private readonly _checkpointName?: string;\n private readonly _idleTimeoutMinutes?: number;\n private readonly _networkIsolation?: SandboxNetworkIsolation;\n private readonly _env: Record<string, string>;\n private readonly _timeout?: number;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _templateOption?: RailwaySandboxOptions['template'];\n\n constructor(options: RailwaySandboxOptions = {}) {\n super({\n ...options,\n name: 'RailwaySandbox',\n processes: new RailwayProcessManager({ env: options.env }),\n });\n\n this.id = options.id ?? this.generateId();\n this._token = options.token ?? process.env.RAILWAY_API_TOKEN;\n this._environmentId = options.environmentId ?? process.env.RAILWAY_ENVIRONMENT_ID;\n this._sandboxId = options.sandboxId;\n this._checkpointName = options.checkpointName;\n this._idleTimeoutMinutes = options.idleTimeoutMinutes;\n this._networkIsolation = options.networkIsolation;\n this._env = options.env ?? {};\n this._timeout = options.timeout;\n this._instructionsOverride = options.instructions;\n this._templateOption = options.template;\n }\n\n private generateId(): string {\n return `railway-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /**\n * Get the underlying Railway Sandbox instance for direct SDK access.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get railway(): Sandbox {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sandbox;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Start the Railway sandbox.\n *\n * Reattaches to an existing sandbox when `sandboxId` is configured,\n * otherwise provisions a new one. Resolves once the sandbox is RUNNING.\n */\n async start(): Promise<void> {\n if (this._sandbox) {\n return;\n }\n\n await this._startRailwaySandbox({ reconnectSandboxId: this._sandboxId, fallbackToCreate: false });\n }\n\n async restart(): Promise<void> {\n const reconnectSandboxId = this._sandbox?.id ?? this._sandboxId;\n this._cancelCheckpointRefresh();\n await this._checkpointRefreshInFlight?.catch(error => {\n this.logger.warn(`${LOG_PREFIX} Failed to flush in-flight checkpoint before restart:`, error);\n });\n this._sandbox = null;\n this._createdAt = null;\n this.status = 'starting';\n\n try {\n await this._startRailwaySandbox({ reconnectSandboxId, fallbackToCreate: true });\n this.status = 'running';\n } catch (error) {\n this.status = 'error';\n throw error;\n }\n }\n\n async withRestartRetry<T>(operation: () => Promise<T>): Promise<T> {\n await this.ensureRunning();\n try {\n return await operation();\n } catch (error) {\n if (!this.isSandboxUnavailableError(error)) {\n throw error;\n }\n\n await this.restart();\n return await operation();\n } finally {\n this._scheduleCheckpointRefresh();\n }\n }\n\n private async _startRailwaySandbox({\n reconnectSandboxId,\n fallbackToCreate,\n }: {\n reconnectSandboxId?: string;\n fallbackToCreate: boolean;\n }): Promise<void> {\n const clientConfig = this._clientConfig();\n const createOptions = this._createOptions(clientConfig);\n\n this._sandbox = reconnectSandboxId\n ? await this._reconnectSandbox(reconnectSandboxId, fallbackToCreate, clientConfig, createOptions)\n : await this._createNewSandbox(createOptions);\n\n this._createdAt = this._sandbox.createdAt ? new Date(this._sandbox.createdAt) : new Date();\n this.logger.debug(`${LOG_PREFIX} Railway sandbox ${this._sandbox.id} ready for logical ID: ${this.id}`);\n this._scheduleCheckpointRefresh();\n }\n\n /**\n * Reconnect to an existing Railway sandbox, creating a fresh one when\n * `fallbackToCreate` is set and the sandbox is unavailable or not running.\n */\n private async _reconnectSandbox(\n reconnectSandboxId: string,\n fallbackToCreate: boolean,\n clientConfig: { token?: string; environmentId?: string },\n createOptions: ReturnType<RailwaySandbox['_createOptions']>,\n ): Promise<Sandbox> {\n this.logger.debug(`${LOG_PREFIX} Reconnecting to Railway sandbox ${reconnectSandboxId}...`);\n\n let connectedSandbox: Sandbox;\n try {\n connectedSandbox = await Sandbox.connect(reconnectSandboxId, clientConfig);\n } catch (error) {\n if (!fallbackToCreate || !this.isSandboxUnavailableError(error)) {\n throw error;\n }\n return this._createNewSandbox(createOptions);\n }\n\n if (connectedSandbox.status === 'RUNNING') {\n return connectedSandbox;\n }\n\n if (!fallbackToCreate) {\n throw new Error(`Railway sandbox ${reconnectSandboxId} is not running (status: ${connectedSandbox.status})`);\n }\n\n return this._createNewSandbox(createOptions);\n }\n\n private _clientConfig(): { token?: string; environmentId?: string } {\n return {\n ...(this._token !== undefined && { token: this._token }),\n ...(this._environmentId !== undefined && { environmentId: this._environmentId }),\n };\n }\n\n private _createOptions(clientConfig: { token?: string; environmentId?: string }) {\n return {\n ...clientConfig,\n ...(this._idleTimeoutMinutes !== undefined && { idleTimeoutMinutes: this._idleTimeoutMinutes }),\n ...(this._networkIsolation !== undefined && { networkIsolation: this._networkIsolation }),\n ...(Object.keys(this._env).length > 0 && { env: this._env }),\n };\n }\n\n private async _createNewSandbox(createOptions: ReturnType<RailwaySandbox['_createOptions']>): Promise<Sandbox> {\n const checkpointSandbox = await this._tryCreateFromCheckpoint(createOptions);\n if (checkpointSandbox) {\n return checkpointSandbox;\n }\n\n if (this._templateOption) {\n const template = this._resolveTemplate();\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from template for: ${this.id}`);\n const sandbox = await Sandbox.create(template, createOptions);\n await this._checkpointSandbox(sandbox);\n return sandbox;\n }\n\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox for: ${this.id}`);\n const sandbox = await Sandbox.create(createOptions);\n await this._checkpointSandbox(sandbox);\n return sandbox;\n }\n\n private async _tryCreateFromCheckpoint(\n createOptions: ReturnType<RailwaySandbox['_createOptions']>,\n ): Promise<Sandbox | undefined> {\n if (!this._checkpointName) {\n return undefined;\n }\n\n this.logger.debug(`${LOG_PREFIX} Creating Railway sandbox from checkpoint ${this._checkpointName} for: ${this.id}`);\n\n try {\n const sandbox = await Sandbox.create(this._checkpointName, createOptions);\n return sandbox;\n } catch (error) {\n if (!this.isCheckpointUnavailableError(error)) {\n throw error;\n }\n return undefined;\n }\n }\n\n private async _checkpointSandbox(sandbox: Sandbox): Promise<void> {\n if (!this._checkpointName) {\n return;\n }\n\n try {\n this.logger.debug(`${LOG_PREFIX} Capturing Railway sandbox checkpoint ${this._checkpointName} for: ${this.id}`);\n await sandbox.checkpoint(this._checkpointName);\n } catch (error) {\n if (!this.isCheckpointAlreadyExistsError(error)) {\n throw error;\n }\n\n await this._deleteCheckpointByName(this._checkpointName);\n await sandbox.checkpoint(this._checkpointName);\n }\n }\n\n private async _deleteCheckpointByName(name: string): Promise<void> {\n try {\n const checkpoint = (await Sandbox.checkpoints(this._clientConfig())).find(checkpoint => checkpoint.key === name);\n if (!checkpoint) {\n return;\n }\n\n await Sandbox.deleteCheckpoint(checkpoint.id, this._clientConfig());\n } catch (error) {\n if (!this.isCheckpointUnavailableError(error)) {\n throw error;\n }\n }\n }\n\n private _scheduleCheckpointRefresh(): void {\n if (!this._checkpointName || !this._sandbox) {\n return;\n }\n\n const idleTimeoutMinutes = this._idleTimeoutMinutes ?? this._sandbox.idleTimeoutMinutes;\n if (!idleTimeoutMinutes) {\n return;\n }\n\n if (this._checkpointRefreshTimer) {\n clearTimeout(this._checkpointRefreshTimer);\n }\n\n const delayMs = Math.max(1_000, idleTimeoutMinutes * 60_000 - 10_000);\n this._checkpointRefreshTimer = setTimeout(() => {\n this._checkpointRefreshTimer = null;\n const sandbox = this._sandbox;\n if (!sandbox) {\n return;\n }\n\n const refresh = this._checkpointSandbox(sandbox).finally(() => {\n if (this._checkpointRefreshInFlight === refresh) {\n this._checkpointRefreshInFlight = null;\n }\n });\n this._checkpointRefreshInFlight = refresh;\n this._checkpointRefreshInFlight.catch(error => {\n this.logger.warn(`${LOG_PREFIX} Failed to refresh Railway sandbox checkpoint ${this._checkpointName}:`, error);\n });\n }, delayMs);\n this._checkpointRefreshTimer.unref?.();\n }\n\n private _cancelCheckpointRefresh(): void {\n if (this._checkpointRefreshTimer) {\n clearTimeout(this._checkpointRefreshTimer);\n this._checkpointRefreshTimer = null;\n }\n }\n\n private async _flushCheckpointRefresh(): Promise<void> {\n this._cancelCheckpointRefresh();\n\n if (this._checkpointRefreshInFlight) {\n await this._checkpointRefreshInFlight;\n return;\n }\n\n if (this._sandbox) {\n await this._checkpointSandbox(this._sandbox);\n }\n }\n\n private isCheckpointUnavailableError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n const message = error.message.toLowerCase();\n return (\n message.includes('checkpoint') &&\n ['not found', 'does not exist', 'missing', 'unknown', 'no checkpoint'].some(phrase => message.includes(phrase))\n );\n }\n\n private isCheckpointAlreadyExistsError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n const message = error.message.toLowerCase();\n return (\n message.includes('checkpoint') &&\n (['already exists', 'must be unused', 'unique'].some(phrase => message.includes(phrase)) ||\n (message.includes('name') && message.includes('used')))\n );\n }\n\n private isSandboxUnavailableError(error: unknown, seen = new Set<unknown>()): boolean {\n if (error && typeof error === 'object') {\n if (seen.has(error)) return false;\n seen.add(error);\n }\n\n if (\n error instanceof SandboxNotFoundError ||\n error instanceof SandboxFailedError ||\n (error instanceof SandboxTimeoutError && error.resource === 'sandbox')\n ) {\n return true;\n }\n\n if (error && typeof error === 'object') {\n const errorLike = error as { name?: unknown; message?: unknown; resource?: unknown; cause?: unknown };\n const name = typeof errorLike.name === 'string' ? errorLike.name : '';\n const message = typeof errorLike.message === 'string' ? errorLike.message.toLowerCase() : '';\n\n if (\n name === 'SandboxNotFoundError' ||\n name === 'SandboxFailedError' ||\n (name === 'SandboxTimeoutError' && errorLike.resource === 'sandbox')\n ) {\n return true;\n }\n\n if (\n message.includes('sandbox') &&\n ['not found', 'destroyed', 'failed', 'not running', 'unavailable'].some(phrase => message.includes(phrase))\n ) {\n return true;\n }\n\n if (errorLike.cause !== undefined) {\n return this.isSandboxUnavailableError(errorLike.cause, seen);\n }\n }\n\n return false;\n }\n\n /**\n * Stop the Railway sandbox.\n *\n * Railway sandboxes have no separate \"stopped\" state — they're either\n * running or destroyed — so stopping destroys the sandbox.\n */\n async stop(): Promise<void> {\n await this._teardown();\n }\n\n /**\n * Destroy the Railway sandbox and release its resources.\n */\n async destroy(): Promise<void> {\n await this._teardown();\n }\n\n private async _teardown(): Promise<void> {\n if (!this._sandbox) {\n this._cancelCheckpointRefresh();\n return;\n }\n const sandbox = this._sandbox;\n try {\n await this._flushCheckpointRefresh();\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Failed to flush checkpoint before teardown:`, error);\n }\n this._sandbox = null;\n try {\n await sandbox.destroy();\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Failed to destroy Railway sandbox ${sandbox.id}:`, error);\n }\n }\n\n /**\n * Resolve the configured template into a `SandboxTemplate` that Railway\n * builds during `Sandbox.create()`. Accepts either a pre-built\n * `SandboxTemplate` or a builder callback over `Sandbox.template()`.\n */\n private _resolveTemplate(): SandboxTemplate {\n const option = this._templateOption!;\n return typeof option === 'function' ? option(Sandbox.template()) : option;\n }\n\n /**\n * Fork this running sandbox into a new, independent `RailwaySandbox`.\n *\n * Clones the filesystem (a fresh boot, not live processes) into the same\n * environment. The returned sandbox is already started and reattached to the\n * forked Railway sandbox; it inherits this sandbox's credentials and defaults\n * unless overridden via `options`.\n *\n * @throws {SandboxNotReadyError} If this sandbox has not been started.\n */\n async fork(\n options: Pick<RailwaySandboxOptions, 'id' | 'idleTimeoutMinutes' | 'networkIsolation' | 'env'> = {},\n ): Promise<RailwaySandbox> {\n const source = this.railway;\n const forked = await source.fork({\n ...(options.idleTimeoutMinutes !== undefined && { idleTimeoutMinutes: options.idleTimeoutMinutes }),\n ...(options.networkIsolation !== undefined && { networkIsolation: options.networkIsolation }),\n ...(options.env !== undefined && { env: options.env }),\n });\n\n const child = new RailwaySandbox({\n ...(options.id !== undefined && { id: options.id }),\n ...(this._token !== undefined && { token: this._token }),\n ...(this._environmentId !== undefined && { environmentId: this._environmentId }),\n sandboxId: forked.id,\n idleTimeoutMinutes: options.idleTimeoutMinutes ?? this._idleTimeoutMinutes,\n networkIsolation: options.networkIsolation ?? this._networkIsolation,\n env: options.env ?? this._env,\n timeout: this._timeout,\n });\n await child._start();\n return child;\n }\n\n // ---------------------------------------------------------------------------\n // Info & Instructions\n // ---------------------------------------------------------------------------\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n metadata: {\n ...(this._sandbox && {\n railwaySandboxId: this._sandbox.id,\n environmentId: this._sandbox.environmentId,\n region: this._sandbox.region,\n networkIsolation: this._sandbox.networkIsolation,\n ...(this._sandbox.idleTimeoutMinutes != null && {\n idleTimeoutMinutes: this._sandbox.idleTimeoutMinutes,\n }),\n }),\n },\n };\n }\n\n getInstructions(): string {\n const defaultInstructions = this._buildDefaultInstructions();\n\n if (typeof this._instructionsOverride === 'string') {\n return this._instructionsOverride;\n }\n if (typeof this._instructionsOverride === 'function') {\n return this._instructionsOverride({ defaultInstructions });\n }\n return defaultInstructions;\n }\n\n private _buildDefaultInstructions(): string {\n const parts: string[] = [];\n parts.push('Railway cloud sandbox: an isolated Debian Linux VM with outbound internet access.');\n\n if (this._networkIsolation === 'PRIVATE') {\n parts.push('Joined to the environment private network.');\n }\n\n if (this._timeout !== undefined) {\n parts.push(`Default command timeout: ${Math.ceil(this._timeout / 1000)}s.`);\n } else {\n parts.push('Commands run until they exit unless a timeout is set.');\n }\n\n if (this._idleTimeoutMinutes !== undefined) {\n parts.push(`Idle timeout: ${this._idleTimeoutMinutes} minute(s).`);\n }\n\n return parts.join(' ');\n }\n\n // ---------------------------------------------------------------------------\n // Command Execution\n // ---------------------------------------------------------------------------\n\n /**\n * Execute a command in the sandbox and return the result.\n */\n async executeCommand(\n command: string,\n args: string[] = [],\n options: ExecuteCommandOptions = {},\n ): Promise<CommandResult> {\n return this.withRestartRetry(async () => {\n const fullCommand = args.length > 0 ? `${command} ${args.map(shellQuote).join(' ')}` : command;\n const timeout = options.timeout ?? this._timeout;\n const env = options.env\n ? Object.fromEntries(\n Object.entries(options.env).filter((entry): entry is [string, string] => entry[1] !== undefined),\n )\n : undefined;\n const startedAt = Date.now();\n const result = await this.railway.exec(fullCommand, {\n ...(timeout !== undefined && { timeoutSec: Math.ceil(timeout / 1000) }),\n ...(options.cwd !== undefined && { cwd: options.cwd }),\n ...(env !== undefined && { env }),\n });\n const exitCode = result.exitCode ?? -1;\n return {\n success: exitCode === 0,\n exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n executionTimeMs: Date.now() - startedAt,\n command,\n args,\n timedOut: result.timedOut,\n };\n });\n }\n}\n","/**\n * Railway sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { railwaySandboxProvider } from '@mastra/railway';\n *\n * const editor = new MastraEditor({\n * sandboxes: { [railwaySandboxProvider.id]: railwaySandboxProvider },\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { RailwaySandbox } from './sandbox';\n\n/**\n * Serializable subset of RailwaySandboxOptions for editor storage.\n */\ninterface RailwayProviderConfig {\n token?: string;\n environmentId?: string;\n sandboxId?: string;\n idleTimeoutMinutes?: number;\n networkIsolation?: 'ISOLATED' | 'PRIVATE';\n env?: Record<string, string>;\n timeout?: number;\n}\n\nexport const railwaySandboxProvider: SandboxProvider<RailwayProviderConfig> = {\n id: 'railway',\n name: 'Railway Sandbox',\n description: 'Ephemeral, isolated Linux VM powered by Railway',\n configSchema: {\n type: 'object',\n properties: {\n token: { type: 'string', description: 'Railway API token (falls back to RAILWAY_API_TOKEN)' },\n environmentId: {\n type: 'string',\n description: 'Railway environment ID (falls back to RAILWAY_ENVIRONMENT_ID)',\n },\n sandboxId: { type: 'string', description: 'Reattach to an existing Railway sandbox by ID' },\n idleTimeoutMinutes: {\n type: 'number',\n description: 'Minutes a sandbox can sit idle before Railway destroys it',\n },\n networkIsolation: {\n type: 'string',\n description: 'Network isolation mode',\n enum: ['ISOLATED', 'PRIVATE'],\n default: 'ISOLATED',\n },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n timeout: { type: 'number', description: 'Default command timeout in ms' },\n },\n },\n createSandbox: config => new RailwaySandbox(config),\n};\n"]}
@@ -27,6 +27,12 @@ export interface RailwaySandboxOptions extends Omit<MastraSandboxOptions, 'proce
27
27
  * creating a new one. When set, `start()` calls `Sandbox.connect()`.
28
28
  */
29
29
  sandboxId?: string;
30
+ /**
31
+ * Reuse a saved Railway sandbox checkpoint as the baseline filesystem for
32
+ * new sandboxes. When the named checkpoint is missing, the sandbox is created
33
+ * normally and a checkpoint is captured after setup succeeds.
34
+ */
35
+ checkpointName?: string;
30
36
  /**
31
37
  * How long the sandbox can sit idle (no `exec` interaction) before Railway
32
38
  * destroys it automatically. Range depends on plan (1–120 minutes on
@@ -113,9 +119,12 @@ export declare class RailwaySandbox extends MastraSandbox {
113
119
  readonly processes: RailwayProcessManager;
114
120
  private _sandbox;
115
121
  private _createdAt;
122
+ private _checkpointRefreshTimer;
123
+ private _checkpointRefreshInFlight;
116
124
  private readonly _token?;
117
125
  private readonly _environmentId?;
118
126
  private readonly _sandboxId?;
127
+ private readonly _checkpointName?;
119
128
  private readonly _idleTimeoutMinutes?;
120
129
  private readonly _networkIsolation?;
121
130
  private readonly _env;
@@ -137,6 +146,26 @@ export declare class RailwaySandbox extends MastraSandbox {
137
146
  * otherwise provisions a new one. Resolves once the sandbox is RUNNING.
138
147
  */
139
148
  start(): Promise<void>;
149
+ restart(): Promise<void>;
150
+ withRestartRetry<T>(operation: () => Promise<T>): Promise<T>;
151
+ private _startRailwaySandbox;
152
+ /**
153
+ * Reconnect to an existing Railway sandbox, creating a fresh one when
154
+ * `fallbackToCreate` is set and the sandbox is unavailable or not running.
155
+ */
156
+ private _reconnectSandbox;
157
+ private _clientConfig;
158
+ private _createOptions;
159
+ private _createNewSandbox;
160
+ private _tryCreateFromCheckpoint;
161
+ private _checkpointSandbox;
162
+ private _deleteCheckpointByName;
163
+ private _scheduleCheckpointRefresh;
164
+ private _cancelCheckpointRefresh;
165
+ private _flushCheckpointRefresh;
166
+ private isCheckpointUnavailableError;
167
+ private isCheckpointAlreadyExistsError;
168
+ private isSandboxUnavailableError;
140
169
  /**
141
170
  * Stop the Railway sandbox.
142
171
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sandbox/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sandbox/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/railway",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Railway cloud sandbox provider for Mastra workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "license": "Apache-2.0",
22
22
  "dependencies": {
23
- "railway": "^3.3.1"
23
+ "railway": "^3.4.1"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/node": "22.19.21",
@@ -31,10 +31,10 @@
31
31
  "tsup": "^8.5.1",
32
32
  "typescript": "^6.0.3",
33
33
  "vitest": "4.1.8",
34
- "@internal/lint": "0.0.110",
35
- "@internal/types-builder": "0.0.85",
36
- "@mastra/core": "1.48.0",
37
- "@internal/workspace-test-utils": "0.0.54"
34
+ "@internal/lint": "0.0.111",
35
+ "@mastra/core": "1.49.0",
36
+ "@internal/workspace-test-utils": "0.0.55",
37
+ "@internal/types-builder": "0.0.86"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@mastra/core": ">=1.12.0-0 <2.0.0-0"