尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Turborepo Factory 深度解析:基于 Eve 与 AI SDK HarnessAgent 的自动化编码工作区与沙箱镜像体系

Turborepo Factory 深度解析:基于 Eve 与 AI SDK HarnessAgent 的自动化编码工作区与沙箱镜像体系 Turborepo Factory 深度解析基于 Eve 与 AI SDK HarnessAgent 的自动化编码工作区与沙箱镜像体系【免费下载链接】turboBuild system optimized for JavaScript and TypeScript, written in Rust项目地址: https://gitcode.com/gh_mirrors/tu/turbo导读Turborepo 仓库中的apps/factory包名examples-agent是一套围绕Eve 事件驱动 Agent 框架构建的编码自动化应用操作员通过网页创建可恢复的编码工作区Workspace工作区背后是 Vercel Sandbox AI SDKHarnessAgent驱动的真实编码会话可选用 fx、Claude Code、Codex、Cursor、OpenCode、Pi 等多种编码 Agent同时它以Factory Image为统一沙箱基座用一条合并即重建、账本裁决并发的流水线保证每次main合并后所有 Agent 都能在同一套构建环境上运行。读完本文你将掌握该应用的架构脉络、工作区生命周期、GitHub 事件闭环、沙箱镜像的构建/消费原理以及本地终端接入与各项关键配置项。一、应用定位Turborepo 的自动化编码操作台apps/factory同时包含三个层次的能力操作员页面operator page一个 Next.js 应用管理工作区列表、Factory Image 构建状态、Eve 调度审计记录API 路由提供工作区创建/恢复、diff 拉取、浏览器终端、Factory Image 触发等接口Eve 应用以 Eve 通道channels和调度schedules形式承载 GitHub 事件处理、工作区会话推进、镜像构建对账等控制面逻辑。需要特别强调的是该应用的访问控制边界操作员页面及其 API 路由依赖 Vercel Deployment Protection 进行访问控制README 明确要求对每个暴露它们的部署环境保持 Deployment Protection 开启。这是整个应用的安全前提后续所有本地接入和 webhook 配置都建立在这一层之上。从仓库结构看[apps/factory/agent](https://link.gitcode.com/i/532eeb263d106bc0337fc4ca30f89c63)目录是核心控制面channels/下是 Eve 通道eve.ts、github.ts、operator.ts、slack.ts、workspace.tslib/下是工厂镜像、工作区存储、HarnessAgent 封装等实现tools/是 Eve 可调用工具schedules/是周期任务含reconcile_factory_images.ts镜像对账调度。二、Workspaces可恢复的编码工作区2.1 一次 Start work 的背后Start work 创建一个持久的 Factory 工作区底层由 AI SDKHarnessAgent驱动。创建时操作员可以选择编码 Agentharnessfx、Claude Code、Codex、Cursor、OpenCode、Pi。这与 agent/lib/harness-agent.ts 中createFactoryHarness的 switch 分支一一对应createClaudeCode、createCodex、createCursor、createOpenCode、createPi、createFx统一走 AI Gateway 鉴权auth: ai-gatewayCursor 除外它使用auth: auto自行控制路由并通过FACTORY_HARNESS_PORT与沙箱内的编码运行时通信。每个工作区拥有一条服务端记录命名空间为 Vercel Sandbox一个可恢复的 Harness 会话resumable harness session一份转录transcript一个可分享的/workspaces/idURL。关键特性是Eve 一次只推进工作区一轮one turn at a time因此另一个浏览器或操作员可以重新打开该 URL继续同一段对话和同一份 checkout代码检出状态不会丢失。从 agent/channels/workspace.ts 的事件处理可以看到turn.completed/turn.cancelled会把工作区置为idle状态而message.completed会把助手消息追加进记录并截断到最近 1000 条。工作区页面支持按需加载当前 Git 状态和截断后的 diff对应 API 路由[app/api/workspaces/[workspaceId]/diff/route.ts](apps/factory/app/api/workspaces/[workspaceId]/diff/route.ts)浏览器内终端对应[app/api/workspaces/[workspaceId]/terminal/route.ts](apps/factory/app/api/workspaces/[workspaceId]/terminal/route.ts)协议定义见 agent/lib/sandbox-terminal.tssandbox ssh name命令直接进入工作区沙箱。当编码 Agent 上报了一个 Turborepo 的 Pull Request URL 时工作区会记录并链接它形成自动化 → PR的闭环追踪。2.2 Eve GitHub 通道Issue 的自动化分流agent/channels/github.ts通道自动处理新开的公开 Issue。处理链路是一个无工具的安全子代理agent/subagents/issue_security_triager/见 instructions.md先审查初始 Issue 内容检查**提示注入prompt injection、复现篡改reproduction tampering**以及其他可疑行为任何可疑信号都失败关闭fail closedFactory 不会检查或运行复现而是发出一条带线程内解释的 Slack 告警通过审查的 Issue 获得置信度评估低/中置信度只发 Slack 告警带线程内理由 生成一份调查报告高置信度才进入下一步——聚焦修复、验证并起草一个agents/issue-*分支的 PR。这一策略非常典型地体现了自动化 Agent 处理社区反馈时的安全边界设计可疑输入绝不被执行未经验证的修复不直接上主干。2.3 跟随 Factory 创建的 PR 与写权限评论GitHub 通道还会跟随 head 分支为agents/*的 Factory 创建的 PR来自具备写权限协作者的 timeline 评论和 inline review 评论会无需mention就启动一轮start a turn该轮会检出当前 PR head、在同一个 GitHub 线程中回复并可把已验证的反馈改动发布回该分支机器人评论、外部用户评论、非 PR 评论、非 Factory 分支的评论一律失败关闭并被忽略。2.4 工作区记录与存储工作区记录以私有 Blob 对象形式存储factory-workspaces/v1/id.json见 agent/lib/workspace-store.ts 中的PREFIX factory-workspaces/v1/。变更路由要求完全同源请求 action 头x-operator-actionisWorkspaceMutationRequest校验不通过即返回 403Vercel Deployment Protection 是外层操作员认证层持久的 Eve 事件流是转录与执行活动的来源存储凭据二选一BLOB_READ_WRITE_TOKEN或同时提供BLOB_STORE_IDVERCEL_OIDC_TOKENisWorkspaceStoreConfigured的实现与 README 完全一致。写入采用基于 Blob etag 的 compare-and-swapmutateWorkspace先读当前记录和 etag再带ifMatch写入冲突BlobPreconditionFailedError则重试最多 5 次MAX_WRITE_ATTEMPTS 5。2.5 Sandbox Drives跨沙箱持久化私有测试版Sandbox Drives 目前是私有测试版。默认情况下 Factory 使用 Eve 的常规会话沙箱存储因此没有 beta 权限也能创建工作区。Vercel 团队完成注册后设置FACTORY_WORKSPACE_DRIVES1即可为每个会话挂载独立的 Drive把 checkout 持久化到替换后的沙箱计算资源上。相关实现在 agent/sandbox.tsisWorkspaceDriveEnabled()为真时通过Drive.getOrCreate按会话 id 创建 Drive并挂载到WORKSPACE_DRIVE_MOUNT_PATH。三、本地终端接入factory CLI在本地终端使用factory命令前需要配置FACTORY_URL指向受保护的部署地址必填scripts/factory.mjs缺失该变量会直接报错退出VERCEL_AUTOMATION_BYPASS_SECRET仅自动化保护的部署需要会作为x-vercel-protection-bypass请求头发送使用factory ssh前还需安装并认证 VercelsandboxCLI。三个核心命令定义在 scripts/factory.mjs# 列出全部工作区id、状态、标题 pnpm --filter examples-agent factory list # 用一段提示词创建并启动一个工作区 pnpm --filter examples-agent factory start Investigate the affected warning and open a PR # SSH 进入指定工作区的沙箱 pnpm --filter examples-agent factory ssh ws_...factory start实际调用POST /api/workspaces带x-operator-action: create-workspace头成功后输出可分享的/workspaces/idURLfactory ssh先请求工作区访问令牌再用sandbox ssh sandbox.name --workdir turborepo进入沙箱。本地终端挂接期间同一个工作区在网页上依然可用。四、Factory Image所有 Agent 的沙箱基座4.1 单一事实来源应用中每个 Agent 都运行在同一套沙箱基础层上即factory image一份 Turborepo checkout外加cargo build和pnpm test所需的全部工具链。agent/lib/factory-image.ts是它的单一事实来源——包括固定的版本号、安装它们的 shell 脚本以及决定何时需要重建的指纹fingerprint。FACTORY_IMAGE_SPECagent/lib/factory-image.ts给出了当前仓库实际的固定版本组件固定值基础镜像vercel/eve:latestNode.js主版本 24pnpm10.28.0Rust 工具链nightly-2026-05-22组件rustfmt、clippyfx0.0.5含 x86_64 / aarch64 的 SHA-256protoc26.1Zig0.15.2Capn Proto1.1.0含源码回退构建校验和性能工具hyperfine、cargo-bloat、twiggycheckout 路径/factory/turborepo状态目录/factory/stateCARGO_HOME / RUSTUP_HOME/usr/local/cargo、/usr/local/rustup镜像安装的内容包括系统构建工具链build-essential、pkg-config、lld、OpenSSL 头文件、jq、zstd、ghCapn Proto、protoc、ZigNode.js、pnpm、fxrust-toolchain.toml指定的 nightly 工具链含rustfmt和clippy工作区node_modulespnpm install --frozen-lockfile预热的 Cargo registrycargo fetch --locked性能技能会用到的hyperfine、cargo-bloat、twiggy。构建被拆成顺序执行的阶段phasessystem-packages→node→pnpm→fx→rust→protoc→zig→checkout→node-modules→cargo-registry→performance-tools→可选warm-build→verify。每个阶段都是幂等的对已从发布快照启动的沙箱重跑会重新核对每个固定版本、快进 checkout 并跳过已完成的工作。最后verify阶段会逐一确认工具存在缺失即exit 1、核对固定工具链已安装、并写出image.json版本清单。4.2 版本漂移防护tests/factory-image.test.mjs的作用是当这些固定版本与rust-toolchain.toml、根目录package.json、CI setup actions、.devcontainer/Dockerfile发生漂移时测试失败——从而保证本地开发容器与 Agent 沙箱始终使用同一套工具链。4.3 指纹机制factoryImageFingerprint()agent/lib/factory-image.ts对以下内容做 SHA-256 摘要并取前 16 位十六进制作为指纹FACTORY_IMAGE_VERSION当前为2改它以强制全量重建序列化后的整个FACTORY_IMAGE_SPEC镜像 preamble 与所有阶段的脚本。被检出的 commit 被刻意排除在指纹之外占位为全零因为它每次合并都会变化、且会在每个会话中单独快进——指纹描述的是工具链而非代码版本。修改任意固定版本、阶段脚本或FACTORY_IMAGE_VERSION都会轮换指纹从而同时重建 Eve 沙箱模板和发布快照。五、每次合并都重建一条没有 GitHub Actions 的流水线5.1 触发链路main分支的 push 通过Vercel Connect 触发器到达POST /api/github/pushapp/api/github/push/route.tsConnect 校验 GitHub 的签名路由校验Connect 附加的 Vercel OIDC 凭据authenticateConnectisFactoryImageConnector其他事件一律已确认并忽略调用与操作员按钮、rebuild_factory_imageEve 工具同一个应用函数triggerFactoryImageBuild。该函数创建构建沙箱并在其中分离detach执行 provisioning 脚本setsid bash -lc ...见factoryImageStartCommand构建不占用请求时间。随后Dashboard 轮询与一分钟一次的 Eve 调度reconcileFactoryImageBuilds对账其标记phase、exit code、warnings、manifest成功后对沙箱打快照并把快照 id 作为当前镜像发布。全程不涉及 GitHub Actions job也不涉及模型调用。5.2 并发裁决账本而非竞速快速连续合并时用**账本ledger**裁决而不是让构建互相竞争认领一次构建会取消所有仍在飞行中的构建标记为 superseded被取代并删除其沙箱每次对账都会在做事前重新读取账本已经输掉的构建既不能上报进度也不能发布——所以main上只有最新的 revision 会被发布。tests/factory-image-ledger.test.mjs覆盖这些状态迁移。账本实现的关键点账本本身是私有 Blob 存储中的factory-image/v1/state.json见 agent/lib/factory-image-registry.ts写入是etag compare-and-swap两个同时落地的合并无法同时认领账本输家基于赢家的状态重试要么被去重、要么取代对方MAX_WRITE_ATTEMPTS 5发布时先做claimFactoryImagePublication防止对账循环重复发布。5.3 从旧镜像快速前进当同一个工具链已存在已发布镜像时新构建会从它启动baseSnapshotId匹配即作为构建沙箱基座因此一次合并触发的构建只需快进 checkout → 刷新依赖 → 重新编译而不是从零搭建环境。5.4 配置清单按 README 逐项配置私有 Vercel Blob store账本与运行注册表共处一室GitHub Vercel Connect connector订阅push、pull_request、pull_request_review_comment权限为 pull-request 读写、contents 写、repository collaborator metadata 读push路由到/api/github/pushpull_request和pull_request_review_comment路由到/eve/v1/github两个目标都带 Deployment Protection bypass 查询参数FACTORY_IMAGE_CONNECTOR_ID设为该 connector 的稳定scl_...IDProduction trigger 目标turborepo-factory项目指向/api/github/push。由于该路径受 Deployment Protection 覆盖需把自动化 bypass token 作为x-vercel-protection-bypass查询参数追加。Connect 用 Vercel OIDC 认证转发请求路由要求其签名的 connector ID直接发往 GitHub 的 webhook 和其他同项目 OIDC 调用者都会被拒绝。操作员页面会展示已发布镜像、工具链指纹、最近构建列表并可通过POST /api/factory-image为当前mainhead 启动一次构建。六、镜像如何被消费6.1 沙箱模板与重校验键agent/sandbox.ts用同样的阶段构建 Eve 沙箱模板保证两边永不漂移——README 称该设计使 Eve 模板与合并 webhook 发布的快照不可能漂移revalidationKey在构建时冻结factory-image:${pointer?.snapshotId ?? none}当工具链指纹变化或更新镜像发布时模板会轮换存在匹配的已发布快照时则从快照启动每个会话随后把 checkout快进到当前main新建的 HarnessAgent 工作区在没有匹配镜像时会在首轮之前提供共享镜像阶段恢复的工作区保留其 checkout、所选 harness 会话和未提交的改动。6.2 部署构建内的预热与超时工具链变化会在下一次Vercel 构建期间从零准备模板因为Eve 会在部署构建中预热沙箱模板以vercel/eve:latest为基准每个阶段到验证完成约需两分钟所有编译 Rust 的阶段都包在超时里性能工具cargo install上限 900 秒、暖构建cargo build上限 2400 秒见TOOL_INSTALL_TIMEOUT_SECONDS/WARM_BUILD_TIMEOUT_SECONDS防止一个异常的上游发布卡死整个部署构建只有合并 webhook 会请求暖cargo build它在构建沙箱内脱离部署路径运行warmBuild: true。6.3 GitHub 令牌交换配置GITHUB_TOKEN_EXCHANGE_URL交换端点接收 Vercel OIDC bearer 认证必须为请求的vercel/turborepo写权限返回{ token: string, expires_at: string }Vercel OIDC 认证 Vercel Sandbox 与 AI GatewayGitHub 授权由沙箱网络策略注入不暴露给 Agent 进程——这是又一层权限隔离设计。七、Agent Runs审计记录操作员页面链接到Vercel Agent Runs——它是 Eve 调度的审计记录HarnessAgent 工作区轮次则通过Workflow observability审计。注意边界工作区 Blob 记录保存的是可恢复的 UI 转录与控制面状态而不是完整的执行审计。一个值得注意的实现细节Eve run 的模型是在第一个模型步骤开始时记录的而非会话开始时——因为 Agent 是动态选择其作者模型的session.started事件不携带模型 id账本从step.started事件填充该字段。八、关键源码地图关注点文件Factory 应用 README本文主体apps/factory/README.md镜像单一事实来源、阶段、指纹agent/lib/factory-image.ts沙箱模板与快照消费agent/sandbox.ts镜像触发与账本认领agent/lib/factory-image-trigger.ts镜像账本etag CAS 写入agent/lib/factory-image-registry.tsHarnessAgent 适配与编码 Agent 选择agent/lib/harness-agent.ts工作区 Blob 存储agent/lib/workspace-store.ts工作区通道与轮次状态机agent/channels/workspace.tsGitHub push webhook 路由app/api/github/push/route.ts本地 factory CLIscripts/factory.mjs镜像固定版本漂移测试tests/factory-image.test.mjs镜像账本状态迁移测试tests/factory-image-ledger.test.mjsIssue 安全三审子代理指令agent/subagents/issue_security_triager/instructions.md结语Turborepo Factory 展示了事件驱动 Agent 编排 可恢复编码会话 快照化沙箱镜像三者如何组合成一个生产级自动化闭环操作员创建的工作区一次推进一轮、可跨浏览器/终端恢复GitHub Issue 与 PR 评论通过失败关闭的安全策略接入自动化修复而每次合并触发的镜像重建由 etag 账本裁决并发、由指纹驱动模板轮换确保所有 Agent 永远运行在同一套可信、可复现、有审计的构建环境上。理解这条链路对任何想要构建仓库级编码 Agent 基础设施的团队都具有直接参考价值。【免费下载链接】turboBuild system optimized for JavaScript and TypeScript, written in Rust项目地址: https://gitcode.com/gh_mirrors/tu/turbo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表