@mastra/railway 0.2.1 → 0.3.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/index.cjs +251 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +249 -22
- package/dist/index.js.map +1 -1
- package/dist/sandbox/index.d.ts +29 -0
- package/dist/sandbox/index.d.ts.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @mastra/railway
|
|
2
2
|
|
|
3
|
+
## 0.3.0-alpha.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 [[`1340fb7`](https://github.com/mastra-ai/mastra/commit/1340fb76262a3ca062130aa71859f07257a0a5a4)]:
|
|
21
|
+
- @mastra/core@1.49.0-alpha.2
|
|
22
|
+
|
|
3
23
|
## 0.2.1
|
|
4
24
|
|
|
5
25
|
### 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
211
|
-
|
|
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
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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;
|
package/dist/index.cjs.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":["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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
209
|
-
|
|
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
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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":";;;;;;AAMO,SAAS,WAAW,GAAA,EAAqB;AAE9C,EAAA,IAAI,wBAAA,CAAyB,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,GAAA;AAE/C,EAAA,OAAO,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA,GAAI,GAAA;AAC5C;ACQO,IAAM,UAAA,GAAa,kBAAA;AAU1B,IAAM,oBAAA,GAAN,cAAmC,aAAA,CAAc;AAAA,EACtC,GAAA;AAAA,EAEQ,WAAA;AAAA,EACA,UAAA;AAAA,EACT,SAAA;AAAA,EACA,YAAA,GAA8C,IAAA;AAAA,EAC9C,OAAA,GAAU,KAAA;AAAA,EAElB,WAAA,CAAY,GAAA,EAAa,UAAA,EAAwB,SAAA,EAAmB,OAAA,EAA+B;AACjG,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAIlB,IAAA,KAAK,KAAK,WAAA,CAAY,IAAA;AAAA,MACpB,CAAC,MAAA,KAAuB;AAEtB,QAAA,IAAA,CAAK,SAAA,GAAY,MAAA,CAAO,QAAA,KAAa,IAAA,CAAK,UAAU,GAAA,GAAM,EAAA,CAAA;AAAA,MAC5D,CAAA;AAAA,MACA,MAAM;AACJ,QAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAChC,UAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AAAA,QACnB;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA,EAEA,IAAI,QAAA,GAA+B;AACjC,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,MAAM,IAAA,GAA+B;AAEnC,IAAA,IAAI,CAAC,KAAK,YAAA,EAAc;AACtB,MAAA,IAAA,CAAK,YAAA,GAAe,KAAK,OAAA,EAAQ;AAAA,IACnC;AACA,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA,EAEA,MAAc,OAAA,GAAkC;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,WAAA;AAC1B,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,KAAa,IAAA,CAAK,UAAU,GAAA,GAAM,EAAA,CAAA;AAC1D,MAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAIjB,MAAA,IAAI,MAAA,CAAO,UAAU,CAAC,IAAA,CAAK,QAAQ,IAAA,CAAK,UAAA,CAAW,OAAO,MAAM,CAAA;AAChE,MAAA,IAAI,MAAA,CAAO,UAAU,CAAC,IAAA,CAAK,QAAQ,IAAA,CAAK,UAAA,CAAW,OAAO,MAAM,CAAA;AAEhE,MAAA,OAAO;AAAA,QACL,SAAS,QAAA,KAAa,CAAA;AAAA,QACtB,QAAA;AAAA,QACA,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,UAAA;AAAA,QACnC,QAAQ,IAAA,CAAK,OAAA;AAAA,QACb,UAAU,MAAA,CAAO;AAAA,OACnB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,QAAA,GAAW,KAAK,SAAA,IAAa,CAAA;AACnC,MAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,QAAA;AAAA,QACA,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,MAAA,EAAQ,KAAK,MAAA,KAAW,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA,CAAA;AAAA,QAC7E,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,UAAA;AAAA,QACnC,QAAQ,IAAA,CAAK;AAAA,OACf;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,GAAyB;AAC7B,IAAA,IAAI,IAAA,CAAK,SAAA,KAAc,MAAA,EAAW,OAAO,KAAA;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA;AAAA,IAC3C,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,KAAA,EAA8B;AAE5C,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,+DAAA,CAAiE,CAAA;AAAA,EAChG;AACF,CAAA;AAcO,IAAM,qBAAA,GAAN,cAAoC,qBAAA,CAAsC;AAAA,EACvE,aAAA,GAAgB,CAAA;AAAA,EAExB,WAAA,CAAY,IAAA,GAAqC,EAAC,EAAG;AACnD,IAAA,KAAA,CAAM,EAAE,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,KAAA,CAAM,OAAA,EAAiB,OAAA,GAA+B,EAAC,EAA2B;AACtF,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,CAAQ,OAAA;AAG7B,IAAA,MAAM,YAAY,EAAE,GAAG,KAAK,GAAA,EAAK,GAAG,QAAQ,GAAA,EAAI;AAChD,IAAA,MAAM,MAAM,MAAA,CAAO,WAAA;AAAA,MACjB,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,CAAE,MAAA,CAAO,CAAC,KAAA,KAAqC,KAAA,CAAM,CAAC,CAAA,KAAM,MAAS;AAAA,KAC/F;AAEA,IAAA,MAAM,GAAA,GAAM,CAAA,aAAA,EAAgB,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAA,CAAK,IAAA,CAAK,aAAA,EAAA,EAAiB,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA;AAI1F,IAAA,IAAI,MAAA;AAEJ,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS;AAAA,MACvC,GAAI,OAAA,CAAQ,OAAA,KAAY,MAAA,IAAa,EAAE,UAAA,EAAY,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,OAAA,GAAU,GAAI,CAAA,EAAE;AAAA,MACrF,GAAI,OAAA,CAAQ,GAAA,KAAQ,UAAa,EAAE,GAAA,EAAK,QAAQ,GAAA,EAAI;AAAA,MACpD,GAAI,OAAO,IAAA,CAAK,GAAG,EAAE,MAAA,GAAS,CAAA,IAAK,EAAE,GAAA,EAAI;AAAA,MACzC,QAAA,EAAU,CAAC,KAAA,KAAkB,MAAA,CAAO,WAAW,KAAK,CAAA;AAAA,MACpD,QAAA,EAAU,CAAC,KAAA,KAAkB,MAAA,CAAO,WAAW,KAAK;AAAA,KACrD,CAAA;AAED,IAAA,MAAA,GAAS,IAAI,oBAAA,CAAqB,GAAA,EAAK,YAAY,IAAA,CAAK,GAAA,IAAO,OAAO,CAAA;AACtE,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,MAAA,CAAO,GAAA,EAAK,MAAM,CAAA;AACpC,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,GAA+B;AACnC,IAAA,OAAO,KAAA,CAAM,KAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA,CAAE,IAAI,CAAA,MAAA,MAAW;AAAA,MACvD,KAAK,MAAA,CAAO,GAAA;AAAA,MACZ,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,OAAA,EAAS,OAAO,QAAA,KAAa,MAAA;AAAA,MAC7B,GAAI,MAAA,CAAO,QAAA,KAAa,UAAa,EAAE,QAAA,EAAU,OAAO,QAAA;AAAS,KACnE,CAAE,CAAA;AAAA,EACJ;AACF;;;ACzDO,IAAM,cAAA,GAAN,MAAM,eAAA,SAAuB,aAAA,CAAc;AAAA,EACvC,EAAA;AAAA,EACA,IAAA,GAAO,gBAAA;AAAA,EACP,QAAA,GAAW,SAAA;AAAA,EACpB,MAAA,GAAyB,SAAA;AAAA,EAIjB,QAAA,GAA2B,IAAA;AAAA,EAC3B,UAAA,GAA0B,IAAA;AAAA,EAEjB,MAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,mBAAA;AAAA,EACA,iBAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,qBAAA;AAAA,EACA,eAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAAiC,EAAC,EAAG;AAC/C,IAAA,KAAA,CAAM;AAAA,MACJ,GAAG,OAAA;AAAA,MACH,IAAA,EAAM,gBAAA;AAAA,MACN,WAAW,IAAI,qBAAA,CAAsB,EAAE,GAAA,EAAK,OAAA,CAAQ,KAAK;AAAA,KAC1D,CAAA;AAED,IAAA,IAAA,CAAK,EAAA,GAAK,OAAA,CAAQ,EAAA,IAAM,IAAA,CAAK,UAAA,EAAW;AACxC,IAAA,IAAA,CAAK,MAAA,GAAS,OAAA,CAAQ,KAAA,IAAS,OAAA,CAAQ,GAAA,CAAI,iBAAA;AAC3C,IAAA,IAAA,CAAK,cAAA,GAAiB,OAAA,CAAQ,aAAA,IAAiB,OAAA,CAAQ,GAAA,CAAI,sBAAA;AAC3D,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,SAAA;AAC1B,IAAA,IAAA,CAAK,sBAAsB,OAAA,CAAQ,kBAAA;AACnC,IAAA,IAAA,CAAK,oBAAoB,OAAA,CAAQ,gBAAA;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,OAAA,CAAQ,GAAA,IAAO,EAAC;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,OAAA;AACxB,IAAA,IAAA,CAAK,wBAAwB,OAAA,CAAQ,YAAA;AACrC,IAAA,IAAA,CAAK,kBAAkB,OAAA,CAAQ,QAAA;AAAA,EACjC;AAAA,EAEQ,UAAA,GAAqB;AAC3B,IAAA,OAAO,mBAAmB,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,OAAA,GAAmB;AACrB,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,MAAM,IAAI,oBAAA,CAAqB,IAAA,CAAK,EAAE,CAAA;AAAA,IACxC;AACA,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAA,GAAe;AAAA,MACnB,GAAI,IAAA,CAAK,MAAA,KAAW,UAAa,EAAE,KAAA,EAAO,KAAK,MAAA,EAAO;AAAA,MACtD,GAAI,IAAA,CAAK,cAAA,KAAmB,UAAa,EAAE,aAAA,EAAe,KAAK,cAAA;AAAe,KAChF;AAEA,IAAA,MAAM,aAAA,GAAgB;AAAA,MACpB,GAAG,YAAA;AAAA,MACH,GAAI,IAAA,CAAK,mBAAA,KAAwB,UAAa,EAAE,kBAAA,EAAoB,KAAK,mBAAA,EAAoB;AAAA,MAC7F,GAAI,IAAA,CAAK,iBAAA,KAAsB,UAAa,EAAE,gBAAA,EAAkB,KAAK,iBAAA,EAAkB;AAAA,MACvF,GAAI,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,GAAS,CAAA,IAAK,EAAE,GAAA,EAAK,IAAA,CAAK,IAAA;AAAK,KAC5D;AAEA,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,iCAAA,EAAoC,IAAA,CAAK,UAAU,CAAA,GAAA,CAAK,CAAA;AACvF,MAAA,IAAA,CAAK,WAAW,MAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,YAAY,YAAY,CAAA;AAAA,IACrE,CAAA,MAAA,IAAW,KAAK,eAAA,EAAiB;AAC/B,MAAA,MAAM,QAAA,GAAW,KAAK,gBAAA,EAAiB;AACvC,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,6CAAA,EAAgD,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AACxF,MAAA,IAAA,CAAK,QAAA,GAAW,MAAM,OAAA,CAAQ,MAAA,CAAO,UAAU,aAAa,CAAA;AAAA,IAC9D,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,+BAAA,EAAkC,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAC1E,MAAA,IAAA,CAAK,QAAA,GAAW,MAAM,OAAA,CAAQ,MAAA,CAAO,aAAa,CAAA;AAAA,IACpD;AAEA,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA,CAAK,QAAA,CAAS,SAAA,GAAY,IAAI,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,mBAAI,IAAI,IAAA,EAAK;AACzF,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,iBAAA,EAAoB,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA,uBAAA,EAA0B,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAAA,EACxG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,GAAsB;AAC1B,IAAA,MAAM,KAAK,SAAA,EAAU;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,GAAyB;AAC7B,IAAA,MAAM,KAAK,SAAA,EAAU;AAAA,EACvB;AAAA,EAEA,MAAc,SAAA,GAA2B;AACvC,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA;AACrB,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,QAAQ,OAAA,EAAQ;AAAA,IACxB,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EAAG,UAAU,sCAAsC,OAAA,CAAQ,EAAE,KAAK,KAAK,CAAA;AAAA,IAC1F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAA,GAAoC;AAC1C,IAAA,MAAM,SAAS,IAAA,CAAK,eAAA;AACpB,IAAA,OAAO,OAAO,MAAA,KAAW,UAAA,GAAa,OAAO,OAAA,CAAQ,QAAA,EAAU,CAAA,GAAI,MAAA;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,IAAA,CACJ,OAAA,GAAiG,EAAC,EACzE;AACzB,IAAA,MAAM,SAAS,IAAA,CAAK,OAAA;AACpB,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,IAAA,CAAK;AAAA,MAC/B,GAAI,OAAA,CAAQ,kBAAA,KAAuB,UAAa,EAAE,kBAAA,EAAoB,QAAQ,kBAAA,EAAmB;AAAA,MACjG,GAAI,OAAA,CAAQ,gBAAA,KAAqB,UAAa,EAAE,gBAAA,EAAkB,QAAQ,gBAAA,EAAiB;AAAA,MAC3F,GAAI,OAAA,CAAQ,GAAA,KAAQ,UAAa,EAAE,GAAA,EAAK,QAAQ,GAAA;AAAI,KACrD,CAAA;AAED,IAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,CAAe;AAAA,MAC/B,GAAI,OAAA,CAAQ,EAAA,KAAO,UAAa,EAAE,EAAA,EAAI,QAAQ,EAAA,EAAG;AAAA,MACjD,GAAI,IAAA,CAAK,MAAA,KAAW,UAAa,EAAE,KAAA,EAAO,KAAK,MAAA,EAAO;AAAA,MACtD,GAAI,IAAA,CAAK,cAAA,KAAmB,UAAa,EAAE,aAAA,EAAe,KAAK,cAAA,EAAe;AAAA,MAC9E,WAAW,MAAA,CAAO,EAAA;AAAA,MAClB,kBAAA,EAAoB,OAAA,CAAQ,kBAAA,IAAsB,IAAA,CAAK,mBAAA;AAAA,MACvD,gBAAA,EAAkB,OAAA,CAAQ,gBAAA,IAAoB,IAAA,CAAK,iBAAA;AAAA,MACnD,GAAA,EAAK,OAAA,CAAQ,GAAA,IAAO,IAAA,CAAK,IAAA;AAAA,MACzB,SAAS,IAAA,CAAK;AAAA,KACf,CAAA;AACD,IAAA,MAAM,MAAM,MAAA,EAAO;AACnB,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAA,GAAgC;AACpC,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,EAAA;AAAA,MACT,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAA,EAAW,IAAA,CAAK,UAAA,oBAAc,IAAI,IAAA,EAAK;AAAA,MACvC,QAAA,EAAU;AAAA,QACR,GAAI,KAAK,QAAA,IAAY;AAAA,UACnB,gBAAA,EAAkB,KAAK,QAAA,CAAS,EAAA;AAAA,UAChC,aAAA,EAAe,KAAK,QAAA,CAAS,aAAA;AAAA,UAC7B,MAAA,EAAQ,KAAK,QAAA,CAAS,MAAA;AAAA,UACtB,gBAAA,EAAkB,KAAK,QAAA,CAAS,gBAAA;AAAA,UAChC,GAAI,IAAA,CAAK,QAAA,CAAS,kBAAA,IAAsB,IAAA,IAAQ;AAAA,YAC9C,kBAAA,EAAoB,KAAK,QAAA,CAAS;AAAA;AACpC;AACF;AACF,KACF;AAAA,EACF;AAAA,EAEA,eAAA,GAA0B;AACxB,IAAA,MAAM,mBAAA,GAAsB,KAAK,yBAAA,EAA0B;AAE3D,IAAA,IAAI,OAAO,IAAA,CAAK,qBAAA,KAA0B,QAAA,EAAU;AAClD,MAAA,OAAO,IAAA,CAAK,qBAAA;AAAA,IACd;AACA,IAAA,IAAI,OAAO,IAAA,CAAK,qBAAA,KAA0B,UAAA,EAAY;AACpD,MAAA,OAAO,IAAA,CAAK,qBAAA,CAAsB,EAAE,mBAAA,EAAqB,CAAA;AAAA,IAC3D;AACA,IAAA,OAAO,mBAAA;AAAA,EACT;AAAA,EAEQ,yBAAA,GAAoC;AAC1C,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,KAAA,CAAM,KAAK,mFAAmF,CAAA;AAE9F,IAAA,IAAI,IAAA,CAAK,sBAAsB,SAAA,EAAW;AACxC,MAAA,KAAA,CAAM,KAAK,4CAA4C,CAAA;AAAA,IACzD;AAEA,IAAA,IAAI,IAAA,CAAK,aAAa,MAAA,EAAW;AAC/B,MAAA,KAAA,CAAM,IAAA,CAAK,4BAA4B,IAAA,CAAK,IAAA,CAAK,KAAK,QAAA,GAAW,GAAI,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,IAC5E,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,KAAK,uDAAuD,CAAA;AAAA,IACpE;AAEA,IAAA,IAAI,IAAA,CAAK,wBAAwB,MAAA,EAAW;AAC1C,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiB,IAAA,CAAK,mBAAmB,CAAA,WAAA,CAAa,CAAA;AAAA,IACnE;AAEA,IAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eACJ,OAAA,EACA,IAAA,GAAiB,EAAC,EAClB,OAAA,GAAiC,EAAC,EACV;AACxB,IAAA,MAAM,KAAK,aAAA,EAAc;AACzB,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,GAAG,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,GAAK,OAAA;AACvF,IAAA,MAAM,gBAAA,GAA0C;AAAA,MAC9C,GAAG,OAAA;AAAA,MACH,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,IAAA,CAAK;AAAA,KACnC;AACA,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,aAAa,gBAAgB,CAAA;AACvE,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,IAAA,EAAK;AACjC,IAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAK;AAAA,EACpC;AACF;;;AC/VO,IAAM,sBAAA,GAAiE;AAAA,EAC5E,EAAA,EAAI,SAAA;AAAA,EACJ,IAAA,EAAM,iBAAA;AAAA,EACN,WAAA,EAAa,iDAAA;AAAA,EACb,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,QAAA;AAAA,IACN,UAAA,EAAY;AAAA,MACV,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,qDAAA,EAAsD;AAAA,MAC5F,aAAA,EAAe;AAAA,QACb,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,SAAA,EAAW,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+CAAA,EAAgD;AAAA,MAC1F,kBAAA,EAAoB;AAAA,QAClB,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,gBAAA,EAAkB;AAAA,QAChB,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa,wBAAA;AAAA,QACb,IAAA,EAAM,CAAC,UAAA,EAAY,SAAS,CAAA;AAAA,QAC5B,OAAA,EAAS;AAAA,OACX;AAAA,MACA,GAAA,EAAK;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa,uBAAA;AAAA,QACb,oBAAA,EAAsB,EAAE,IAAA,EAAM,QAAA;AAAS,OACzC;AAAA,MACA,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+BAAA;AAAgC;AAC1E,GACF;AAAA,EACA,aAAA,EAAe,CAAA,MAAA,KAAU,IAAI,cAAA,CAAe,MAAM;AACpD","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":";;;;;;;AAMO,SAAS,WAAW,GAAA,EAAqB;AAE9C,EAAA,IAAI,wBAAA,CAAyB,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,GAAA;AAE/C,EAAA,OAAO,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA,GAAI,GAAA;AAC5C;ACQO,IAAM,UAAA,GAAa,kBAAA;AAU1B,IAAM,oBAAA,GAAN,cAAmC,aAAA,CAAc;AAAA,EACtC,GAAA;AAAA,EAEQ,WAAA;AAAA,EACA,UAAA;AAAA,EACT,SAAA;AAAA,EACA,YAAA,GAA8C,IAAA;AAAA,EAC9C,OAAA,GAAU,KAAA;AAAA,EAElB,WAAA,CAAY,GAAA,EAAa,UAAA,EAAwB,SAAA,EAAmB,OAAA,EAA+B;AACjG,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAIlB,IAAA,KAAK,KAAK,WAAA,CAAY,IAAA;AAAA,MACpB,CAAC,MAAA,KAAuB;AAEtB,QAAA,IAAA,CAAK,SAAA,GAAY,MAAA,CAAO,QAAA,KAAa,IAAA,CAAK,UAAU,GAAA,GAAM,EAAA,CAAA;AAAA,MAC5D,CAAA;AAAA,MACA,MAAM;AACJ,QAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAChC,UAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AAAA,QACnB;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA,EAEA,IAAI,QAAA,GAA+B;AACjC,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,MAAM,IAAA,GAA+B;AAEnC,IAAA,IAAI,CAAC,KAAK,YAAA,EAAc;AACtB,MAAA,IAAA,CAAK,YAAA,GAAe,KAAK,OAAA,EAAQ;AAAA,IACnC;AACA,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA,EAEA,MAAc,OAAA,GAAkC;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,WAAA;AAC1B,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,KAAa,IAAA,CAAK,UAAU,GAAA,GAAM,EAAA,CAAA;AAC1D,MAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAIjB,MAAA,IAAI,MAAA,CAAO,UAAU,CAAC,IAAA,CAAK,QAAQ,IAAA,CAAK,UAAA,CAAW,OAAO,MAAM,CAAA;AAChE,MAAA,IAAI,MAAA,CAAO,UAAU,CAAC,IAAA,CAAK,QAAQ,IAAA,CAAK,UAAA,CAAW,OAAO,MAAM,CAAA;AAEhE,MAAA,OAAO;AAAA,QACL,SAAS,QAAA,KAAa,CAAA;AAAA,QACtB,QAAA;AAAA,QACA,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,UAAA;AAAA,QACnC,QAAQ,IAAA,CAAK,OAAA;AAAA,QACb,UAAU,MAAA,CAAO;AAAA,OACnB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,QAAA,GAAW,KAAK,SAAA,IAAa,CAAA;AACnC,MAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,QAAA;AAAA,QACA,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,MAAA,EAAQ,KAAK,MAAA,KAAW,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA,CAAA;AAAA,QAC7E,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,UAAA;AAAA,QACnC,QAAQ,IAAA,CAAK;AAAA,OACf;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,GAAyB;AAC7B,IAAA,IAAI,IAAA,CAAK,SAAA,KAAc,MAAA,EAAW,OAAO,KAAA;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA;AAAA,IAC3C,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,KAAA,EAA8B;AAE5C,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,+DAAA,CAAiE,CAAA;AAAA,EAChG;AACF,CAAA;AAcO,IAAM,qBAAA,GAAN,cAAoC,qBAAA,CAAsC;AAAA,EACvE,aAAA,GAAgB,CAAA;AAAA,EAExB,WAAA,CAAY,IAAA,GAAqC,EAAC,EAAG;AACnD,IAAA,KAAA,CAAM,EAAE,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,KAAA,CAAM,OAAA,EAAiB,OAAA,GAA+B,EAAC,EAA2B;AACtF,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,CAAQ,OAAA;AAG7B,IAAA,MAAM,YAAY,EAAE,GAAG,KAAK,GAAA,EAAK,GAAG,QAAQ,GAAA,EAAI;AAChD,IAAA,MAAM,MAAM,MAAA,CAAO,WAAA;AAAA,MACjB,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,CAAE,MAAA,CAAO,CAAC,KAAA,KAAqC,KAAA,CAAM,CAAC,CAAA,KAAM,MAAS;AAAA,KAC/F;AAEA,IAAA,MAAM,GAAA,GAAM,CAAA,aAAA,EAAgB,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAA,CAAK,IAAA,CAAK,aAAA,EAAA,EAAiB,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA;AAI1F,IAAA,IAAI,MAAA;AAEJ,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS;AAAA,MACvC,GAAI,OAAA,CAAQ,OAAA,KAAY,MAAA,IAAa,EAAE,UAAA,EAAY,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,OAAA,GAAU,GAAI,CAAA,EAAE;AAAA,MACrF,GAAI,OAAA,CAAQ,GAAA,KAAQ,UAAa,EAAE,GAAA,EAAK,QAAQ,GAAA,EAAI;AAAA,MACpD,GAAI,OAAO,IAAA,CAAK,GAAG,EAAE,MAAA,GAAS,CAAA,IAAK,EAAE,GAAA,EAAI;AAAA,MACzC,QAAA,EAAU,CAAC,KAAA,KAAkB,MAAA,CAAO,WAAW,KAAK,CAAA;AAAA,MACpD,QAAA,EAAU,CAAC,KAAA,KAAkB,MAAA,CAAO,WAAW,KAAK;AAAA,KACrD,CAAA;AAED,IAAA,MAAA,GAAS,IAAI,oBAAA,CAAqB,GAAA,EAAK,YAAY,IAAA,CAAK,GAAA,IAAO,OAAO,CAAA;AACtE,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,MAAA,CAAO,GAAA,EAAK,MAAM,CAAA;AACpC,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,GAA+B;AACnC,IAAA,OAAO,KAAA,CAAM,KAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA,CAAE,IAAI,CAAA,MAAA,MAAW;AAAA,MACvD,KAAK,MAAA,CAAO,GAAA;AAAA,MACZ,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,OAAA,EAAS,OAAO,QAAA,KAAa,MAAA;AAAA,MAC7B,GAAI,MAAA,CAAO,QAAA,KAAa,UAAa,EAAE,QAAA,EAAU,OAAO,QAAA;AAAS,KACnE,CAAE,CAAA;AAAA,EACJ;AACF;;;ACnDO,IAAM,cAAA,GAAN,MAAM,eAAA,SAAuB,aAAA,CAAc;AAAA,EACvC,EAAA;AAAA,EACA,IAAA,GAAO,gBAAA;AAAA,EACP,QAAA,GAAW,SAAA;AAAA,EACpB,MAAA,GAAyB,SAAA;AAAA,EAIjB,QAAA,GAA2B,IAAA;AAAA,EAC3B,UAAA,GAA0B,IAAA;AAAA,EAC1B,uBAAA,GAAgE,IAAA;AAAA,EAChE,0BAAA,GAAmD,IAAA;AAAA,EAE1C,MAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,eAAA;AAAA,EACA,mBAAA;AAAA,EACA,iBAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,qBAAA;AAAA,EACA,eAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAAiC,EAAC,EAAG;AAC/C,IAAA,KAAA,CAAM;AAAA,MACJ,GAAG,OAAA;AAAA,MACH,IAAA,EAAM,gBAAA;AAAA,MACN,WAAW,IAAI,qBAAA,CAAsB,EAAE,GAAA,EAAK,OAAA,CAAQ,KAAK;AAAA,KAC1D,CAAA;AAED,IAAA,IAAA,CAAK,EAAA,GAAK,OAAA,CAAQ,EAAA,IAAM,IAAA,CAAK,UAAA,EAAW;AACxC,IAAA,IAAA,CAAK,MAAA,GAAS,OAAA,CAAQ,KAAA,IAAS,OAAA,CAAQ,GAAA,CAAI,iBAAA;AAC3C,IAAA,IAAA,CAAK,cAAA,GAAiB,OAAA,CAAQ,aAAA,IAAiB,OAAA,CAAQ,GAAA,CAAI,sBAAA;AAC3D,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,SAAA;AAC1B,IAAA,IAAA,CAAK,kBAAkB,OAAA,CAAQ,cAAA;AAC/B,IAAA,IAAA,CAAK,sBAAsB,OAAA,CAAQ,kBAAA;AACnC,IAAA,IAAA,CAAK,oBAAoB,OAAA,CAAQ,gBAAA;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,OAAA,CAAQ,GAAA,IAAO,EAAC;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,OAAA;AACxB,IAAA,IAAA,CAAK,wBAAwB,OAAA,CAAQ,YAAA;AACrC,IAAA,IAAA,CAAK,kBAAkB,OAAA,CAAQ,QAAA;AAAA,EACjC;AAAA,EAEQ,UAAA,GAAqB;AAC3B,IAAA,OAAO,mBAAmB,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,OAAA,GAAmB;AACrB,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,MAAM,IAAI,oBAAA,CAAqB,IAAA,CAAK,EAAE,CAAA;AAAA,IACxC;AACA,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,CAAK,qBAAqB,EAAE,kBAAA,EAAoB,KAAK,UAAA,EAAY,gBAAA,EAAkB,OAAO,CAAA;AAAA,EAClG;AAAA,EAEA,MAAM,OAAA,GAAyB;AAC7B,IAAA,MAAM,kBAAA,GAAqB,IAAA,CAAK,QAAA,EAAU,EAAA,IAAM,IAAA,CAAK,UAAA;AACrD,IAAA,IAAA,CAAK,wBAAA,EAAyB;AAC9B,IAAA,MAAM,IAAA,CAAK,0BAAA,EAA4B,KAAA,CAAM,CAAA,KAAA,KAAS;AACpD,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,UAAU,yDAAyD,KAAK,CAAA;AAAA,IAC9F,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,IAAA,IAAA,CAAK,MAAA,GAAS,UAAA;AAEd,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,oBAAA,CAAqB,EAAE,kBAAA,EAAoB,gBAAA,EAAkB,MAAM,CAAA;AAC9E,MAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AAAA,IAChB,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,GAAS,OAAA;AACd,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,iBAAoB,SAAA,EAAyC;AACjE,IAAA,MAAM,KAAK,aAAA,EAAc;AACzB,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,SAAA,EAAU;AAAA,IACzB,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,CAAC,IAAA,CAAK,yBAAA,CAA0B,KAAK,CAAA,EAAG;AAC1C,QAAA,MAAM,KAAA;AAAA,MACR;AAEA,MAAA,MAAM,KAAK,OAAA,EAAQ;AACnB,MAAA,OAAO,MAAM,SAAA,EAAU;AAAA,IACzB,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,0BAAA,EAA2B;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,MAAc,oBAAA,CAAqB;AAAA,IACjC,kBAAA;AAAA,IACA;AAAA,GACF,EAGkB;AAChB,IAAA,MAAM,YAAA,GAAe,KAAK,aAAA,EAAc;AACxC,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,cAAA,CAAe,YAAY,CAAA;AAEtD,IAAA,IAAA,CAAK,QAAA,GAAW,kBAAA,GACZ,MAAM,IAAA,CAAK,iBAAA,CAAkB,kBAAA,EAAoB,gBAAA,EAAkB,YAAA,EAAc,aAAa,CAAA,GAC9F,MAAM,IAAA,CAAK,kBAAkB,aAAa,CAAA;AAE9C,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA,CAAK,QAAA,CAAS,SAAA,GAAY,IAAI,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,mBAAI,IAAI,IAAA,EAAK;AACzF,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,iBAAA,EAAoB,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA,uBAAA,EAA0B,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AACtG,IAAA,IAAA,CAAK,0BAAA,EAA2B;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,iBAAA,CACZ,kBAAA,EACA,gBAAA,EACA,cACA,aAAA,EACkB;AAClB,IAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,iCAAA,EAAoC,kBAAkB,CAAA,GAAA,CAAK,CAAA;AAE1F,IAAA,IAAI,gBAAA;AACJ,IAAA,IAAI;AACF,MAAA,gBAAA,GAAmB,MAAM,OAAA,CAAQ,OAAA,CAAQ,kBAAA,EAAoB,YAAY,CAAA;AAAA,IAC3E,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,CAAC,gBAAA,IAAoB,CAAC,IAAA,CAAK,yBAAA,CAA0B,KAAK,CAAA,EAAG;AAC/D,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,OAAO,IAAA,CAAK,kBAAkB,aAAa,CAAA;AAAA,IAC7C;AAEA,IAAA,IAAI,gBAAA,CAAiB,WAAW,SAAA,EAAW;AACzC,MAAA,OAAO,gBAAA;AAAA,IACT;AAEA,IAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,kBAAkB,CAAA,yBAAA,EAA4B,gBAAA,CAAiB,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,IAC7G;AAEA,IAAA,OAAO,IAAA,CAAK,kBAAkB,aAAa,CAAA;AAAA,EAC7C;AAAA,EAEQ,aAAA,GAA4D;AAClE,IAAA,OAAO;AAAA,MACL,GAAI,IAAA,CAAK,MAAA,KAAW,UAAa,EAAE,KAAA,EAAO,KAAK,MAAA,EAAO;AAAA,MACtD,GAAI,IAAA,CAAK,cAAA,KAAmB,UAAa,EAAE,aAAA,EAAe,KAAK,cAAA;AAAe,KAChF;AAAA,EACF;AAAA,EAEQ,eAAe,YAAA,EAA0D;AAC/E,IAAA,OAAO;AAAA,MACL,GAAG,YAAA;AAAA,MACH,GAAI,IAAA,CAAK,mBAAA,KAAwB,UAAa,EAAE,kBAAA,EAAoB,KAAK,mBAAA,EAAoB;AAAA,MAC7F,GAAI,IAAA,CAAK,iBAAA,KAAsB,UAAa,EAAE,gBAAA,EAAkB,KAAK,iBAAA,EAAkB;AAAA,MACvF,GAAI,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,GAAS,CAAA,IAAK,EAAE,GAAA,EAAK,IAAA,CAAK,IAAA;AAAK,KAC5D;AAAA,EACF;AAAA,EAEA,MAAc,kBAAkB,aAAA,EAA+E;AAC7G,IAAA,MAAM,iBAAA,GAAoB,MAAM,IAAA,CAAK,wBAAA,CAAyB,aAAa,CAAA;AAC3E,IAAA,IAAI,iBAAA,EAAmB;AACrB,MAAA,OAAO,iBAAA;AAAA,IACT;AAEA,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,MAAM,QAAA,GAAW,KAAK,gBAAA,EAAiB;AACvC,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,6CAAA,EAAgD,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AACxF,MAAA,MAAMA,QAAAA,GAAU,MAAM,OAAA,CAAQ,MAAA,CAAO,UAAU,aAAa,CAAA;AAC5D,MAAA,MAAM,IAAA,CAAK,mBAAmBA,QAAO,CAAA;AACrC,MAAA,OAAOA,QAAAA;AAAA,IACT;AAEA,IAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,+BAAA,EAAkC,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAC1E,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,MAAA,CAAO,aAAa,CAAA;AAClD,IAAA,MAAM,IAAA,CAAK,mBAAmB,OAAO,CAAA;AACrC,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAc,yBACZ,aAAA,EAC8B;AAC9B,IAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AACzB,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,0CAAA,EAA6C,KAAK,eAAe,CAAA,MAAA,EAAS,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAElH,IAAA,IAAI;AACF,MAAA,MAAM,UAAU,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,iBAAiB,aAAa,CAAA;AACxE,MAAA,OAAO,OAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,CAAC,IAAA,CAAK,4BAAA,CAA6B,KAAK,CAAA,EAAG;AAC7C,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB,OAAA,EAAiC;AAChE,IAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AACzB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,sCAAA,EAAyC,KAAK,eAAe,CAAA,MAAA,EAAS,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAC9G,MAAA,MAAM,OAAA,CAAQ,UAAA,CAAW,IAAA,CAAK,eAAe,CAAA;AAAA,IAC/C,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,CAAC,IAAA,CAAK,8BAAA,CAA+B,KAAK,CAAA,EAAG;AAC/C,QAAA,MAAM,KAAA;AAAA,MACR;AAEA,MAAA,MAAM,IAAA,CAAK,uBAAA,CAAwB,IAAA,CAAK,eAAe,CAAA;AACvD,MAAA,MAAM,OAAA,CAAQ,UAAA,CAAW,IAAA,CAAK,eAAe,CAAA;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAc,wBAAwB,IAAA,EAA6B;AACjE,IAAA,IAAI;AACF,MAAA,MAAM,UAAA,GAAA,CAAc,MAAM,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,aAAA,EAAe,CAAA,EAAG,IAAA,CAAK,CAAAC,WAAAA,KAAcA,WAAAA,CAAW,QAAQ,IAAI,CAAA;AAC/G,MAAA,IAAI,CAAC,UAAA,EAAY;AACf,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,QAAQ,gBAAA,CAAiB,UAAA,CAAW,EAAA,EAAI,IAAA,CAAK,eAAe,CAAA;AAAA,IACpE,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,CAAC,IAAA,CAAK,4BAAA,CAA6B,KAAK,CAAA,EAAG;AAC7C,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,0BAAA,GAAmC;AACzC,IAAA,IAAI,CAAC,IAAA,CAAK,eAAA,IAAmB,CAAC,KAAK,QAAA,EAAU;AAC3C,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,kBAAA,GAAqB,IAAA,CAAK,mBAAA,IAAuB,IAAA,CAAK,QAAA,CAAS,kBAAA;AACrE,IAAA,IAAI,CAAC,kBAAA,EAAoB;AACvB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAK,uBAAA,EAAyB;AAChC,MAAA,YAAA,CAAa,KAAK,uBAAuB,CAAA;AAAA,IAC3C;AAEA,IAAA,MAAM,UAAU,IAAA,CAAK,GAAA,CAAI,GAAA,EAAO,kBAAA,GAAqB,MAAS,GAAM,CAAA;AACpE,IAAA,IAAA,CAAK,uBAAA,GAA0B,WAAW,MAAM;AAC9C,MAAA,IAAA,CAAK,uBAAA,GAA0B,IAAA;AAC/B,MAAA,MAAM,UAAU,IAAA,CAAK,QAAA;AACrB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAU,IAAA,CAAK,kBAAA,CAAmB,OAAO,CAAA,CAAE,QAAQ,MAAM;AAC7D,QAAA,IAAI,IAAA,CAAK,+BAA+B,OAAA,EAAS;AAC/C,UAAA,IAAA,CAAK,0BAAA,GAA6B,IAAA;AAAA,QACpC;AAAA,MACF,CAAC,CAAA;AACD,MAAA,IAAA,CAAK,0BAAA,GAA6B,OAAA;AAClC,MAAA,IAAA,CAAK,0BAAA,CAA2B,MAAM,CAAA,KAAA,KAAS;AAC7C,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EAAG,UAAU,iDAAiD,IAAA,CAAK,eAAe,KAAK,KAAK,CAAA;AAAA,MAC/G,CAAC,CAAA;AAAA,IACH,GAAG,OAAO,CAAA;AACV,IAAA,IAAA,CAAK,wBAAwB,KAAA,IAAQ;AAAA,EACvC;AAAA,EAEQ,wBAAA,GAAiC;AACvC,IAAA,IAAI,KAAK,uBAAA,EAAyB;AAChC,MAAA,YAAA,CAAa,KAAK,uBAAuB,CAAA;AACzC,MAAA,IAAA,CAAK,uBAAA,GAA0B,IAAA;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,MAAc,uBAAA,GAAyC;AACrD,IAAA,IAAA,CAAK,wBAAA,EAAyB;AAE9B,IAAA,IAAI,KAAK,0BAAA,EAA4B;AACnC,MAAA,MAAM,IAAA,CAAK,0BAAA;AACX,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,MAAM,IAAA,CAAK,kBAAA,CAAmB,IAAA,CAAK,QAAQ,CAAA;AAAA,IAC7C;AAAA,EACF;AAAA,EAEQ,6BAA6B,KAAA,EAAyB;AAC5D,IAAA,IAAI,EAAE,iBAAiB,KAAA,CAAA,EAAQ;AAC7B,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,WAAA,EAAY;AAC1C,IAAA,OACE,QAAQ,QAAA,CAAS,YAAY,CAAA,IAC7B,CAAC,aAAa,gBAAA,EAAkB,SAAA,EAAW,SAAA,EAAW,eAAe,EAAE,IAAA,CAAK,CAAA,MAAA,KAAU,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,EAElH;AAAA,EAEQ,+BAA+B,KAAA,EAAyB;AAC9D,IAAA,IAAI,EAAE,iBAAiB,KAAA,CAAA,EAAQ;AAC7B,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,WAAA,EAAY;AAC1C,IAAA,OACE,OAAA,CAAQ,SAAS,YAAY,CAAA,KAC5B,CAAC,gBAAA,EAAkB,gBAAA,EAAkB,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAA,MAAA,KAAU,QAAQ,QAAA,CAAS,MAAM,CAAC,CAAA,IACpF,OAAA,CAAQ,SAAS,MAAM,CAAA,IAAK,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,CAAA;AAAA,EAE1D;AAAA,EAEQ,yBAAA,CAA0B,KAAA,EAAgB,IAAA,mBAAO,IAAI,KAAa,EAAY;AACpF,IAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACtC,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,KAAA;AAC5B,MAAA,IAAA,CAAK,IAAI,KAAK,CAAA;AAAA,IAChB;AAEA,IAAA,IACE,KAAA,YAAiB,wBACjB,KAAA,YAAiB,kBAAA,IAChB,iBAAiB,mBAAA,IAAuB,KAAA,CAAM,aAAa,SAAA,EAC5D;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACtC,MAAA,MAAM,SAAA,GAAY,KAAA;AAClB,MAAA,MAAM,OAAO,OAAO,SAAA,CAAU,IAAA,KAAS,QAAA,GAAW,UAAU,IAAA,GAAO,EAAA;AACnE,MAAA,MAAM,OAAA,GAAU,OAAO,SAAA,CAAU,OAAA,KAAY,WAAW,SAAA,CAAU,OAAA,CAAQ,aAAY,GAAI,EAAA;AAE1F,MAAA,IACE,IAAA,KAAS,0BACT,IAAA,KAAS,oBAAA,IACR,SAAS,qBAAA,IAAyB,SAAA,CAAU,aAAa,SAAA,EAC1D;AACA,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,IACE,QAAQ,QAAA,CAAS,SAAS,CAAA,IAC1B,CAAC,aAAa,WAAA,EAAa,QAAA,EAAU,aAAA,EAAe,aAAa,EAAE,IAAA,CAAK,CAAA,MAAA,KAAU,QAAQ,QAAA,CAAS,MAAM,CAAC,CAAA,EAC1G;AACA,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,IAAI,SAAA,CAAU,UAAU,MAAA,EAAW;AACjC,QAAA,OAAO,IAAA,CAAK,yBAAA,CAA0B,SAAA,CAAU,KAAA,EAAO,IAAI,CAAA;AAAA,MAC7D;AAAA,IACF;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,GAAsB;AAC1B,IAAA,MAAM,KAAK,SAAA,EAAU;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,GAAyB;AAC7B,IAAA,MAAM,KAAK,SAAA,EAAU;AAAA,EACvB;AAAA,EAEA,MAAc,SAAA,GAA2B;AACvC,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,IAAA,CAAK,wBAAA,EAAyB;AAC9B,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA;AACrB,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,uBAAA,EAAwB;AAAA,IACrC,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,UAAU,gDAAgD,KAAK,CAAA;AAAA,IACrF;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,QAAQ,OAAA,EAAQ;AAAA,IACxB,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,EAAG,UAAU,sCAAsC,OAAA,CAAQ,EAAE,KAAK,KAAK,CAAA;AAAA,IAC1F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAA,GAAoC;AAC1C,IAAA,MAAM,SAAS,IAAA,CAAK,eAAA;AACpB,IAAA,OAAO,OAAO,MAAA,KAAW,UAAA,GAAa,OAAO,OAAA,CAAQ,QAAA,EAAU,CAAA,GAAI,MAAA;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,IAAA,CACJ,OAAA,GAAiG,EAAC,EACzE;AACzB,IAAA,MAAM,SAAS,IAAA,CAAK,OAAA;AACpB,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,IAAA,CAAK;AAAA,MAC/B,GAAI,OAAA,CAAQ,kBAAA,KAAuB,UAAa,EAAE,kBAAA,EAAoB,QAAQ,kBAAA,EAAmB;AAAA,MACjG,GAAI,OAAA,CAAQ,gBAAA,KAAqB,UAAa,EAAE,gBAAA,EAAkB,QAAQ,gBAAA,EAAiB;AAAA,MAC3F,GAAI,OAAA,CAAQ,GAAA,KAAQ,UAAa,EAAE,GAAA,EAAK,QAAQ,GAAA;AAAI,KACrD,CAAA;AAED,IAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,CAAe;AAAA,MAC/B,GAAI,OAAA,CAAQ,EAAA,KAAO,UAAa,EAAE,EAAA,EAAI,QAAQ,EAAA,EAAG;AAAA,MACjD,GAAI,IAAA,CAAK,MAAA,KAAW,UAAa,EAAE,KAAA,EAAO,KAAK,MAAA,EAAO;AAAA,MACtD,GAAI,IAAA,CAAK,cAAA,KAAmB,UAAa,EAAE,aAAA,EAAe,KAAK,cAAA,EAAe;AAAA,MAC9E,WAAW,MAAA,CAAO,EAAA;AAAA,MAClB,kBAAA,EAAoB,OAAA,CAAQ,kBAAA,IAAsB,IAAA,CAAK,mBAAA;AAAA,MACvD,gBAAA,EAAkB,OAAA,CAAQ,gBAAA,IAAoB,IAAA,CAAK,iBAAA;AAAA,MACnD,GAAA,EAAK,OAAA,CAAQ,GAAA,IAAO,IAAA,CAAK,IAAA;AAAA,MACzB,SAAS,IAAA,CAAK;AAAA,KACf,CAAA;AACD,IAAA,MAAM,MAAM,MAAA,EAAO;AACnB,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAA,GAAgC;AACpC,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,EAAA;AAAA,MACT,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAA,EAAW,IAAA,CAAK,UAAA,oBAAc,IAAI,IAAA,EAAK;AAAA,MACvC,QAAA,EAAU;AAAA,QACR,GAAI,KAAK,QAAA,IAAY;AAAA,UACnB,gBAAA,EAAkB,KAAK,QAAA,CAAS,EAAA;AAAA,UAChC,aAAA,EAAe,KAAK,QAAA,CAAS,aAAA;AAAA,UAC7B,MAAA,EAAQ,KAAK,QAAA,CAAS,MAAA;AAAA,UACtB,gBAAA,EAAkB,KAAK,QAAA,CAAS,gBAAA;AAAA,UAChC,GAAI,IAAA,CAAK,QAAA,CAAS,kBAAA,IAAsB,IAAA,IAAQ;AAAA,YAC9C,kBAAA,EAAoB,KAAK,QAAA,CAAS;AAAA;AACpC;AACF;AACF,KACF;AAAA,EACF;AAAA,EAEA,eAAA,GAA0B;AACxB,IAAA,MAAM,mBAAA,GAAsB,KAAK,yBAAA,EAA0B;AAE3D,IAAA,IAAI,OAAO,IAAA,CAAK,qBAAA,KAA0B,QAAA,EAAU;AAClD,MAAA,OAAO,IAAA,CAAK,qBAAA;AAAA,IACd;AACA,IAAA,IAAI,OAAO,IAAA,CAAK,qBAAA,KAA0B,UAAA,EAAY;AACpD,MAAA,OAAO,IAAA,CAAK,qBAAA,CAAsB,EAAE,mBAAA,EAAqB,CAAA;AAAA,IAC3D;AACA,IAAA,OAAO,mBAAA;AAAA,EACT;AAAA,EAEQ,yBAAA,GAAoC;AAC1C,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,KAAA,CAAM,KAAK,mFAAmF,CAAA;AAE9F,IAAA,IAAI,IAAA,CAAK,sBAAsB,SAAA,EAAW;AACxC,MAAA,KAAA,CAAM,KAAK,4CAA4C,CAAA;AAAA,IACzD;AAEA,IAAA,IAAI,IAAA,CAAK,aAAa,MAAA,EAAW;AAC/B,MAAA,KAAA,CAAM,IAAA,CAAK,4BAA4B,IAAA,CAAK,IAAA,CAAK,KAAK,QAAA,GAAW,GAAI,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,IAC5E,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,KAAK,uDAAuD,CAAA;AAAA,IACpE;AAEA,IAAA,IAAI,IAAA,CAAK,wBAAwB,MAAA,EAAW;AAC1C,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiB,IAAA,CAAK,mBAAmB,CAAA,WAAA,CAAa,CAAA;AAAA,IACnE;AAEA,IAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eACJ,OAAA,EACA,IAAA,GAAiB,EAAC,EAClB,OAAA,GAAiC,EAAC,EACV;AACxB,IAAA,OAAO,IAAA,CAAK,iBAAiB,YAAY;AACvC,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,GAAG,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,GAAK,OAAA;AACvF,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,IAAA,CAAK,QAAA;AACxC,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,GAChB,MAAA,CAAO,WAAA;AAAA,QACL,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA,CAAE,MAAA,CAAO,CAAC,KAAA,KAAqC,KAAA,CAAM,CAAC,CAAA,KAAM,MAAS;AAAA,OACjG,GACA,MAAA;AACJ,MAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,WAAA,EAAa;AAAA,QAClD,GAAI,YAAY,MAAA,IAAa,EAAE,YAAY,IAAA,CAAK,IAAA,CAAK,OAAA,GAAU,GAAI,CAAA,EAAE;AAAA,QACrE,GAAI,OAAA,CAAQ,GAAA,KAAQ,UAAa,EAAE,GAAA,EAAK,QAAQ,GAAA,EAAI;AAAA,QACpD,GAAI,GAAA,KAAQ,MAAA,IAAa,EAAE,GAAA;AAAI,OAChC,CAAA;AACD,MAAA,MAAM,QAAA,GAAW,OAAO,QAAA,IAAY,EAAA;AACpC,MAAA,OAAO;AAAA,QACL,SAAS,QAAA,KAAa,CAAA;AAAA,QACtB,QAAA;AAAA,QACA,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,QAC9B,OAAA;AAAA,QACA,IAAA;AAAA,QACA,UAAU,MAAA,CAAO;AAAA,OACnB;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACF;;;ACjpBO,IAAM,sBAAA,GAAiE;AAAA,EAC5E,EAAA,EAAI,SAAA;AAAA,EACJ,IAAA,EAAM,iBAAA;AAAA,EACN,WAAA,EAAa,iDAAA;AAAA,EACb,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,QAAA;AAAA,IACN,UAAA,EAAY;AAAA,MACV,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,qDAAA,EAAsD;AAAA,MAC5F,aAAA,EAAe;AAAA,QACb,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,SAAA,EAAW,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+CAAA,EAAgD;AAAA,MAC1F,kBAAA,EAAoB;AAAA,QAClB,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,gBAAA,EAAkB;AAAA,QAChB,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa,wBAAA;AAAA,QACb,IAAA,EAAM,CAAC,UAAA,EAAY,SAAS,CAAA;AAAA,QAC5B,OAAA,EAAS;AAAA,OACX;AAAA,MACA,GAAA,EAAK;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa,uBAAA;AAAA,QACb,oBAAA,EAAsB,EAAE,IAAA,EAAM,QAAA;AAAS,OACzC;AAAA,MACA,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+BAAA;AAAgC;AAC1E,GACF;AAAA,EACA,aAAA,EAAe,CAAA,MAAA,KAAU,IAAI,cAAA,CAAe,MAAM;AACpD","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"]}
|
package/dist/sandbox/index.d.ts
CHANGED
|
@@ -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":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,WAAW,EACZ,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAwB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,OAAO,
|
|
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.
|
|
3
|
+
"version": "0.3.0-alpha.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.
|
|
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/
|
|
34
|
+
"@internal/workspace-test-utils": "0.0.54",
|
|
35
35
|
"@internal/types-builder": "0.0.85",
|
|
36
|
-
"@
|
|
37
|
-
"@
|
|
36
|
+
"@internal/lint": "0.0.110",
|
|
37
|
+
"@mastra/core": "1.49.0-alpha.2"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@mastra/core": ">=1.12.0-0 <2.0.0-0"
|