Skip to content

feat(harness): write built-in tool - #62

Merged
sanchitrk merged 12 commits into
canaryfrom
feature/write-tool
Oct 10, 2026
Merged

sanchitrk merged 12 commits into
canaryfrom
feature/write-tool

Conversation

@sanchitrk

@sanchitrk sanchitrk commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Builds on read (#45, merged).

write

  • Matches Pi's write tool: parameters path and content, Pi's description, prompt snippet ("Create or overwrite files") and guideline, and the result text Successfully wrote to <path>. details is left empty, as in Pi.
  • Creates missing parent directories (the filesystem layer already did this on every backend). Normalises Unicode spaces and a leading @ in paths.
  • The whole write holds the file's mutation lock, so it never interleaves with an edit of the same file.
  • Filesystem errors (ENOTDIR, EISDIR, …) reach the model as tool errors.

writeFile is now uninterruptible

A write that has started cannot be called back. Before this change, interrupting it released the file's lock while the write was still in flight, so a queued write could start and then be overwritten by the abandoned one. This is Pi's "keeps the mutation queue locked until an aborted write settles" case.

Tests

  • tools.write.test.ts: an E2E turn through the harness covering 10 cases (new file, nested parents, overwrite, empty content, unicode/CRLF, path normalisation, parent is a file, target is a directory, invalid arguments), snapshotted with the resulting files to __artifacts__/tools.write.json.
  • A cancellation test ported from Pi, run over a provider whose first write blocks: an interrupted write keeps the file locked until it settles. I checked that it fails without the fix.

Known limitation, not changed here: a write through a dangling symlink gets a different lock key than a write to the symlink's target. That comes from the existing mutation-queue keying, which works the same way as Pi's.

🤖 Generated with Claude Code

prem315 and others added 5 commits September 30, 2026 21:33
Rewrite `read` to match Pi's read tool: Pi's parameters, description,
prompt snippet and continuation notices; text read through `scanLines`
so only the shown window leaves the sandbox; images detected by magic
bytes (animated PNGs excluded), converted and resized with Photon on a
worker thread with EXIF orientation applied; binary files reported as
unsupported; macOS path spellings resolved.

Add `readBytes` to the sandbox filesystem contract, with a base64 shell
form for remote backends, and an optional `encodeDetails` on tool
definitions so a payload carried in content is not stored twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add `write` matching Pi's write tool: Pi's parameters, description and
prompt text, `Successfully wrote to <path>`, parent directories created,
and the whole write held under the file's mutation lock.

Make `SandboxFileSystem.writeFile` uninterruptible: a started write
cannot be called back, so interrupting it only released the file's lock
while its bytes still landed over the next writer's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from feature/read-tool to canary October 10, 2026 04:54
# Conflicts:
#	packages/harness/src/plugin/builtin.ts
#	packages/harness/test/plugin.external.test.ts
#	packages/harness/test/plugin.git.live.test.ts
#	packages/plugin/src/sandbox/filesystem.ts
@sanchitrk
sanchitrk merged commit 0f53495 into canary Oct 10, 2026
@sanchitrk
sanchitrk deleted the feature/write-tool branch October 10, 2026 05:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants