Skip to content

computer: Add workspace file tools - #81

Open
aron-cf wants to merge 13 commits into
stack/improve-tools-02-computer-fs-plumbingfrom
stack/improve-tools-03-file-tools
Open

computer: Add workspace file tools#81
aron-cf wants to merge 13 commits into
stack/improve-tools-02-computer-fs-plumbingfrom
stack/improve-tools-03-file-tools

Conversation

@aron-cf

@aron-cf aron-cf commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Stack 3 of 7. Base: stack/improve-tools-02-computer-fs-plumbing. Head: stack/improve-tools-03-file-tools.

The Computer tool set lacked recursive path search, text search, and deletion. Writes could also race an edit between its read and write phases, losing one caller's update.

This change adds find, grep, and delete to createAITools. Search remains available in read-only mode, while deletion follows the existing read-only policy for mutations. edit, write, and delete now share a store-scoped lock keyed by normalized path. Search responses are bounded and return offsets that remain valid for result sets of any size.

Verification

npm run typecheck --workspace @cloudflare/computer
npm test --workspace @cloudflare/computer -- src/tools/ai.test.ts

The next stack part improves read output and adds model-facing image and PDF content.

@changeset-bot

changeset-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

馃 Changeset detected

Latest commit: 5391ec5

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

This PR includes changesets to release 1 package
Name Type
@cloudflare/computer Minor

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

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Thanks for your interest in Cloudflare Computer.

This repository does not accept unsolicited pull requests. Please use one of the accepted contribution paths instead:

If a maintainer asked you to open this pull request, they can add the allow-pr label and reopen it.

@github-actions github-actions Bot closed this Aug 7, 2026
@aron-cf aron-cf added the allow-pr Allow a PR to remain open. label Aug 7, 2026
@aron-cf aron-cf reopened this Aug 7, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 7, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 5391ec5

@aron-cf
aron-cf marked this pull request as ready for review August 7, 2026 15:21
@aron-cf
aron-cf force-pushed the stack/improve-tools-03-file-tools branch from 88b9b07 to 8166cb0 Compare August 7, 2026 15:29
@aron-cf
aron-cf force-pushed the stack/improve-tools-03-file-tools branch from 8166cb0 to 6f86cf0 Compare August 10, 2026 10:03

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment thread packages/dofs/src/fs/grep.ts
path,
async () => {
try {
await store.remove(path, { recursive, force: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

馃煛 Deleting a path that does not exist reports success

Deletion always suppresses the missing-path error (force: true at packages/computer/src/tools/fs/delete.ts:30), so removing a path that is not there returns a success result instead of telling the caller nothing was found.

Impact: A model that mistypes a path is told the file was deleted and can proceed on the false belief that the file is gone.

How `force` swallows ENOENT

store.remove forwards to ws.fs.rm (packages/computer/src/tools/fs/store.ts:112-114), and rm returns silently when the node cannot be resolved and force is set (packages/dofs/src/fs/rm.ts:113-117). The tool then returns { deleted: path }. Since the tool input has no force flag, the caller has no way to get the ENOENT signal. Passing force: recursive === true (or not forcing at all, and mapping ENOENT to a structured error) would keep the useful ENOTEMPTY/ENOENT feedback.

Suggested change
await store.remove(path, { recursive, force: true });
await store.remove(path, { recursive });
Open in Devin Review

Was this helpful? React with 馃憤 or 馃憥 to provide feedback.

@aron-cf
aron-cf force-pushed the stack/improve-tools-03-file-tools branch 2 times, most recently from 6dbf9dd to c872ff0 Compare August 10, 2026 14:13
@aron-cf
aron-cf force-pushed the stack/improve-tools-03-file-tools branch from c872ff0 to ca97036 Compare August 10, 2026 14:40

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review


const matches: WorkspaceGrepMatch[] = [];
const state: ScanState = { seen: 0, accepted: 0 };
const filePaths = node.type === "file" ? [canonical] : filesUnder(db, canonical, options.include);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

馃煛 Text search now returns results in a different file order than before

Files to search are collected in walk order instead of sorted path order (filesUnder(...) at packages/dofs/src/fs/grep.ts:71), so results for a directory come back in a different sequence than they used to.

Impact: Callers that relied on results arriving in path order, including anyone re-running a paged search built against the old order, see results grouped differently.

Depth-first walk order versus lexicographic path order

The previous implementation collected find(db, canonical) results, filtered to files, and called .sort(), giving lexicographic path order. The new filesUnder generator (packages/dofs/src/fs/grep.ts:116-124) yields entries in the depth-first order produced by walk in packages/dofs/src/fs/find.ts:93-118, which descends into a directory as soon as it is encountered.

These differ whenever a directory name is a prefix of a sibling file name. With /d/b/c.txt and /d/b.txt, dirents sort as b, b.txt, so the walk yields /d/b/c.txt before /d/b.txt, while lexicographic order puts /d/b.txt first (. is 0x2E, / is 0x2F). The existing test "applies offset and limit across files in path and line order" only uses root-level files, so it does not catch the difference. The new order is still deterministic, so pagination within one order remains consistent; the change is in the contract, not in stability. If path order is still intended, the walk results need sorting (which costs the streaming benefit) or the documented ordering needs updating.

Prompt for agents
packages/dofs/src/fs/grep.ts previously sorted the candidate file paths lexicographically before scanning; it now consumes iterateFoundEntries lazily, which yields depth-first walk order. The two orders differ when a directory name is a prefix of a sibling file name (for example /d/b/c.txt is yielded before /d/b.txt). Decide whether grep's documented result ordering is path order or traversal order, then either restore sorting (accepting that it materializes the file list again) or update the documentation and the test named "applies offset and limit across files in path and line order" so the intended contract is explicit.
Open in Devin Review

Was this helpful? React with 馃憤 or 馃憥 to provide feedback.

@aron-cf
aron-cf force-pushed the stack/improve-tools-03-file-tools branch from ca97036 to 5e62be9 Compare August 10, 2026 18:15
@aron-cf
aron-cf force-pushed the stack/improve-tools-03-file-tools branch from 5e62be9 to 27b4253 Compare August 10, 2026 20:49
Share a store-scoped, normalized-path lock between edit and write so
read-modify-write cycles cannot clobber concurrent writes or block
unrelated workspaces.
Expose the missing workspace tools, keep find and grep available in
read-only mode, bound their result pages, and serialize delete with
other mutations.
Allow any non-negative grep offset so continuation values emitted after
large result sets remain valid inputs to the next tool call.
Record the new search and deletion tools and shared mutation locking
with the Computer package that exposes them.
@aron-cf
aron-cf force-pushed the stack/improve-tools-03-file-tools branch from 27b4253 to 5391ec5 Compare August 10, 2026 21:23
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