@mastra/platform-workspace 0.0.0-esbuild-bundle-worker-20260807173433
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 +462 -0
- package/LICENSE.md +30 -0
- package/README.md +115 -0
- package/dist/address-registry.d.ts +47 -0
- package/dist/address-registry.d.ts.map +1 -0
- package/dist/client.d.ts +44 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/direct-exec.d.ts +98 -0
- package/dist/direct-exec.d.ts.map +1 -0
- package/dist/filesystem.d.ts +62 -0
- package/dist/filesystem.d.ts.map +1 -0
- package/dist/index.cjs +1493 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1459 -0
- package/dist/index.js.map +1 -0
- package/dist/private-net-exec.d.ts +114 -0
- package/dist/private-net-exec.d.ts.map +1 -0
- package/dist/provider.d.ts +6 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/sandbox.d.ts +393 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import type { RequestContext } from '@mastra/core/di';
|
|
2
|
+
import type { CommandResult, ExecuteCommandOptions, InstructionsOption, MastraSandboxOptions, ProcessInfo, ProviderStatus, SandboxCloneOptions, SandboxInfo, SpawnProcessOptions } from '@mastra/core/workspace';
|
|
3
|
+
import { MastraSandbox, ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';
|
|
4
|
+
import type { PlatformClientOptions } from './client.js';
|
|
5
|
+
import type { DirectExecWebSocketFactory } from './direct-exec.js';
|
|
6
|
+
import type { PrivateNetFetch } from './private-net-exec.js';
|
|
7
|
+
export type PlatformSandboxNetworkIsolation = 'ISOLATED' | 'PRIVATE';
|
|
8
|
+
/**
|
|
9
|
+
* In-process `sandboxId → instanceUrl` map that lets
|
|
10
|
+
* {@link PlatformSandbox.executeCommand} dial the in-sandbox sidecar over
|
|
11
|
+
* Railway's private network instead of paying for a lease + WebSocket
|
|
12
|
+
* round-trip through Railway's public control plane.
|
|
13
|
+
*
|
|
14
|
+
* The workspace proxy discovers each sandbox's IPv6 during
|
|
15
|
+
* `POST /v1/projects/:pid/sandbox` and returns it as `instanceUrl` on the
|
|
16
|
+
* create + get responses (see the platform inline-discovery issue). The
|
|
17
|
+
* `PlatformSandbox` client copies that field into this registry from both
|
|
18
|
+
* {@link PlatformSandbox.start} branches (fresh provision + reattach), evicts
|
|
19
|
+
* on {@link PlatformSandbox.destroy}, and evicts again on any observed
|
|
20
|
+
* transport failure so the next exec falls back to the lease path cleanly.
|
|
21
|
+
*
|
|
22
|
+
* See:
|
|
23
|
+
* - `.scratch/factory-deploy/issue-runtime-sandbox-address-discovery.md`
|
|
24
|
+
* - `.scratch/factory-deploy/issue-platform-sandbox-exec-via-private-network.md`
|
|
25
|
+
*/
|
|
26
|
+
export interface SandboxAddressRegistry {
|
|
27
|
+
set(sandboxId: string, instanceUrl: string): void;
|
|
28
|
+
get(sandboxId: string): string | undefined;
|
|
29
|
+
delete(sandboxId: string): void;
|
|
30
|
+
}
|
|
31
|
+
export interface PlatformSandboxOptions extends Omit<MastraSandboxOptions, 'processes'>, PlatformClientOptions {
|
|
32
|
+
id?: string;
|
|
33
|
+
environmentId?: string;
|
|
34
|
+
sandboxId?: string;
|
|
35
|
+
idleTimeoutMinutes?: number;
|
|
36
|
+
networkIsolation?: PlatformSandboxNetworkIsolation;
|
|
37
|
+
env?: Record<string, string>;
|
|
38
|
+
timeout?: number;
|
|
39
|
+
instructions?: InstructionsOption;
|
|
40
|
+
/**
|
|
41
|
+
* Injected WebSocket factory used by the direct-exec code path. Defaults to
|
|
42
|
+
* the global `WebSocket` (available on Node 22+, this package's minimum) and
|
|
43
|
+
* only exists so tests can drive the exec state machine deterministically
|
|
44
|
+
* without a real network socket.
|
|
45
|
+
*/
|
|
46
|
+
webSocketFactory?: DirectExecWebSocketFactory;
|
|
47
|
+
/**
|
|
48
|
+
* Injected fetch implementation used by the private-network exec code path
|
|
49
|
+
* to dial the in-sandbox sidecar. Defaults to `globalThis.fetch` and only
|
|
50
|
+
* exists so tests can drive that transport without a real HTTP server.
|
|
51
|
+
* Note: this is separate from the `fetch` on {@link PlatformClientOptions},
|
|
52
|
+
* which is used for calls to the workspace proxy.
|
|
53
|
+
*/
|
|
54
|
+
privateNetFetch?: PrivateNetFetch;
|
|
55
|
+
/**
|
|
56
|
+
* Registry that maps `sandboxId → instanceUrl` for the private-network
|
|
57
|
+
* exec path. When set, {@link PlatformSandbox.start} populates it from the
|
|
58
|
+
* `instanceUrl` field workspace-proxy returns on create + get responses,
|
|
59
|
+
* and {@link PlatformSandbox.executeCommand} looks it up before every exec
|
|
60
|
+
* and tries the private-network transport first, falling back to the lease
|
|
61
|
+
* path on any transport failure (and invalidating the registry entry so
|
|
62
|
+
* the next call goes to the lease path cleanly). When absent, all execs
|
|
63
|
+
* go straight to the lease path — this is the pre-existing behavior and
|
|
64
|
+
* the expected mode outside the shipyard runtime. See
|
|
65
|
+
* {@link SandboxAddressRegistry}.
|
|
66
|
+
*/
|
|
67
|
+
addressRegistry?: SandboxAddressRegistry;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Diagnostic error thrown when the direct-exec WebSocket transport fails
|
|
71
|
+
* twice in a row (opening handshake refused or socket closed mid-stream
|
|
72
|
+
* without an `exit` frame). Distinguishes "the sandbox transport is broken"
|
|
73
|
+
* from "your command failed" so callers can decide whether to retry at a
|
|
74
|
+
* higher level (e.g. reprovision the sandbox) or surface the error.
|
|
75
|
+
*
|
|
76
|
+
* `opened` is `true` when the WebSocket completed its handshake at least
|
|
77
|
+
* once before closing; `false` when Railway refused the upgrade outright.
|
|
78
|
+
*/
|
|
79
|
+
export declare class SandboxExecTransportError extends Error {
|
|
80
|
+
readonly sandboxId: string | undefined;
|
|
81
|
+
readonly command: string;
|
|
82
|
+
readonly attempts: number;
|
|
83
|
+
readonly opened: boolean;
|
|
84
|
+
readonly closeCode: number | undefined;
|
|
85
|
+
readonly closeReason: string | undefined;
|
|
86
|
+
readonly wsEndpoint: string;
|
|
87
|
+
constructor(message: string, diagnostics: {
|
|
88
|
+
sandboxId?: string;
|
|
89
|
+
command: string;
|
|
90
|
+
attempts: number;
|
|
91
|
+
opened: boolean;
|
|
92
|
+
closeCode?: number;
|
|
93
|
+
closeReason?: string;
|
|
94
|
+
wsEndpoint: string;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Outcome of {@link PlatformSandbox.captureCheckpoint}. Mirrors the shape of
|
|
99
|
+
* the OSS `@mastra/railway` `RailwaySandbox.captureCheckpoint()` return so a
|
|
100
|
+
* caller (e.g. the factory fleet) can branch on `status`/`reason` uniformly
|
|
101
|
+
* across providers without knowing which one is underneath.
|
|
102
|
+
*
|
|
103
|
+
* `captured` and `coalesced` both represent a successful capture the caller
|
|
104
|
+
* can persist against — they carry the checkpoint name inline so callers
|
|
105
|
+
* don't have to reach back into the sandbox instance to learn what was
|
|
106
|
+
* written. `skipped` carries a machine-readable `reason` so the discriminant
|
|
107
|
+
* set stays extensible.
|
|
108
|
+
*
|
|
109
|
+
* Note: the platform proxy's own `skipped` (returned when the upstream
|
|
110
|
+
* sandbox is already destroyed) is mapped to `sandbox-not-running` here to
|
|
111
|
+
* keep the discriminant identical to the OSS provider. The diagnostic
|
|
112
|
+
* distinction (pre-flight vs post-hoc discovery) is preserved in log lines,
|
|
113
|
+
* not the return type — see {@link PlatformSandbox.captureCheckpoint}.
|
|
114
|
+
*/
|
|
115
|
+
export type CaptureCheckpointResult = {
|
|
116
|
+
status: 'captured';
|
|
117
|
+
checkpointName: string;
|
|
118
|
+
} | {
|
|
119
|
+
status: 'coalesced';
|
|
120
|
+
checkpointName: string;
|
|
121
|
+
} | {
|
|
122
|
+
status: 'skipped';
|
|
123
|
+
reason: 'no-checkpoint-name-configured' | 'sandbox-not-running';
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Thrown when `/exec-lease` returns 410 Gone — the sandbox has been destroyed
|
|
127
|
+
* (Railway destroy, quota reclamation, etc.). The client cannot recover from
|
|
128
|
+
* this on its own because it does not own the binding store; only the fleet
|
|
129
|
+
* layer can clear the stale sandbox id and provision a fresh one. Callers
|
|
130
|
+
* (typically `SandboxFleet`) must catch this and reprovision-and-replay.
|
|
131
|
+
*
|
|
132
|
+
* When this is thrown the cached `_lease` and `_sandboxId` on the sandbox
|
|
133
|
+
* instance are cleared, so the next `ensureRunning()` on a reused instance
|
|
134
|
+
* will re-provision cleanly.
|
|
135
|
+
*/
|
|
136
|
+
export declare class SandboxDestroyedError extends Error {
|
|
137
|
+
readonly sandboxId: string | undefined;
|
|
138
|
+
readonly command: string;
|
|
139
|
+
readonly attempts: number;
|
|
140
|
+
constructor(message: string, diagnostics: {
|
|
141
|
+
sandboxId?: string;
|
|
142
|
+
command: string;
|
|
143
|
+
attempts: number;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
declare class PlatformProcessManager extends SandboxProcessManager<PlatformSandbox> {
|
|
147
|
+
private spawnCounter;
|
|
148
|
+
/**
|
|
149
|
+
* Spawn a process on the remote sandbox.
|
|
150
|
+
*
|
|
151
|
+
* `command` is interpreted as a shell string by the remote shell, matching
|
|
152
|
+
* the {@link MastraSandbox} contract. See {@link PlatformSandbox.executeCommand}
|
|
153
|
+
* for the untrusted-input caveat: never pass untrusted values as `command`.
|
|
154
|
+
*/
|
|
155
|
+
spawn(command: string, options?: SpawnProcessOptions): Promise<ProcessHandle>;
|
|
156
|
+
list(): Promise<ProcessInfo[]>;
|
|
157
|
+
}
|
|
158
|
+
export declare class PlatformSandbox extends MastraSandbox {
|
|
159
|
+
readonly id: string;
|
|
160
|
+
readonly name = "PlatformSandbox";
|
|
161
|
+
readonly provider = "platform";
|
|
162
|
+
status: ProviderStatus;
|
|
163
|
+
readonly processes: PlatformProcessManager;
|
|
164
|
+
private readonly _client;
|
|
165
|
+
private readonly _environmentId;
|
|
166
|
+
private _sandboxId?;
|
|
167
|
+
private readonly _idleTimeoutMinutes?;
|
|
168
|
+
private readonly _networkIsolation?;
|
|
169
|
+
private readonly _env;
|
|
170
|
+
private readonly _timeout?;
|
|
171
|
+
private readonly _instructionsOverride?;
|
|
172
|
+
private _createdAt;
|
|
173
|
+
private readonly _webSocketFactory?;
|
|
174
|
+
private readonly _privateNetFetch?;
|
|
175
|
+
/**
|
|
176
|
+
* Registry that maps `sandboxId → instanceUrl` for the private-network
|
|
177
|
+
* exec path. Injected by the composition site via
|
|
178
|
+
* {@link PlatformSandboxOptions.addressRegistry} and populated by this
|
|
179
|
+
* class itself in `start()` when the workspace-proxy's create/reattach
|
|
180
|
+
* response includes an `instanceUrl` field. The registry IS the cache —
|
|
181
|
+
* there is no per-instance mirror on `PlatformSandbox`, so every exec is
|
|
182
|
+
* a `Map.get()` (in the default in-process impl) against the live view.
|
|
183
|
+
* When absent, executes go straight to the lease path with no extra
|
|
184
|
+
* round-trip.
|
|
185
|
+
*/
|
|
186
|
+
private readonly _addressRegistry?;
|
|
187
|
+
/**
|
|
188
|
+
* Cached exec lease for this sandbox. `null` before the first exec and
|
|
189
|
+
* after {@link destroy}. Refreshed when `expiresAt - LEASE_REFRESH_MARGIN_MS < now`
|
|
190
|
+
* (see {@link _ensureLease}); a lease without a disclosed `expiresAt`
|
|
191
|
+
* is refreshed on every call.
|
|
192
|
+
*/
|
|
193
|
+
private _lease;
|
|
194
|
+
/**
|
|
195
|
+
* In-flight mint request; concurrent `_ensureLease` callers on a cold or
|
|
196
|
+
* near-expiry cache all await this single promise so we don't burn N
|
|
197
|
+
* `POST /exec-lease` round-trips when the sandbox is doing N parallel execs.
|
|
198
|
+
* Cleared (regardless of success or failure) when the request settles.
|
|
199
|
+
*/
|
|
200
|
+
private _leaseInFlight;
|
|
201
|
+
/**
|
|
202
|
+
* True when this sandbox was constructed with a caller-supplied `id` (the
|
|
203
|
+
* recovery key the proxy hashes into an on-provider checkpoint name).
|
|
204
|
+
* `captureCheckpoint()` needs this to distinguish "no checkpoint intent"
|
|
205
|
+
* (auto-generated random id — capture would land under a name no future
|
|
206
|
+
* boot would look for) from "capture on demand". Cloned sandboxes route
|
|
207
|
+
* `checkpointName` through `id`, so both entry points set this the same
|
|
208
|
+
* way.
|
|
209
|
+
*/
|
|
210
|
+
private readonly _hasRecoveryKey;
|
|
211
|
+
/**
|
|
212
|
+
* In-flight `captureCheckpoint()` request. Concurrent callers on the same
|
|
213
|
+
* instance coalesce onto this single promise so we don't burn N `POST
|
|
214
|
+
* /checkpoint` round-trips when the fleet fires several turn-end captures
|
|
215
|
+
* before the first one resolves. Cleared when the request settles.
|
|
216
|
+
*/
|
|
217
|
+
private _captureInFlight;
|
|
218
|
+
constructor(options?: PlatformSandboxOptions);
|
|
219
|
+
private generateId;
|
|
220
|
+
/**
|
|
221
|
+
* Construct a sibling {@link PlatformSandbox} that inherits this sandbox's
|
|
222
|
+
* credentials and defaults (access token, project, environment, network
|
|
223
|
+
* isolation, timeout, instructions, env, idle timeout) with per-instance
|
|
224
|
+
* overrides from `options`.
|
|
225
|
+
*
|
|
226
|
+
* Performs no I/O and does not require this sandbox to be started — the
|
|
227
|
+
* returned sandbox is not started and provisions (or reattaches, when
|
|
228
|
+
* `sandboxId` is set) on its own `start()`. Use it when one configured
|
|
229
|
+
* sandbox acts as the template for a fleet of independent sandboxes
|
|
230
|
+
* (e.g. one per project).
|
|
231
|
+
*/
|
|
232
|
+
clone(options?: SandboxCloneOptions): PlatformSandbox;
|
|
233
|
+
start(): Promise<void>;
|
|
234
|
+
/**
|
|
235
|
+
* Copy `response.instanceUrl` into the injected {@link SandboxAddressRegistry}
|
|
236
|
+
* when both are present. Called from both {@link start} branches (fresh
|
|
237
|
+
* provision + reattach) with the workspace-proxy response for this sandbox.
|
|
238
|
+
*
|
|
239
|
+
* The proxy discovers the IPv6 during `Sandbox.create()` and stores it in
|
|
240
|
+
* `environment_sandboxes.instance_url`; both the create response and
|
|
241
|
+
* `GET /sandbox/:id` echo the same field. The runtime does not do any
|
|
242
|
+
* discovery of its own — it only mirrors the field into an in-process map
|
|
243
|
+
* so {@link executeCommand} can `Map.get()` before every exec without an
|
|
244
|
+
* HTTP round-trip.
|
|
245
|
+
*
|
|
246
|
+
* `null`/absent `instanceUrl` (proxy discovery failed, or an older proxy
|
|
247
|
+
* that predates the field) leaves the registry untouched — executes fall
|
|
248
|
+
* through to the lease path with no branch here.
|
|
249
|
+
*/
|
|
250
|
+
private _populateAddressFromResponse;
|
|
251
|
+
stop(): Promise<void>;
|
|
252
|
+
destroy(): Promise<void>;
|
|
253
|
+
/**
|
|
254
|
+
* Capture the sandbox's checkpoint on demand, outside any refresh timer the
|
|
255
|
+
* workspace-proxy owns internally.
|
|
256
|
+
*
|
|
257
|
+
* Intended for callers (e.g. a factory-side scheduler) that want to refresh
|
|
258
|
+
* the recovery checkpoint at semantic moments — turn end, session-idle,
|
|
259
|
+
* pre-teardown — rather than only just before the upstream's idle destroy.
|
|
260
|
+
*
|
|
261
|
+
* Mirrors the OSS `@mastra/railway` `RailwaySandbox.captureCheckpoint()`
|
|
262
|
+
* shape so factory can call `sandbox.captureCheckpoint()` uniformly and
|
|
263
|
+
* branch on `status`/`reason` without knowing which provider is underneath.
|
|
264
|
+
* Both `captured` and `coalesced` carry the checkpoint name inline so the
|
|
265
|
+
* caller can persist a session→checkpoint binding atomically with the
|
|
266
|
+
* awaited capture.
|
|
267
|
+
*
|
|
268
|
+
* Skip semantics:
|
|
269
|
+
* - No caller-supplied `id`: returns `{ status: 'skipped', reason:
|
|
270
|
+
* 'no-checkpoint-name-configured' }`. An auto-generated random id is
|
|
271
|
+
* never a meaningful recovery key (no future boot would look for a
|
|
272
|
+
* checkpoint under it), so capturing would silently produce dead data.
|
|
273
|
+
* - Not started (no `_sandboxId`): returns `{ status: 'skipped', reason:
|
|
274
|
+
* 'sandbox-not-running' }` without a round-trip.
|
|
275
|
+
* - Upstream 410 (workspace-proxy or Railway reports the sandbox is
|
|
276
|
+
* already destroyed): returns the same `sandbox-not-running` skip so
|
|
277
|
+
* the discriminant matches the pre-flight case. Local state
|
|
278
|
+
* (`_sandboxId`, `_lease`, sidecar address) is cleared as a side
|
|
279
|
+
* effect so the next `start()` provisions fresh instead of reattaching
|
|
280
|
+
* to a dead id. The diagnostic distinction (pre-flight vs post-hoc)
|
|
281
|
+
* is preserved in log level: debug for the expected pre-flight skip,
|
|
282
|
+
* warn for the surprise upstream destroy.
|
|
283
|
+
*
|
|
284
|
+
* Concurrent callers on the same instance coalesce onto a single in-flight
|
|
285
|
+
* `POST /checkpoint` so N simultaneous turn-end fires (e.g. several tabs)
|
|
286
|
+
* do not each round-trip the proxy. Both the originator and joiners
|
|
287
|
+
* receive `{ status: 'coalesced', ... }` for the joined result — the
|
|
288
|
+
* outer contract does not distinguish who started the request, only that
|
|
289
|
+
* one upstream capture was made.
|
|
290
|
+
*
|
|
291
|
+
* Never throws for expected outcomes. Transport failures (5xx, 4xx other
|
|
292
|
+
* than 410) propagate as {@link PlatformApiError}; a 410 is normalized
|
|
293
|
+
* to a skip as described above.
|
|
294
|
+
*/
|
|
295
|
+
captureCheckpoint(): Promise<CaptureCheckpointResult>;
|
|
296
|
+
/**
|
|
297
|
+
* The single `POST /checkpoint` attempt behind {@link captureCheckpoint}.
|
|
298
|
+
*
|
|
299
|
+
* Split out so the coalescing wrapper can install a shared in-flight
|
|
300
|
+
* promise without inlining the transport + response-mapping logic.
|
|
301
|
+
* Joined callers observe `{ status: 'coalesced', ... }` — the initiator
|
|
302
|
+
* sees the underlying `captured` / `coalesced` / `skipped` result the
|
|
303
|
+
* proxy returned. Both are legitimate: the OSS mirror uses the same
|
|
304
|
+
* "initiator sees the truth, joiners see coalesced" split.
|
|
305
|
+
*/
|
|
306
|
+
private _doCaptureCheckpoint;
|
|
307
|
+
/**
|
|
308
|
+
* Clear local state that would otherwise let the caller keep exec'ing
|
|
309
|
+
* against a sandbox the upstream has already destroyed. Mirrors what
|
|
310
|
+
* `destroy()` does minus the outbound DELETE — the sandbox is already
|
|
311
|
+
* gone, so all that remains is to stop pointing at it.
|
|
312
|
+
*
|
|
313
|
+
* Also resets `status` to `'pending'` so a subsequent `_start()` on this
|
|
314
|
+
* reused instance re-runs provisioning instead of short-circuiting on
|
|
315
|
+
* the cached `'running'` state (see `MastraSandbox._start`).
|
|
316
|
+
*/
|
|
317
|
+
private _clearDestroyedState;
|
|
318
|
+
/**
|
|
319
|
+
* Execute a command on the remote sandbox.
|
|
320
|
+
*
|
|
321
|
+
* `command` is a **shell string**: it is concatenated verbatim into the
|
|
322
|
+
* command line sent to the remote shell, which lets callers use pipes,
|
|
323
|
+
* redirects, and chaining (`ls -la | grep foo`). This matches the contract
|
|
324
|
+
* of {@link MastraSandbox} and the local sandbox implementation.
|
|
325
|
+
*
|
|
326
|
+
* `args`, when provided, are always shell-quoted so they cannot inject
|
|
327
|
+
* additional shell syntax.
|
|
328
|
+
*
|
|
329
|
+
* Security: callers MUST NOT pass untrusted input as `command`. If any part
|
|
330
|
+
* of the invocation is derived from an untrusted source, pass it through
|
|
331
|
+
* `args` (which is safely quoted) or shell-quote it yourself before
|
|
332
|
+
* inclusion. Untrusted `command` values allow arbitrary shell syntax
|
|
333
|
+
* execution on the remote sandbox.
|
|
334
|
+
*/
|
|
335
|
+
executeCommand(command: string, args?: string[], options?: ExecuteCommandOptions): Promise<CommandResult>;
|
|
336
|
+
/**
|
|
337
|
+
* Run a single exec against the direct-exec transport, with one in-flight
|
|
338
|
+
* retry on WebSocket transport failure (socket closed without an `exit`
|
|
339
|
+
* frame and the exec did not time out). The retry mints a fresh lease
|
|
340
|
+
* — the failure could be a stale JWT — and reopens a new WebSocket.
|
|
341
|
+
*
|
|
342
|
+
* Error taxonomy:
|
|
343
|
+
* - **410 on `/exec-lease`** (either attempt) → the sandbox is gone.
|
|
344
|
+
* Nulls the cached `_lease` and `_sandboxId` and throws
|
|
345
|
+
* {@link SandboxDestroyedError}. Callers (typically `SandboxFleet`) must
|
|
346
|
+
* catch this, clear the stale binding, and reprovision + replay.
|
|
347
|
+
* - **Persistent transport failure** (both WS attempts close without an
|
|
348
|
+
* `exit` frame against a live sandbox) → {@link SandboxExecTransportError}
|
|
349
|
+
* with WebSocket close diagnostics.
|
|
350
|
+
* - **Other `PlatformApiError`s** (404/500/501) propagate directly.
|
|
351
|
+
* - **Real command result** (exit code from Railway's exit frame, or
|
|
352
|
+
* `timedOut: true`) returns normally.
|
|
353
|
+
*
|
|
354
|
+
* Returns a result with a real `exitCode` OR `timedOut: true`. Never
|
|
355
|
+
* returns `{ exitCode: null, timedOut: false }` — that case throws.
|
|
356
|
+
*/
|
|
357
|
+
private _runDirectExec;
|
|
358
|
+
/**
|
|
359
|
+
* Try to run the exec against the in-sandbox sidecar over Railway's private
|
|
360
|
+
* network. Returns the result on success (including non-zero exit codes and
|
|
361
|
+
* timeouts — those are real command results, not failures). Returns
|
|
362
|
+
* `undefined` when the caller should fall back to the lease path:
|
|
363
|
+
*
|
|
364
|
+
* - Transport failure (connection refused, mid-stream drop, no `exit`
|
|
365
|
+
* frame). The registry entry is evicted so subsequent execs skip the
|
|
366
|
+
* private-net dial until the sidecar re-registers.
|
|
367
|
+
* - Sidecar answered with a non-2xx HTTP status. Registry is left intact —
|
|
368
|
+
* the address is still valid; something else is wrong (bad request,
|
|
369
|
+
* sidecar bug). Only this specific exec falls back.
|
|
370
|
+
*/
|
|
371
|
+
private _tryExecViaPrivateNetwork;
|
|
372
|
+
/**
|
|
373
|
+
* Evict this sandbox's entry from the address registry after an observed
|
|
374
|
+
* transport failure. The entry stays gone until the next start() re-reads
|
|
375
|
+
* `instanceUrl` from a workspace-proxy response — until then, execs skip
|
|
376
|
+
* the private-net dial and go straight to the lease path.
|
|
377
|
+
*/
|
|
378
|
+
private _invalidateAddress;
|
|
379
|
+
/**
|
|
380
|
+
* Return a cached exec lease, minting a fresh one when the cache is empty
|
|
381
|
+
* or the JWT is within {@link LEASE_REFRESH_MARGIN_MS} of `expiresAt`.
|
|
382
|
+
*
|
|
383
|
+
* Callers are expected to be on the "sandbox is running" path; we don't
|
|
384
|
+
* re-check `_sandboxId` here because `executeCommand` already gated on it.
|
|
385
|
+
*/
|
|
386
|
+
private _ensureLease;
|
|
387
|
+
getInfo(): Promise<SandboxInfo>;
|
|
388
|
+
getInstructions(opts?: {
|
|
389
|
+
requestContext?: RequestContext;
|
|
390
|
+
}): string;
|
|
391
|
+
}
|
|
392
|
+
export {};
|
|
393
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mastra/platform-workspace",
|
|
3
|
+
"version": "0.0.0-esbuild-bundle-worker-20260807173433",
|
|
4
|
+
"description": "Mastra Platform workspace sandbox and filesystem providers",
|
|
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
|
+
"license": "Apache-2.0",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "22.20.1",
|
|
24
|
+
"@vitest/coverage-v8": "4.1.10",
|
|
25
|
+
"@vitest/ui": "4.1.10",
|
|
26
|
+
"eslint": "^10.4.1",
|
|
27
|
+
"tsdown": "0.22.9",
|
|
28
|
+
"typescript": "^6.0.3",
|
|
29
|
+
"vitest": "4.1.10",
|
|
30
|
+
"@internal/lint": "0.0.0-esbuild-bundle-worker-20260807173433",
|
|
31
|
+
"@internal/types-builder": "0.0.0-esbuild-bundle-worker-20260807173433",
|
|
32
|
+
"@mastra/core": "0.0.0-esbuild-bundle-worker-20260807173433"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@mastra/core": "0.0.0-esbuild-bundle-worker-20260807173433"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"CHANGELOG.md"
|
|
40
|
+
],
|
|
41
|
+
"homepage": "https://mastra.ai",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/mastra-ai/mastra.git",
|
|
45
|
+
"directory": "workspaces/platform-workspace"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/mastra-ai/mastra/issues"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=22.13.0"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsdown --silent --config tsdown.config.ts",
|
|
55
|
+
"build:lib": "pnpm build",
|
|
56
|
+
"build:watch": "pnpm build --watch",
|
|
57
|
+
"test:unit": "vitest run --exclude '**/*.integration.test.ts'",
|
|
58
|
+
"test:cloud": "vitest run --passWithNoTests ./src/**/*.integration.test.ts",
|
|
59
|
+
"test:watch": "vitest watch",
|
|
60
|
+
"test": "pnpm test:unit",
|
|
61
|
+
"lint": "oxlint . && eslint .",
|
|
62
|
+
"lint:fix": "oxlint --fix . && eslint --fix ."
|
|
63
|
+
}
|
|
64
|
+
}
|