@mastra/railway 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @mastra/railway
2
2
 
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - dependencies updates: ([#17861](https://github.com/mastra-ai/mastra/pull/17861))
8
+ - Updated dependency [`railway@^3.3.1` ↗︎](https://www.npmjs.com/package/railway/v/3.3.1) (from `^3.1.1`, in `dependencies`)
9
+
10
+ - Improved process execution by using Railway SDK's native `cwd` and `env` exec options. ([#17902](https://github.com/mastra-ai/mastra/pull/17902))
11
+ Commands now run with the configured working directory and environment variables without client-side shell wrapping.
12
+ - Updated dependencies [[`de66bb0`](https://github.com/mastra-ai/mastra/commit/de66bb040570444c702ce4d8e1e228a5de2949cb), [`67bf8e2`](https://github.com/mastra-ai/mastra/commit/67bf8e206dfe583954d96015cf0d09f7ac50e45f), [`8216d05`](https://github.com/mastra-ai/mastra/commit/8216d0528d866eb9a07f5d4c87ea3bb1e1139b45), [`d18b23c`](https://github.com/mastra-ai/mastra/commit/d18b23c5e29dfc381e73e3c51fcf6c779afd1823), [`5eb94eb`](https://github.com/mastra-ai/mastra/commit/5eb94ebcf66d4e28c9e26d5821ac93379bab20a0), [`1fa3e12`](https://github.com/mastra-ai/mastra/commit/1fa3e123582b63cfe49de4ee52dc6a065e8d956a), [`f9ee2ac`](https://github.com/mastra-ai/mastra/commit/f9ee2ac661af584e61bc063ac208c9035cd752ef), [`c853d53`](https://github.com/mastra-ai/mastra/commit/c853d535d2df84ab89db1adb4c28900c54c9a2d2), [`d8df1f8`](https://github.com/mastra-ai/mastra/commit/d8df1f8e947e1966c9d4e54713df56d0d0d65226), [`9192ddb`](https://github.com/mastra-ai/mastra/commit/9192ddbced8949113b30de444cbe763f075b59f5), [`ae96523`](https://github.com/mastra-ai/mastra/commit/ae965231f562d9766b0c90c49a69fc68acaa031c), [`17d5a92`](https://github.com/mastra-ai/mastra/commit/17d5a9211aa293b4d4418de3de70dc0394d58101), [`5573693`](https://github.com/mastra-ai/mastra/commit/5573693b589822250e20dfe6cf66e9ff3bc96da8), [`ec4da8a`](https://github.com/mastra-ai/mastra/commit/ec4da8a09e0d2ab452c6ee2c786042ea826b77e5), [`adc44e1`](https://github.com/mastra-ai/mastra/commit/adc44e13c7e570b91e86b20ea7556e61d819db31), [`ed346c0`](https://github.com/mastra-ai/mastra/commit/ed346c0bee2d8496690a4e538bfba1e46894660f), [`c9ce1b2`](https://github.com/mastra-ai/mastra/commit/c9ce1b28d10871110648f9d7b6d76e880b9fa999), [`3ef01fd`](https://github.com/mastra-ai/mastra/commit/3ef01fd130b53d5bd4f828beb174e516a2eb1158), [`245a9a3`](https://github.com/mastra-ai/mastra/commit/245a9a315705fce17ddd980f78a92504b6615c4a), [`dc0b611`](https://github.com/mastra-ai/mastra/commit/dc0b6119b769bd00ee2c5df9259fb376fe63077a), [`38b5de8`](https://github.com/mastra-ai/mastra/commit/38b5de8e5d1d41a69522addf53d96f4b3a1d5bf0), [`dc0b611`](https://github.com/mastra-ai/mastra/commit/dc0b6119b769bd00ee2c5df9259fb376fe63077a), [`dd6a66e`](https://github.com/mastra-ai/mastra/commit/dd6a66ea0b32e0dea8059aec6b35d151e2c87dc4), [`d785c59`](https://github.com/mastra-ai/mastra/commit/d785c593b67fcb4cdc4fab9fdbde5f3b7665efc0), [`1fa3e12`](https://github.com/mastra-ai/mastra/commit/1fa3e123582b63cfe49de4ee52dc6a065e8d956a), [`8b984f4`](https://github.com/mastra-ai/mastra/commit/8b984f4361c202270ceb69257185c4756c9a7c56), [`bf08402`](https://github.com/mastra-ai/mastra/commit/bf084022374fa5d06ca70ed67a86dd64e379071b), [`81fe587`](https://github.com/mastra-ai/mastra/commit/81fe587275035715c1720ddf3fee0505cf053036), [`1fa3e12`](https://github.com/mastra-ai/mastra/commit/1fa3e123582b63cfe49de4ee52dc6a065e8d956a), [`403c438`](https://github.com/mastra-ai/mastra/commit/403c438e417278989ce247233d2c465b8d902cdd), [`f8ba195`](https://github.com/mastra-ai/mastra/commit/f8ba1954e27ee2b20586cc6cd9cf13c002c232f2)]:
13
+ - @mastra/core@1.43.0
14
+
3
15
  ## 0.1.0
4
16
 
5
17
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -11,12 +11,6 @@ function shellQuote(arg) {
11
11
  return "'" + arg.replace(/'/g, "'\\''") + "'";
12
12
  }
13
13
  var LOG_PREFIX = "[RailwaySandbox]";
14
- function buildSpawnCommand(command, cwd, env = {}) {
15
- const envAssignments = Object.entries(env).map(([key, value]) => `${key}=${shellQuote(value)}`).join(" ");
16
- const envPrefix = envAssignments ? `env ${envAssignments} ` : "";
17
- const inner = cwd ? `cd ${shellQuote(cwd)} && ${command}` : command;
18
- return `${envPrefix}sh -c ${shellQuote(inner)}`;
19
- }
20
14
  var RailwayProcessHandle = class extends workspace.ProcessHandle {
21
15
  pid;
22
16
  _execHandle;
@@ -99,14 +93,15 @@ var RailwayProcessManager = class extends workspace.SandboxProcessManager {
99
93
  async spawn(command, options = {}) {
100
94
  const railway = this.sandbox.railway;
101
95
  const mergedEnv = { ...this.env, ...options.env };
102
- const envs = Object.fromEntries(
96
+ const env = Object.fromEntries(
103
97
  Object.entries(mergedEnv).filter((entry) => entry[1] !== void 0)
104
98
  );
105
- const fullCommand = buildSpawnCommand(command, options.cwd, envs);
106
99
  const pid = `railway-proc-${Date.now().toString(36)}-${(this._spawnCounter++).toString(36)}`;
107
100
  let handle;
108
- const execHandle = railway.exec(fullCommand, {
101
+ const execHandle = railway.exec(command, {
109
102
  ...options.timeout !== void 0 && { timeoutSec: Math.ceil(options.timeout / 1e3) },
103
+ ...options.cwd !== void 0 && { cwd: options.cwd },
104
+ ...Object.keys(env).length > 0 && { env },
110
105
  onStdout: (chunk) => handle.emitStdout(chunk),
111
106
  onStderr: (chunk) => handle.emitStderr(chunk)
112
107
  });
@@ -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)` 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 { shellQuote } from '../utils/shell-quote';\nimport type { RailwaySandbox } from './index';\n\nexport const LOG_PREFIX = '[RailwaySandbox]';\n\n/**\n * Build a shell command that applies a working directory and environment\n * variables, since Railway's `exec` takes neither per-call. Env vars are\n * exported via `env` so they apply to the command's process group.\n */\nexport function buildSpawnCommand(command: string, cwd?: string, env: Record<string, string> = {}): string {\n const envAssignments = Object.entries(env)\n .map(([key, value]) => `${key}=${shellQuote(value)}`)\n .join(' ');\n\n const envPrefix = envAssignments ? `env ${envAssignments} ` : '';\n // Wrap in a subshell so a `cd` and the user command compose cleanly.\n const inner = cwd ? `cd ${shellQuote(cwd)} && ${command}` : command;\n return `${envPrefix}sh -c ${shellQuote(inner)}`;\n}\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 envs = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n const fullCommand = buildSpawnCommand(command, options.cwd, envs);\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(fullCommand, {\n ...(options.timeout !== undefined && { timeoutSec: Math.ceil(options.timeout / 1000) }),\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. The template is built (`.build()`) on first\n * `start()` if not already built.\n * ```ts\n * template: t => t.withPackages('git', 'curl').run('npm i -g pnpm')\n * ```\n * - Pre-built `SandboxTemplate` — pass a template you built yourself to reuse\n * it across sandboxes without rebuilding.\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 = await this._resolveTemplate(clientConfig);\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 * Build the configured template into a ready-to-use base. Accepts either a\n * pre-built `SandboxTemplate` or a builder callback over `Sandbox.template()`.\n * Calls `.build()` so the recipe is materialised before `Sandbox.create()`.\n */\n private async _resolveTemplate(buildOptions: { token?: string; environmentId?: string }): Promise<SandboxTemplate> {\n const option = this._templateOption!;\n const template = typeof option === 'function' ? option(Sandbox.template()) : option;\n this.logger.debug(`${LOG_PREFIX} Building Railway sandbox template for: ${this.id}`);\n return template.build(buildOptions);\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"],"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. The template is built (`.build()`) on first\n * `start()` if not already built.\n * ```ts\n * template: t => t.withPackages('git', 'curl').run('npm i -g pnpm')\n * ```\n * - Pre-built `SandboxTemplate` — pass a template you built yourself to reuse\n * it across sandboxes without rebuilding.\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 = await this._resolveTemplate(clientConfig);\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 * Build the configured template into a ready-to-use base. Accepts either a\n * pre-built `SandboxTemplate` or a builder callback over `Sandbox.template()`.\n * Calls `.build()` so the recipe is materialised before `Sandbox.create()`.\n */\n private async _resolveTemplate(buildOptions: { token?: string; environmentId?: string }): Promise<SandboxTemplate> {\n const option = this._templateOption!;\n const template = typeof option === 'function' ? option(Sandbox.template()) : option;\n this.logger.debug(`${LOG_PREFIX} Building Railway sandbox template for: ${this.id}`);\n return template.build(buildOptions);\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"]}
package/dist/index.js CHANGED
@@ -9,12 +9,6 @@ function shellQuote(arg) {
9
9
  return "'" + arg.replace(/'/g, "'\\''") + "'";
10
10
  }
11
11
  var LOG_PREFIX = "[RailwaySandbox]";
12
- function buildSpawnCommand(command, cwd, env = {}) {
13
- const envAssignments = Object.entries(env).map(([key, value]) => `${key}=${shellQuote(value)}`).join(" ");
14
- const envPrefix = envAssignments ? `env ${envAssignments} ` : "";
15
- const inner = cwd ? `cd ${shellQuote(cwd)} && ${command}` : command;
16
- return `${envPrefix}sh -c ${shellQuote(inner)}`;
17
- }
18
12
  var RailwayProcessHandle = class extends ProcessHandle {
19
13
  pid;
20
14
  _execHandle;
@@ -97,14 +91,15 @@ var RailwayProcessManager = class extends SandboxProcessManager {
97
91
  async spawn(command, options = {}) {
98
92
  const railway = this.sandbox.railway;
99
93
  const mergedEnv = { ...this.env, ...options.env };
100
- const envs = Object.fromEntries(
94
+ const env = Object.fromEntries(
101
95
  Object.entries(mergedEnv).filter((entry) => entry[1] !== void 0)
102
96
  );
103
- const fullCommand = buildSpawnCommand(command, options.cwd, envs);
104
97
  const pid = `railway-proc-${Date.now().toString(36)}-${(this._spawnCounter++).toString(36)}`;
105
98
  let handle;
106
- const execHandle = railway.exec(fullCommand, {
99
+ const execHandle = railway.exec(command, {
107
100
  ...options.timeout !== void 0 && { timeoutSec: Math.ceil(options.timeout / 1e3) },
101
+ ...options.cwd !== void 0 && { cwd: options.cwd },
102
+ ...Object.keys(env).length > 0 && { env },
108
103
  onStdout: (chunk) => handle.emitStdout(chunk),
109
104
  onStderr: (chunk) => handle.emitStderr(chunk)
110
105
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/shell-quote.ts","../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../src/provider.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Shell-quote a single argument for safe use in a command string.\n *\n * Arguments containing only safe characters are returned as-is.\n * All others are wrapped in single quotes with embedded single quotes escaped.\n */\nexport function shellQuote(arg: string): string {\n // Safe characters that don't need quoting\n if (/^[a-zA-Z0-9._\\-/@:=]+$/.test(arg)) return arg;\n // Wrap in single quotes, escaping any embedded single quotes\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n","/**\n * Railway Process Manager\n *\n * Implements SandboxProcessManager for Railway sandboxes.\n * Wraps the Railway SDK's `Sandbox.exec()` API.\n *\n * Railway's `exec(command)` 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 { shellQuote } from '../utils/shell-quote';\nimport type { RailwaySandbox } from './index';\n\nexport const LOG_PREFIX = '[RailwaySandbox]';\n\n/**\n * Build a shell command that applies a working directory and environment\n * variables, since Railway's `exec` takes neither per-call. Env vars are\n * exported via `env` so they apply to the command's process group.\n */\nexport function buildSpawnCommand(command: string, cwd?: string, env: Record<string, string> = {}): string {\n const envAssignments = Object.entries(env)\n .map(([key, value]) => `${key}=${shellQuote(value)}`)\n .join(' ');\n\n const envPrefix = envAssignments ? `env ${envAssignments} ` : '';\n // Wrap in a subshell so a `cd` and the user command compose cleanly.\n const inner = cwd ? `cd ${shellQuote(cwd)} && ${command}` : command;\n return `${envPrefix}sh -c ${shellQuote(inner)}`;\n}\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 envs = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n const fullCommand = buildSpawnCommand(command, options.cwd, envs);\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(fullCommand, {\n ...(options.timeout !== undefined && { timeoutSec: Math.ceil(options.timeout / 1000) }),\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. The template is built (`.build()`) on first\n * `start()` if not already built.\n * ```ts\n * template: t => t.withPackages('git', 'curl').run('npm i -g pnpm')\n * ```\n * - Pre-built `SandboxTemplate` — pass a template you built yourself to reuse\n * it across sandboxes without rebuilding.\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 = await this._resolveTemplate(clientConfig);\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 * Build the configured template into a ready-to-use base. Accepts either a\n * pre-built `SandboxTemplate` or a builder callback over `Sandbox.template()`.\n * Calls `.build()` so the recipe is materialised before `Sandbox.create()`.\n */\n private async _resolveTemplate(buildOptions: { token?: string; environmentId?: string }): Promise<SandboxTemplate> {\n const option = this._templateOption!;\n const template = typeof option === 'function' ? option(Sandbox.template()) : option;\n this.logger.debug(`${LOG_PREFIX} Building Railway sandbox template for: ${this.id}`);\n return template.build(buildOptions);\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":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Shell-quote a single argument for safe use in a command string.\n *\n * Arguments containing only safe characters are returned as-is.\n * All others are wrapped in single quotes with embedded single quotes escaped.\n */\nexport function shellQuote(arg: string): string {\n // Safe characters that don't need quoting\n if (/^[a-zA-Z0-9._\\-/@:=]+$/.test(arg)) return arg;\n // Wrap in single quotes, escaping any embedded single quotes\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n","/**\n * Railway Process Manager\n *\n * Implements SandboxProcessManager for Railway sandboxes.\n * Wraps the Railway SDK's `Sandbox.exec()` API.\n *\n * Railway's `exec(command, options)` accepts per-call `cwd` and `env` options\n * (since SDK v3.3.1) and returns an `ExecHandle` that runs the command\n * server-side, independently of the client. Each spawn() starts one exec.\n * The handle streams output via `onStdout`/`onStderr` callbacks wired to\n * `emitStdout`/`emitStderr`, exposes a durable `sessionName`, and can be\n * terminated with `kill(signal)`.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ExecHandle, ExecResult } from 'railway';\nimport type { RailwaySandbox } from './index';\n\nexport const LOG_PREFIX = '[RailwaySandbox]';\n\n// =============================================================================\n// Railway Process Handle\n// =============================================================================\n\n/**\n * Wraps a Railway ExecHandle to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n */\nclass RailwayProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _execHandle: ExecHandle;\n private readonly _startTime: number;\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _killed = false;\n\n constructor(pid: string, execHandle: ExecHandle, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._execHandle = execHandle;\n this._startTime = startTime;\n\n // Resolve exit code once the command completes so exitCode is available\n // without an explicit wait().\n void this._execHandle.then(\n (result: ExecResult) => {\n // -1 means terminated by a signal (e.g. after kill()).\n this._exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n },\n () => {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n },\n );\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n async wait(): Promise<CommandResult> {\n // Idempotent — cache the promise so repeated calls return the same result.\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n try {\n const result = await this._execHandle;\n const exitCode = result.exitCode ?? (this._killed ? 137 : -1);\n this._exitCode = exitCode;\n\n // Railway captures output server-side; surface it through the base buffers\n // if streaming callbacks didn't already populate them.\n if (result.stdout && !this.stdout) this.emitStdout(result.stdout);\n if (result.stderr && !this.stderr) this.emitStderr(result.stderr);\n\n return {\n success: exitCode === 0,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n timedOut: result.timedOut,\n };\n } catch (error) {\n const exitCode = this._exitCode ?? 1;\n this._exitCode = exitCode;\n return {\n success: false,\n exitCode,\n stdout: this.stdout,\n stderr: this.stderr || (error instanceof Error ? error.message : String(error)),\n executionTimeMs: Date.now() - this._startTime,\n killed: this._killed,\n };\n }\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n try {\n return await this._execHandle.kill('TERM');\n } catch {\n // Command may already be gone.\n return false;\n }\n }\n\n async sendStdin(_data: string): Promise<void> {\n // Railway's exec API does not expose stdin streaming.\n throw new Error(`${LOG_PREFIX} sending stdin is not supported by the Railway sandbox provider`);\n }\n}\n\n// =============================================================================\n// Railway Process Manager\n// =============================================================================\n\nexport interface RailwayProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Railway implementation of SandboxProcessManager.\n * Uses the Railway SDK's `Sandbox.exec()` with one exec per spawned process.\n */\nexport class RailwayProcessManager extends SandboxProcessManager<RailwaySandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: RailwayProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n const railway = this.sandbox.railway;\n\n // Merge default env with per-spawn env.\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n const pid = `railway-proc-${Date.now().toString(36)}-${(this._spawnCounter++).toString(36)}`;\n\n // Deferred reference — callbacks fire asynchronously after the handle is\n // assigned, so `handle` is always defined by the time they run.\n let handle: RailwayProcessHandle;\n\n const execHandle = railway.exec(command, {\n ...(options.timeout !== undefined && { timeoutSec: Math.ceil(options.timeout / 1000) }),\n ...(options.cwd !== undefined && { cwd: options.cwd }),\n ...(Object.keys(env).length > 0 && { env }),\n onStdout: (chunk: string) => handle.emitStdout(chunk),\n onStderr: (chunk: string) => handle.emitStderr(chunk),\n });\n\n handle = new RailwayProcessHandle(pid, execHandle, Date.now(), options);\n this._tracked.set(handle.pid, handle);\n return handle;\n }\n\n /**\n * List tracked processes.\n *\n * Railway has no API to enumerate running exec sessions by sandbox, so this\n * reports the processes this manager spawned.\n */\n async list(): Promise<ProcessInfo[]> {\n return Array.from(this._tracked.values()).map(handle => ({\n pid: handle.pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n ...(handle.exitCode !== undefined && { exitCode: handle.exitCode }),\n }));\n }\n}\n","/**\n * Railway Sandbox Provider\n *\n * A Railway sandbox implementation for Mastra workspaces. Provisions an\n * ephemeral, isolated Linux VM on Railway, runs commands in it via the\n * Railway TypeScript SDK, and destroys it on teardown.\n *\n * @see https://docs.railway.com/sandboxes\n */\n\nimport type {\n CommandResult,\n ExecuteCommandOptions,\n InstructionsOption,\n MastraSandboxOptions,\n ProviderStatus,\n SandboxInfo,\n} from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { Sandbox } from 'railway';\nimport type { SandboxNetworkIsolation, SandboxTemplate } from 'railway';\nimport { shellQuote } from '../utils/shell-quote';\nimport { LOG_PREFIX, RailwayProcessManager } from './process-manager';\n\n// =============================================================================\n// Railway Sandbox Options\n// =============================================================================\n\n/**\n * Railway sandbox provider configuration.\n */\nexport interface RailwaySandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance. */\n id?: string;\n /** Railway API token. Falls back to the RAILWAY_API_TOKEN env var. */\n token?: string;\n /** Railway environment ID. Falls back to the RAILWAY_ENVIRONMENT_ID env var. */\n environmentId?: string;\n /**\n * Reattach to an existing Railway sandbox by its Railway ID instead of\n * creating a new one. When set, `start()` calls `Sandbox.connect()`.\n */\n sandboxId?: string;\n /**\n * How long the sandbox can sit idle (no `exec` interaction) before Railway\n * destroys it automatically. Range depends on plan (1–120 minutes on\n * Hobby/Pro, 1–5 on Trial/Free). Defaults to the plan default when omitted.\n */\n idleTimeoutMinutes?: number;\n /**\n * Network isolation mode.\n * - `ISOLATED` (default): outbound internet only, no private network access.\n * - `PRIVATE`: joins the environment's private network.\n */\n networkIsolation?: SandboxNetworkIsolation;\n /** Environment variables baked into the sandbox, available to every command. */\n env?: Record<string, string>;\n /**\n * Provision the sandbox from a custom base image built with the Railway\n * template builder. Use this to pre-install packages or run setup steps so\n * every sandbox created from it starts ready.\n *\n * - Builder callback — receives the base `Sandbox.template()` and returns the\n * configured template. The template is built (`.build()`) on first\n * `start()` if not already built.\n * ```ts\n * template: t => t.withPackages('git', 'curl').run('npm i -g pnpm')\n * ```\n * - Pre-built `SandboxTemplate` — pass a template you built yourself to reuse\n * it across sandboxes without rebuilding.\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 = await this._resolveTemplate(clientConfig);\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 * Build the configured template into a ready-to-use base. Accepts either a\n * pre-built `SandboxTemplate` or a builder callback over `Sandbox.template()`.\n * Calls `.build()` so the recipe is materialised before `Sandbox.create()`.\n */\n private async _resolveTemplate(buildOptions: { token?: string; environmentId?: string }): Promise<SandboxTemplate> {\n const option = this._templateOption!;\n const template = typeof option === 'function' ? option(Sandbox.template()) : option;\n this.logger.debug(`${LOG_PREFIX} Building Railway sandbox template for: ${this.id}`);\n return template.build(buildOptions);\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"]}
@@ -4,7 +4,8 @@
4
4
  * Implements SandboxProcessManager for Railway sandboxes.
5
5
  * Wraps the Railway SDK's `Sandbox.exec()` API.
6
6
  *
7
- * Railway's `exec(command)` returns an `ExecHandle` that runs the command
7
+ * Railway's `exec(command, options)` accepts per-call `cwd` and `env` options
8
+ * (since SDK v3.3.1) and returns an `ExecHandle` that runs the command
8
9
  * server-side, independently of the client. Each spawn() starts one exec.
9
10
  * The handle streams output via `onStdout`/`onStderr` callbacks wired to
10
11
  * `emitStdout`/`emitStderr`, exposes a durable `sessionName`, and can be
@@ -14,12 +15,6 @@ import { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';
14
15
  import type { ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';
15
16
  import type { RailwaySandbox } from './index.js';
16
17
  export declare const LOG_PREFIX = "[RailwaySandbox]";
17
- /**
18
- * Build a shell command that applies a working directory and environment
19
- * variables, since Railway's `exec` takes neither per-call. Env vars are
20
- * exported via `env` so they apply to the command's process group.
21
- */
22
- export declare function buildSpawnCommand(command: string, cwd?: string, env?: Record<string, string>): string;
23
18
  export interface RailwayProcessManagerOptions {
24
19
  env?: Record<string, string | undefined>;
25
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../src/sandbox/process-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAiB,WAAW,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG9F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,eAAO,MAAM,UAAU,qBAAqB,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,CASzG;AA2GD,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,qBAAqB,CAAC,cAAc,CAAC;IAC9E,OAAO,CAAC,aAAa,CAAK;gBAEd,IAAI,GAAE,4BAAiC;IAI7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC;IA2BvF;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAQrC"}
1
+ {"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../src/sandbox/process-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAiB,WAAW,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE9F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,eAAO,MAAM,UAAU,qBAAqB,CAAC;AA2G7C,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,qBAAqB,CAAC,cAAc,CAAC;IAC9E,OAAO,CAAC,aAAa,CAAK;gBAEd,IAAI,GAAE,4BAAiC;IAI7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC;IA4BvF;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAQrC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/railway",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Railway cloud sandbox provider for Mastra workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,21 +20,21 @@
20
20
  },
21
21
  "license": "Apache-2.0",
22
22
  "dependencies": {
23
- "railway": "^3.1.1"
23
+ "railway": "^3.3.1"
24
24
  },
25
25
  "devDependencies": {
26
- "@types/node": "22.19.15",
27
- "@vitest/coverage-v8": "4.1.5",
28
- "@vitest/ui": "4.1.5",
29
- "dotenv": "^17.3.1",
26
+ "@types/node": "22.19.21",
27
+ "@vitest/coverage-v8": "4.1.8",
28
+ "@vitest/ui": "4.1.8",
29
+ "dotenv": "^17.4.2",
30
30
  "eslint": "^10.4.1",
31
31
  "tsup": "^8.5.1",
32
32
  "typescript": "^6.0.3",
33
- "vitest": "4.1.5",
34
- "@internal/lint": "0.0.104",
35
- "@internal/types-builder": "0.0.79",
36
- "@internal/workspace-test-utils": "0.0.48",
37
- "@mastra/core": "1.42.0"
33
+ "vitest": "4.1.8",
34
+ "@internal/lint": "0.0.105",
35
+ "@internal/workspace-test-utils": "0.0.49",
36
+ "@mastra/core": "1.43.0",
37
+ "@internal/types-builder": "0.0.80"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@mastra/core": ">=1.12.0-0 <2.0.0-0"