Repository navigation
docs(shell): migrating to @cloudflare/computer - #2552
mattzcarey wants to merge 1 commit into
Conversation
|
| - `created_at` and `modified_at`. Computer stamps the time of the copy. | ||
| - `mime_type`. Computer doesn't store a MIME type per file. | ||
|
|
||
| After you've checked the copied files, drop the old table with `DROP TABLE cf_workspace_default` and delete any R2 objects under the old prefix. |
There was a problem hiding this comment.
🔴 Other workspaces lose their R2 files
When namespaces share an R2 prefix, deleting all objects beneath it removes files outside the migrated workspace. r2_key includes the namespace after that shared prefix, so other Shell workspaces retain rows pointing to deleted objects.
Learn more
Shell lets one Durable Object use multiple namespaces, each with its own SQL table. Its R2 keys use the prefix followed by the namespace and file path, as shown by r2Key. A user migrating only the default namespace can keep another namespace on Shell with the same prefix. Removing the entire prefix erases that other namespace's content, while its metadata still exists.
Example: code and default both use r2Prefix: "agent-1". Migrating default and deleting agent-1/* also removes agent-1/code/src/main.ts, although cf_workspace_code still references it.
Recommended fix: Limit R2 cleanup to the r2_key values read from the migrated namespace's table before dropping it; do not delete the whole shared prefix. Verify migrated data before deleting those keys.
Was this helpful? React with 👍 or 👎 to provide feedback.
| if (entry.type === "directory") { | ||
| await to.fs.mkdir(entry.path, { recursive: true }); | ||
| } else if (entry.type === "symlink") { | ||
| await to.fs.symlink(entry.target!, entry.path); |
There was a problem hiding this comment.
🔴 Interrupted symlink copies block migration retries
If a later copy fails, the next onStart retries earlier symlinks and hits existing links. The marker stays unset, so every startup repeats the failed migration.
Learn more
The example uses a single completion marker after copying all entries. A failure after a symlink is written, such as a later R2 read or filesystem write error, leaves the marker absent. The next onStart reruns the loop, and creating the same symlink again fails because its path already exists. The agent then cannot complete its startup until the partially copied link is removed or the script is changed.
Example: Copy /shortcut first, then fail while reading /z-large.bin. On restart the copy reaches /shortcut again, receives EEXIST, and never gets to /z-large.bin.
Recommended fix: Make link copying resumable by checking the destination with lstat and comparing readlink to the source target before skipping it. Handle mismatched entries explicitly so a failed or interrupted run can safely resume.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
|
||
| - Computer only runs inside a Durable Object. It takes `ctx.storage`. D1, custom `SqlBackend`s, and `InMemoryFs` have no replacement. | ||
| - One Durable Object storage holds one Computer workspace. Shell's `namespace` option has no equivalent yet ([cloudflare/computer#219](https://github.com/cloudflare/computer/issues/219)). | ||
| - Computer keeps all file content in SQLite and does not write large files to R2 yet ([cloudflare/computer#217](https://github.com/cloudflare/computer/issues/217)). R2 mounts are read-only. |
|
|
||
| The schema is documented in [`docs/03_filesystem_schema.md`](https://github.com/cloudflare/computer/blob/main/docs/03_filesystem_schema.md). The DDL that ships is in [`packages/dofs/src/schema/`](https://github.com/cloudflare/computer/tree/main/packages/dofs/src/schema): `core.ts` for the filesystem tables, `sync.ts` for sync state, and `migrations.ts` for version upgrades. | ||
|
|
||
| Don't insert rows into the `vfs_*` tables by hand. Chunk hashes, the revision counter, and the change log have to agree with each other. Write through `workspace.fs` and Computer keeps them consistent. |
| } | ||
| ``` | ||
|
|
||
| Run the copy once, for example from `onStart`, and record that it ran so it doesn't repeat: |
| Things the copy does not keep: | ||
|
|
||
| - `created_at` and `modified_at`. Computer stamps the time of the copy. | ||
| - `mime_type`. Computer doesn't store a MIME type per file. |
| - `created_at` and `modified_at`. Computer stamps the time of the copy. | ||
| - `mime_type`. Computer doesn't store a MIME type per file. | ||
|
|
||
| After you've checked the copied files, drop the old table with `DROP TABLE cf_workspace_default` and delete any R2 objects under the old prefix. |
|
✅ agents import sizes: no significant changes ( |
agents
@cloudflare/ai-chat
@cloudflare/codemode
hono-agents
@cloudflare/shell
@cloudflare/think
@cloudflare/voice
@cloudflare/worker-bundler
commit: |
Adds
docs/shell/migrating-to-computer.mdand marks@cloudflare/shelldeprecated in its docs and README. The guide covers what changes when you switch, both storage schemas, and a script that copies a Shell workspace into Computer throughworkspace.fs.We're deprecating Shell so there's one way to give an agent a workspace: a
Workspacefrom@cloudflare/computer.cf_workspace_<namespace>andvfs_*), so switching packages doesn't move any data.First PR in the Shell deprecation stack. Docs only.