@mastra/vercel 0.1.0 → 0.2.0-alpha.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 +27 -0
- package/dist/index.cjs +384 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +383 -2
- package/dist/index.js.map +1 -1
- package/dist/microvm/index.d.ts +118 -0
- package/dist/microvm/index.d.ts.map +1 -0
- package/dist/microvm/process-manager.d.ts +25 -0
- package/dist/microvm/process-manager.d.ts.map +1 -0
- package/dist/microvm-provider.d.ts +29 -0
- package/dist/microvm-provider.d.ts.map +1 -0
- package/package.json +12 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @mastra/vercel
|
|
2
2
|
|
|
3
|
+
## 0.2.0-alpha.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added `VercelMicroVMSandbox`, a new workspace sandbox provider backed by the [Vercel Sandbox](https://vercel.com/docs/vercel-sandbox) ephemeral Firecracker MicroVM product (`@vercel/sandbox`). It provides a persistent in-session filesystem, `sudo` access, exposed ports, command execution, and background processes via the process manager. This is distinct from the existing `VercelSandbox`, which runs commands as stateless Vercel serverless Functions and is unchanged. Also exports `VercelMicroVMProcessManager` and the `vercelMicroVMSandboxProvider` editor descriptor (provider id `vercel-microvm`). Closes #16704. ([#17332](https://github.com/mastra-ai/mastra/pull/17332))
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { Workspace } from '@mastra/core/workspace';
|
|
11
|
+
import { VercelMicroVMSandbox } from '@mastra/vercel';
|
|
12
|
+
|
|
13
|
+
const workspace = new Workspace({
|
|
14
|
+
sandbox: new VercelMicroVMSandbox({
|
|
15
|
+
runtime: 'node24',
|
|
16
|
+
timeout: 600_000,
|
|
17
|
+
ports: [3000],
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await workspace.init();
|
|
22
|
+
const result = await workspace.sandbox.executeCommand('node', ['--version']);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [[`8ace89d`](https://github.com/mastra-ai/mastra/commit/8ace89df77f762e622d3b9f7f65ad7524350d050), [`fa63872`](https://github.com/mastra-ai/mastra/commit/fa6387280954e6b667bec5714b55ba082bc627ff), [`f07b646`](https://github.com/mastra-ai/mastra/commit/f07b64604ab7d25391179790b7fd4823df9e2dff), [`d8838ae`](https://github.com/mastra-ai/mastra/commit/d8838ae80b69780361693d27098f7f6684af12fe), [`40f9297`](https://github.com/mastra-ai/mastra/commit/40f9297003b921c62373d3e8d3a4bda76c9f6de3), [`0f0d1ba`](https://github.com/mastra-ai/mastra/commit/0f0d1ba67bfcb2204e571401662f1eceefc03357), [`8c31bcd`](https://github.com/mastra-ai/mastra/commit/8c31bcdb00e597880d5939b1b7d7566fbe5dacae), [`95b14cd`](https://github.com/mastra-ai/mastra/commit/95b14cdd820e86d97ac05fe568424c513a252e31), [`aa36be2`](https://github.com/mastra-ai/mastra/commit/aa36be23aa513b7dc53cb8ca16b7fab8f20e43ad), [`212c635`](https://github.com/mastra-ai/mastra/commit/212c635203e61d036ab41db8ff86c3893dc795b3), [`d8838ae`](https://github.com/mastra-ai/mastra/commit/d8838ae80b69780361693d27098f7f6684af12fe), [`9aa5a73`](https://github.com/mastra-ai/mastra/commit/9aa5a73e7e110f6e9365eec69364a33d5f03bb56), [`f73c789`](https://github.com/mastra-ai/mastra/commit/f73c789e8ef21561580395d2c410119cab5848c8), [`8bd16da`](https://github.com/mastra-ai/mastra/commit/8bd16da73a4cb874d739373643dbd6a6e7f88684), [`c8630f8`](https://github.com/mastra-ai/mastra/commit/c8630f80d4f40cb5d22e60ab162b618b1907167a), [`47f71dc`](https://github.com/mastra-ai/mastra/commit/47f71dc6fbcbd12d71e21a979e676e20a02bd77d), [`50ceae2`](https://github.com/mastra-ai/mastra/commit/50ceae270878e2f8fb2b2c6c2faab09df0007c8a), [`8cdde58`](https://github.com/mastra-ai/mastra/commit/8cdde5875bbba6702d9df226f2b20232b8d75d6c), [`847ff1e`](https://github.com/mastra-ai/mastra/commit/847ff1e0d94368d94b2e173e4e0908e115568ef3), [`259d409`](https://github.com/mastra-ai/mastra/commit/259d409a514174299dbde1ff5e1121209b3ba850), [`9e16c68`](https://github.com/mastra-ai/mastra/commit/9e16c6818b6485ccb43df28aba6f3a2219d28662), [`cefca33`](https://github.com/mastra-ai/mastra/commit/cefca33ae666e69810c935fedf95a929c173d1d7), [`d00e8c5`](https://github.com/mastra-ai/mastra/commit/d00e8c50daebe5bce5bf2f48bde39c86fc3d2fe4), [`36fa7e2`](https://github.com/mastra-ai/mastra/commit/36fa7e24d14e58a1eb46147097b32f583e5b8775), [`87e9774`](https://github.com/mastra-ai/mastra/commit/87e97741c1e493cd6d62f478eb810b49bda4d57c), [`65a72e7`](https://github.com/mastra-ai/mastra/commit/65a72e70c25eedea8ff985a6624b96be2850236b), [`0f77241`](https://github.com/mastra-ai/mastra/commit/0f7724108806703799a8ba80ad0f09414afd5066), [`92ff509`](https://github.com/mastra-ai/mastra/commit/92ff5098ef8a990438ca038077021a5f7541ec1d), [`3fce5e7`](https://github.com/mastra-ai/mastra/commit/3fce5e70d011d289043e75003ef3336ed4aa43c3), [`a763592`](https://github.com/mastra-ai/mastra/commit/a763592c3db46963ef1011cfe16fe372816e775e), [`80c7737`](https://github.com/mastra-ai/mastra/commit/80c7737e32d7917b5f356957d67c169d01744fd3), [`3f1cf47`](https://github.com/mastra-ai/mastra/commit/3f1cf476f74c1e4cc2df908837e05853a5347e31)]:
|
|
28
|
+
- @mastra/core@1.38.0-alpha.3
|
|
29
|
+
|
|
3
30
|
## 0.1.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var workspace = require('@mastra/core/workspace');
|
|
4
|
+
var sandbox = require('@vercel/sandbox');
|
|
4
5
|
|
|
5
6
|
// src/sandbox/index.ts
|
|
6
7
|
|
|
@@ -446,8 +447,391 @@ var vercelSandboxProvider = {
|
|
|
446
447
|
},
|
|
447
448
|
createSandbox: (config) => new VercelSandbox(config)
|
|
448
449
|
};
|
|
450
|
+
var VercelMicroVMProcessHandle = class extends workspace.ProcessHandle {
|
|
451
|
+
pid;
|
|
452
|
+
_command;
|
|
453
|
+
_startTime;
|
|
454
|
+
_timeout;
|
|
455
|
+
_exitCode;
|
|
456
|
+
_waitPromise = null;
|
|
457
|
+
_streamingPromise = null;
|
|
458
|
+
_killed = false;
|
|
459
|
+
constructor(command, startTime, options) {
|
|
460
|
+
super(options);
|
|
461
|
+
this.pid = command.cmdId;
|
|
462
|
+
this._command = command;
|
|
463
|
+
this._startTime = startTime;
|
|
464
|
+
this._timeout = options?.timeout;
|
|
465
|
+
}
|
|
466
|
+
get exitCode() {
|
|
467
|
+
return this._exitCode;
|
|
468
|
+
}
|
|
469
|
+
/** @internal Set by the process manager after streaming starts. */
|
|
470
|
+
set streamingPromise(p) {
|
|
471
|
+
this._streamingPromise = p;
|
|
472
|
+
}
|
|
473
|
+
async wait() {
|
|
474
|
+
if (!this._waitPromise) {
|
|
475
|
+
this._waitPromise = this._doWait();
|
|
476
|
+
}
|
|
477
|
+
return this._waitPromise;
|
|
478
|
+
}
|
|
479
|
+
async _doWait() {
|
|
480
|
+
const finishedPromise = this._command.wait().then((finished) => {
|
|
481
|
+
if (this._exitCode === void 0) this._exitCode = finished.exitCode;
|
|
482
|
+
}).catch(() => {
|
|
483
|
+
if (this._exitCode === void 0) this._exitCode = 1;
|
|
484
|
+
});
|
|
485
|
+
if (this._timeout) {
|
|
486
|
+
let timeoutId;
|
|
487
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
488
|
+
timeoutId = setTimeout(() => resolve("timeout"), this._timeout);
|
|
489
|
+
});
|
|
490
|
+
const outcome = await Promise.race([finishedPromise.then(() => "done"), timeoutPromise]);
|
|
491
|
+
clearTimeout(timeoutId);
|
|
492
|
+
if (outcome === "timeout") {
|
|
493
|
+
await this.kill();
|
|
494
|
+
this._exitCode = 124;
|
|
495
|
+
await this._streamingPromise?.catch(() => {
|
|
496
|
+
});
|
|
497
|
+
return {
|
|
498
|
+
success: false,
|
|
499
|
+
exitCode: 124,
|
|
500
|
+
stdout: this.stdout,
|
|
501
|
+
stderr: this.stderr || `Command timed out after ${this._timeout}ms`,
|
|
502
|
+
executionTimeMs: Date.now() - this._startTime,
|
|
503
|
+
killed: true,
|
|
504
|
+
timedOut: true
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
} else {
|
|
508
|
+
await finishedPromise;
|
|
509
|
+
}
|
|
510
|
+
await this._streamingPromise?.catch(() => {
|
|
511
|
+
});
|
|
512
|
+
if (this._killed) {
|
|
513
|
+
return {
|
|
514
|
+
success: false,
|
|
515
|
+
exitCode: this._exitCode ?? 137,
|
|
516
|
+
stdout: this.stdout,
|
|
517
|
+
stderr: this.stderr,
|
|
518
|
+
executionTimeMs: Date.now() - this._startTime,
|
|
519
|
+
killed: true,
|
|
520
|
+
timedOut: false
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
success: this._exitCode === 0,
|
|
525
|
+
exitCode: this._exitCode ?? 1,
|
|
526
|
+
stdout: this.stdout,
|
|
527
|
+
stderr: this.stderr,
|
|
528
|
+
executionTimeMs: Date.now() - this._startTime
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
async kill() {
|
|
532
|
+
if (this._exitCode !== void 0 && !this._killed) return false;
|
|
533
|
+
this._killed = true;
|
|
534
|
+
if (this._exitCode === void 0) this._exitCode = 137;
|
|
535
|
+
try {
|
|
536
|
+
await this._command.kill();
|
|
537
|
+
} catch {
|
|
538
|
+
}
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
async sendStdin(_data) {
|
|
542
|
+
throw new Error("VercelMicroVMSandbox does not support sending stdin to running processes.");
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
var VercelMicroVMProcessManager = class extends workspace.SandboxProcessManager {
|
|
546
|
+
async spawn(command, options = {}) {
|
|
547
|
+
const mergedEnv = { ...this.env, ...options.env };
|
|
548
|
+
const env = Object.fromEntries(
|
|
549
|
+
Object.entries(mergedEnv).filter((entry) => entry[1] !== void 0)
|
|
550
|
+
);
|
|
551
|
+
const cmd = await this.sandbox.sandbox.runCommand({
|
|
552
|
+
cmd: "sh",
|
|
553
|
+
args: ["-c", command],
|
|
554
|
+
...options.cwd ? { cwd: options.cwd } : {},
|
|
555
|
+
...Object.keys(env).length ? { env } : {},
|
|
556
|
+
detached: true
|
|
557
|
+
});
|
|
558
|
+
const handle = new VercelMicroVMProcessHandle(cmd, Date.now(), options);
|
|
559
|
+
const streamingPromise = (async () => {
|
|
560
|
+
for await (const log of cmd.logs()) {
|
|
561
|
+
if (log.stream === "stdout") handle.emitStdout(log.data);
|
|
562
|
+
else handle.emitStderr(log.data);
|
|
563
|
+
}
|
|
564
|
+
})().catch(() => {
|
|
565
|
+
});
|
|
566
|
+
handle.streamingPromise = streamingPromise;
|
|
567
|
+
this._tracked.set(handle.pid, handle);
|
|
568
|
+
return handle;
|
|
569
|
+
}
|
|
570
|
+
async list() {
|
|
571
|
+
const result = [];
|
|
572
|
+
for (const [pid, handle] of this._tracked) {
|
|
573
|
+
result.push({
|
|
574
|
+
pid,
|
|
575
|
+
command: handle.command,
|
|
576
|
+
running: handle.exitCode === void 0,
|
|
577
|
+
exitCode: handle.exitCode
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
return result;
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
// src/microvm/index.ts
|
|
585
|
+
var LOG_PREFIX2 = "[VercelMicroVMSandbox]";
|
|
586
|
+
var VercelMicroVMSandbox = class extends workspace.MastraSandbox {
|
|
587
|
+
id;
|
|
588
|
+
name = "VercelMicroVMSandbox";
|
|
589
|
+
provider = "vercel-microvm";
|
|
590
|
+
status = "pending";
|
|
591
|
+
_sandbox = null;
|
|
592
|
+
_createdAt = null;
|
|
593
|
+
_sandboxName;
|
|
594
|
+
_token;
|
|
595
|
+
_teamId;
|
|
596
|
+
_projectId;
|
|
597
|
+
_runtime;
|
|
598
|
+
_timeout;
|
|
599
|
+
_vcpus;
|
|
600
|
+
_ports;
|
|
601
|
+
_env;
|
|
602
|
+
_metadata;
|
|
603
|
+
_instructionsOverride;
|
|
604
|
+
constructor(options = {}) {
|
|
605
|
+
super({
|
|
606
|
+
...options,
|
|
607
|
+
name: "VercelMicroVMSandbox",
|
|
608
|
+
processes: new VercelMicroVMProcessManager({ env: options.env ?? {} })
|
|
609
|
+
});
|
|
610
|
+
this.id = options.id ?? `vercel-microvm-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
611
|
+
this._sandboxName = options.sandboxName;
|
|
612
|
+
this._token = options.token ?? process.env.VERCEL_TOKEN;
|
|
613
|
+
this._teamId = options.teamId ?? process.env.VERCEL_TEAM_ID;
|
|
614
|
+
this._projectId = options.projectId ?? process.env.VERCEL_PROJECT_ID;
|
|
615
|
+
this._runtime = options.runtime ?? "node24";
|
|
616
|
+
this._timeout = options.timeout ?? 3e5;
|
|
617
|
+
this._vcpus = options.resources?.vcpus;
|
|
618
|
+
this._ports = options.ports;
|
|
619
|
+
this._env = options.env ?? {};
|
|
620
|
+
this._metadata = options.metadata ?? {};
|
|
621
|
+
this._instructionsOverride = options.instructions;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* The underlying `@vercel/sandbox` instance.
|
|
625
|
+
* Throws if the sandbox has not been started yet.
|
|
626
|
+
*/
|
|
627
|
+
get sandbox() {
|
|
628
|
+
if (!this._sandbox) {
|
|
629
|
+
throw new workspace.SandboxNotReadyError(this.id);
|
|
630
|
+
}
|
|
631
|
+
return this._sandbox;
|
|
632
|
+
}
|
|
633
|
+
// ---------------------------------------------------------------------------
|
|
634
|
+
// Lifecycle
|
|
635
|
+
// ---------------------------------------------------------------------------
|
|
636
|
+
async start() {
|
|
637
|
+
if (this._sandbox) {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
const hasExplicitCreds = Boolean(this._token || this._teamId || this._projectId);
|
|
641
|
+
if (hasExplicitCreds && !(this._token && this._teamId && this._projectId)) {
|
|
642
|
+
throw new Error(
|
|
643
|
+
`${LOG_PREFIX2} Incomplete credentials. Provide token, teamId, and projectId together (or the VERCEL_TOKEN, VERCEL_TEAM_ID, and VERCEL_PROJECT_ID env vars), or omit all three to use the VERCEL_OIDC_TOKEN.`
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
this.logger.debug(`${LOG_PREFIX2} Creating sandbox...`, { runtime: this._runtime, timeout: this._timeout });
|
|
647
|
+
this._sandbox = await sandbox.Sandbox.create({
|
|
648
|
+
...this._sandboxName ? { name: this._sandboxName } : {},
|
|
649
|
+
runtime: this._runtime,
|
|
650
|
+
timeout: this._timeout,
|
|
651
|
+
...this._vcpus ? { resources: { vcpus: this._vcpus } } : {},
|
|
652
|
+
...this._ports?.length ? { ports: this._ports } : {},
|
|
653
|
+
...Object.keys(this._env).length ? { env: this._env } : {},
|
|
654
|
+
...hasExplicitCreds ? { token: this._token, teamId: this._teamId, projectId: this._projectId } : {}
|
|
655
|
+
});
|
|
656
|
+
this._createdAt = /* @__PURE__ */ new Date();
|
|
657
|
+
this.logger.debug(`${LOG_PREFIX2} Sandbox ready: ${this._sandbox.name}`);
|
|
658
|
+
}
|
|
659
|
+
async stop() {
|
|
660
|
+
await this._teardown();
|
|
661
|
+
}
|
|
662
|
+
async destroy() {
|
|
663
|
+
await this._teardown();
|
|
664
|
+
}
|
|
665
|
+
async _teardown() {
|
|
666
|
+
if (!this._sandbox) {
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
try {
|
|
670
|
+
await this._sandbox.stop();
|
|
671
|
+
} catch (error) {
|
|
672
|
+
this.logger.warn(`${LOG_PREFIX2} Error stopping sandbox:`, error);
|
|
673
|
+
}
|
|
674
|
+
this._sandbox = null;
|
|
675
|
+
}
|
|
676
|
+
// ---------------------------------------------------------------------------
|
|
677
|
+
// Command Execution
|
|
678
|
+
// ---------------------------------------------------------------------------
|
|
679
|
+
async executeCommand(command, args, options) {
|
|
680
|
+
await this.ensureRunning();
|
|
681
|
+
const startTime = Date.now();
|
|
682
|
+
const fullCommand = args?.length ? `${command} ${args.join(" ")}` : command;
|
|
683
|
+
this.logger.debug(`${LOG_PREFIX2} Executing: ${fullCommand}`, { cwd: options?.cwd });
|
|
684
|
+
const mergedEnv = { ...this._env, ...options?.env };
|
|
685
|
+
const env = Object.fromEntries(
|
|
686
|
+
Object.entries(mergedEnv).filter((entry) => entry[1] !== void 0)
|
|
687
|
+
);
|
|
688
|
+
let timeoutId;
|
|
689
|
+
const abortController = new AbortController();
|
|
690
|
+
const forwardAbort = () => abortController.abort();
|
|
691
|
+
if (options?.abortSignal) {
|
|
692
|
+
if (options.abortSignal.aborted) abortController.abort();
|
|
693
|
+
else options.abortSignal.addEventListener("abort", forwardAbort, { once: true });
|
|
694
|
+
}
|
|
695
|
+
const signal = abortController.signal;
|
|
696
|
+
const timeoutPromise = options?.timeout ? new Promise((resolve) => {
|
|
697
|
+
timeoutId = setTimeout(() => resolve("timeout"), options.timeout);
|
|
698
|
+
}) : null;
|
|
699
|
+
try {
|
|
700
|
+
const commandPromise = this.sandbox.runCommand({
|
|
701
|
+
cmd: command,
|
|
702
|
+
args: args ?? [],
|
|
703
|
+
...options?.cwd ? { cwd: options.cwd } : {},
|
|
704
|
+
...Object.keys(env).length ? { env } : {},
|
|
705
|
+
signal
|
|
706
|
+
});
|
|
707
|
+
const finished = timeoutPromise ? await Promise.race([commandPromise, timeoutPromise]) : await commandPromise;
|
|
708
|
+
if (finished === "timeout") {
|
|
709
|
+
abortController.abort();
|
|
710
|
+
return {
|
|
711
|
+
command: fullCommand,
|
|
712
|
+
args,
|
|
713
|
+
success: false,
|
|
714
|
+
exitCode: 124,
|
|
715
|
+
stdout: "",
|
|
716
|
+
stderr: `Command timed out after ${options.timeout}ms`,
|
|
717
|
+
executionTimeMs: Date.now() - startTime,
|
|
718
|
+
timedOut: true
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
const [stdout, stderr] = await Promise.all([finished.stdout(), finished.stderr()]);
|
|
722
|
+
if (options?.onStdout && stdout) options.onStdout(stdout);
|
|
723
|
+
if (options?.onStderr && stderr) options.onStderr(stderr);
|
|
724
|
+
return {
|
|
725
|
+
command: fullCommand,
|
|
726
|
+
args,
|
|
727
|
+
success: finished.exitCode === 0,
|
|
728
|
+
exitCode: finished.exitCode,
|
|
729
|
+
stdout,
|
|
730
|
+
stderr,
|
|
731
|
+
executionTimeMs: Date.now() - startTime
|
|
732
|
+
};
|
|
733
|
+
} finally {
|
|
734
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
735
|
+
options?.abortSignal?.removeEventListener("abort", forwardAbort);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
// ---------------------------------------------------------------------------
|
|
739
|
+
// Info & Instructions
|
|
740
|
+
// ---------------------------------------------------------------------------
|
|
741
|
+
getInfo() {
|
|
742
|
+
const domains = {};
|
|
743
|
+
if (this._sandbox && this._ports?.length) {
|
|
744
|
+
for (const port of this._ports) {
|
|
745
|
+
try {
|
|
746
|
+
domains[port] = this._sandbox.domain(port);
|
|
747
|
+
} catch {
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return {
|
|
752
|
+
id: this.id,
|
|
753
|
+
name: this.name,
|
|
754
|
+
provider: this.provider,
|
|
755
|
+
status: this.status,
|
|
756
|
+
createdAt: this._createdAt ?? /* @__PURE__ */ new Date(),
|
|
757
|
+
metadata: {
|
|
758
|
+
...this._metadata,
|
|
759
|
+
sandboxName: this._sandbox?.name,
|
|
760
|
+
runtime: this._runtime,
|
|
761
|
+
timeout: this._timeout,
|
|
762
|
+
...this._vcpus ? { vcpus: this._vcpus } : {},
|
|
763
|
+
...this._ports?.length ? { ports: this._ports, domains } : {}
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
// Matches the resolveInstructions pattern in @mastra/core/workspace.
|
|
768
|
+
getInstructions(opts) {
|
|
769
|
+
if (this._instructionsOverride === void 0) return this._getDefaultInstructions();
|
|
770
|
+
if (typeof this._instructionsOverride === "string") return this._instructionsOverride;
|
|
771
|
+
const defaultInstructions = this._getDefaultInstructions();
|
|
772
|
+
return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });
|
|
773
|
+
}
|
|
774
|
+
_getDefaultInstructions() {
|
|
775
|
+
return [
|
|
776
|
+
"Vercel Sandbox: an ephemeral Firecracker MicroVM running Amazon Linux 2023.",
|
|
777
|
+
`- Runtime: ${this._runtime}. Working directory defaults to /vercel/sandbox.`,
|
|
778
|
+
"- Persistent filesystem within the session; state is lost when the sandbox stops.",
|
|
779
|
+
"- Runs as the vercel-sandbox user with sudo access (install packages via dnf).",
|
|
780
|
+
`- The sandbox auto-terminates after ${Math.round(this._timeout / 1e3)} seconds.`,
|
|
781
|
+
...this._ports?.length ? [`- Exposed ports: ${this._ports.join(", ")} (reachable via public HTTPS domains).`] : [],
|
|
782
|
+
"- Background/long-running processes are supported via the process tools.",
|
|
783
|
+
"- Filesystem mounting (FUSE) is not supported."
|
|
784
|
+
].join("\n");
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
// src/microvm-provider.ts
|
|
789
|
+
var vercelMicroVMSandboxProvider = {
|
|
790
|
+
id: "vercel-microvm",
|
|
791
|
+
name: "Vercel Sandbox (MicroVM)",
|
|
792
|
+
description: "Ephemeral Firecracker MicroVM sandbox powered by Vercel Sandbox",
|
|
793
|
+
configSchema: {
|
|
794
|
+
type: "object",
|
|
795
|
+
properties: {
|
|
796
|
+
token: { type: "string", description: "Vercel API token (falls back to VERCEL_TOKEN; omit to use OIDC)" },
|
|
797
|
+
teamId: { type: "string", description: "Vercel team ID (falls back to VERCEL_TEAM_ID)" },
|
|
798
|
+
projectId: { type: "string", description: "Vercel project ID (falls back to VERCEL_PROJECT_ID)" },
|
|
799
|
+
runtime: {
|
|
800
|
+
type: "string",
|
|
801
|
+
description: "Sandbox runtime",
|
|
802
|
+
enum: ["node24", "node22", "node26", "python3.13"],
|
|
803
|
+
default: "node24"
|
|
804
|
+
},
|
|
805
|
+
timeout: { type: "number", description: "Auto-terminate timeout in milliseconds", default: 3e5 },
|
|
806
|
+
vcpus: { type: "number", description: "Number of vCPUs (2048 MB memory per vCPU)" },
|
|
807
|
+
ports: {
|
|
808
|
+
type: "array",
|
|
809
|
+
description: "Ports to expose (up to 4)",
|
|
810
|
+
items: { type: "number" }
|
|
811
|
+
},
|
|
812
|
+
env: {
|
|
813
|
+
type: "object",
|
|
814
|
+
description: "Environment variables",
|
|
815
|
+
additionalProperties: { type: "string" }
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
},
|
|
819
|
+
createSandbox: (config) => new VercelMicroVMSandbox({
|
|
820
|
+
token: config.token,
|
|
821
|
+
teamId: config.teamId,
|
|
822
|
+
projectId: config.projectId,
|
|
823
|
+
runtime: config.runtime,
|
|
824
|
+
timeout: config.timeout,
|
|
825
|
+
...config.vcpus ? { resources: { vcpus: config.vcpus } } : {},
|
|
826
|
+
ports: config.ports,
|
|
827
|
+
env: config.env
|
|
828
|
+
})
|
|
829
|
+
};
|
|
449
830
|
|
|
831
|
+
exports.VercelMicroVMProcessManager = VercelMicroVMProcessManager;
|
|
832
|
+
exports.VercelMicroVMSandbox = VercelMicroVMSandbox;
|
|
450
833
|
exports.VercelSandbox = VercelSandbox;
|
|
834
|
+
exports.vercelMicroVMSandboxProvider = vercelMicroVMSandboxProvider;
|
|
451
835
|
exports.vercelSandboxProvider = vercelSandboxProvider;
|
|
452
836
|
//# sourceMappingURL=index.cjs.map
|
|
453
837
|
//# sourceMappingURL=index.cjs.map
|