Skip to content

computer: Fix issues found by a deployed test of the stack - #190

Open
mattzcarey wants to merge 5 commits into
feat/js-no-execution-capfrom
fix/lab-findings
Open

mattzcarey wants to merge 5 commits into
feat/js-no-execution-capfrom
fix/lab-findings

Conversation

@mattzcarey

@mattzcarey mattzcarey commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Stacked on #189.

These fixes come from running the stack on a deployed Worker and trying to break it. The lab Durable Object had a JavaScript backend with ws:container, ws:git, a host module, and a source module, plus WorkerShellBackend and ContainerBackend, driven through createAITools both locally and through getWorkspace(stub). Each fix is its own commit.

Remote clients offered a publish that failed. A remote client's assets getter returned the stub's property, which over RPC is always a placeholder. createAITools built from getWorkspace(stub) therefore offered publish on a Workspace with no assets, and calling it failed with "The RPC receiver does not implement the method assets". The stub now exposes a plain hasAssets boolean, read once when the client is created, as useThink already is.

A result with an undefined field failed the run.

export default () => ({ kept: 1, dropped: undefined });
// before: failed, "Workspace code inputs and results must be JSON-compatible values."
// after:  completed, { kept: 1 }

The result is framed as JSON, which drops the field anyway. Values like this are common in ordinary code, so the check now treats an undefined field as absent.

A cyclic argument overflowed the stack. The isolate's early size check (#183) walked arguments without tracking what it had seen. It now stops at a repeated object and reports "must be acyclic", the same wording the host uses.

ws:container dropped the sync result. exec now also returns sync:

const { exitCode, stdout, sync } = await exec("npm install");
// sync: { status: "complete" | "pending", skipped: string[], skippedCount: number, error?: string }

pending means the container's file changes have not reached the Workspace yet, and skipped lists paths the Workspace refused, such as files in a read-only mount. The list is capped at 100 with skippedCount giving the full count, and the error is cut to 1 KiB, so a large skip can't push the result past the bridge's limits after the command has run. The lab showed one more case the report cannot catch. A file the isolate writes while the command runs is replaced by the container's version, without being reported as skipped. The module's description and docs/17_isolate_javascript.md now say the sync is last-writer-wins.

ws:git's description didn't mention -C, although cli accepts a leading -C <path>.

Script runner tests check the cyclic-argument error and the dropped undefined field in a real Dynamic Worker, and both fail without their fixes. client.test.ts checks that local and remote clients without assets leave publish out. The container module tests cover a pending sync with skipped paths.

ws:git accepts a leading -C <path> in cli, but its description for the
model did not say so, so a model reading it had no reason to use it.
…ut assets

A remote client's assets getter returned the stub's assets property,
which over RPC is always a placeholder, never undefined. createAITools
therefore offered publish on a remote client even when the Workspace
had no assets publisher, and calling it failed because the receiver
did not implement assets.

The Workspace stub now exposes a plain hasAssets boolean, which the
client reads once when it is created, as it already does for useThink.
A client without assets reports undefined, locally and remotely.
…eanly

A run that returned { kept: 1, dropped: undefined } failed with "must
be JSON-compatible values", although the result is framed as JSON,
which drops undefined fields. Values like that are common in ordinary
code, so the check now treats an undefined field as absent.

The isolate's early size check walked arguments without tracking what
it had seen, so a cyclic argument overflowed the stack. It now stops
at a repeated object and reports that values must be acyclic, the same
wording the host uses.
ws:container returned the exit code and output but dropped the sync
result, so code that called exec could not tell whether the
container's file changes had reached the Workspace, or which ones the
Workspace had refused.

exec now also returns sync: its status, the skipped paths, and the
error when the pull is still pending. The module's description and
the docs also say the sync is last-writer-wins, because a file the
isolate writes while the command runs is replaced by the container's
version without being reported as skipped.
@mattzcarey mattzcarey added the allow-pr Allow a PR to remain open. label Oct 2, 2026
@changeset-bot

changeset-bot Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ba0b9d8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@cloudflare/computer Patch
@cloudflare/dofs Patch
@cloudflare/computer-rpc Patch
@cloudflare/computerd Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

devin-ai-integration[bot]

This comment was marked as resolved.

@pkg-pr-new

pkg-pr-new Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@cloudflare/computer@190

commit: ba0b9d8

A command that wrote thousands of files into a read-only mount made
the sync summary larger than the bridge's response limits allow. exec
then failed after the command had already run and its changes had
been pulled, losing the exit code and inviting a retry that repeats
the side effects.

The summary now lists at most 100 skipped paths, adds skippedCount
with the full count, and cuts a pending sync's error to 1 KiB.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

allow-pr Allow a PR to remain open.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant