From 7f14ab26ddb5cccf971650d70ab4ea2b23d732b3 Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Fri, 26 Sep 2025 20:08:21 +0530 Subject: [PATCH] copilot: Ensure minimum Node version (#38945) Closes #38918 Release Notes: - N/A --- Cargo.lock | 1 + crates/copilot/Cargo.toml | 1 + crates/copilot/src/copilot.rs | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 5bbe2f880ba8fb631ccbe382aa0a029f05a78ce2..a24c27144fee39f15b6ca4f46d79cef6ac46656b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3696,6 +3696,7 @@ dependencies = [ "paths", "project", "rpc", + "semver", "serde", "serde_json", "settings", diff --git a/crates/copilot/Cargo.toml b/crates/copilot/Cargo.toml index 0fc119f31125f4ef3925799fd98fd47cac7ca9da..a0a49d6f25d42e6a578db1f1ec886e50f437e414 100644 --- a/crates/copilot/Cargo.toml +++ b/crates/copilot/Cargo.toml @@ -43,6 +43,7 @@ node_runtime.workspace = true parking_lot.workspace = true paths.workspace = true project.workspace = true +semver.workspace = true serde.workspace = true serde_json.workspace = true settings.workspace = true diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 49753c3a6d9460b86d50e395d394b6af9a819693..ffcae93b40ad07de9e577e1d2d1558505c8b6de2 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -25,6 +25,7 @@ use node_runtime::{NodeRuntime, VersionStrategy}; use parking_lot::Mutex; use project::DisableAiSettings; use request::StatusNotification; +use semver::Version; use serde_json::json; use settings::Settings; use settings::SettingsStore; @@ -485,6 +486,8 @@ impl Copilot { let start_language_server = async { let server_path = get_copilot_lsp(fs, node_runtime.clone()).await?; let node_path = node_runtime.binary_path().await?; + ensure_node_version_for_copilot(&node_path).await?; + let arguments: Vec = vec![server_path.into(), "--stdio".into()]; let binary = LanguageServerBinary { path: node_path, @@ -1161,6 +1164,44 @@ async fn clear_copilot_config_dir() { remove_matching(copilot_chat::copilot_chat_config_dir(), |_| true).await } +async fn ensure_node_version_for_copilot(node_path: &Path) -> anyhow::Result<()> { + const MIN_COPILOT_NODE_VERSION: Version = Version::new(20, 8, 0); + + log::info!("Checking Node.js version for Copilot at: {:?}", node_path); + + let output = util::command::new_smol_command(node_path) + .arg("--version") + .output() + .await + .with_context(|| format!("checking Node.js version at {:?}", node_path))?; + + if !output.status.success() { + anyhow::bail!( + "failed to run node --version for Copilot. stdout: {}, stderr: {}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr), + ); + } + + let version_str = String::from_utf8_lossy(&output.stdout); + let version = Version::parse(version_str.trim().trim_start_matches('v')) + .with_context(|| format!("parsing Node.js version from '{}'", version_str.trim()))?; + + if version < MIN_COPILOT_NODE_VERSION { + anyhow::bail!( + "GitHub Copilot language server requires Node.js {MIN_COPILOT_NODE_VERSION} or later, but found {version}. \ + Please update your Node.js version or configure a different Node.js path in settings." + ); + } + + log::info!( + "Node.js version {} meets Copilot requirements (>= {})", + version, + MIN_COPILOT_NODE_VERSION + ); + Ok(()) +} + async fn get_copilot_lsp(fs: Arc, node_runtime: NodeRuntime) -> anyhow::Result { const PACKAGE_NAME: &str = "@github/copilot-language-server"; const SERVER_PATH: &str =