Vercel Sandbox
最后更新 查看 Markdown 源文件
Vercel Sandbox 适配器将已初始化的 @vercel/sandbox Sandbox 适配为 Flue 的沙箱接口。当应用代码应在 Vercel 管理的沙箱中而非其主机文件系统上执行智能体工作时,可以使用它。
快速开始
使用 Vercel Sandbox 蓝图为现有 Flue 项目添加托管 Linux 沙箱能力。在终端或你选择的编码智能体中运行以下命令:
flue add sandbox vercel
概述
蓝图会在需要时安装 @vercel/sandbox,并在你的源码根目录下创建 sandboxes/vercel.ts。生成的适配器接受已初始化的 Vercel Sandbox;认证、运行时选择、保留和清理仍由应用管理。
// flue-blueprint: sandbox/vercel@1
import { sandboxFromDriver, useModel } from '@flue/runtime';
import type { SandboxDriver, SandboxFactory, Sandbox, FileStat } from '@flue/runtime';
import type { Sandbox as VercelSandbox } from '@vercel/sandbox';
class VercelSandboxDriver implements SandboxDriver {
constructor(private sandbox: VercelSandbox) {}
/* ... 使用 sandbox.fs 生成的文件系统操作 ... */
async stat(path: string): Promise<FileStat> {
const stat = await this.sandbox.fs.stat(path);
return {
isFile: stat.isFile(),
isDirectory: stat.isDirectory(),
isSymbolicLink: stat.isSymbolicLink(),
size: stat.size,
mtime: stat.mtime,
};
}
async exec(
command: string,
options?: {
cwd?: string;
env?: Record<string, string>;
timeoutMs?: number;
signal?: AbortSignal;
},
): Promise<{ stdout: string; stderr: string; exitCode: number }> {
const timeoutSignal =
typeof options?.timeoutMs === 'number' ? AbortSignal.timeout(options.timeoutMs) : undefined;
const callerSignal = options?.signal;
const signal =
callerSignal && timeoutSignal
? AbortSignal.any([callerSignal, timeoutSignal])
: (callerSignal ?? timeoutSignal);
try {
const response = await this.sandbox.runCommand({
cmd: 'bash',
args: ['-c', command],
cwd: options?.cwd,
env: options?.env,
signal,
});
const [stdout, stderr] = await Promise.all([
response.stdout({ signal }),
response.stderr({ signal }),
]);
return { stdout, stderr, exitCode: response.exitCode };
} catch (err) {
if (callerSignal?.aborted) throw err;
const aborted =
timeoutSignal?.aborted &&
(err === timeoutSignal.reason ||
(err instanceof Error && (err.name === 'AbortError' || err.name === 'TimeoutError')));
if (aborted) {
return {
stdout: '',
stderr: `[flue:vercel] 命令在 ${options?.timeoutMs} 毫秒后超时。`,
exitCode: 124,
};
}
throw err;
}
}
}
export function vercel(sandbox: VercelSandbox): SandboxFactory {
return {
async createSandbox(): Promise<Sandbox> {
const sandboxCwd = '/vercel/sandbox';
const driver = new VercelSandboxDriver(sandbox);
return sandboxFromDriver(driver, sandboxCwd);
},
};
}将已初始化的 Vercel Sandbox 传递给 vercel(...),并将返回的工厂传递给智能体的 useSandbox(...) 调用。适配器映射提供商完整的文件统计信息,从 /vercel/sandbox 解析相对路径,向命令执行和输出读取转发组合信号,传播调用方取消,仅将 timeoutMs 取消映射为退出码 124。
配置
| 变量 | 用途 |
|---|---|
VERCEL_OIDC_TOKEN | OIDC 认证必需 — 在 Vercel 上自动注入;在本地使用 OIDC 时需显式设置。 |
| 覀求 | 用途 |
|---|---|
| Vercel 支持的认证 | 必需 — 在 Vercel 上使用 OIDC,在 Vercel 外使用访问令牌或其他支持的认证流程。 |
@vercel/sandbox 包 | 必需 — 创建由 Flue 适配的 Vercel Sandbox。 |
| 应用自有的生命周期 | 必需 — 创建沙箱并决定其保留和清理策略。 |
典型用法
import { Sandbox } from '@vercel/sandbox';
import { useModel, useSandbox } from '@flue/runtime';
import { vercel } from '../sandboxes/vercel';
export function Assistant() {
useModel('anthropic/claude-sonnet-4-6');
useSandbox({
// 按照 SandboxFactory 契约,延迟执行:构造此对象成本很低;
// 昂贵的 Vercel 沙箱创建只在 createSandbox() 内部的初始化阶段
// 执行一次 —— 永远不会在重新渲染时执行。
async createSandbox(options) {
const sandbox = await Sandbox.create({ runtime: 'node24' });
return vercel(sandbox).createSandbox(options);
},
});
}
将 Vercel 认证值保存在可信的应用配置中,并确定沙箱应该是每次任务新建还是为稳定的智能体身份复用。