项目简介
Cloudflare Computer 在 Durable Object 中提供基于 SQLite 的虚拟文件系统,并支持容器、Shell 隔离和 JavaScript 隔离等可插拔执行后端。通过统一入口 workspace.runtime.exec 运行代码,支持 FUSE 挂载、RPC 同步和持久化相对导入。
README 预览
# Cloudflare Computer\n\nCloudflare Computer is a virtual filesystem that lives inside a\nDurable Object. The Durable Object holds the authoritative state in\nSQLite and exposes one pluggable execution surface through\n`workspace.runtime`. Three backends ship today:\n\n- **Container** projects the SQLite state into a sandbox container as\n a real FUSE mount. A sandbox-side daemon (`computerd`) mounts the state\n as a filesystem and syncs changes back over a capnweb RPC channel.\n Full Linux userland, real binaries, real network.\n- **Isolate shell** runs [just-bash](https://github.com/vercel-labs/just-bash)\n in a Dynamic Worker. It reaches the authoritative Workspace over\n Workers RPC, so there is no second store or sync round trip.\n- **Isolate JavaScript** runs an ECMAScript module in a fresh Dynamic\n Worker with structured input/results, durable relative imports,\n configured libraries, Workspace-backed `node:fs/promises`, and trusted `ws:git` and\n `ws:artifacts` modules.\n\nA Workspace may register multiple backends under stable IDs.\n`workspace.runtime.exec(source, { backend })` is the single execution\nentry point; the selected backend defines whether `source` is a shell\ncommand or an ECMAScript module. Backends connect lazily on first use.\n\nWorkspace can also be constructed without a backend at all, giving\ncallers the filesystem on its own.\n\n> [!IMPORTANT]\n> **PREVIEW ONLY** This package is provided as a preview for feedback only.\n> APIs are unstable and the design is subject to change.\n>\n> Suitable for experiments, exploration and prototypes. It is NOT suitable\n> for production use at this time.\n>\n> The specification under [`docs/`](docs/) is forward-looking — read it for\n> intent, not as description of the code today.\n\n## Using it\n\nIf you want to build on Cloudflare Computer, install\n[`@cloudflare/computer`](packages/computer/README.md) and follow that\npackage's README — it has the installation steps, the entrypoint map,\nand常见问题 (5)
故障排除如何修复在 Cloudflare Computer 中运行 worker-shell exec 时出现的 "Cannot read properties of undefined (reading 'WorkspaceServiceProxy')" 错误?
此错误有两个可能的配置原因。请同时修复这两个问题:
1. 在 wrangler.toml 中添加必需的 enable_ctx_exports 兼容性标志:
compatibility_flags = ["nodejs_compat", "experimental", "enable_ctx_exports"]
如果使用 `wrangler.json`:json{
"compatibility_flags": ["nodejs_compat", "experimental", "enable_ctx_exports"]
}
2. 从你的 Worker 入口文件重新导出 `WorkspaceServiceProxy`:jsexport { WorkspaceServiceProxy } from "@cloudflare/computer";
重启或重新部署 Wrangler,然后重试:bashcurl -X POST localhost:8787/exec \
-H 'content-type: application/json' \
-d '{"cmd":"echo hi"}'
``
如果没有
enable_ctx_exports,ctx.exports 将为 undefined;如果没有重新导出,WorkspaceServiceProxy 本身也会缺失。这两种错误都会产生相同的误导性报错。该问题在 @cloudflare/computer@0.2.0、wrangler@4.123.0 和 workerd@1.20260811.1` 中均有观察到。故障排除如何修复 @cloudflare/computer 的 `edit` 工具在 `oldText` 不完全匹配时重写整个文件并移除智能引号、破折号或行尾空白的问题?
根本原因:当精确匹配失败时,packages/computer/src/tools/fs/edit-diff.ts 中的 applyEditsToNormalizedContent 会针对经过模糊规范化(fuzzy-normalized)的副本进行匹配,但却错误地将该规范化副本同时用作写入和生成 diff 的 baseContent。因此,无关的 Unicode 标点符号和行尾空白会被压平抹除。
临时解决方法:让 oldText 逐字节精确匹配。移除意外添加的行尾空格,并保留智能引号(U+201C/U+201D)、长破折号(U+2014)以及文件原有的 Unicode 规范化形式。对于该复现示例,请将:
oldText: "let target = 1; "
改为:
oldText: "let target = 1;"
可以使用 sed -n l path/to/file 或 od -c path/to/file 检查不可见字符。
永久修复:仅将规范化后的内容用于匹配,维护一张从规范化字符映射回原始文件的源偏移量表(source-offset map),将替换内容拼接到原始内容中,并基于原始内容与编辑后内容生成 diff。拒绝存在歧义的映射,例如 Unicode 规范化导致字符合并的情况,或匹配仅覆盖扩展连字(ligature)一部分的情况。该修复由 PR fix: preserve files during fuzzy edits (#51) 实现。
受影响版本:@cloudflare/computer 0.1.0-alpha.1,对应提交 76d9e75。使用以下命令验证:
npm test --workspace @cloudflare/computer -- src/tools/fs/repro.test.ts故障排除为什么 Worker JavaScript capability 大小错误显示的是字面量 ${maxCapabilityBytes},而不是配置的字节限制?
限制值在大小比较中会被插值,但错误消息是作为普通的双引号字符串生成的,因此 ${maxCapabilityBytes} 不会被替换。修复 packages/computer/src/backends/worker-javascript/module-graph.ts 中的 capabilitiesModule(),在生成模块时插入配置的值,例如:throw new Error(${JSON.stringify(Workspace capability request exceeds ${maxCapabilityBytes} bytes.)});。当 maxCapabilityBytes: 256 时,生成的运行时代码必须变为:throw new Error("Workspace capability request exceeds 256 bytes.");。重新构建或重新生成 Worker 模块并重新部署。如果有可用版本,请更新到包含 PR #99 的版本,而不是手动修补。
故障排除I don't have any information about a project called "computerd" or its 0.3.0 release, so I can't tell you the actual reason for that endpoint change. It may be a project that isn't widely documented in my training data, or one that was released after my knowledge cutoff.
For the real answer, I'd check the project's CHANGELOG.md, the GitHub release notes for 0.3.0, or the commit/PR that introduced the change — those usually explain the motivation.
If it helps, common reasons projects make this kind of move include consolidating HTTP and WebSocket traffic under a single path prefix (simplifying reverse proxy configs like nginx or Caddy), avoiding route conflicts with other handlers, or aligning with a versioned API structure — but that's general speculation, not knowledge of this specific change.
在 computerd 0.3.0 中,Cap'n Web 端点已整合:WebSocket 连接应使用 /api,不再使用 /ws。服务器通过带有 Upgrade 头的 GET 请求来区分 WebSocket 请求与 HTTP 请求。旧的 /ws 路径已被移除。请注意,HTTP 批处理支持也在 0.3.0 中被移除,因为在 streams 迁移之后,它无法连接到 RPC 调用返回的 streams。
故障排除为什么 Workspace.fs 会暴露 symlink()、readlink()、lstat() 和 chmod(),而文档中却说符号链接是内部的?
文档已过时。在已发布的 API 中,这些方法是有意在 WorkspaceFilesystem 上公开的,并由 WorkspaceFilesystemStub 在 Workers RPC 边界上进行镜像。
将它们用作基于 Promise 的文件系统 API:
await workspace.fs.symlink(targetPath, linkPath);
const target = await workspace.fs.readlink(linkPath);
const linkStats = await workspace.fs.lstat(linkPath);
await workspace.fs.chmod(filePath, 0o644);
stat() 会跟随末尾的符号链接并报告目标,而 lstat() 报告链接本身。相关错误包括:路径不存在时的 ENOENT、参数或操作无效时的 EINVAL,以及遇到过多符号链接时的 ELOOP。
修复方法是更新 docs/04_filesystem_interface.md,补充 symlink、readlink、lstat 和 chmod 的文档,并删除符号链接仅供内部使用的说法。移除这些方法将是一个破坏性的 API 变更。