feat(coding-agent): consolidated and optimize archive handling

- Centralized archive operations into a new `utils/zip.ts` module with unified support for ZIP, tar, and tar.gz formats.
- Optimized ZIP reading using lazy, ranged central-directory access and implemented ZIP64 support for large files.
- Hardened archive extraction with directory traversal protection and configured memory limits for loading and extraction.
- Refactored tool-specific logic to utilize the new centralized utility and deleted the redundant `archive-reader.ts`.
This commit is contained in:
can1357
2026-06-18 19:20:52 +02:00
parent 38d1d3a2f5
commit 021d82ac1f
11 changed files with 911 additions and 815 deletions
+2 -2
View File
@@ -6,7 +6,7 @@
- Entry: `packages/coding-agent/src/tools/write.ts`
- Model-facing prompt: `packages/coding-agent/src/prompts/tools/write.md`
- Key collaborators:
- `packages/coding-agent/src/tools/archive-reader.ts` — parse `archive.ext:entry` selectors.
- `packages/coding-agent/src/utils/zip.ts` — the unified ZIP/tar wrapper: parse `archive.ext:entry` selectors and rewrite the archive whole.
- `packages/coding-agent/src/tools/sqlite-reader.ts` — detect SQLite paths and perform row insert/update/delete.
- `packages/coding-agent/src/tools/conflict-detect.ts` — parse `conflict://` URIs and splice recorded merge-conflict regions.
- `packages/coding-agent/src/lsp/index.ts` — format-on-write and diagnostics writethrough.
@@ -56,7 +56,7 @@ Single-shot result.
1. `WriteTool.execute()` in `packages/coding-agent/src/tools/write.ts` strips pasted `[PATH#HASH]` headers and `LINE:` hashline prefixes from `content` when the session is in hashline display mode.
2. If `path` is an internal URL whose handler exposes `write`, the tool delegates directly to `handler.write(...)` and returns.
3. `conflict://...` paths are handled next by the merge-conflict resolver. Scope reads such as `conflict://<id>/ours` are rejected as read-only; writable conflict URIs must omit the scope.
4. It calls `#resolveArchiveWritePath()` next. That uses `parseArchivePathCandidates()` from `packages/coding-agent/src/tools/archive-reader.ts`, checks candidate archive files on disk (longest match first), and falls back to the shortest candidate archive path even when the archive file does not exist yet.
4. It calls `#resolveArchiveWritePath()` next. That uses `parseArchivePathCandidates()` from `packages/coding-agent/src/utils/zip.ts`, checks candidate archive files on disk (longest match first), and falls back to the shortest candidate archive path even when the archive file does not exist yet.
5. Archive writes call `enforcePlanModeWrite(..., { op: exists ? "update" : "create" })`, then `#writeArchiveEntry()`.
- The parent directory of the archive file is created with `fs.mkdir(..., { recursive: true })`.
- `.zip` archives are read with `fflate.unzipSync()`, the target entry is replaced in an in-memory map, and the archive is rewritten with `fflate.zipSync()` + `Bun.write()`.