@mastra/vercel 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 ADDED
@@ -0,0 +1,25 @@
1
+ # @mastra/vercel
2
+
3
+ ## 0.1.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added Vercel serverless sandbox provider for executing commands as Vercel Functions. Deploys code as serverless functions and executes commands via HTTP invocation — providing globally-distributed, zero-infrastructure execution. ([#14710](https://github.com/mastra-ai/mastra/pull/14710))
8
+
9
+ **Usage:**
10
+
11
+ ```typescript
12
+ import { VercelSandbox } from '@mastra/vercel';
13
+ import { Workspace } from '@mastra/core/workspace';
14
+
15
+ const workspace = new Workspace({
16
+ sandbox: new VercelSandbox({
17
+ token: process.env.VERCEL_TOKEN,
18
+ }),
19
+ });
20
+ ```
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [[`9140989`](https://github.com/mastra-ai/mastra/commit/91409890e83f4f1d9c1b39223f1af91a6a53b549), [`d7c98cf`](https://github.com/mastra-ai/mastra/commit/d7c98cfc9d75baba9ecbf1a8835b5183d0a0aec8), [`acf5fbc`](https://github.com/mastra-ai/mastra/commit/acf5fbcb890dc7ca7167bec386ce5874dfadb997), [`24ca2ae`](https://github.com/mastra-ai/mastra/commit/24ca2ae57538ec189fabb9daee6175ad27035853), [`0762516`](https://github.com/mastra-ai/mastra/commit/07625167e029a8268ea7aaf0402416e6d8832874), [`2de3d36`](https://github.com/mastra-ai/mastra/commit/2de3d36932b7f73ad26bc403f7da26cfe89e903e), [`d3736cb`](https://github.com/mastra-ai/mastra/commit/d3736cb9ce074d2b8e8b00218a01f790fe81a1b4), [`c627366`](https://github.com/mastra-ai/mastra/commit/c6273666f9ef4c8c617c68b7d07fe878a322f85c)]:
25
+ - @mastra/core@1.18.1-alpha.1
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Executor function source code deployed to Vercel as a serverless function.
3
+ *
4
+ * Returns a string because it's sent as inline file content via
5
+ * the Vercel Deployments API — no separate build step needed.
6
+ *
7
+ * The secret and user env vars are embedded as constants in the source
8
+ * because the Vercel Deployments API does not support setting env vars
9
+ * directly — they must be configured via vercel.json or project settings.
10
+ */
11
+ export declare function getExecutorSource(secret: string, env: Record<string, string>): string;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/executor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CA6ErF"}
package/dist/index.cjs ADDED
@@ -0,0 +1,453 @@
1
+ 'use strict';
2
+
3
+ var workspace = require('@mastra/core/workspace');
4
+
5
+ // src/sandbox/index.ts
6
+
7
+ // src/executor/index.ts
8
+ function getExecutorSource(secret, env) {
9
+ const envEntries = Object.entries(env).map(([k, v]) => ` ${JSON.stringify(k)}: ${JSON.stringify(v)}`).join(",\n");
10
+ return `
11
+ const { execFileSync } = require('child_process');
12
+
13
+ const SANDBOX_SECRET = ${JSON.stringify(secret)};
14
+ const SANDBOX_ENV = {
15
+ ${envEntries}
16
+ };
17
+
18
+ module.exports = async (req, res) => {
19
+ // Auth check
20
+ const authHeader = req.headers['authorization'] || '';
21
+ if (!SANDBOX_SECRET || authHeader !== 'Bearer ' + SANDBOX_SECRET) {
22
+ return res.status(401).json({ error: 'Unauthorized' });
23
+ }
24
+
25
+ if (req.method !== 'POST') {
26
+ return res.status(405).json({ error: 'Method not allowed' });
27
+ }
28
+
29
+ const { command, args = [], env = {}, cwd, timeout = 55000 } = req.body || {};
30
+
31
+ if (!command) {
32
+ return res.status(400).json({ error: 'Missing required field: command' });
33
+ }
34
+
35
+ const execCwd = cwd || '/tmp';
36
+ const execEnv = { ...process.env, ...SANDBOX_ENV, ...env };
37
+
38
+ // When args is empty the caller sent a full shell command string
39
+ // (e.g. "echo hello" or "ls -la | grep foo"). Run it through
40
+ // /bin/sh so builtins and pipes work. When args is non-empty the
41
+ // caller split the command properly \u2014 use execFileSync to avoid
42
+ // shell injection.
43
+ const useShell = !args || args.length === 0;
44
+ const execCommand = useShell ? '/bin/sh' : command;
45
+ const execArgs = useShell ? ['-c', command] : args;
46
+
47
+ const startTime = Date.now();
48
+ let timedOut = false;
49
+
50
+ try {
51
+ const stdout = execFileSync(execCommand, execArgs, {
52
+ cwd: execCwd,
53
+ env: execEnv,
54
+ timeout,
55
+ maxBuffer: 10 * 1024 * 1024,
56
+ encoding: 'utf-8',
57
+ stdio: ['pipe', 'pipe', 'pipe'],
58
+ });
59
+
60
+ return res.status(200).json({
61
+ success: true,
62
+ exitCode: 0,
63
+ stdout: stdout || '',
64
+ stderr: '',
65
+ executionTimeMs: Date.now() - startTime,
66
+ timedOut: false,
67
+ });
68
+ } catch (error) {
69
+ timedOut = error.killed || false;
70
+
71
+ return res.status(200).json({
72
+ success: false,
73
+ exitCode: error.status != null ? error.status : 1,
74
+ stdout: error.stdout || '',
75
+ stderr: error.stderr || '',
76
+ executionTimeMs: Date.now() - startTime,
77
+ timedOut,
78
+ });
79
+ }
80
+ };
81
+ `;
82
+ }
83
+
84
+ // src/sandbox/index.ts
85
+ var LOG_PREFIX = "[VercelSandbox]";
86
+ var VERCEL_API_BASE = "https://api.vercel.com";
87
+ function shellQuote(arg) {
88
+ if (/^[a-zA-Z0-9._\-\/=:@]+$/.test(arg)) return arg;
89
+ return `'${arg.replace(/'/g, "'\\''")}'`;
90
+ }
91
+ var VercelSandbox = class extends workspace.MastraSandbox {
92
+ id;
93
+ name = "VercelSandbox";
94
+ provider = "vercel";
95
+ status = "pending";
96
+ _token;
97
+ _teamId;
98
+ _projectName;
99
+ _regions;
100
+ _maxDuration;
101
+ _memory;
102
+ _env;
103
+ _commandTimeout;
104
+ _instructionsOverride;
105
+ _secret;
106
+ _deploymentUrl = null;
107
+ _deploymentId = null;
108
+ _protectionBypass = null;
109
+ _createdAt = null;
110
+ constructor(options = {}) {
111
+ super({ name: "VercelSandbox" });
112
+ this.id = `vercel-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
113
+ this._token = options.token || process.env.VERCEL_TOKEN || "";
114
+ this._teamId = options.teamId;
115
+ this._projectName = options.projectName;
116
+ this._regions = options.regions ?? ["iad1"];
117
+ this._maxDuration = options.maxDuration ?? 60;
118
+ this._memory = options.memory ?? 1024;
119
+ this._env = options.env ?? {};
120
+ this._commandTimeout = options.commandTimeout ?? 55e3;
121
+ this._instructionsOverride = options.instructions;
122
+ this._secret = crypto.randomUUID();
123
+ }
124
+ // ---------------------------------------------------------------------------
125
+ // Lifecycle
126
+ // ---------------------------------------------------------------------------
127
+ async start() {
128
+ if (this._deploymentUrl) {
129
+ return;
130
+ }
131
+ if (!this._token) {
132
+ throw new Error(`${LOG_PREFIX} Missing Vercel API token. Set VERCEL_TOKEN env var or pass token option.`);
133
+ }
134
+ if (this._deploymentId) {
135
+ this.logger.debug(`${LOG_PREFIX} Cleaning up stale deployment ${this._deploymentId} before restarting...`);
136
+ try {
137
+ const resp = await this._vercelFetch(`/v13/deployments/${this._deploymentId}`, { method: "DELETE" });
138
+ if (!resp.ok && resp.status !== 404) {
139
+ this.logger.warn(`${LOG_PREFIX} Failed to delete stale deployment: ${resp.status}`);
140
+ }
141
+ } catch (error) {
142
+ this.logger.warn(`${LOG_PREFIX} Error deleting stale deployment:`, error);
143
+ }
144
+ this._deploymentId = null;
145
+ }
146
+ this.logger.debug(`${LOG_PREFIX} Deploying executor function...`);
147
+ const vercelJson = JSON.stringify({
148
+ functions: {
149
+ "api/execute.js": {
150
+ memory: this._memory,
151
+ maxDuration: this._maxDuration
152
+ }
153
+ },
154
+ regions: this._regions
155
+ });
156
+ const deploymentBody = {
157
+ name: this._projectName ?? `mastra-sandbox-${this.id}`,
158
+ files: [
159
+ {
160
+ file: "api/execute.js",
161
+ data: getExecutorSource(this._secret, this._env)
162
+ },
163
+ {
164
+ file: "vercel.json",
165
+ data: vercelJson
166
+ }
167
+ ],
168
+ projectSettings: {
169
+ framework: null
170
+ },
171
+ target: "production"
172
+ };
173
+ const createResp = await this._vercelFetch("/v13/deployments", {
174
+ method: "POST",
175
+ body: JSON.stringify(deploymentBody)
176
+ });
177
+ if (!createResp.ok) {
178
+ const errorBody = await createResp.text();
179
+ throw new Error(`${LOG_PREFIX} Failed to create deployment: ${createResp.status} ${errorBody}`);
180
+ }
181
+ const deployment = await createResp.json();
182
+ this._deploymentId = deployment.id;
183
+ this.logger.debug(`${LOG_PREFIX} Deployment created: ${deployment.id}, polling for READY...`);
184
+ const maxWaitMs = 12e4;
185
+ const pollIntervalMs = 3e3;
186
+ const deadline = Date.now() + maxWaitMs;
187
+ while (Date.now() < deadline) {
188
+ const statusResp = await this._vercelFetch(`/v13/deployments/${deployment.id}`);
189
+ if (!statusResp.ok) {
190
+ throw new Error(`${LOG_PREFIX} Failed to check deployment status: ${statusResp.status}`);
191
+ }
192
+ const statusBody = await statusResp.json();
193
+ if (statusBody.readyState === "READY") {
194
+ this._deploymentUrl = `https://${statusBody.url}`;
195
+ this._createdAt = /* @__PURE__ */ new Date();
196
+ this.logger.debug(`${LOG_PREFIX} Deployment ready: ${this._deploymentUrl}`);
197
+ if (deployment.projectId) {
198
+ try {
199
+ this._protectionBypass = await this._acquireProtectionBypass(deployment.projectId);
200
+ } catch {
201
+ }
202
+ }
203
+ try {
204
+ await fetch(`${this._deploymentUrl}/api/execute`, {
205
+ method: "POST",
206
+ headers: this._executorHeaders(),
207
+ body: JSON.stringify({ command: "echo", args: ["warm"] })
208
+ });
209
+ } catch {
210
+ }
211
+ return;
212
+ }
213
+ if (statusBody.readyState === "ERROR" || statusBody.readyState === "CANCELED") {
214
+ throw new Error(`${LOG_PREFIX} Deployment failed with state: ${statusBody.readyState}`);
215
+ }
216
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
217
+ }
218
+ throw new Error(`${LOG_PREFIX} Deployment timed out after ${maxWaitMs}ms`);
219
+ }
220
+ async stop() {
221
+ this._deploymentUrl = null;
222
+ }
223
+ async destroy() {
224
+ if (this._deploymentId) {
225
+ try {
226
+ const resp = await this._vercelFetch(`/v13/deployments/${this._deploymentId}`, {
227
+ method: "DELETE"
228
+ });
229
+ if (!resp.ok) {
230
+ if (resp.status === 404) {
231
+ this.logger.debug(`${LOG_PREFIX} Deployment already deleted (404)`);
232
+ } else {
233
+ this.logger.warn(`${LOG_PREFIX} Failed to delete deployment: ${resp.status}`);
234
+ }
235
+ }
236
+ } catch (error) {
237
+ this.logger.warn(`${LOG_PREFIX} Error deleting deployment:`, error);
238
+ }
239
+ this._deploymentId = null;
240
+ }
241
+ this._deploymentUrl = null;
242
+ this._protectionBypass = null;
243
+ }
244
+ // ---------------------------------------------------------------------------
245
+ // Command Execution
246
+ // ---------------------------------------------------------------------------
247
+ async executeCommand(command, args, options) {
248
+ await this.ensureRunning();
249
+ if (!this._deploymentUrl) {
250
+ throw new workspace.SandboxNotReadyError(this.id);
251
+ }
252
+ const fullCommand = args?.length ? `${command} ${args.map((a) => shellQuote(a)).join(" ")}` : command;
253
+ this.logger.debug(`${LOG_PREFIX} Executing: ${fullCommand}`);
254
+ const body = {
255
+ command,
256
+ args: args ?? [],
257
+ env: options?.env ?? {},
258
+ cwd: options?.cwd ?? "/tmp",
259
+ timeout: options?.timeout ?? this._commandTimeout
260
+ };
261
+ const maxRetries = 2;
262
+ let lastError = null;
263
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
264
+ try {
265
+ const resp = await fetch(`${this._deploymentUrl}/api/execute`, {
266
+ method: "POST",
267
+ headers: this._executorHeaders(),
268
+ body: JSON.stringify(body),
269
+ signal: options?.abortSignal
270
+ });
271
+ if ((resp.status === 429 || resp.status === 502 || resp.status === 503) && attempt < maxRetries) {
272
+ this.logger.debug(`${LOG_PREFIX} Retryable status ${resp.status}, attempt ${attempt + 1}/${maxRetries}`);
273
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * (attempt + 1)));
274
+ continue;
275
+ }
276
+ if (resp.status === 504) {
277
+ return {
278
+ command: fullCommand,
279
+ args,
280
+ success: false,
281
+ exitCode: 124,
282
+ stdout: "",
283
+ stderr: "Function execution timed out (504 Gateway Timeout)",
284
+ executionTimeMs: options?.timeout ?? this._commandTimeout,
285
+ timedOut: true
286
+ };
287
+ }
288
+ if (!resp.ok) {
289
+ const errorText = await resp.text();
290
+ throw new Error(`${LOG_PREFIX} Execute failed: ${resp.status} ${errorText}`);
291
+ }
292
+ const result = await resp.json();
293
+ if (options?.onStdout && result.stdout) {
294
+ options.onStdout(result.stdout);
295
+ }
296
+ if (options?.onStderr && result.stderr) {
297
+ options.onStderr(result.stderr);
298
+ }
299
+ return {
300
+ command: fullCommand,
301
+ args,
302
+ success: result.success,
303
+ exitCode: result.exitCode,
304
+ stdout: result.stdout,
305
+ stderr: result.stderr,
306
+ executionTimeMs: result.executionTimeMs,
307
+ timedOut: result.timedOut
308
+ };
309
+ } catch (error) {
310
+ if (error instanceof DOMException && error.name === "AbortError") {
311
+ throw error;
312
+ }
313
+ lastError = error;
314
+ if (attempt < maxRetries) {
315
+ this.logger.debug(`${LOG_PREFIX} Request error, attempt ${attempt + 1}/${maxRetries}:`, error);
316
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * (attempt + 1)));
317
+ continue;
318
+ }
319
+ }
320
+ }
321
+ throw lastError ?? new Error(`${LOG_PREFIX} executeCommand failed after retries`);
322
+ }
323
+ // ---------------------------------------------------------------------------
324
+ // Info & Instructions
325
+ // ---------------------------------------------------------------------------
326
+ // Matches the resolveInstructions pattern in packages/core/src/workspace/utils.ts
327
+ getInstructions(opts) {
328
+ if (this._instructionsOverride === void 0) return this._getDefaultInstructions();
329
+ if (typeof this._instructionsOverride === "string") return this._instructionsOverride;
330
+ const defaultInstructions = this._getDefaultInstructions();
331
+ return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });
332
+ }
333
+ _getDefaultInstructions() {
334
+ return [
335
+ "Vercel serverless sandbox.",
336
+ "Limitations:",
337
+ "- Stateless: no persistent filesystem between invocations.",
338
+ "- No interactive shell or streaming stdin.",
339
+ "- No long-running or background processes.",
340
+ `- Maximum execution time: ${this._maxDuration} seconds.`,
341
+ "- Only /tmp is writable (ephemeral, cleared between invocations).",
342
+ "- Shell commands (pipes, builtins) are supported via /bin/sh -c."
343
+ ].join("\n");
344
+ }
345
+ async getInfo() {
346
+ return {
347
+ id: this.id,
348
+ name: this.name,
349
+ provider: this.provider,
350
+ status: this.status,
351
+ createdAt: this._createdAt ?? /* @__PURE__ */ new Date(),
352
+ metadata: {
353
+ deploymentId: this._deploymentId,
354
+ deploymentUrl: this._deploymentUrl,
355
+ regions: this._regions,
356
+ maxDuration: this._maxDuration,
357
+ memory: this._memory
358
+ }
359
+ };
360
+ }
361
+ // ---------------------------------------------------------------------------
362
+ // Private Helpers
363
+ // ---------------------------------------------------------------------------
364
+ /**
365
+ * Fetch an existing protection bypass token for the project, or create one
366
+ * if none exists. Returns the token string, or null if acquisition fails.
367
+ */
368
+ async _acquireProtectionBypass(projectId) {
369
+ const projResp = await this._vercelFetch(`/v9/projects/${projectId}`);
370
+ if (projResp.ok) {
371
+ const project = await projResp.json();
372
+ const existing = project.protectionBypass ? Object.keys(project.protectionBypass)[0] : void 0;
373
+ if (existing) {
374
+ this.logger.debug(`${LOG_PREFIX} Using existing protection bypass token`);
375
+ return existing;
376
+ }
377
+ }
378
+ this.logger.debug(`${LOG_PREFIX} Creating protection bypass token...`);
379
+ const createResp = await this._vercelFetch(`/v1/projects/${projectId}/protection-bypass`, {
380
+ method: "PATCH",
381
+ body: JSON.stringify({})
382
+ });
383
+ if (createResp.ok) {
384
+ const result = await createResp.json();
385
+ const created = result.protectionBypass ? Object.keys(result.protectionBypass)[0] : void 0;
386
+ if (created) {
387
+ this.logger.debug(`${LOG_PREFIX} Protection bypass token created`);
388
+ return created;
389
+ }
390
+ }
391
+ this.logger.debug(`${LOG_PREFIX} Could not acquire protection bypass token (project may not require it)`);
392
+ return null;
393
+ }
394
+ _executorHeaders() {
395
+ const headers = {
396
+ "Content-Type": "application/json",
397
+ Authorization: `Bearer ${this._secret}`
398
+ };
399
+ if (this._protectionBypass) {
400
+ headers["x-vercel-protection-bypass"] = this._protectionBypass;
401
+ }
402
+ return headers;
403
+ }
404
+ async _vercelFetch(path, options = {}) {
405
+ const url = new URL(path, VERCEL_API_BASE);
406
+ if (this._teamId) {
407
+ url.searchParams.set("teamId", this._teamId);
408
+ }
409
+ return fetch(url.toString(), {
410
+ ...options,
411
+ headers: {
412
+ "Content-Type": "application/json",
413
+ Authorization: `Bearer ${this._token}`,
414
+ ...options.headers ?? {}
415
+ }
416
+ });
417
+ }
418
+ };
419
+
420
+ // src/provider.ts
421
+ var vercelSandboxProvider = {
422
+ id: "vercel",
423
+ name: "Vercel Sandbox",
424
+ description: "Serverless sandbox powered by Vercel Functions",
425
+ configSchema: {
426
+ type: "object",
427
+ properties: {
428
+ token: { type: "string", description: "Vercel API token" },
429
+ teamId: { type: "string", description: "Vercel team ID" },
430
+ projectName: { type: "string", description: "Existing Vercel project name" },
431
+ regions: {
432
+ type: "array",
433
+ description: "Deployment regions",
434
+ items: { type: "string" },
435
+ default: ["iad1"]
436
+ },
437
+ maxDuration: { type: "number", description: "Function max duration in seconds", default: 60 },
438
+ memory: { type: "number", description: "Function memory in MB", default: 1024 },
439
+ env: {
440
+ type: "object",
441
+ description: "Environment variables",
442
+ additionalProperties: { type: "string" }
443
+ },
444
+ commandTimeout: { type: "number", description: "Per-invocation timeout in ms", default: 55e3 }
445
+ }
446
+ },
447
+ createSandbox: (config) => new VercelSandbox(config)
448
+ };
449
+
450
+ exports.VercelSandbox = VercelSandbox;
451
+ exports.vercelSandboxProvider = vercelSandboxProvider;
452
+ //# sourceMappingURL=index.cjs.map
453
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/executor/index.ts","../src/sandbox/index.ts","../src/provider.ts"],"names":["MastraSandbox","SandboxNotReadyError"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Executor function source code deployed to Vercel as a serverless function.\n *\n * Returns a string because it's sent as inline file content via\n * the Vercel Deployments API — no separate build step needed.\n *\n * The secret and user env vars are embedded as constants in the source\n * because the Vercel Deployments API does not support setting env vars\n * directly — they must be configured via vercel.json or project settings.\n */\nexport function getExecutorSource(secret: string, env: Record<string, string>): string {\n const envEntries = Object.entries(env)\n .map(([k, v]) => ` ${JSON.stringify(k)}: ${JSON.stringify(v)}`)\n .join(',\\n');\n\n return `\nconst { execFileSync } = require('child_process');\n\nconst SANDBOX_SECRET = ${JSON.stringify(secret)};\nconst SANDBOX_ENV = {\n${envEntries}\n};\n\nmodule.exports = async (req, res) => {\n // Auth check\n const authHeader = req.headers['authorization'] || '';\n if (!SANDBOX_SECRET || authHeader !== 'Bearer ' + SANDBOX_SECRET) {\n return res.status(401).json({ error: 'Unauthorized' });\n }\n\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' });\n }\n\n const { command, args = [], env = {}, cwd, timeout = 55000 } = req.body || {};\n\n if (!command) {\n return res.status(400).json({ error: 'Missing required field: command' });\n }\n\n const execCwd = cwd || '/tmp';\n const execEnv = { ...process.env, ...SANDBOX_ENV, ...env };\n\n // When args is empty the caller sent a full shell command string\n // (e.g. \"echo hello\" or \"ls -la | grep foo\"). Run it through\n // /bin/sh so builtins and pipes work. When args is non-empty the\n // caller split the command properly — use execFileSync to avoid\n // shell injection.\n const useShell = !args || args.length === 0;\n const execCommand = useShell ? '/bin/sh' : command;\n const execArgs = useShell ? ['-c', command] : args;\n\n const startTime = Date.now();\n let timedOut = false;\n\n try {\n const stdout = execFileSync(execCommand, execArgs, {\n cwd: execCwd,\n env: execEnv,\n timeout,\n maxBuffer: 10 * 1024 * 1024,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n return res.status(200).json({\n success: true,\n exitCode: 0,\n stdout: stdout || '',\n stderr: '',\n executionTimeMs: Date.now() - startTime,\n timedOut: false,\n });\n } catch (error) {\n timedOut = error.killed || false;\n\n return res.status(200).json({\n success: false,\n exitCode: error.status != null ? error.status : 1,\n stdout: error.stdout || '',\n stderr: error.stderr || '',\n executionTimeMs: Date.now() - startTime,\n timedOut,\n });\n }\n};\n`;\n}\n","/**\n * Vercel Sandbox Provider\n *\n * Deploys code as Vercel serverless functions and executes commands\n * via HTTP invocation. Stateless — no persistent filesystem, no\n * interactive shell, no long-running processes.\n *\n * @see https://vercel.com/docs/rest-api\n */\n\nimport type { RequestContext } from '@mastra/core/di';\nimport type {\n SandboxInfo,\n CommandResult,\n ExecuteCommandOptions,\n MastraSandboxOptions,\n ProviderStatus,\n InstructionsOption,\n} from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { getExecutorSource } from '../executor';\n\nconst LOG_PREFIX = '[VercelSandbox]';\n\nconst VERCEL_API_BASE = 'https://api.vercel.com';\n\n/**\n * Shell-quote an argument for safe interpolation into a shell command string.\n * Mirrors the implementation in packages/core/src/workspace/sandbox/utils.ts\n * which is not publicly exported.\n */\nfunction shellQuote(arg: string): string {\n if (/^[a-zA-Z0-9._\\-\\/=:@]+$/.test(arg)) return arg;\n return `'${arg.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n// =============================================================================\n// Options\n// =============================================================================\n\nexport interface VercelSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Vercel API token. Falls back to VERCEL_TOKEN env var. */\n token?: string;\n /** Vercel team ID for team-scoped deployments. */\n teamId?: string;\n /** Existing Vercel project name. Auto-generated if omitted. */\n projectName?: string;\n /** Deployment regions. @default ['iad1'] */\n regions?: string[];\n /** Function max duration in seconds. @default 60 */\n maxDuration?: number;\n /** Function memory in MB. @default 1024 */\n memory?: number;\n /** Environment variables baked into the deployed function. */\n env?: Record<string, string>;\n /** Per-invocation command timeout in ms. @default 55000 */\n commandTimeout?: number;\n /**\n * Custom instructions that override the default instructions\n * returned by `getInstructions()`.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\nexport class VercelSandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'VercelSandbox';\n readonly provider = 'vercel';\n status: ProviderStatus = 'pending';\n\n private readonly _token: string;\n private readonly _teamId?: string;\n private readonly _projectName?: string;\n private readonly _regions: string[];\n private readonly _maxDuration: number;\n private readonly _memory: number;\n private readonly _env: Record<string, string>;\n private readonly _commandTimeout: number;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _secret: string;\n\n private _deploymentUrl: string | null = null;\n private _deploymentId: string | null = null;\n private _protectionBypass: string | null = null;\n private _createdAt: Date | null = null;\n\n constructor(options: VercelSandboxOptions = {}) {\n super({ name: 'VercelSandbox' });\n\n this.id = `vercel-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n this._token = options.token || process.env.VERCEL_TOKEN || '';\n this._teamId = options.teamId;\n this._projectName = options.projectName;\n this._regions = options.regions ?? ['iad1'];\n this._maxDuration = options.maxDuration ?? 60;\n this._memory = options.memory ?? 1024;\n this._env = options.env ?? {};\n this._commandTimeout = options.commandTimeout ?? 55_000;\n this._instructionsOverride = options.instructions;\n this._secret = crypto.randomUUID();\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async start(): Promise<void> {\n if (this._deploymentUrl) {\n return;\n }\n\n if (!this._token) {\n throw new Error(`${LOG_PREFIX} Missing Vercel API token. Set VERCEL_TOKEN env var or pass token option.`);\n }\n\n // Clean up any stale deployment from a previous stop() → start() cycle.\n // Without this, the old _deploymentId is overwritten and that deployment leaks.\n if (this._deploymentId) {\n this.logger.debug(`${LOG_PREFIX} Cleaning up stale deployment ${this._deploymentId} before restarting...`);\n try {\n const resp = await this._vercelFetch(`/v13/deployments/${this._deploymentId}`, { method: 'DELETE' });\n if (!resp.ok && resp.status !== 404) {\n this.logger.warn(`${LOG_PREFIX} Failed to delete stale deployment: ${resp.status}`);\n }\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Error deleting stale deployment:`, error);\n }\n this._deploymentId = null;\n }\n\n this.logger.debug(`${LOG_PREFIX} Deploying executor function...`);\n\n const vercelJson = JSON.stringify({\n functions: {\n 'api/execute.js': {\n memory: this._memory,\n maxDuration: this._maxDuration,\n },\n },\n regions: this._regions,\n });\n\n // Create the deployment\n const deploymentBody: Record<string, unknown> = {\n name: this._projectName ?? `mastra-sandbox-${this.id}`,\n files: [\n {\n file: 'api/execute.js',\n data: getExecutorSource(this._secret, this._env),\n },\n {\n file: 'vercel.json',\n data: vercelJson,\n },\n ],\n projectSettings: {\n framework: null,\n },\n target: 'production',\n };\n\n const createResp = await this._vercelFetch('/v13/deployments', {\n method: 'POST',\n body: JSON.stringify(deploymentBody),\n });\n\n if (!createResp.ok) {\n const errorBody = await createResp.text();\n throw new Error(`${LOG_PREFIX} Failed to create deployment: ${createResp.status} ${errorBody}`);\n }\n\n const deployment = (await createResp.json()) as { id: string; url: string; readyState: string; projectId?: string };\n this._deploymentId = deployment.id;\n\n this.logger.debug(`${LOG_PREFIX} Deployment created: ${deployment.id}, polling for READY...`);\n\n // Poll until ready\n const maxWaitMs = 120_000;\n const pollIntervalMs = 3_000;\n const deadline = Date.now() + maxWaitMs;\n\n while (Date.now() < deadline) {\n const statusResp = await this._vercelFetch(`/v13/deployments/${deployment.id}`);\n if (!statusResp.ok) {\n throw new Error(`${LOG_PREFIX} Failed to check deployment status: ${statusResp.status}`);\n }\n\n const statusBody = (await statusResp.json()) as { readyState: string; url: string };\n\n if (statusBody.readyState === 'READY') {\n this._deploymentUrl = `https://${statusBody.url}`;\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Deployment ready: ${this._deploymentUrl}`);\n\n // Acquire a deployment protection bypass token.\n // Pro/Enterprise teams have Deployment Protection enabled by default,\n // which intercepts HTTP requests with an SSO login page before they\n // reach the serverless function. The bypass token lets us skip that.\n if (deployment.projectId) {\n try {\n this._protectionBypass = await this._acquireProtectionBypass(deployment.projectId);\n } catch {\n // Non-fatal — if the project has no deployment protection, this is unnecessary.\n }\n }\n\n // Warm-up ping\n try {\n await fetch(`${this._deploymentUrl}/api/execute`, {\n method: 'POST',\n headers: this._executorHeaders(),\n body: JSON.stringify({ command: 'echo', args: ['warm'] }),\n });\n } catch {\n // Warm-up failure is non-fatal\n }\n\n return;\n }\n\n if (statusBody.readyState === 'ERROR' || statusBody.readyState === 'CANCELED') {\n throw new Error(`${LOG_PREFIX} Deployment failed with state: ${statusBody.readyState}`);\n }\n\n await new Promise(resolve => setTimeout(resolve, pollIntervalMs));\n }\n\n throw new Error(`${LOG_PREFIX} Deployment timed out after ${maxWaitMs}ms`);\n }\n\n async stop(): Promise<void> {\n // Only clear the URL (disconnects from the deployment) but keep\n // _deploymentId so a subsequent destroy() can still clean up the\n // cloud resource. Clearing both would make destroy() a no-op and\n // leak the deployment.\n this._deploymentUrl = null;\n }\n\n async destroy(): Promise<void> {\n if (this._deploymentId) {\n try {\n const resp = await this._vercelFetch(`/v13/deployments/${this._deploymentId}`, {\n method: 'DELETE',\n });\n if (!resp.ok) {\n // 404 means the deployment is already gone — that's fine.\n // Other status codes indicate infrastructure issues (auth, network)\n // and should be surfaced more visibly.\n if (resp.status === 404) {\n this.logger.debug(`${LOG_PREFIX} Deployment already deleted (404)`);\n } else {\n this.logger.warn(`${LOG_PREFIX} Failed to delete deployment: ${resp.status}`);\n }\n }\n } catch (error) {\n // Network-level failure — warn rather than debug so it's visible\n this.logger.warn(`${LOG_PREFIX} Error deleting deployment:`, error);\n }\n this._deploymentId = null;\n }\n this._deploymentUrl = null;\n this._protectionBypass = null;\n }\n\n // ---------------------------------------------------------------------------\n // Command Execution\n // ---------------------------------------------------------------------------\n\n async executeCommand(command: string, args?: string[], options?: ExecuteCommandOptions): Promise<CommandResult> {\n await this.ensureRunning();\n\n if (!this._deploymentUrl) {\n throw new SandboxNotReadyError(this.id);\n }\n\n const fullCommand = args?.length ? `${command} ${args.map(a => shellQuote(a)).join(' ')}` : command;\n this.logger.debug(`${LOG_PREFIX} Executing: ${fullCommand}`);\n\n const body = {\n command,\n args: args ?? [],\n env: options?.env ?? {},\n cwd: options?.cwd ?? '/tmp',\n timeout: options?.timeout ?? this._commandTimeout,\n };\n\n const maxRetries = 2;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const resp = await fetch(`${this._deploymentUrl}/api/execute`, {\n method: 'POST',\n headers: this._executorHeaders(),\n body: JSON.stringify(body),\n signal: options?.abortSignal,\n });\n\n // Retry on transient errors\n if ((resp.status === 429 || resp.status === 502 || resp.status === 503) && attempt < maxRetries) {\n this.logger.debug(`${LOG_PREFIX} Retryable status ${resp.status}, attempt ${attempt + 1}/${maxRetries}`);\n await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));\n continue;\n }\n\n // Gateway timeout → timedOut\n if (resp.status === 504) {\n return {\n command: fullCommand,\n args,\n success: false,\n exitCode: 124,\n stdout: '',\n stderr: 'Function execution timed out (504 Gateway Timeout)',\n executionTimeMs: options?.timeout ?? this._commandTimeout,\n timedOut: true,\n };\n }\n\n if (!resp.ok) {\n const errorText = await resp.text();\n throw new Error(`${LOG_PREFIX} Execute failed: ${resp.status} ${errorText}`);\n }\n\n const result = (await resp.json()) as {\n success: boolean;\n exitCode: number;\n stdout: string;\n stderr: string;\n executionTimeMs: number;\n timedOut: boolean;\n };\n\n // Stream callbacks\n if (options?.onStdout && result.stdout) {\n options.onStdout(result.stdout);\n }\n if (options?.onStderr && result.stderr) {\n options.onStderr(result.stderr);\n }\n\n return {\n command: fullCommand,\n args,\n success: result.success,\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n executionTimeMs: result.executionTimeMs,\n timedOut: result.timedOut,\n };\n } catch (error) {\n if (error instanceof DOMException && error.name === 'AbortError') {\n throw error;\n }\n lastError = error as Error;\n if (attempt < maxRetries) {\n this.logger.debug(`${LOG_PREFIX} Request error, attempt ${attempt + 1}/${maxRetries}:`, error);\n await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));\n continue;\n }\n }\n }\n\n throw lastError ?? new Error(`${LOG_PREFIX} executeCommand failed after retries`);\n }\n\n // ---------------------------------------------------------------------------\n // Info & Instructions\n // ---------------------------------------------------------------------------\n\n // Matches the resolveInstructions pattern in packages/core/src/workspace/utils.ts\n getInstructions(opts?: { requestContext?: RequestContext }): string {\n if (this._instructionsOverride === undefined) return this._getDefaultInstructions();\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n const defaultInstructions = this._getDefaultInstructions();\n return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });\n }\n\n private _getDefaultInstructions(): string {\n return [\n 'Vercel serverless sandbox.',\n 'Limitations:',\n '- Stateless: no persistent filesystem between invocations.',\n '- No interactive shell or streaming stdin.',\n '- No long-running or background processes.',\n `- Maximum execution time: ${this._maxDuration} seconds.`,\n '- Only /tmp is writable (ephemeral, cleared between invocations).',\n '- Shell commands (pipes, builtins) are supported via /bin/sh -c.',\n ].join('\\n');\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 deploymentId: this._deploymentId,\n deploymentUrl: this._deploymentUrl,\n regions: this._regions,\n maxDuration: this._maxDuration,\n memory: this._memory,\n },\n };\n }\n\n // ---------------------------------------------------------------------------\n // Private Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Fetch an existing protection bypass token for the project, or create one\n * if none exists. Returns the token string, or null if acquisition fails.\n */\n private async _acquireProtectionBypass(projectId: string): Promise<string | null> {\n // 1. Check if the project already has a bypass token.\n const projResp = await this._vercelFetch(`/v9/projects/${projectId}`);\n if (projResp.ok) {\n const project = (await projResp.json()) as {\n protectionBypass?: Record<string, unknown>;\n };\n const existing = project.protectionBypass ? Object.keys(project.protectionBypass)[0] : undefined;\n if (existing) {\n this.logger.debug(`${LOG_PREFIX} Using existing protection bypass token`);\n return existing;\n }\n }\n\n // 2. No token exists — create one via the dedicated endpoint.\n this.logger.debug(`${LOG_PREFIX} Creating protection bypass token...`);\n const createResp = await this._vercelFetch(`/v1/projects/${projectId}/protection-bypass`, {\n method: 'PATCH',\n body: JSON.stringify({}),\n });\n if (createResp.ok) {\n const result = (await createResp.json()) as {\n protectionBypass?: Record<string, unknown>;\n };\n const created = result.protectionBypass ? Object.keys(result.protectionBypass)[0] : undefined;\n if (created) {\n this.logger.debug(`${LOG_PREFIX} Protection bypass token created`);\n return created;\n }\n }\n\n this.logger.debug(`${LOG_PREFIX} Could not acquire protection bypass token (project may not require it)`);\n return null;\n }\n\n private _executorHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._secret}`,\n };\n if (this._protectionBypass) {\n headers['x-vercel-protection-bypass'] = this._protectionBypass;\n }\n return headers;\n }\n\n private async _vercelFetch(path: string, options: RequestInit = {}): Promise<Response> {\n const url = new URL(path, VERCEL_API_BASE);\n if (this._teamId) {\n url.searchParams.set('teamId', this._teamId);\n }\n\n return fetch(url.toString(), {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._token}`,\n ...((options.headers as Record<string, string>) ?? {}),\n },\n });\n }\n}\n","/**\n * Vercel sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { vercelSandboxProvider } from '@mastra/vercel';\n *\n * const editor = new MastraEditor({\n * sandboxes: [vercelSandboxProvider],\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { VercelSandbox } from './sandbox';\n\n/**\n * Serializable subset of VercelSandboxOptions for editor storage.\n */\ninterface VercelProviderConfig {\n token?: string;\n teamId?: string;\n projectName?: string;\n regions?: string[];\n maxDuration?: number;\n memory?: number;\n env?: Record<string, string>;\n commandTimeout?: number;\n}\n\nexport const vercelSandboxProvider: SandboxProvider<VercelProviderConfig> = {\n id: 'vercel',\n name: 'Vercel Sandbox',\n description: 'Serverless sandbox powered by Vercel Functions',\n configSchema: {\n type: 'object',\n properties: {\n token: { type: 'string', description: 'Vercel API token' },\n teamId: { type: 'string', description: 'Vercel team ID' },\n projectName: { type: 'string', description: 'Existing Vercel project name' },\n regions: {\n type: 'array',\n description: 'Deployment regions',\n items: { type: 'string' },\n default: ['iad1'],\n },\n maxDuration: { type: 'number', description: 'Function max duration in seconds', default: 60 },\n memory: { type: 'number', description: 'Function memory in MB', default: 1024 },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n commandTimeout: { type: 'number', description: 'Per-invocation timeout in ms', default: 55000 },\n },\n },\n createSandbox: config => new VercelSandbox(config),\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export { VercelSandbox, type VercelSandboxOptions } from './sandbox/index.js';
2
+ export { vercelSandboxProvider } from './provider.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,450 @@
1
+ import { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';
2
+
3
+ // src/sandbox/index.ts
4
+
5
+ // src/executor/index.ts
6
+ function getExecutorSource(secret, env) {
7
+ const envEntries = Object.entries(env).map(([k, v]) => ` ${JSON.stringify(k)}: ${JSON.stringify(v)}`).join(",\n");
8
+ return `
9
+ const { execFileSync } = require('child_process');
10
+
11
+ const SANDBOX_SECRET = ${JSON.stringify(secret)};
12
+ const SANDBOX_ENV = {
13
+ ${envEntries}
14
+ };
15
+
16
+ module.exports = async (req, res) => {
17
+ // Auth check
18
+ const authHeader = req.headers['authorization'] || '';
19
+ if (!SANDBOX_SECRET || authHeader !== 'Bearer ' + SANDBOX_SECRET) {
20
+ return res.status(401).json({ error: 'Unauthorized' });
21
+ }
22
+
23
+ if (req.method !== 'POST') {
24
+ return res.status(405).json({ error: 'Method not allowed' });
25
+ }
26
+
27
+ const { command, args = [], env = {}, cwd, timeout = 55000 } = req.body || {};
28
+
29
+ if (!command) {
30
+ return res.status(400).json({ error: 'Missing required field: command' });
31
+ }
32
+
33
+ const execCwd = cwd || '/tmp';
34
+ const execEnv = { ...process.env, ...SANDBOX_ENV, ...env };
35
+
36
+ // When args is empty the caller sent a full shell command string
37
+ // (e.g. "echo hello" or "ls -la | grep foo"). Run it through
38
+ // /bin/sh so builtins and pipes work. When args is non-empty the
39
+ // caller split the command properly \u2014 use execFileSync to avoid
40
+ // shell injection.
41
+ const useShell = !args || args.length === 0;
42
+ const execCommand = useShell ? '/bin/sh' : command;
43
+ const execArgs = useShell ? ['-c', command] : args;
44
+
45
+ const startTime = Date.now();
46
+ let timedOut = false;
47
+
48
+ try {
49
+ const stdout = execFileSync(execCommand, execArgs, {
50
+ cwd: execCwd,
51
+ env: execEnv,
52
+ timeout,
53
+ maxBuffer: 10 * 1024 * 1024,
54
+ encoding: 'utf-8',
55
+ stdio: ['pipe', 'pipe', 'pipe'],
56
+ });
57
+
58
+ return res.status(200).json({
59
+ success: true,
60
+ exitCode: 0,
61
+ stdout: stdout || '',
62
+ stderr: '',
63
+ executionTimeMs: Date.now() - startTime,
64
+ timedOut: false,
65
+ });
66
+ } catch (error) {
67
+ timedOut = error.killed || false;
68
+
69
+ return res.status(200).json({
70
+ success: false,
71
+ exitCode: error.status != null ? error.status : 1,
72
+ stdout: error.stdout || '',
73
+ stderr: error.stderr || '',
74
+ executionTimeMs: Date.now() - startTime,
75
+ timedOut,
76
+ });
77
+ }
78
+ };
79
+ `;
80
+ }
81
+
82
+ // src/sandbox/index.ts
83
+ var LOG_PREFIX = "[VercelSandbox]";
84
+ var VERCEL_API_BASE = "https://api.vercel.com";
85
+ function shellQuote(arg) {
86
+ if (/^[a-zA-Z0-9._\-\/=:@]+$/.test(arg)) return arg;
87
+ return `'${arg.replace(/'/g, "'\\''")}'`;
88
+ }
89
+ var VercelSandbox = class extends MastraSandbox {
90
+ id;
91
+ name = "VercelSandbox";
92
+ provider = "vercel";
93
+ status = "pending";
94
+ _token;
95
+ _teamId;
96
+ _projectName;
97
+ _regions;
98
+ _maxDuration;
99
+ _memory;
100
+ _env;
101
+ _commandTimeout;
102
+ _instructionsOverride;
103
+ _secret;
104
+ _deploymentUrl = null;
105
+ _deploymentId = null;
106
+ _protectionBypass = null;
107
+ _createdAt = null;
108
+ constructor(options = {}) {
109
+ super({ name: "VercelSandbox" });
110
+ this.id = `vercel-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
111
+ this._token = options.token || process.env.VERCEL_TOKEN || "";
112
+ this._teamId = options.teamId;
113
+ this._projectName = options.projectName;
114
+ this._regions = options.regions ?? ["iad1"];
115
+ this._maxDuration = options.maxDuration ?? 60;
116
+ this._memory = options.memory ?? 1024;
117
+ this._env = options.env ?? {};
118
+ this._commandTimeout = options.commandTimeout ?? 55e3;
119
+ this._instructionsOverride = options.instructions;
120
+ this._secret = crypto.randomUUID();
121
+ }
122
+ // ---------------------------------------------------------------------------
123
+ // Lifecycle
124
+ // ---------------------------------------------------------------------------
125
+ async start() {
126
+ if (this._deploymentUrl) {
127
+ return;
128
+ }
129
+ if (!this._token) {
130
+ throw new Error(`${LOG_PREFIX} Missing Vercel API token. Set VERCEL_TOKEN env var or pass token option.`);
131
+ }
132
+ if (this._deploymentId) {
133
+ this.logger.debug(`${LOG_PREFIX} Cleaning up stale deployment ${this._deploymentId} before restarting...`);
134
+ try {
135
+ const resp = await this._vercelFetch(`/v13/deployments/${this._deploymentId}`, { method: "DELETE" });
136
+ if (!resp.ok && resp.status !== 404) {
137
+ this.logger.warn(`${LOG_PREFIX} Failed to delete stale deployment: ${resp.status}`);
138
+ }
139
+ } catch (error) {
140
+ this.logger.warn(`${LOG_PREFIX} Error deleting stale deployment:`, error);
141
+ }
142
+ this._deploymentId = null;
143
+ }
144
+ this.logger.debug(`${LOG_PREFIX} Deploying executor function...`);
145
+ const vercelJson = JSON.stringify({
146
+ functions: {
147
+ "api/execute.js": {
148
+ memory: this._memory,
149
+ maxDuration: this._maxDuration
150
+ }
151
+ },
152
+ regions: this._regions
153
+ });
154
+ const deploymentBody = {
155
+ name: this._projectName ?? `mastra-sandbox-${this.id}`,
156
+ files: [
157
+ {
158
+ file: "api/execute.js",
159
+ data: getExecutorSource(this._secret, this._env)
160
+ },
161
+ {
162
+ file: "vercel.json",
163
+ data: vercelJson
164
+ }
165
+ ],
166
+ projectSettings: {
167
+ framework: null
168
+ },
169
+ target: "production"
170
+ };
171
+ const createResp = await this._vercelFetch("/v13/deployments", {
172
+ method: "POST",
173
+ body: JSON.stringify(deploymentBody)
174
+ });
175
+ if (!createResp.ok) {
176
+ const errorBody = await createResp.text();
177
+ throw new Error(`${LOG_PREFIX} Failed to create deployment: ${createResp.status} ${errorBody}`);
178
+ }
179
+ const deployment = await createResp.json();
180
+ this._deploymentId = deployment.id;
181
+ this.logger.debug(`${LOG_PREFIX} Deployment created: ${deployment.id}, polling for READY...`);
182
+ const maxWaitMs = 12e4;
183
+ const pollIntervalMs = 3e3;
184
+ const deadline = Date.now() + maxWaitMs;
185
+ while (Date.now() < deadline) {
186
+ const statusResp = await this._vercelFetch(`/v13/deployments/${deployment.id}`);
187
+ if (!statusResp.ok) {
188
+ throw new Error(`${LOG_PREFIX} Failed to check deployment status: ${statusResp.status}`);
189
+ }
190
+ const statusBody = await statusResp.json();
191
+ if (statusBody.readyState === "READY") {
192
+ this._deploymentUrl = `https://${statusBody.url}`;
193
+ this._createdAt = /* @__PURE__ */ new Date();
194
+ this.logger.debug(`${LOG_PREFIX} Deployment ready: ${this._deploymentUrl}`);
195
+ if (deployment.projectId) {
196
+ try {
197
+ this._protectionBypass = await this._acquireProtectionBypass(deployment.projectId);
198
+ } catch {
199
+ }
200
+ }
201
+ try {
202
+ await fetch(`${this._deploymentUrl}/api/execute`, {
203
+ method: "POST",
204
+ headers: this._executorHeaders(),
205
+ body: JSON.stringify({ command: "echo", args: ["warm"] })
206
+ });
207
+ } catch {
208
+ }
209
+ return;
210
+ }
211
+ if (statusBody.readyState === "ERROR" || statusBody.readyState === "CANCELED") {
212
+ throw new Error(`${LOG_PREFIX} Deployment failed with state: ${statusBody.readyState}`);
213
+ }
214
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
215
+ }
216
+ throw new Error(`${LOG_PREFIX} Deployment timed out after ${maxWaitMs}ms`);
217
+ }
218
+ async stop() {
219
+ this._deploymentUrl = null;
220
+ }
221
+ async destroy() {
222
+ if (this._deploymentId) {
223
+ try {
224
+ const resp = await this._vercelFetch(`/v13/deployments/${this._deploymentId}`, {
225
+ method: "DELETE"
226
+ });
227
+ if (!resp.ok) {
228
+ if (resp.status === 404) {
229
+ this.logger.debug(`${LOG_PREFIX} Deployment already deleted (404)`);
230
+ } else {
231
+ this.logger.warn(`${LOG_PREFIX} Failed to delete deployment: ${resp.status}`);
232
+ }
233
+ }
234
+ } catch (error) {
235
+ this.logger.warn(`${LOG_PREFIX} Error deleting deployment:`, error);
236
+ }
237
+ this._deploymentId = null;
238
+ }
239
+ this._deploymentUrl = null;
240
+ this._protectionBypass = null;
241
+ }
242
+ // ---------------------------------------------------------------------------
243
+ // Command Execution
244
+ // ---------------------------------------------------------------------------
245
+ async executeCommand(command, args, options) {
246
+ await this.ensureRunning();
247
+ if (!this._deploymentUrl) {
248
+ throw new SandboxNotReadyError(this.id);
249
+ }
250
+ const fullCommand = args?.length ? `${command} ${args.map((a) => shellQuote(a)).join(" ")}` : command;
251
+ this.logger.debug(`${LOG_PREFIX} Executing: ${fullCommand}`);
252
+ const body = {
253
+ command,
254
+ args: args ?? [],
255
+ env: options?.env ?? {},
256
+ cwd: options?.cwd ?? "/tmp",
257
+ timeout: options?.timeout ?? this._commandTimeout
258
+ };
259
+ const maxRetries = 2;
260
+ let lastError = null;
261
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
262
+ try {
263
+ const resp = await fetch(`${this._deploymentUrl}/api/execute`, {
264
+ method: "POST",
265
+ headers: this._executorHeaders(),
266
+ body: JSON.stringify(body),
267
+ signal: options?.abortSignal
268
+ });
269
+ if ((resp.status === 429 || resp.status === 502 || resp.status === 503) && attempt < maxRetries) {
270
+ this.logger.debug(`${LOG_PREFIX} Retryable status ${resp.status}, attempt ${attempt + 1}/${maxRetries}`);
271
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * (attempt + 1)));
272
+ continue;
273
+ }
274
+ if (resp.status === 504) {
275
+ return {
276
+ command: fullCommand,
277
+ args,
278
+ success: false,
279
+ exitCode: 124,
280
+ stdout: "",
281
+ stderr: "Function execution timed out (504 Gateway Timeout)",
282
+ executionTimeMs: options?.timeout ?? this._commandTimeout,
283
+ timedOut: true
284
+ };
285
+ }
286
+ if (!resp.ok) {
287
+ const errorText = await resp.text();
288
+ throw new Error(`${LOG_PREFIX} Execute failed: ${resp.status} ${errorText}`);
289
+ }
290
+ const result = await resp.json();
291
+ if (options?.onStdout && result.stdout) {
292
+ options.onStdout(result.stdout);
293
+ }
294
+ if (options?.onStderr && result.stderr) {
295
+ options.onStderr(result.stderr);
296
+ }
297
+ return {
298
+ command: fullCommand,
299
+ args,
300
+ success: result.success,
301
+ exitCode: result.exitCode,
302
+ stdout: result.stdout,
303
+ stderr: result.stderr,
304
+ executionTimeMs: result.executionTimeMs,
305
+ timedOut: result.timedOut
306
+ };
307
+ } catch (error) {
308
+ if (error instanceof DOMException && error.name === "AbortError") {
309
+ throw error;
310
+ }
311
+ lastError = error;
312
+ if (attempt < maxRetries) {
313
+ this.logger.debug(`${LOG_PREFIX} Request error, attempt ${attempt + 1}/${maxRetries}:`, error);
314
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * (attempt + 1)));
315
+ continue;
316
+ }
317
+ }
318
+ }
319
+ throw lastError ?? new Error(`${LOG_PREFIX} executeCommand failed after retries`);
320
+ }
321
+ // ---------------------------------------------------------------------------
322
+ // Info & Instructions
323
+ // ---------------------------------------------------------------------------
324
+ // Matches the resolveInstructions pattern in packages/core/src/workspace/utils.ts
325
+ getInstructions(opts) {
326
+ if (this._instructionsOverride === void 0) return this._getDefaultInstructions();
327
+ if (typeof this._instructionsOverride === "string") return this._instructionsOverride;
328
+ const defaultInstructions = this._getDefaultInstructions();
329
+ return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });
330
+ }
331
+ _getDefaultInstructions() {
332
+ return [
333
+ "Vercel serverless sandbox.",
334
+ "Limitations:",
335
+ "- Stateless: no persistent filesystem between invocations.",
336
+ "- No interactive shell or streaming stdin.",
337
+ "- No long-running or background processes.",
338
+ `- Maximum execution time: ${this._maxDuration} seconds.`,
339
+ "- Only /tmp is writable (ephemeral, cleared between invocations).",
340
+ "- Shell commands (pipes, builtins) are supported via /bin/sh -c."
341
+ ].join("\n");
342
+ }
343
+ async getInfo() {
344
+ return {
345
+ id: this.id,
346
+ name: this.name,
347
+ provider: this.provider,
348
+ status: this.status,
349
+ createdAt: this._createdAt ?? /* @__PURE__ */ new Date(),
350
+ metadata: {
351
+ deploymentId: this._deploymentId,
352
+ deploymentUrl: this._deploymentUrl,
353
+ regions: this._regions,
354
+ maxDuration: this._maxDuration,
355
+ memory: this._memory
356
+ }
357
+ };
358
+ }
359
+ // ---------------------------------------------------------------------------
360
+ // Private Helpers
361
+ // ---------------------------------------------------------------------------
362
+ /**
363
+ * Fetch an existing protection bypass token for the project, or create one
364
+ * if none exists. Returns the token string, or null if acquisition fails.
365
+ */
366
+ async _acquireProtectionBypass(projectId) {
367
+ const projResp = await this._vercelFetch(`/v9/projects/${projectId}`);
368
+ if (projResp.ok) {
369
+ const project = await projResp.json();
370
+ const existing = project.protectionBypass ? Object.keys(project.protectionBypass)[0] : void 0;
371
+ if (existing) {
372
+ this.logger.debug(`${LOG_PREFIX} Using existing protection bypass token`);
373
+ return existing;
374
+ }
375
+ }
376
+ this.logger.debug(`${LOG_PREFIX} Creating protection bypass token...`);
377
+ const createResp = await this._vercelFetch(`/v1/projects/${projectId}/protection-bypass`, {
378
+ method: "PATCH",
379
+ body: JSON.stringify({})
380
+ });
381
+ if (createResp.ok) {
382
+ const result = await createResp.json();
383
+ const created = result.protectionBypass ? Object.keys(result.protectionBypass)[0] : void 0;
384
+ if (created) {
385
+ this.logger.debug(`${LOG_PREFIX} Protection bypass token created`);
386
+ return created;
387
+ }
388
+ }
389
+ this.logger.debug(`${LOG_PREFIX} Could not acquire protection bypass token (project may not require it)`);
390
+ return null;
391
+ }
392
+ _executorHeaders() {
393
+ const headers = {
394
+ "Content-Type": "application/json",
395
+ Authorization: `Bearer ${this._secret}`
396
+ };
397
+ if (this._protectionBypass) {
398
+ headers["x-vercel-protection-bypass"] = this._protectionBypass;
399
+ }
400
+ return headers;
401
+ }
402
+ async _vercelFetch(path, options = {}) {
403
+ const url = new URL(path, VERCEL_API_BASE);
404
+ if (this._teamId) {
405
+ url.searchParams.set("teamId", this._teamId);
406
+ }
407
+ return fetch(url.toString(), {
408
+ ...options,
409
+ headers: {
410
+ "Content-Type": "application/json",
411
+ Authorization: `Bearer ${this._token}`,
412
+ ...options.headers ?? {}
413
+ }
414
+ });
415
+ }
416
+ };
417
+
418
+ // src/provider.ts
419
+ var vercelSandboxProvider = {
420
+ id: "vercel",
421
+ name: "Vercel Sandbox",
422
+ description: "Serverless sandbox powered by Vercel Functions",
423
+ configSchema: {
424
+ type: "object",
425
+ properties: {
426
+ token: { type: "string", description: "Vercel API token" },
427
+ teamId: { type: "string", description: "Vercel team ID" },
428
+ projectName: { type: "string", description: "Existing Vercel project name" },
429
+ regions: {
430
+ type: "array",
431
+ description: "Deployment regions",
432
+ items: { type: "string" },
433
+ default: ["iad1"]
434
+ },
435
+ maxDuration: { type: "number", description: "Function max duration in seconds", default: 60 },
436
+ memory: { type: "number", description: "Function memory in MB", default: 1024 },
437
+ env: {
438
+ type: "object",
439
+ description: "Environment variables",
440
+ additionalProperties: { type: "string" }
441
+ },
442
+ commandTimeout: { type: "number", description: "Per-invocation timeout in ms", default: 55e3 }
443
+ }
444
+ },
445
+ createSandbox: (config) => new VercelSandbox(config)
446
+ };
447
+
448
+ export { VercelSandbox, vercelSandboxProvider };
449
+ //# sourceMappingURL=index.js.map
450
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/executor/index.ts","../src/sandbox/index.ts","../src/provider.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Executor function source code deployed to Vercel as a serverless function.\n *\n * Returns a string because it's sent as inline file content via\n * the Vercel Deployments API — no separate build step needed.\n *\n * The secret and user env vars are embedded as constants in the source\n * because the Vercel Deployments API does not support setting env vars\n * directly — they must be configured via vercel.json or project settings.\n */\nexport function getExecutorSource(secret: string, env: Record<string, string>): string {\n const envEntries = Object.entries(env)\n .map(([k, v]) => ` ${JSON.stringify(k)}: ${JSON.stringify(v)}`)\n .join(',\\n');\n\n return `\nconst { execFileSync } = require('child_process');\n\nconst SANDBOX_SECRET = ${JSON.stringify(secret)};\nconst SANDBOX_ENV = {\n${envEntries}\n};\n\nmodule.exports = async (req, res) => {\n // Auth check\n const authHeader = req.headers['authorization'] || '';\n if (!SANDBOX_SECRET || authHeader !== 'Bearer ' + SANDBOX_SECRET) {\n return res.status(401).json({ error: 'Unauthorized' });\n }\n\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' });\n }\n\n const { command, args = [], env = {}, cwd, timeout = 55000 } = req.body || {};\n\n if (!command) {\n return res.status(400).json({ error: 'Missing required field: command' });\n }\n\n const execCwd = cwd || '/tmp';\n const execEnv = { ...process.env, ...SANDBOX_ENV, ...env };\n\n // When args is empty the caller sent a full shell command string\n // (e.g. \"echo hello\" or \"ls -la | grep foo\"). Run it through\n // /bin/sh so builtins and pipes work. When args is non-empty the\n // caller split the command properly — use execFileSync to avoid\n // shell injection.\n const useShell = !args || args.length === 0;\n const execCommand = useShell ? '/bin/sh' : command;\n const execArgs = useShell ? ['-c', command] : args;\n\n const startTime = Date.now();\n let timedOut = false;\n\n try {\n const stdout = execFileSync(execCommand, execArgs, {\n cwd: execCwd,\n env: execEnv,\n timeout,\n maxBuffer: 10 * 1024 * 1024,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n return res.status(200).json({\n success: true,\n exitCode: 0,\n stdout: stdout || '',\n stderr: '',\n executionTimeMs: Date.now() - startTime,\n timedOut: false,\n });\n } catch (error) {\n timedOut = error.killed || false;\n\n return res.status(200).json({\n success: false,\n exitCode: error.status != null ? error.status : 1,\n stdout: error.stdout || '',\n stderr: error.stderr || '',\n executionTimeMs: Date.now() - startTime,\n timedOut,\n });\n }\n};\n`;\n}\n","/**\n * Vercel Sandbox Provider\n *\n * Deploys code as Vercel serverless functions and executes commands\n * via HTTP invocation. Stateless — no persistent filesystem, no\n * interactive shell, no long-running processes.\n *\n * @see https://vercel.com/docs/rest-api\n */\n\nimport type { RequestContext } from '@mastra/core/di';\nimport type {\n SandboxInfo,\n CommandResult,\n ExecuteCommandOptions,\n MastraSandboxOptions,\n ProviderStatus,\n InstructionsOption,\n} from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { getExecutorSource } from '../executor';\n\nconst LOG_PREFIX = '[VercelSandbox]';\n\nconst VERCEL_API_BASE = 'https://api.vercel.com';\n\n/**\n * Shell-quote an argument for safe interpolation into a shell command string.\n * Mirrors the implementation in packages/core/src/workspace/sandbox/utils.ts\n * which is not publicly exported.\n */\nfunction shellQuote(arg: string): string {\n if (/^[a-zA-Z0-9._\\-\\/=:@]+$/.test(arg)) return arg;\n return `'${arg.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n// =============================================================================\n// Options\n// =============================================================================\n\nexport interface VercelSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Vercel API token. Falls back to VERCEL_TOKEN env var. */\n token?: string;\n /** Vercel team ID for team-scoped deployments. */\n teamId?: string;\n /** Existing Vercel project name. Auto-generated if omitted. */\n projectName?: string;\n /** Deployment regions. @default ['iad1'] */\n regions?: string[];\n /** Function max duration in seconds. @default 60 */\n maxDuration?: number;\n /** Function memory in MB. @default 1024 */\n memory?: number;\n /** Environment variables baked into the deployed function. */\n env?: Record<string, string>;\n /** Per-invocation command timeout in ms. @default 55000 */\n commandTimeout?: number;\n /**\n * Custom instructions that override the default instructions\n * returned by `getInstructions()`.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\nexport class VercelSandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'VercelSandbox';\n readonly provider = 'vercel';\n status: ProviderStatus = 'pending';\n\n private readonly _token: string;\n private readonly _teamId?: string;\n private readonly _projectName?: string;\n private readonly _regions: string[];\n private readonly _maxDuration: number;\n private readonly _memory: number;\n private readonly _env: Record<string, string>;\n private readonly _commandTimeout: number;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _secret: string;\n\n private _deploymentUrl: string | null = null;\n private _deploymentId: string | null = null;\n private _protectionBypass: string | null = null;\n private _createdAt: Date | null = null;\n\n constructor(options: VercelSandboxOptions = {}) {\n super({ name: 'VercelSandbox' });\n\n this.id = `vercel-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n this._token = options.token || process.env.VERCEL_TOKEN || '';\n this._teamId = options.teamId;\n this._projectName = options.projectName;\n this._regions = options.regions ?? ['iad1'];\n this._maxDuration = options.maxDuration ?? 60;\n this._memory = options.memory ?? 1024;\n this._env = options.env ?? {};\n this._commandTimeout = options.commandTimeout ?? 55_000;\n this._instructionsOverride = options.instructions;\n this._secret = crypto.randomUUID();\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async start(): Promise<void> {\n if (this._deploymentUrl) {\n return;\n }\n\n if (!this._token) {\n throw new Error(`${LOG_PREFIX} Missing Vercel API token. Set VERCEL_TOKEN env var or pass token option.`);\n }\n\n // Clean up any stale deployment from a previous stop() → start() cycle.\n // Without this, the old _deploymentId is overwritten and that deployment leaks.\n if (this._deploymentId) {\n this.logger.debug(`${LOG_PREFIX} Cleaning up stale deployment ${this._deploymentId} before restarting...`);\n try {\n const resp = await this._vercelFetch(`/v13/deployments/${this._deploymentId}`, { method: 'DELETE' });\n if (!resp.ok && resp.status !== 404) {\n this.logger.warn(`${LOG_PREFIX} Failed to delete stale deployment: ${resp.status}`);\n }\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Error deleting stale deployment:`, error);\n }\n this._deploymentId = null;\n }\n\n this.logger.debug(`${LOG_PREFIX} Deploying executor function...`);\n\n const vercelJson = JSON.stringify({\n functions: {\n 'api/execute.js': {\n memory: this._memory,\n maxDuration: this._maxDuration,\n },\n },\n regions: this._regions,\n });\n\n // Create the deployment\n const deploymentBody: Record<string, unknown> = {\n name: this._projectName ?? `mastra-sandbox-${this.id}`,\n files: [\n {\n file: 'api/execute.js',\n data: getExecutorSource(this._secret, this._env),\n },\n {\n file: 'vercel.json',\n data: vercelJson,\n },\n ],\n projectSettings: {\n framework: null,\n },\n target: 'production',\n };\n\n const createResp = await this._vercelFetch('/v13/deployments', {\n method: 'POST',\n body: JSON.stringify(deploymentBody),\n });\n\n if (!createResp.ok) {\n const errorBody = await createResp.text();\n throw new Error(`${LOG_PREFIX} Failed to create deployment: ${createResp.status} ${errorBody}`);\n }\n\n const deployment = (await createResp.json()) as { id: string; url: string; readyState: string; projectId?: string };\n this._deploymentId = deployment.id;\n\n this.logger.debug(`${LOG_PREFIX} Deployment created: ${deployment.id}, polling for READY...`);\n\n // Poll until ready\n const maxWaitMs = 120_000;\n const pollIntervalMs = 3_000;\n const deadline = Date.now() + maxWaitMs;\n\n while (Date.now() < deadline) {\n const statusResp = await this._vercelFetch(`/v13/deployments/${deployment.id}`);\n if (!statusResp.ok) {\n throw new Error(`${LOG_PREFIX} Failed to check deployment status: ${statusResp.status}`);\n }\n\n const statusBody = (await statusResp.json()) as { readyState: string; url: string };\n\n if (statusBody.readyState === 'READY') {\n this._deploymentUrl = `https://${statusBody.url}`;\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Deployment ready: ${this._deploymentUrl}`);\n\n // Acquire a deployment protection bypass token.\n // Pro/Enterprise teams have Deployment Protection enabled by default,\n // which intercepts HTTP requests with an SSO login page before they\n // reach the serverless function. The bypass token lets us skip that.\n if (deployment.projectId) {\n try {\n this._protectionBypass = await this._acquireProtectionBypass(deployment.projectId);\n } catch {\n // Non-fatal — if the project has no deployment protection, this is unnecessary.\n }\n }\n\n // Warm-up ping\n try {\n await fetch(`${this._deploymentUrl}/api/execute`, {\n method: 'POST',\n headers: this._executorHeaders(),\n body: JSON.stringify({ command: 'echo', args: ['warm'] }),\n });\n } catch {\n // Warm-up failure is non-fatal\n }\n\n return;\n }\n\n if (statusBody.readyState === 'ERROR' || statusBody.readyState === 'CANCELED') {\n throw new Error(`${LOG_PREFIX} Deployment failed with state: ${statusBody.readyState}`);\n }\n\n await new Promise(resolve => setTimeout(resolve, pollIntervalMs));\n }\n\n throw new Error(`${LOG_PREFIX} Deployment timed out after ${maxWaitMs}ms`);\n }\n\n async stop(): Promise<void> {\n // Only clear the URL (disconnects from the deployment) but keep\n // _deploymentId so a subsequent destroy() can still clean up the\n // cloud resource. Clearing both would make destroy() a no-op and\n // leak the deployment.\n this._deploymentUrl = null;\n }\n\n async destroy(): Promise<void> {\n if (this._deploymentId) {\n try {\n const resp = await this._vercelFetch(`/v13/deployments/${this._deploymentId}`, {\n method: 'DELETE',\n });\n if (!resp.ok) {\n // 404 means the deployment is already gone — that's fine.\n // Other status codes indicate infrastructure issues (auth, network)\n // and should be surfaced more visibly.\n if (resp.status === 404) {\n this.logger.debug(`${LOG_PREFIX} Deployment already deleted (404)`);\n } else {\n this.logger.warn(`${LOG_PREFIX} Failed to delete deployment: ${resp.status}`);\n }\n }\n } catch (error) {\n // Network-level failure — warn rather than debug so it's visible\n this.logger.warn(`${LOG_PREFIX} Error deleting deployment:`, error);\n }\n this._deploymentId = null;\n }\n this._deploymentUrl = null;\n this._protectionBypass = null;\n }\n\n // ---------------------------------------------------------------------------\n // Command Execution\n // ---------------------------------------------------------------------------\n\n async executeCommand(command: string, args?: string[], options?: ExecuteCommandOptions): Promise<CommandResult> {\n await this.ensureRunning();\n\n if (!this._deploymentUrl) {\n throw new SandboxNotReadyError(this.id);\n }\n\n const fullCommand = args?.length ? `${command} ${args.map(a => shellQuote(a)).join(' ')}` : command;\n this.logger.debug(`${LOG_PREFIX} Executing: ${fullCommand}`);\n\n const body = {\n command,\n args: args ?? [],\n env: options?.env ?? {},\n cwd: options?.cwd ?? '/tmp',\n timeout: options?.timeout ?? this._commandTimeout,\n };\n\n const maxRetries = 2;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const resp = await fetch(`${this._deploymentUrl}/api/execute`, {\n method: 'POST',\n headers: this._executorHeaders(),\n body: JSON.stringify(body),\n signal: options?.abortSignal,\n });\n\n // Retry on transient errors\n if ((resp.status === 429 || resp.status === 502 || resp.status === 503) && attempt < maxRetries) {\n this.logger.debug(`${LOG_PREFIX} Retryable status ${resp.status}, attempt ${attempt + 1}/${maxRetries}`);\n await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));\n continue;\n }\n\n // Gateway timeout → timedOut\n if (resp.status === 504) {\n return {\n command: fullCommand,\n args,\n success: false,\n exitCode: 124,\n stdout: '',\n stderr: 'Function execution timed out (504 Gateway Timeout)',\n executionTimeMs: options?.timeout ?? this._commandTimeout,\n timedOut: true,\n };\n }\n\n if (!resp.ok) {\n const errorText = await resp.text();\n throw new Error(`${LOG_PREFIX} Execute failed: ${resp.status} ${errorText}`);\n }\n\n const result = (await resp.json()) as {\n success: boolean;\n exitCode: number;\n stdout: string;\n stderr: string;\n executionTimeMs: number;\n timedOut: boolean;\n };\n\n // Stream callbacks\n if (options?.onStdout && result.stdout) {\n options.onStdout(result.stdout);\n }\n if (options?.onStderr && result.stderr) {\n options.onStderr(result.stderr);\n }\n\n return {\n command: fullCommand,\n args,\n success: result.success,\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n executionTimeMs: result.executionTimeMs,\n timedOut: result.timedOut,\n };\n } catch (error) {\n if (error instanceof DOMException && error.name === 'AbortError') {\n throw error;\n }\n lastError = error as Error;\n if (attempt < maxRetries) {\n this.logger.debug(`${LOG_PREFIX} Request error, attempt ${attempt + 1}/${maxRetries}:`, error);\n await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));\n continue;\n }\n }\n }\n\n throw lastError ?? new Error(`${LOG_PREFIX} executeCommand failed after retries`);\n }\n\n // ---------------------------------------------------------------------------\n // Info & Instructions\n // ---------------------------------------------------------------------------\n\n // Matches the resolveInstructions pattern in packages/core/src/workspace/utils.ts\n getInstructions(opts?: { requestContext?: RequestContext }): string {\n if (this._instructionsOverride === undefined) return this._getDefaultInstructions();\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n const defaultInstructions = this._getDefaultInstructions();\n return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });\n }\n\n private _getDefaultInstructions(): string {\n return [\n 'Vercel serverless sandbox.',\n 'Limitations:',\n '- Stateless: no persistent filesystem between invocations.',\n '- No interactive shell or streaming stdin.',\n '- No long-running or background processes.',\n `- Maximum execution time: ${this._maxDuration} seconds.`,\n '- Only /tmp is writable (ephemeral, cleared between invocations).',\n '- Shell commands (pipes, builtins) are supported via /bin/sh -c.',\n ].join('\\n');\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 deploymentId: this._deploymentId,\n deploymentUrl: this._deploymentUrl,\n regions: this._regions,\n maxDuration: this._maxDuration,\n memory: this._memory,\n },\n };\n }\n\n // ---------------------------------------------------------------------------\n // Private Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Fetch an existing protection bypass token for the project, or create one\n * if none exists. Returns the token string, or null if acquisition fails.\n */\n private async _acquireProtectionBypass(projectId: string): Promise<string | null> {\n // 1. Check if the project already has a bypass token.\n const projResp = await this._vercelFetch(`/v9/projects/${projectId}`);\n if (projResp.ok) {\n const project = (await projResp.json()) as {\n protectionBypass?: Record<string, unknown>;\n };\n const existing = project.protectionBypass ? Object.keys(project.protectionBypass)[0] : undefined;\n if (existing) {\n this.logger.debug(`${LOG_PREFIX} Using existing protection bypass token`);\n return existing;\n }\n }\n\n // 2. No token exists — create one via the dedicated endpoint.\n this.logger.debug(`${LOG_PREFIX} Creating protection bypass token...`);\n const createResp = await this._vercelFetch(`/v1/projects/${projectId}/protection-bypass`, {\n method: 'PATCH',\n body: JSON.stringify({}),\n });\n if (createResp.ok) {\n const result = (await createResp.json()) as {\n protectionBypass?: Record<string, unknown>;\n };\n const created = result.protectionBypass ? Object.keys(result.protectionBypass)[0] : undefined;\n if (created) {\n this.logger.debug(`${LOG_PREFIX} Protection bypass token created`);\n return created;\n }\n }\n\n this.logger.debug(`${LOG_PREFIX} Could not acquire protection bypass token (project may not require it)`);\n return null;\n }\n\n private _executorHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._secret}`,\n };\n if (this._protectionBypass) {\n headers['x-vercel-protection-bypass'] = this._protectionBypass;\n }\n return headers;\n }\n\n private async _vercelFetch(path: string, options: RequestInit = {}): Promise<Response> {\n const url = new URL(path, VERCEL_API_BASE);\n if (this._teamId) {\n url.searchParams.set('teamId', this._teamId);\n }\n\n return fetch(url.toString(), {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this._token}`,\n ...((options.headers as Record<string, string>) ?? {}),\n },\n });\n }\n}\n","/**\n * Vercel sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { vercelSandboxProvider } from '@mastra/vercel';\n *\n * const editor = new MastraEditor({\n * sandboxes: [vercelSandboxProvider],\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { VercelSandbox } from './sandbox';\n\n/**\n * Serializable subset of VercelSandboxOptions for editor storage.\n */\ninterface VercelProviderConfig {\n token?: string;\n teamId?: string;\n projectName?: string;\n regions?: string[];\n maxDuration?: number;\n memory?: number;\n env?: Record<string, string>;\n commandTimeout?: number;\n}\n\nexport const vercelSandboxProvider: SandboxProvider<VercelProviderConfig> = {\n id: 'vercel',\n name: 'Vercel Sandbox',\n description: 'Serverless sandbox powered by Vercel Functions',\n configSchema: {\n type: 'object',\n properties: {\n token: { type: 'string', description: 'Vercel API token' },\n teamId: { type: 'string', description: 'Vercel team ID' },\n projectName: { type: 'string', description: 'Existing Vercel project name' },\n regions: {\n type: 'array',\n description: 'Deployment regions',\n items: { type: 'string' },\n default: ['iad1'],\n },\n maxDuration: { type: 'number', description: 'Function max duration in seconds', default: 60 },\n memory: { type: 'number', description: 'Function memory in MB', default: 1024 },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n commandTimeout: { type: 'number', description: 'Per-invocation timeout in ms', default: 55000 },\n },\n },\n createSandbox: config => new VercelSandbox(config),\n};\n"]}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Vercel sandbox provider descriptor for MastraEditor.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { vercelSandboxProvider } from '@mastra/vercel';
7
+ *
8
+ * const editor = new MastraEditor({
9
+ * sandboxes: [vercelSandboxProvider],
10
+ * });
11
+ * ```
12
+ */
13
+ import type { SandboxProvider } from '@mastra/core/editor';
14
+ /**
15
+ * Serializable subset of VercelSandboxOptions for editor storage.
16
+ */
17
+ interface VercelProviderConfig {
18
+ token?: string;
19
+ teamId?: string;
20
+ projectName?: string;
21
+ regions?: string[];
22
+ maxDuration?: number;
23
+ memory?: number;
24
+ env?: Record<string, string>;
25
+ commandTimeout?: number;
26
+ }
27
+ export declare const vercelSandboxProvider: SandboxProvider<VercelProviderConfig>;
28
+ export {};
29
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D;;GAEG;AACH,UAAU,oBAAoB;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,qBAAqB,EAAE,eAAe,CAAC,oBAAoB,CA2BvE,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Vercel Sandbox Provider
3
+ *
4
+ * Deploys code as Vercel serverless functions and executes commands
5
+ * via HTTP invocation. Stateless — no persistent filesystem, no
6
+ * interactive shell, no long-running processes.
7
+ *
8
+ * @see https://vercel.com/docs/rest-api
9
+ */
10
+ import type { RequestContext } from '@mastra/core/di';
11
+ import type { SandboxInfo, CommandResult, ExecuteCommandOptions, MastraSandboxOptions, ProviderStatus, InstructionsOption } from '@mastra/core/workspace';
12
+ import { MastraSandbox } from '@mastra/core/workspace';
13
+ export interface VercelSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {
14
+ /** Vercel API token. Falls back to VERCEL_TOKEN env var. */
15
+ token?: string;
16
+ /** Vercel team ID for team-scoped deployments. */
17
+ teamId?: string;
18
+ /** Existing Vercel project name. Auto-generated if omitted. */
19
+ projectName?: string;
20
+ /** Deployment regions. @default ['iad1'] */
21
+ regions?: string[];
22
+ /** Function max duration in seconds. @default 60 */
23
+ maxDuration?: number;
24
+ /** Function memory in MB. @default 1024 */
25
+ memory?: number;
26
+ /** Environment variables baked into the deployed function. */
27
+ env?: Record<string, string>;
28
+ /** Per-invocation command timeout in ms. @default 55000 */
29
+ commandTimeout?: number;
30
+ /**
31
+ * Custom instructions that override the default instructions
32
+ * returned by `getInstructions()`.
33
+ */
34
+ instructions?: InstructionsOption;
35
+ }
36
+ export declare class VercelSandbox extends MastraSandbox {
37
+ readonly id: string;
38
+ readonly name = "VercelSandbox";
39
+ readonly provider = "vercel";
40
+ status: ProviderStatus;
41
+ private readonly _token;
42
+ private readonly _teamId?;
43
+ private readonly _projectName?;
44
+ private readonly _regions;
45
+ private readonly _maxDuration;
46
+ private readonly _memory;
47
+ private readonly _env;
48
+ private readonly _commandTimeout;
49
+ private readonly _instructionsOverride?;
50
+ private readonly _secret;
51
+ private _deploymentUrl;
52
+ private _deploymentId;
53
+ private _protectionBypass;
54
+ private _createdAt;
55
+ constructor(options?: VercelSandboxOptions);
56
+ start(): Promise<void>;
57
+ stop(): Promise<void>;
58
+ destroy(): Promise<void>;
59
+ executeCommand(command: string, args?: string[], options?: ExecuteCommandOptions): Promise<CommandResult>;
60
+ getInstructions(opts?: {
61
+ requestContext?: RequestContext;
62
+ }): string;
63
+ private _getDefaultInstructions;
64
+ getInfo(): Promise<SandboxInfo>;
65
+ /**
66
+ * Fetch an existing protection bypass token for the project, or create one
67
+ * if none exists. Returns the token string, or null if acquisition fails.
68
+ */
69
+ private _acquireProtectionBypass;
70
+ private _executorHeaders;
71
+ private _vercelFetch;
72
+ }
73
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sandbox/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAwB,MAAM,wBAAwB,CAAC;AAqB7E,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC;IACnF,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAMD,qBAAa,aAAc,SAAQ,aAAa;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,QAAQ,YAAY;IAC7B,MAAM,EAAE,cAAc,CAAa;IAEnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAqB;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,UAAU,CAAqB;gBAE3B,OAAO,GAAE,oBAAyB;IAoBxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA4HtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BxB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,aAAa,CAAC;IAwG/G,eAAe,CAAC,IAAI,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,MAAM;IAOnE,OAAO,CAAC,uBAAuB;IAazB,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC;IAqBrC;;;OAGG;YACW,wBAAwB;IAmCtC,OAAO,CAAC,gBAAgB;YAWV,YAAY;CAe3B"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@mastra/vercel",
3
+ "version": "0.0.0",
4
+ "description": "Vercel serverless 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
+ "devDependencies": {
34
+ "@internal/lint": "workspace:*",
35
+ "@internal/types-builder": "workspace:*",
36
+ "@mastra/core": "workspace:*",
37
+ "@types/node": "22.19.15",
38
+ "@vitest/coverage-v8": "catalog:",
39
+ "@vitest/ui": "catalog:",
40
+ "dotenv": "^17.3.1",
41
+ "eslint": "^9.39.4",
42
+ "tsup": "^8.5.1",
43
+ "typescript": "catalog:",
44
+ "vitest": "catalog:"
45
+ },
46
+ "peerDependencies": {
47
+ "@mastra/core": ">=1.12.0-0 <2.0.0-0"
48
+ },
49
+ "files": [
50
+ "dist",
51
+ "CHANGELOG.md"
52
+ ],
53
+ "homepage": "https://mastra.ai",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "git+https://github.com/mastra-ai/mastra.git",
57
+ "directory": "workspaces/vercel"
58
+ },
59
+ "bugs": {
60
+ "url": "https://github.com/mastra-ai/mastra/issues"
61
+ },
62
+ "engines": {
63
+ "node": ">=22.13.0"
64
+ }
65
+ }