Description
Npm.add in packages/core/src/npm.ts has a cache fast-path that uses npa(pkg).name to resolve the installed package's directory. For non-registry specs (https tarballs, git URLs, github shorthand, file: paths), npa(pkg).name returns undefined and the code falls through to the spec string itself. The resulting path looks like <cache>/node_modules/<full-spec-string>/ which doesn't exist — the package is actually installed at <cache>/node_modules/<actualName>/.
The fresh-install path doesn't have this issue: it uses tree.edgesOut.values().next().value.to.{name,path} which Arborist provides correctly. Only the cache hit path is broken.
| Spec |
npa(pkg).name |
Cache fast-path |
prettier |
"prettier" |
works |
@scope/pkg@1.0.0 |
"@scope/pkg" |
works |
https://example.com/foo.tgz |
undefined |
broken |
git+https://github.com/x/y.git |
undefined |
broken |
github:owner/repo |
undefined |
broken |
file:./local.tgz |
undefined |
broken |
Plugins
This blocks any plugin distribution that doesn't go through the npm registry — private GitHub releases, git URLs, github shorthand, local tarballs.
OpenCode version
Reproduces on current dev (packages/core/src/npm.ts:Npm.add lines 195-207, unchanged since the core package was extracted from opencode).
Steps to reproduce
# Configure opencode with any non-registry plugin spec
echo '{"plugin": ["https://example.com/releases/v1.0.0/example-pkg-1.0.0.tgz"]}' > ~/.config/opencode/opencode.json
# First run installs cleanly via fresh-install path
opencode run "OK" # works
# Second run hits cache fast-path, fails
opencode run "OK"
# ERROR service=plugin error=ENOENT: no such file or directory, open
# '<cache>/node_modules/https:/example.com/.../1.0.0.tgz/package.json'
Will open a fix PR shortly.
Description
Npm.addinpackages/core/src/npm.tshas a cache fast-path that usesnpa(pkg).nameto resolve the installed package's directory. For non-registry specs (https tarballs, git URLs, github shorthand, file: paths),npa(pkg).namereturnsundefinedand the code falls through to the spec string itself. The resulting path looks like<cache>/node_modules/<full-spec-string>/which doesn't exist — the package is actually installed at<cache>/node_modules/<actualName>/.The fresh-install path doesn't have this issue: it uses
tree.edgesOut.values().next().value.to.{name,path}which Arborist provides correctly. Only the cache hit path is broken.npa(pkg).nameprettier"prettier"@scope/pkg@1.0.0"@scope/pkg"https://example.com/foo.tgzundefinedgit+https://github.com/x/y.gitundefinedgithub:owner/repoundefinedfile:./local.tgzundefinedPlugins
This blocks any plugin distribution that doesn't go through the npm registry — private GitHub releases, git URLs, github shorthand, local tarballs.
OpenCode version
Reproduces on current
dev(packages/core/src/npm.ts:Npm.addlines 195-207, unchanged since thecorepackage was extracted fromopencode).Steps to reproduce
Will open a fix PR shortly.