Repository navigation
fix(agent-host): install agents without renaming into place - #89
Merged
Merged
Conversation
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>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
package.jsonwritten last. It counts as installed only once that file names the pinned version, so an interrupted package is laid down again next time..installedmarker holding the pin's sha512 is written after it. Binaries installed before this have no marker and are downloaded once more.fs.rmSync's own retries for transient EBUSY/EPERM.Two existing bugs found along the way:
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/), notpackage/. 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'spackage.jsonre-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