Conversation
Npm.add and Npm.which keyed the package cache directory by the raw specifier string. Callers passed different forms of the same package: the plugin loader normalizes bare names to @latest before calling Npm.add, while the provider loader, the V1 config plugin refs and the core dynamic providers pass their specifier verbatim. One package could end up installed under two cache roots (packages/name@latest and packages/name), double-evaluating the module in one process and never refreshing the stale bare copy. Cache roots are now keyed by a canonical specifier: a bare name resolves to name@latest, while versioned, git and file specs keep their own root. Existing bare-name cache dirs become harmless leftovers as every caller converges on the @latest root. Refs anomalyco#48514
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.
Issue for this PR
Closes #48514
Type of change
What does this PR do?
Npm.addandNpm.whichkeyed the package cache directory by the raw specifier string, and callers pass different forms of the same package: the plugin loader normalizes bare names to@latestbefore callingNpm.add(plugin/shared.ts), while the provider loader (provider.ts), the V1 config plugin refs (config/plugin/external.ts) and the core dynamic providers pass their specifier verbatim. One package ends up installed under two cache roots, e.g.packages/opencode-worktree-guard@latestandpackages/opencode-worktree-guardcreated seconds apart in one boot.Two consequences: the package module is evaluated twice in one process (a plugin counting module evaluations on a
globalThissymbol warns "Module loaded 2 times" on every boot - reproducible withopencode-worktree-guard0.3.7), and per #48514 the bare copy is returned forever without ever being refreshed.Cache roots are now keyed by a canonical specifier: a bare name resolves to
name@latest, while versioned, git and file specs keep their own root. All five call sites converge on one install; existing bare-name dirs become harmless leftovers. The separate "existing installs never refresh" aspect (#25293) is untouched by this change.How did you verify your code works?
Npm.cacheKeyunit tests: bare name and@latestresolve to the same key (plain and scoped), versioned ranges / git specs keep their own rootbun run typecheckclean on packages/core;bun test test/npm.test.ts6/6 on bun 1.3.14Screenshots / recordings
Not a UI change.
Checklist