Skip to content

fix(agent-host): install agents without renaming into place - #89

Merged
deymosh merged 2 commits into
masterfrom
fix/agent-install-without-renames
Oct 7, 2026
Merged

deymosh merged 2 commits into
masterfrom
fix/agent-install-without-renames

Conversation

@deymosh

@deymosh deymosh commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Reworks how agent runtimes are laid down, after a review of the rename-retry workaround.

Before: each package of the DeepSeek Harness tree was extracted into a staging directory and renamed into place, and each agent binary was written to a temp file and renamed. A Windows host's bind mount, or a Windows disk an antivirus is scanning, refuses such renames for a moment. The retry budget was about 2.5 s (npm's own is up to 60 s), so a slow scan failed the whole install.

Now nothing is renamed into place:

  • A tree package is extracted straight into its directory with package.json written last. It counts as installed only once that file names the pinned version, so an interrupted package is laid down again next time.
  • A binary is written in place, and an .installed marker holding the pin's sha512 is written after it. Binaries installed before this have no marker and are downloaded once more.
  • Removing a package directory goes through fs.rmSync's own retries for transient EBUSY/EPERM.

Two existing bugs found along the way:

  • Laying a package down again replaced its directory, including packages nested in its node_modules. Those had been judged installed beforehand, so they were never restored. Nested entries are now redone with their parent.
  • @types/* tarballs ship under their own name (node/, retry/), not package/. They landed one level too deep, so the DeepSeek runtime downloaded 3 packages again on every host start. The extractor now strips any single top-level directory, as npm does.

Verified live (Linux, empty cache, Claude's bundled binary hidden so it installs on demand): Claude Code 2.1.283, OpenCode 1.18.32 and DeepSeek Harness 0.2.0-rc.2 all installed and ran --version. A second warm-up downloaded nothing. Removing one package's package.json re-fetched exactly that package. Agent host typecheck and tests (503) pass. Not run live: Windows native and musl. CI runs the installer tests on Windows.

🤖 Generated with Claude Code

deymosh and others added 2 commits October 7, 2026 17:24
Agent runtimes were staged and then renamed into place, one directory
rename per package of the DeepSeek Harness tree and one file rename per
agent binary. Some filesystems the cache lives on refuse such a rename
for a moment after the files were written: a Windows host's directory
bind-mounted into the bridge container, or a Windows disk an antivirus
is scanning. The renames were retried for about 2.5 s, which an
antivirus scan can easily outlast, failing the whole install.

Completeness is now recorded instead of made atomic by a rename:

- a package of a tree is extracted straight into its directory with its
  package.json written last, and counts as installed only once that file
  names the pinned version, so a package cut off mid-extraction is laid
  down again by the next install;
- an agent binary is written in place and counts as installed only once
  a marker beside it holds the pin's sha512 (a binary installed before
  this has no marker and is downloaded once more).

Laying a package down again replaces its directory, nested packages
included; those were judged installed beforehand and so were neither
fetched nor restored, leaving the tree without them. Everything nested
under a package being laid down is now laid down with it.

Co-Authored-By: Claude Code <noreply@anthropic.com>
npm strips whatever single top-level directory a package tarball has,
and most have package/. DefinitelyTyped's packages do not: @types/node
ships under node/, @types/retry under retry/. The tree installer only
stripped package/, so those landed one directory too deep, their
package.json was never where the installer looked, and the DeepSeek
Harness runtime downloaded three packages again on every host start.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@deymosh
deymosh merged commit 2c2ce47 into master Oct 7, 2026
6 checks passed
@deymosh deymosh mentioned this pull request Oct 7, 2026
@deymosh
deymosh deleted the fix/agent-install-without-renames branch October 7, 2026 15:50
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.

1 participant