Cloudflare Computer push/pull API详解:10分钟搞懂手动同步与exec自动同步的边界
2026/8/31 12:46:40 网站建设 项目流程

Cloudflare Computer push/pull API详解:10分钟搞懂手动同步与exec自动同步的边界

【免费下载链接】computerGive your agent a computer 👾项目地址: https://gitcode.com/GitHub_Trending/computer1/computer

Cloudflare Computer 是让 AI Agent 拥有一台"计算机"的开源虚拟文件系统,它的核心数据同步机制就是 push/pull API。本文将从新手视角讲清楚两件事:workspace.push()/workspace.pull()手动同步在什么场景该用,以及runtime.exec()命令执行时自动同步的"安全围栏"如何工作——帮你精准判断哪种同步方式适合你的应用。

一张图看懂 Cloudflare Computer 同步架构

整个系统只有两个主角:

  • Durable Object(DO 侧):用 SQLite 存储权威的虚拟文件系统,是"事实来源",重启不丢数据;
  • Container 侧:沙箱容器里的computerd守护进程,把同一份文件系统通过 FUSE 挂载成真实目录,让命令像操作本地磁盘一样工作。

两者之间通过一条 WebSocket 通道跑push/pull 双向同步协议:每次变更都会被盖上单调递增的"修订号"(revision),谁有新变更就推给谁,接收方按增量合并,不用每次传整棵目录树。协议全貌见 docs/02_sync_protocol.md。

两条同步路径:手动 push/pull 与 exec 自动同步

手动同步:什么时候该自己调 push() 和 pull()

Workspace对外只暴露两个同步方法(实现见 packages/computer/src/workspace.ts):

方法方向作用
workspace.push()DO → 容器把宿主侧新写的文件推送到容器,返回推送条目数
workspace.pull()容器 → DO把容器侧产生的变更拉回 SQLite,返回{ applied, skipped }

关键点:包内没有后台轮询线程,同步完全由你显式触发。以下场景必须手动调用:

  • 纯文件系统流程:你在 DO 侧用workspace.fs.writeFile()写了文件,想让容器里的命令"看见"它——先push()
  • Agent 交接:Agent A 在容器里干完活,Agent B 接手前先pull(),确保读到 A 的最终写入(文档称之为"显式同步点");
  • 容器重启后computerd的本地数据库是进程级的,重启会丢本地状态,下一次 push 会被当作全新基线重新灌入,通常由重连逻辑自动兜底。

exec 自动同步:push → 执行 → pull 的括号结构

只要走命令执行路径,同步就自动发生,你不需要手动调用。packages/computer/src/shell.ts 把每次exec()包成一个固定结构:

push(预推)→ 在容器里 spawn 命令 → 事件流/结果返回 → pull(回拉)

这个"括号"有三个新手容易忽略的细节:

  1. 预推是安全闸门,不是优化。push 失败会直接让exec()拒绝执行,命令不会带着过期的工作区跑起来;
  2. 回拉是幂等的。pull 按 256 条一批提交检查点,中途崩溃也只重放一小批,而且结果里带sync.status"complete"表示同步完成,"pending"表示命令本身成功了但回拉失败——可以之后用retryPendingSync()恢复,不会重跑你的命令
  3. 重连只重试一次。同步操作天然幂等(靠水位线保证),所以传输中断后可以安全重放;但"命令可能已经启动"的场景绝不重放,宁可报错也不让你执行两遍。

执行结果的pushed/pulled计数就是这对括号的统计,API 定义见 docs/05_runtime_interface.md。

同步边界速查表:哪些自动、哪些不自动

操作是否自动同步说明
workspace.runtime.exec("...")✅ 自动命令前后各同步一次(push 括号 + pull 括号)
workspace.fs.writeFile()等宿主侧写❌ 不自动需手动push(),或等下一次 exec 的预推顺带发出
容器内 FUSE 写文件⏳ 暂存每次写都盖章 revision,等下一次pull()才回到 SQLite
worker-javascript/worker-shell后端🚫 无需同步直接读写宿主权威存储,sync: "none",计数恒为 0
挂 R2/Artifacts 的只读挂载🚫 拒绝回写容器侧写入只读挂载点会被跳过,体现在skipped[]

一句话总结边界:命令执行自带同步围栏;凡是绕过 exec 直接操作文件系统的场景,同步责任就落在调用者身上。

同步协议为什么快:三个关键设计

  • 增量而非快照:每次变更打上 revision,同步只传"对端没见过"的部分;同一路径改 5 次,线上只走 1 条合并后的记录(coalesce,见 packages/dofs/src/sync/coalesce.ts);
  • 按内容分块去重:文件按 512 KiB 切块,用 SHA-256 哈希寻址。两个路径放同一份node_modules只传一次;改大文件只传动过的块。协商机制直接借用了 git 的 haves/wants 思路——hasObjects()问"你有什么",fetchObjects()/pushObjects()补传缺的;
  • 忽略列表省钱fetchChanges默认忽略node_modules,一次npm install不会把几万个碎片文件灌回 DO。容器里照样能用这些文件,只是不跨线上行。

完整 RPC 面(6 个方法:push/fetchChanges/watermarks/readEntry/hasObjects/fetchObjects)定义在 packages/rpc/src/interface.ts,帧格式说明见 docs/08_capnweb_interface.md。

冲突语义:最后是"谁最后写赢"

多容器共享同一个 Workspace 时,同步采用last-write-wins:先拉远端再推本地,但不做内容合并——两个容器改同一文件,谁的 push 先到 DO 谁的版本存活,另一个的修改被静默覆盖。这与不带锁的 NFS 共享挂载语义一致。

对新手来说,安全姿势有三条:

  1. 一个 Workspace 同时只有一个活跃写者——绝大多数 Agent 场景都符合;
  2. 多 Agent 分区写:A 只写/workspace/a/,B 只写/workspace/b/,冲突从结构上不可能发生;
  3. 交接处显式 pull:把 workspace 文件当作各 Agent 的私有草稿区,而非共享可变状态。

详见 docs/02_sync_protocol.md 的"Conflict semantics"一节。

最佳实践清单

  • 📌 只读文件(配置、脚手架):宿主侧写好后 push 一次即可,之后无需再管;
  • 📌 长任务 exec:不用关心同步,看sync.status"complete"即收敛;
  • 📌 构建产物(node_modulesdist):保持默认忽略,避免无谓流量;
  • 📌 多 Agent 流水线:在交接点手动pull(),别假设自动围栏存在。

去哪里看源码

资料路径
同步协议设计文档docs/02_sync_protocol.md
手动同步门面(Workspace 类)packages/computer/src/workspace.ts
exec 自动同步括号packages/computer/src/shell.ts
双向同步驱动(pullOnce / pushOnce / tick)packages/rpc/src/sync-driver.ts
RPC 线格式定义packages/rpc/src/interface.ts
运行时接口与结果类型docs/05_runtime_interface.md

掌握这条"手动 vs 自动"的边界,你就已经能正确驾驭 Cloudflare Computer 的数据一致性了——exec 里放心跑,exec 外自己管。

【免费下载链接】computerGive your agent a computer 👾项目地址: https://gitcode.com/GitHub_Trending/computer1/computer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询