{"version":3,"file":"index.mjs","names":["RailwaySandbox","events: ProcessOutputEvent[]","state: \"running\" | \"exited\" | \"killed\""],"sources":["../../../src/providers/railway/index.ts"],"sourcesContent":["import {\n  Sandbox as RailwaySandbox,\n  type ExecHandle,\n  type ExecSignal,\n  type SandboxTemplate,\n} from \"railway\";\nimport { SandboxError } from \"../../core/errors\";\nimport type { SandboxProvider } from \"../../core/provider\";\nimport type { ProcessOutputEvent, SandboxProcess, SandboxSnapshot } from \"../../core/types\";\nimport { commandString, unsupported } from \"../../internal/provider-utils\";\nimport { railwayCapabilities } from \"../capabilities\";\n\ninterface RailwayBaseOptions {\n  /** Railway API token. Defaults to RAILWAY_API_TOKEN. */\n  token?: string;\n  /** Railway environment id. Defaults to RAILWAY_ENVIRONMENT_ID. */\n  environmentId?: string;\n  /** Minutes before Railway destroys an idle sandbox. */\n  idleTimeoutMinutes?: number;\n  /** Whether the sandbox can access the environment's private network. */\n  networkIsolation?: \"ISOLATED\" | \"PRIVATE\";\n}\n\nexport type RailwayOptions = RailwayBaseOptions &\n  ({ checkpoint?: string; template?: never } | { checkpoint?: never; template?: SandboxTemplate });\n\nexport { railwayCapabilities } from \"../capabilities\";\n\nexport function railway(options: RailwayOptions = {}): SandboxProvider<RailwaySandbox> {\n  const credentials = {\n    token: options.token,\n    environmentId: options.environmentId,\n  };\n\n  return {\n    id: \"railway\",\n    capabilities: railwayCapabilities,\n    async create(createOptions) {\n      assertNotAborted(createOptions.signal);\n      const createConfig = {\n        ...credentials,\n        idleTimeoutMinutes: options.idleTimeoutMinutes,\n        networkIsolation: options.networkIsolation,\n        env: { ...createOptions.env },\n      };\n      const pending = options.checkpoint\n        ? RailwaySandbox.create(options.checkpoint, createConfig)\n        : options.template\n          ? RailwaySandbox.create(options.template, createConfig)\n          : RailwaySandbox.create(createConfig);\n      const raw = await awaitCreation(pending, createOptions.signal, createOptions.timeout);\n      try {\n        await raw.files.mkdir(createOptions.cwd);\n      } catch (error) {\n        await raw.destroy().catch(() => undefined);\n        throw error;\n      }\n\n      return {\n        id: raw.id,\n        raw,\n        capabilities: railwayCapabilities,\n        files: {\n          async write(path, value) {\n            await raw.files.write(path, value);\n          },\n          read: (path) => raw.files.read(path, { format: \"bytes\" }),\n          async list(path) {\n            return (await raw.files.list(path)).map((entry) => ({\n              name: entry.name,\n              path: `${path.replace(/\\/$/, \"\")}/${entry.name}`,\n              type: entry.isDir ? (\"directory\" as const) : (\"file\" as const),\n              size: entry.isDir ? undefined : entry.size,\n            }));\n          },\n          mkdir: (path) => raw.files.mkdir(path),\n          async remove(path) {\n            const result = await raw.exec(\n              commandString({ command: \"rm\", args: [\"-rf\", \"--\", path] }),\n            );\n            if (result.exitCode !== 0) {\n              throw new Error(`files.remove failed: ${result.stderr || result.stdout}`);\n            }\n          },\n          exists: (path) => raw.files.exists(path),\n        },\n        async run(command, runOptions) {\n          assertNotAborted(runOptions.signal);\n          const started = performance.now();\n          const handle = raw.exec(commandString(command), {\n            cwd: runOptions.cwd,\n            env: { ...runOptions.env },\n            timeoutSec: timeoutSeconds(runOptions.timeout),\n          });\n          const removeAbort = bindAbort(handle, runOptions.signal);\n          try {\n            const result = await handle;\n            if (result.timedOut) {\n              throw new SandboxError({\n                code: \"timeout\",\n                provider: \"railway\",\n                operation: \"process.run\",\n                message: `Command timed out after ${runOptions.timeout}ms`,\n              });\n            }\n            return {\n              stdout: result.stdout,\n              stderr: result.stderr,\n              exitCode: result.exitCode ?? -1,\n              success: result.exitCode === 0,\n              signal: result.exitCode === null ? \"unknown\" : undefined,\n              durationMs: Math.round(performance.now() - started),\n            };\n          } finally {\n            removeAbort();\n          }\n        },\n        async start(command, runOptions) {\n          assertNotAborted(runOptions.signal);\n          const events: ProcessOutputEvent[] = [];\n          const waiters = new Set<() => void>();\n          let state: \"running\" | \"exited\" | \"killed\" = \"running\";\n          const wake = () => {\n            for (const waiter of waiters) waiter();\n            waiters.clear();\n          };\n          const push = (stream: \"stdout\" | \"stderr\", data: string) => {\n            events.push({ stream, data, timestamp: new Date() });\n            wake();\n          };\n          const handle = raw.exec(commandString(command), {\n            cwd: runOptions.cwd,\n            env: { ...runOptions.env },\n            timeoutSec: timeoutSeconds(runOptions.timeout),\n            onStdout: (chunk) => push(\"stdout\", chunk),\n            onStderr: (chunk) => push(\"stderr\", chunk),\n          });\n          const removeAbort = bindAbort(handle, runOptions.signal);\n          const completed = handle\n            .then((result) => ({ exitCode: result.exitCode ?? -1 }))\n            .finally(() => {\n              if (state === \"running\") state = \"exited\";\n              removeAbort();\n              wake();\n            });\n          const id = await handle.sessionName;\n\n          return {\n            id,\n            async status() {\n              return state;\n            },\n            async *output() {\n              let index = 0;\n              while (state === \"running\" || index < events.length) {\n                while (index < events.length) yield events[index++]!;\n                if (state !== \"running\") break;\n                await new Promise<void>((resolve) => waiters.add(resolve));\n              }\n            },\n            async write() {\n              unsupported(\"railway\", \"process.stdin\");\n            },\n            wait: () => completed,\n            async kill(signal = \"SIGTERM\") {\n              const nativeSignal = signal.replace(/^SIG/, \"\") as ExecSignal;\n              await handle.kill(nativeSignal);\n              state = \"killed\";\n              wake();\n            },\n          } satisfies SandboxProcess;\n        },\n        async expose() {\n          unsupported(\"railway\", \"ports.expose\");\n        },\n        snapshots: {\n          async create(snapshotOptions) {\n            const checkpoint = await raw.checkpoint(\n              snapshotOptions?.name ?? `sandbox-sdk-${Date.now()}`,\n            );\n            return {\n              id: checkpoint.id,\n              name: checkpoint.key,\n              mode: \"filesystem\",\n              createdAt: new Date(checkpoint.createdAt),\n            } satisfies SandboxSnapshot;\n          },\n          async delete(snapshot) {\n            await RailwaySandbox.deleteCheckpoint(\n              typeof snapshot === \"string\" ? snapshot : snapshot.id,\n              credentials,\n            );\n          },\n          async restore() {\n            unsupported(\"railway\", \"snapshot.restore\");\n          },\n        },\n        async stop() {\n          await raw.destroy();\n        },\n      };\n    },\n  };\n}\n\nfunction timeoutSeconds(timeout?: number): number | undefined {\n  return timeout === undefined ? undefined : Math.max(1, Math.ceil(timeout / 1_000));\n}\n\nfunction bindAbort(handle: ExecHandle, signal?: AbortSignal): () => void {\n  if (!signal) return () => undefined;\n  const abort = () => void handle.kill(\"TERM\").catch(() => undefined);\n  signal.addEventListener(\"abort\", abort, { once: true });\n  return () => signal.removeEventListener(\"abort\", abort);\n}\n\nasync function awaitCreation(\n  promise: Promise<RailwaySandbox>,\n  signal?: AbortSignal,\n  timeoutMs?: number,\n): Promise<RailwaySandbox> {\n  if (!signal && timeoutMs === undefined) return promise;\n  return new Promise<RailwaySandbox>((resolve, reject) => {\n    let settled = false;\n    const finish = (callback: () => void) => {\n      if (settled) return;\n      settled = true;\n      signal?.removeEventListener(\"abort\", onAbort);\n      if (timer) clearTimeout(timer);\n      callback();\n    };\n    const onAbort = () =>\n      finish(() => reject(signal?.reason ?? new DOMException(\"Aborted\", \"AbortError\")));\n    const timer = timeoutMs\n      ? setTimeout(\n          () => finish(() => reject(new Error(`Sandbox creation timed out after ${timeoutMs}ms`))),\n          timeoutMs,\n        )\n      : undefined;\n    signal?.addEventListener(\"abort\", onAbort, { once: true });\n    promise.then(\n      (sandbox) => {\n        if (settled) {\n          void sandbox.destroy().catch(() => undefined);\n          return;\n        }\n        finish(() => resolve(sandbox));\n      },\n      (error) => finish(() => reject(error)),\n    );\n  });\n}\n\nfunction assertNotAborted(signal?: AbortSignal): void {\n  if (signal?.aborted) throw signal.reason ?? new DOMException(\"Aborted\", \"AbortError\");\n}\n\nexport type { RailwaySandbox, SandboxTemplate as RailwaySandboxTemplate };\n"],"mappings":"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"}