用途
ai-sandbox 用于在隔离沙箱内运行 harness 适配器(Claude Code、Codex、OpenCode)。适配器声明 requires: [SandboxCapability],若没有中间件提供该能力,chat() 会报错;withSandbox(...) 负责提供它。随后适配器在沙箱内运行代理 CLI,并流式回传其事件。
基本用法
通过 defineSandbox 定义沙箱,指定 id、provider 与 workspace,再把 withSandbox(sandbox) 作为 chat() 的中间件。示例中 provider 使用 dockerSandbox({ image: 'node:22' }),workspace 使用 defineWorkspace,source 为 git 仓库(url、ref),声明 packageManager(如 pnpm)、setup 命令(corepack enable、pnpm install)以及 scripts。返回时使用 toServerSentEventsResponse(stream)。
声明式工作区配置
- source:git 源,githubRepo / gitSource 默认使用 --depth 1 --single-branch,可通过 depth 覆盖(如 10 或 'full')。
- setup:接受字符串数组(全部串行),或接受带 serial、parallel 回调的函数,在持久 shell 中执行,cwd/env 在串行步骤间保留。
- skills:agentSkill、gitSkill、mcpSkill、fileSkill。每个 skill 类型按 harness 投影(Claude Code → .mcp.json;Codex → .codex/config.toml;OpenCode → opencode.json)。CLI 不支持的 skills/plugins 会 console.warn 并跳过。gitSkill 的 into 为沙箱内绝对路径,默认 <root>/.tanstack-skills/<repo-basename>。
- instructions:写入工作区根目录的 AGENTS.md;CLAUDE.md 与 GEMINI.md 以符号链接创建(失败时回退为副本)。
- plugins:按 CLI 概念投影,不支持时警告并跳过。
类型安全密钥
createSecrets 生成 SecretRef;底层字符串存放在不可枚举的符号键注册表中,不会被记录日志、快照或写入沙箱存储。将 secrets 传给 defineWorkspace({ secrets }) 以便 skill 与 MCP 投影器解析。secret: secrets.GH 用于 gitSkill 私有仓库认证;secrets.GH / bearer(secrets.GH) 用于 MCP header 值。
快速初始化与快照
setup 完成后,若 provider 支持快照会自动创建(snapshot: 'after-setup'),后续运行从快照恢复并跳过 setup;可用 snapshotMaxAge(如 '24h')控制过期重建。不支持快照的 provider 会静默跳过。
可移植快照
可移植快照把已完成的工作区文件保存在应用持久化中,与 provider 原生 bootstrap 快照相互独立。需按顺序配置 withPersistence(snapshots.persistence) 与 withSandbox(sandbox, { instances, snapshots }),两处使用相同 persistence。每次成功的终态运行会保存常规文件、空目录、持久对话数据与线程产物;后续运行只把最新检查点恢复到新的私有沙箱,不会覆盖正在使用的沙箱。默认策略排除 .git、node_modules、.env* 路径段(任意深度)、仅工作区根目录的投影标记、根目录 CLAUDE.md 与 GEMINI.md,以及直接的 .claude/skills/<name>、.codex/skills/<name>、.grok/skills/<name> 路径。解析后的密钥在存储前会被脱敏。符号链接、可执行文件与特殊文件系统条目会导致捕获或恢复失败。每个线程只有一个写租约。blob 保留需手动管理。用户标记状态可调用 snapshots.save(需 threadId、runId、label,要求可复用的活跃沙箱);分支可调用 snapshots.fork(需线程 id、检查点 id、目标线程 id,目标线程须为空,存储须实现原子 forkFromCheckpoint);发送产物可调用 snapshots.readArtifact(先授权调用方,确认检查点归属该线程,返回元数据与字节)。SQLite 检查点存储中,检查点写入、head 更新与所有 blob 引用更新需在同一事务内;fork 及其复制对话也需同一事务。
Providers
- localProcessSandbox():在宿主机运行,无隔离,仅用于开发循环。
- dockerSandbox({ image }):隔离容器,支持快照、fork、按 id 恢复。
- daytonaSandbox({ apiKey, snapshot, autoStopInterval, ephemeral }):Daytona 云沙箱,setup 后快照,恢复会启动已停止或归档的沙箱;/workspace 映射到 /home/daytona/workspace;安装包的 setup 需使用 sudo -n。 三者实现同一 SandboxHandle:fs(read/write/list/mkdir/remove/rename/exists)、git(clone/status/add/commit/push/pull/branch)、process(exec + duplex spawn)、ports.connect(port)、env.set、可选 snapshot()/fork()、destroy()。provider 通过 capabilities() 声明支持情况,调用不支持的可选方法抛 UnsupportedCapabilityError。
策略
defineSandboxPolicy 可设置 default: 'allow' 等;策略传给 defineSandbox({ policy }),harness 适配器会将其映射为原生权限。Claude Code 可使用 default: 'ask' 加 allow/ask/deny 列表进行命令级拒绝。Headless Grok Build / Codex 建议保持 auto-approve,隔离依赖外层沙箱而非策略中的 commands.deny。
生命周期与恢复
reuse: 'thread' 按 threadId 复用一个沙箱;复合键包含 provider + workspace 哈希 + tenant,更改仓库/setup/镜像会重新创建。顺序为:恢复运行中 → 恢复快照 → 创建并 bootstrap。恢复记账默认在内存中(单进程);跨进程/多副本需实现持久 SandboxInstanceStore(BYO)并作为 withSandbox(sandbox, { instances }) 传入,多副本需配合分布式锁(withLocks 或 locks 选项)。store 选项优先于环境中的 SandboxInstanceStoreCapability,后者优先于内存回退。聊天记录持久化(withPersistence)独立存在,需要历史与实例复用时组合使用。可用 runSandboxInstanceStoreConformance 验证适配器;defineSandboxInstanceStore({ get, upsert, delete }) 用于内联类型。
文件事件钩子
可在 defineSandbox({ hooks }) 声明沙箱级钩子(onFile、onFileCreate、onFileChange、onFileDelete、onReady、onError、onDestroy),或通过 chat 中间件的 sandbox 组声明运行级钩子。fileEvents 默认为 true,设为 false 可完全禁用监视。sandbox.file CUSTOM 事件会自动发出,可从流中读取(含 type、path、timestamp)。watchWorkspace() 可作为在 chat() 运行之外监听的底层构建块,支持 ignore(默认 ['.git', 'node_modules'])。可启用 sandbox 调试分类以记录 watcher 启停、事件分发与生命周期转换。
限制
资料未提供收费、价格、平台与效果信息。无自动垃圾回收,blob 保留需手动管理;快照捕获仅支持常规文件与空目录,拒绝符号链接、可执行文件与特殊条目;localProcessSandbox 无隔离。