Skip to content

effect(patch,tool): migrate patch/index and tool/read to AppFileSystem#27155

Merged
kitlangton merged 1 commit into
devfrom
effect/patch-and-read-tool-effect
May 14, 2026
Merged

effect(patch,tool): migrate patch/index and tool/read to AppFileSystem#27155
kitlangton merged 1 commit into
devfrom
effect/patch-and-read-tool-effect

Conversation

@kitlangton
Copy link
Copy Markdown
Contributor

Summary

  • src/patch/index.ts: the apply path now returns Effect<...> values backed by AppFileSystem.Service. The pure parser, chunk replacer, and shell-argv parser stay sync. deriveNewContentsFromChunks is now a pure function that takes the original file text as an argument — callers (apply_patch tool and applyHunksToFiles) supply the content they already have, removing the embedded readFileSync.
  • src/tool/apply_patch.ts: passes the already-read source text to deriveNewContentsFromChunks instead of letting the parser do its own filesystem read.
  • src/tool/read.ts: drops fs.createReadStream + readline in favor of a Stream pipeline over AppFileSystem.Service.stream. Offset / limit / byte-cap behavior is preserved.

Shape change in patch/index.ts

  • applyHunksToFiles, applyPatch, and maybeParseApplyPatchVerified are now Effect.fn(...) values returning Effect<...>; they require AppFileSystem.Service.
  • deriveNewContentsFromChunks(filePath, chunks, originalText) now accepts the original text and is fully pure (no fs I/O).
  • The parser surface (parsePatch, maybeParseApplyPatch) is unchanged.

Line-streaming behavior in tool/read.ts

  • Uses AppFileSystem.Service.stream + a manual TextDecoder ({ stream: true }) + Stream.splitLines + Stream.runForEach.
  • The manual decoder is intentional: Stream.decodeText drops the final unterminated line when the source ends without a flush, and Stream.runForEachWhile drops the last splitLines chunk. The done flag in the callback replaces the original break for the byte-cap path so line counting matches the previous semantics.
  • Offset / limit / MAX_LINE_LENGTH truncation / MAX_BYTES cut / more / cut flags all match the previous helper.

Refs

  • packages/opencode/specs/effect/tools.mdread.ts and patch/index.ts cleanups marked done.

Test plan

  • bun run typecheck
  • bun run test test/patch/patch.test.ts (20 pass)
  • bun run test test/tool/apply_patch.test.ts (27 pass)
  • bun run test test/tool/read.test.ts (39 pass)
  • bun run test — 2574 pass, 0 fail

The patch apply path now returns Effect<...> values backed by
AppFileSystem.Service. The parser, chunk replacer, and shell-argv parser
remain pure helpers. deriveNewContentsFromChunks now takes the original
text instead of doing its own readFileSync so callers (apply_patch tool,
applyHunksToFiles) can supply the content they already have.

tool/read.ts swaps its fs.createReadStream + readline helper for a
Stream pipeline over AppFileSystem.Service.stream — TextDecoder + map
keeps the trailing unterminated line that Stream.decodeText and
Stream.runForEachWhile both drop today. Limit / offset / byte-cap
behaviour is preserved.
@kitlangton kitlangton force-pushed the effect/patch-and-read-tool-effect branch from 3690488 to ba8fba5 Compare May 13, 2026 23:42
@kitlangton kitlangton marked this pull request as ready for review May 13, 2026 23:48
@kitlangton kitlangton merged commit aa8a41d into dev May 14, 2026
10 checks passed
@kitlangton kitlangton deleted the effect/patch-and-read-tool-effect branch May 14, 2026 00:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant