Cherry-pick of #56635 to preview ---- We currently run node on the JS wrapper around the native binaries shipped with https://github.com/github/copilot-language-server-release. According to their README, this is not required, and it seems like it is just an option provided so that you can run the server with `npx`. 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) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #55891 Release Notes: - Stopped relying on node for running the Copilot language server that provides edit predictions. The system node version should no longer affect whether Copilot edit predictions work in Zed Co-authored-by: Ben Kunkle <ben@zed.dev>
This commit is contained in:
co-authored by
Ben Kunkle
parent
f40b5b5e57
commit
7032a1781c
Generated
-1
@@ -3648,7 +3648,6 @@ dependencies = [
|
||||
"pretty_assertions",
|
||||
"project",
|
||||
"rpc",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"settings",
|
||||
|
||||
@@ -40,7 +40,6 @@ 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
|
||||
|
||||
@@ -27,7 +27,6 @@ use parking_lot::Mutex;
|
||||
use project::project_settings::ProjectSettings;
|
||||
use project::{DisableAiSettings, Project};
|
||||
use request::DidChangeStatus;
|
||||
use semver::Version;
|
||||
use serde_json::json;
|
||||
use settings::{Settings, SettingsStore};
|
||||
use std::{
|
||||
@@ -567,17 +566,11 @@ impl Copilot {
|
||||
cx: &mut AsyncApp,
|
||||
) {
|
||||
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 server_path = get_copilot_lsp(fs, node_runtime).await?;
|
||||
|
||||
let arguments: Vec<OsString> = vec![
|
||||
"--experimental-sqlite".into(),
|
||||
server_path.into(),
|
||||
"--stdio".into(),
|
||||
];
|
||||
let arguments: Vec<OsString> = vec!["--stdio".into()];
|
||||
let binary = LanguageServerBinary {
|
||||
path: node_path,
|
||||
path: server_path,
|
||||
arguments,
|
||||
env,
|
||||
};
|
||||
@@ -1396,44 +1389,6 @@ 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_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<dyn Fs>, node_runtime: NodeRuntime) -> anyhow::Result<PathBuf> {
|
||||
const PACKAGE_NAME: &str = "@github/copilot-language-server";
|
||||
const SERVER_PATH: &str =
|
||||
@@ -1443,17 +1398,19 @@ async fn get_copilot_lsp(fs: Arc<dyn Fs>, node_runtime: NodeRuntime) -> anyhow::
|
||||
.npm_package_latest_version(PACKAGE_NAME)
|
||||
.await?;
|
||||
let server_path = paths::copilot_dir().join(SERVER_PATH);
|
||||
let binary_path = copilot_lsp_native_binary_path()?;
|
||||
|
||||
fs.create_dir(paths::copilot_dir()).await?;
|
||||
|
||||
let should_install = node_runtime
|
||||
.should_install_npm_package(
|
||||
PACKAGE_NAME,
|
||||
&server_path,
|
||||
paths::copilot_dir(),
|
||||
VersionStrategy::Latest(&latest_version),
|
||||
)
|
||||
.await;
|
||||
let should_install = !fs.is_file(&binary_path).await
|
||||
|| node_runtime
|
||||
.should_install_npm_package(
|
||||
PACKAGE_NAME,
|
||||
&server_path,
|
||||
paths::copilot_dir(),
|
||||
VersionStrategy::Latest(&latest_version),
|
||||
)
|
||||
.await;
|
||||
if should_install {
|
||||
node_runtime
|
||||
.npm_install_packages(
|
||||
@@ -1463,7 +1420,40 @@ async fn get_copilot_lsp(fs: Arc<dyn Fs>, node_runtime: NodeRuntime) -> anyhow::
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(server_path)
|
||||
if fs.is_file(&binary_path).await {
|
||||
return Ok(binary_path);
|
||||
}
|
||||
|
||||
anyhow::bail!("GitHub Copilot native language server binary was not installed")
|
||||
}
|
||||
|
||||
fn copilot_lsp_native_binary_path() -> anyhow::Result<PathBuf> {
|
||||
let platform = match env::consts::OS {
|
||||
"linux" => "linux",
|
||||
"macos" => "darwin",
|
||||
"windows" => "win32",
|
||||
platform => anyhow::bail!("unsupported Copilot language server platform: {platform}"),
|
||||
};
|
||||
let architecture = match env::consts::ARCH {
|
||||
"aarch64" => "arm64",
|
||||
"x86_64" => "x64",
|
||||
architecture => {
|
||||
anyhow::bail!("unsupported Copilot language server architecture: {architecture}")
|
||||
}
|
||||
};
|
||||
|
||||
let package_name = format!("copilot-language-server-{platform}-{architecture}");
|
||||
|
||||
let executable_name = if cfg!(target_os = "windows") {
|
||||
"copilot-language-server.exe"
|
||||
} else {
|
||||
"copilot-language-server"
|
||||
};
|
||||
Ok(paths::copilot_dir()
|
||||
.join("node_modules")
|
||||
.join("@github")
|
||||
.join(package_name)
|
||||
.join(executable_name))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user