@mastra/railway 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/README.md +135 -0
- package/package.json +68 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @mastra/railway
|
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# @mastra/railway
|
|
2
|
+
|
|
3
|
+
Railway cloud sandbox provider for [Mastra](https://mastra.ai) workspaces.
|
|
4
|
+
|
|
5
|
+
Implements the `WorkspaceSandbox` interface using [Railway Sandboxes](https://docs.railway.com/sandboxes) — ephemeral, isolated Linux VMs provisioned on demand through Railway's TypeScript SDK. Supports command execution with streaming output, command timeouts, configurable idle timeout, network isolation, and reattaching to an existing sandbox.
|
|
6
|
+
|
|
7
|
+
> Railway Sandboxes are available through Priority Boarding and the SDK may change in breaking ways between releases.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @mastra/railway @mastra/core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
The provider reads credentials from the environment by default:
|
|
18
|
+
|
|
19
|
+
| Option | Environment variable |
|
|
20
|
+
| --------------- | ------------------------ |
|
|
21
|
+
| `token` | `RAILWAY_API_TOKEN` |
|
|
22
|
+
| `environmentId` | `RAILWAY_ENVIRONMENT_ID` |
|
|
23
|
+
|
|
24
|
+
Pass them explicitly to override the environment values.
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Basic
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { Workspace } from '@mastra/core/workspace';
|
|
32
|
+
import { RailwaySandbox } from '@mastra/railway';
|
|
33
|
+
|
|
34
|
+
const sandbox = new RailwaySandbox({
|
|
35
|
+
// token + environmentId read from RAILWAY_API_TOKEN / RAILWAY_ENVIRONMENT_ID
|
|
36
|
+
idleTimeoutMinutes: 30,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const workspace = new Workspace({ sandbox });
|
|
40
|
+
await workspace.init();
|
|
41
|
+
|
|
42
|
+
const result = await workspace.sandbox.executeCommand('echo', ['Hello!']);
|
|
43
|
+
console.log(result.stdout); // "Hello!"
|
|
44
|
+
|
|
45
|
+
await workspace.destroy();
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Private networking
|
|
49
|
+
|
|
50
|
+
Join the environment's private network to reach other services (for example
|
|
51
|
+
`postgres.railway.internal`):
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const sandbox = new RailwaySandbox({
|
|
55
|
+
networkIsolation: 'PRIVATE',
|
|
56
|
+
env: { NODE_ENV: 'production' },
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Reattach to an existing sandbox
|
|
61
|
+
|
|
62
|
+
A Railway sandbox outlives the process that created it. Reconnect by its
|
|
63
|
+
Railway ID instead of provisioning a new one:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const sandbox = new RailwaySandbox({ sandboxId: 'existing-railway-sandbox-id' });
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Custom base image (templates)
|
|
70
|
+
|
|
71
|
+
Pre-install packages and run setup steps so every sandbox starts ready. Pass a
|
|
72
|
+
builder callback over the Railway template builder — it's built once on the
|
|
73
|
+
first `start()`:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const sandbox = new RailwaySandbox({
|
|
77
|
+
template: t => t.withPackages('git', 'curl').run('npm i -g pnpm').workdir('/app'),
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
You can also pass a pre-built `SandboxTemplate` to reuse it across sandboxes
|
|
82
|
+
without rebuilding. Templates are ignored when `sandboxId` is set (reattach).
|
|
83
|
+
|
|
84
|
+
### Fork a running sandbox
|
|
85
|
+
|
|
86
|
+
Clone a running sandbox's filesystem into a new, independent sandbox (a fresh
|
|
87
|
+
boot, not live processes). The returned `RailwaySandbox` is already started:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
const child = await sandbox.fork({ idleTimeoutMinutes: 15 });
|
|
91
|
+
const result = await child.executeCommand('cat', ['/app/state.json']);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Long-running processes
|
|
95
|
+
|
|
96
|
+
Use the process manager to spawn background commands and stream their output:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const handle = await sandbox.processes.spawn('npm run dev', {
|
|
100
|
+
onStdout: chunk => process.stdout.write(chunk),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Later
|
|
104
|
+
await handle.kill();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Options
|
|
108
|
+
|
|
109
|
+
| Option | Type | Description |
|
|
110
|
+
| -------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
111
|
+
| `token` | `string` | Railway API token. Falls back to `RAILWAY_API_TOKEN`. |
|
|
112
|
+
| `environmentId` | `string` | Railway environment ID. Falls back to `RAILWAY_ENVIRONMENT_ID`. |
|
|
113
|
+
| `sandboxId` | `string` | Reattach to an existing Railway sandbox by ID instead of creating one. |
|
|
114
|
+
| `idleTimeoutMinutes` | `number` | Minutes a sandbox can sit idle before Railway destroys it. Range/default depend on the plan. |
|
|
115
|
+
| `networkIsolation` | `'ISOLATED' \| 'PRIVATE'` | Network mode. `ISOLATED` (default) is outbound-only; `PRIVATE` joins the private network. |
|
|
116
|
+
| `env` | `Record<string, string>` | Environment variables baked into the sandbox. |
|
|
117
|
+
| `template` | `SandboxTemplate \| (base) => SandboxTemplate` | Provision from a custom base image built with the Railway template builder. Ignored on reattach. |
|
|
118
|
+
| `timeout` | `number` | Default command timeout in milliseconds. Commands run until they exit when omitted. |
|
|
119
|
+
| `instructions` | `string \| (opts) => string` | Override the default agent instructions. |
|
|
120
|
+
|
|
121
|
+
## Editor provider
|
|
122
|
+
|
|
123
|
+
Register the provider with `MastraEditor` to hydrate stored sandbox configs:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { railwaySandboxProvider } from '@mastra/railway';
|
|
127
|
+
|
|
128
|
+
const editor = new MastraEditor({
|
|
129
|
+
sandboxes: { [railwaySandboxProvider.id]: railwaySandboxProvider },
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
Apache-2.0
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mastra/railway",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Railway cloud sandbox provider for Mastra workspaces",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup --silent --config tsup.config.ts",
|
|
23
|
+
"build:lib": "pnpm build",
|
|
24
|
+
"build:watch": "pnpm build --watch",
|
|
25
|
+
"test:unit": "vitest run --exclude '**/*.integration.test.ts'",
|
|
26
|
+
"test:watch": "vitest watch",
|
|
27
|
+
"test": "vitest run ./src/**/*.integration.test.ts",
|
|
28
|
+
"test:cloud": "pnpm test",
|
|
29
|
+
"lint": "eslint ."
|
|
30
|
+
},
|
|
31
|
+
"license": "Apache-2.0",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"railway": "^3.1.1"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@internal/lint": "workspace:*",
|
|
37
|
+
"@internal/types-builder": "workspace:*",
|
|
38
|
+
"@internal/workspace-test-utils": "workspace:*",
|
|
39
|
+
"@mastra/core": "workspace:*",
|
|
40
|
+
"@types/node": "22.19.15",
|
|
41
|
+
"@vitest/coverage-v8": "catalog:",
|
|
42
|
+
"@vitest/ui": "catalog:",
|
|
43
|
+
"dotenv": "^17.3.1",
|
|
44
|
+
"eslint": "^10.4.1",
|
|
45
|
+
"tsup": "^8.5.1",
|
|
46
|
+
"typescript": "catalog:",
|
|
47
|
+
"vitest": "catalog:"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@mastra/core": ">=1.12.0-0 <2.0.0-0"
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"dist",
|
|
54
|
+
"CHANGELOG.md"
|
|
55
|
+
],
|
|
56
|
+
"homepage": "https://mastra.ai",
|
|
57
|
+
"repository": {
|
|
58
|
+
"type": "git",
|
|
59
|
+
"url": "git+https://github.com/mastra-ai/mastra.git",
|
|
60
|
+
"directory": "workspaces/railway"
|
|
61
|
+
},
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/mastra-ai/mastra/issues"
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=22.13.0"
|
|
67
|
+
}
|
|
68
|
+
}
|