node_runtime: Respect npm release-age filters for managed npm installs (#56957)

Zed-managed npm installers were resolving a concrete latest version with
`npm info` and then installing `package@version`. That is brittle when
users
configure npm release-age filtering via `before` or `min-release-age`:
npm's
installer applies those rules during resolution, but our pinned install
target
could disagree with it, and therefore fail to install.

This changes managed npm installs to install `package@latest` and let
npm apply
its own resolver and user config. The local latest-version lookup
remains as a
best-effort cache freshness check, not as the exact install target.

Exact extension API installs remain unchanged because extensions
explicitly
request a package and version. If we want to revisit that we can.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #53611

Release Notes:

- Fixed npm-backed tool installs to better respect npm release-age
filters.
This commit is contained in:
Ben Brandt authored and GitHub committed 2026-05-18 21:10:06 +00:00
1 parent 10fc0fb527
commit 2a00db06ce
15 files changed
+405 -119

No files matched your search

+6 -16
View File
@@ -786,7 +786,7 @@ impl LspInstaller for PyrightLspAdapter {
fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
_latest_version: Self::BinaryVersion,
container_dir: PathBuf,
delegate: &Arc<dyn LspAdapterDelegate>,
) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
@@ -795,13 +795,8 @@ impl LspInstaller for PyrightLspAdapter {
async move {
let server_path = container_dir.join(Self::SERVER_PATH);
let latest_version = latest_version.to_string();
node.npm_install_packages(
&container_dir,
&[(Self::SERVER_NAME.as_ref(), latest_version.as_str())],
)
.await?;
node.npm_install_latest_packages(&container_dir, &[Self::SERVER_NAME.as_ref()])
.await?;
let env = delegate.shell_env().await;
Ok(LanguageServerBinary {
@@ -2252,7 +2247,7 @@ impl LspInstaller for BasedPyrightLspAdapter {
fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
_latest_version: Self::BinaryVersion,
container_dir: PathBuf,
delegate: &Arc<dyn LspAdapterDelegate>,
) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
@@ -2261,13 +2256,8 @@ impl LspInstaller for BasedPyrightLspAdapter {
async move {
let server_path = container_dir.join(Self::SERVER_PATH);
let latest_version = latest_version.to_string();
node.npm_install_packages(
&container_dir,
&[(Self::SERVER_NAME.as_ref(), latest_version.as_str())],
)
.await?;
node.npm_install_latest_packages(&container_dir, &[Self::SERVER_NAME.as_ref()])
.await?;
let env = delegate.shell_env().await;
Ok(LanguageServerBinary {