ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Flue × Vercel Sandbox 适配器实战:把 Vercel 托管的 Linux 沙箱接入 Agent 工作区

Flue × Vercel Sandbox 适配器实战:把 Vercel 托管的 Linux 沙箱接入 Agent 工作区 Flue × Vercel Sandbox 适配器实战把 Vercel 托管的 Linux 沙箱接入 Agent 工作区【免费下载链接】flueThe sandbox agent framework.项目地址: https://gitcode.com/GitHub_Trending/flue1/flue在 FlueThe sandbox agent framework中useSandbox()是给 Agent 挂载文件系统与 Shell 的入口。本篇技术指南围绕 Flue 官方提供的 Vercel Sandbox 生态适配器文档位于 apps/docs/src/content/docs/ecosystem/sandboxes/vercel.md对应蓝图见 blueprints/sandbox--vercel.md展开讲解如何通过一条命令把 Vercel Sandbox 蓝本加入现有 Flue 项目深入解读生成的sandboxes/vercel.ts适配器源码、SandboxDriver底层契约、OIDC 认证配置并给出可在实际 Agent 中直接落地的接线示例。读完你将掌握如何在几秒钟内为 Agent 提供 Vercel 托管的隔离 Linux 沙箱、如何理解并定制超时与取消语义、以及如何在 Vercel 部署与本地开发两种环境下正确配置认证。适配器解决了什么问题Vercel Sandbox 适配器的核心定位非常明确它把一个已经初始化好的vercel/sandboxSandbox实例适配成 Flue 的沙箱接口SandboxFactory。当你的应用代码希望让 Agent 的工作在 Vercel 托管的沙箱内执行而不是运行在宿主机的文件系统上时就用它。理解这个定位要抓住两点边界适配adapt而非托管provisionVercel Sandbox 的创建、运行时选择、保留策略与清理retention and cleanup全部由应用自己持有——Flue 只连接你交给它的沙箱永远不会自行创建或销毁 Vercel 侧的沙箱基础设施。接口统一适配后返回的是标准SandboxFactory与 guide/sandboxes.md 中描述的虚拟沙箱、local()本地沙箱以及 E2B、Modal、Cloudflare 等其他远端适配器走的是同一套契约Agent 核心逻辑无需区分底层运行模式。快速开始一条命令接入在终端或你的 coding agent 中对已有 Flue 项目执行flue add sandbox vercel这条命令由 Flue CLI 的蓝图系统驱动对应flue add命令。flue add sandbox docs-url的通用形态也支持为未收录的提供商生成适配器详见 guide/sandboxes.md。就 Vercel 而言蓝图会完成两件事按需安装vercel/sandbox依赖。蓝图要求的版本为^2.2.1若你的package.json尚未列出它会用项目锁文件对应的包管理器执行安装例如npm install vercel/sandbox^2.2.1在 source-root 生成sandboxes/vercel.ts。选择写入目录的优先级为root/.flue/→root/src/→root/取第一个已存在的源码目录缺失的父目录会自动创建。文件头部会带// flue-blueprint: sandbox/vercel1标记便于后续升级时对照比对。读懂生成的适配器sandboxes/vercel.ts蓝图会原样写入一份符合SandboxDriver契约的适配器文件核心结构如下为阅读方便做了精简完整版本见 blueprints/sandbox--vercel.md// flue-blueprint: sandbox/vercel1 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) {} async stat(path: string): PromiseFileStat { 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?: Recordstring, 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] Command timed out after ${options?.timeoutMs} milliseconds., exitCode: 124, }; } throw err; } } } export function vercel(sandbox: VercelSandbox): SandboxFactory { return { async createSandbox(): PromiseSandbox { const sandboxCwd /vercel/sandbox; const driver new VercelSandboxDriver(sandbox); return sandboxFromDriver(driver, sandboxCwd); }, }; }文件操作直接映射到sandbox.fsVercelSandboxDriver将SandboxDriver的每个文件动词一一映射到 Vercel SDK 的sandbox.fsreadFile/readFileBuffer/writeFile/stat/readdir/exists/mkdir/rm。其中stat会把 Vercel 的 stat 结果转成 Flue 的FileStat结构isFile、isDirectory、isSymbolicLink、size、mtime供 Agent 的标准文件工具read、write、edit、grep、glob使用。execbash 包装与超时/取消的精确语义exec通过runCommand({ cmd: bash, args: [-c, command], ... })执行命令其取消语义是全文件最值得细读的部分信号合成用AbortSignal.timeout(options.timeoutMs)把timeoutMs转成超时信号再用AbortSignal.any([callerSignal, timeoutSignal])与调用方信号合并谁先触发谁生效命令输出读取response.stdout/stderr也传入同一信号保证读取阶段同样可被取消。三路分支对应蓝图注释中的设计意图仅超时 → 返回可恢复的 124 形态ShellResultexitCode: 124stderr 注明超时毫秒数遵循timeout(1)约定仅调用方取消 → 直接throw err让宿主的中止语义向上传播两者同时触发 → 若调用方信号先触发则传播否则按超时处理。这正是 reference/sandbox-api.md 中规定的exec实现契约的落地超时过期以ShellResultexitCode: 124解析signal中止则以AbortError拒绝。从源码结构看sandboxes/vercel.ts也是少数把signal真正透传给提供商 SDK 的适配器Vercel SDK 原生接受AbortSignal因此在 guide/sandboxes.md 中它被归类为能真正停止命令的一类而不是只把远端命令遗弃为孤儿进程。vercel()返回沙箱工厂vercel(sandbox)接收一个已初始化的 VercelSandbox返回SandboxFactory。工厂的createSandbox()把工作目录固定为/vercel/sandbox构造 driver 后交给sandboxFromDriver(driver, sandboxCwd)包装成标准的Sandbox。底层契约SandboxDriver与sandboxFromDriververcel(sandbox)之所以只需要短短几行是因为通用逻辑全部沉淀在flue/runtime的 packages/runtime/src/sandbox.ts 中。sandboxFromDriver(driver, cwd, options?)为任意远端提供商适配器统一提供三层能力路径解析相对文件路径以及相对/缺省的exec工作目录都基于cwd此处即/vercel/sandbox解析并做 POSIX 归一化driver方法收到的永远是绝对路径。这也解释了文档中从/vercel/sandbox解析相对路径的表述。writeFile父目录创建保证先尝试直接写失败后对父目录执行一次mkdir(parent, { recursive: true })再重试一次——跨沙箱模式的统一契约适配器侧无需自己实现。exec中止竞态abort race调用前已中止的信号在driver.exec被调用前就拒绝飞行中的中止也会立即拒绝调用方绝不会等待提供商 promise 自行结算——被释放的提供商调用成为孤儿命令OrphanedExecSettlement其最终结算无论 fulfill 还是 reject比如迟到的SandboxDiedError被消费掉绝不写入会话只能通过options.onOrphanSettled在带外观察用于日志、计费或收割。此外该文件顶部的SandboxDriver接口注释明确了一个要点适配器不应自行实现第二套 abort race本地Promise.race或自加的前后signal.aborted检查因为sandboxFromDriver已经负责了面向调用方的拒绝与孤儿记账适配器只需在 SDK 具备真实取消原语时透传signal即可——Vercel 适配器正是这样做的。配置与认证VERCEL_OIDC_TOKEN文档给出了一张精简的配置表完整语义如下变量用途VERCEL_OIDC_TOKENOIDC 认证必需——在 Vercel 平台上自动注入本地使用 OIDC 时需显式设置前置要求说明Vercel 支持的认证方式必需——在 Vercel 上走 OIDC离开 Vercel 后使用 access token 或其他受支持的认证流程vercel/sandbox包必需——创建被 Flue 适配的 Vercel Sandbox应用持有的生命周期必需——由应用创建沙箱并决定其保留与清理策略关于认证蓝图文档blueprints/sandbox--vercel.md补充了更详细的实操路径。Vercel Sandbox 使用的是 Vercel 的OIDC token 体系而非简单的 API keySDK 会自动从环境变量读取VERCEL_OIDC_TOKEN。分两种情况在 Vercel 部署中运行无需任何设置平台自动注入 token。本地或非 Vercel 环境运行需要先关联 Vercel 项目并拉取开发 tokennpx vercel link npx vercel env pull这会生成.vercel/.env.development.local或类似文件其中已填充VERCEL_OIDC_TOKEN。一次性运行时可让flue run指向它flue run path-to-agent-module --message ... --env .vercel/.env.development.local注意默认情况下flue run加载的是项目根目录的.env而vite dev与构建后的服务读取的是 shell 环境process.env因此在这些场景需要把 token 导出到 shell 环境变量中。对于 OIDC 不可用的非 Vercel CI 等环境可以使用 Vercel access token 替代具体配置方式参见 Vercel 官方认证文档——永远不要自行发明 token 值。在 Agent 中接线适配器生成的vercel(...)工厂要配合useSandbox(...)使用。文档给出的典型用法如下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({ // Lazy符合 SandboxFactory 契约构造此对象很廉价 // 昂贵的 Vercel 沙箱创建只会在 createSandbox() 内、初始化时执行一次—— // 永远不会在重渲染时发生。 async createSandbox(options) { const sandbox await Sandbox.create({ runtime: node24 }); return vercel(sandbox).createSandbox(options); }, }); }要点解析懒工厂语义useSandbox接受的工厂对象每次渲染都会重新构造但这很廉价真正昂贵的工作Sandbox.create({ runtime: node24 })即创建 Vercel 托管的 Linux 沙箱被封装在createSandbox()内运行时只在初始化 Agent 时调用一次重渲染永不触发。useSandbox的规则来自 guide/sandboxes.md每次渲染至多调用一次同一次渲染中的第二次调用会抛错子 Agent 内调用也会抛错——委托者共享父级环境useSandbox(factory, { cwd })的cwd会在初始化时针对沙箱自身基目录解析一次决定默认命令执行目录与工作区发现AGENTS.md、skills、目录清单发生的位置。沙箱创建时机Sandbox.create()发生一次之后该 harness 的每次会话与任务会话共享返回的沙箱。若希望按会话获得持久工作区可让createSandbox({ id })用options.idAgent 实例 id作为键查找或复用提供商侧的沙箱资源。生命周期决策文档明确建议把 Vercel 认证值放在受信任的应用配置中并自主决定沙箱是每任务全新还是可复用以维持稳定的 Agent 身份。依赖、验证与运行接入后的完整落地步骤安装依赖确认package.json中包含vercel/sandbox^2.2.1按项目锁文件选择pnpm add/yarn add。类型检查运行npx tsc --noEmit确认新生成的sandboxes/vercel.ts无类型错误。核对导入路径确认 Agent 中import { vercel } from ../sandboxes/vercel与你实际写入适配器的目录一致root/.flue/sandboxes/vercel.ts、root/src/sandboxes/vercel.ts或root/sandboxes/vercel.ts。准备运行时认证按上文认证一节确保VERCEL_OIDC_TOKEN在运行时可用。试运行flue run path-to-the-agent-module --message ...或使用vite dev启动完整应用体验。另外注意若 Agent 需要 HTTP 端点才需要在app.ts中挂载createAgentRouter(...)来自flue/runtime/routing仅使用flue run与dispatch()时无需挂载。小结与延伸阅读Vercel Sandbox 适配器是薄适配器理念的典型范例应用持有 Vercel 沙箱的完整生命周期Flue 只负责把它包装成统一的SandboxFactory而超时、取消、孤儿进程与路径解析等复杂语义全部由flue/runtime的sandboxFromDriver统一兜底。如果希望进一步理解沙箱对 Agent 能力的整体影响文件/Shell 工具、工作区上下文、Workspace Skills、子代理继承见 guide/sandboxes.mdSandboxFactory、Sandbox、SandboxDriver的完整接口契约与适配器编写规范见 reference/sandbox-api.md其他远端提供商Cloudflare、E2B、Daytona、Modal 等的适配方式见 apps/docs/src/content/docs/ecosystem/sandboxes 目录下的对应文档。【免费下载链接】flueThe sandbox agent framework.项目地址: https://gitcode.com/GitHub_Trending/flue1/flue创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表