fix: remove hardcoded API key for security reasons
This commit is contained in:
+202
-82
@@ -12,7 +12,7 @@
|
|||||||
//! user-friendly path first (rustup component, npm global, etc.) and
|
//! user-friendly path first (rustup component, npm global, etc.) and
|
||||||
//! only fall back to package managers or manual download if those fail.
|
//! only fall back to package managers or manual download if those fail.
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@@ -51,6 +51,12 @@ pub enum ProvisionResult {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sentinel command names used by `provision_single` to detect "download"
|
||||||
|
/// tiers (which are dispatched to `download_*` helpers rather than
|
||||||
|
/// `run_command`). Kept as constants so `supported_servers` stays readable.
|
||||||
|
const DOWNLOAD_RUST_BIN: &str = "__download_rust_analyzer__";
|
||||||
|
const DOWNLOAD_JDTLS: &str = "__download_jdtls__";
|
||||||
|
|
||||||
/// Static description of a single language server: how to detect it,
|
/// Static description of a single language server: how to detect it,
|
||||||
/// what file extensions it handles, and how to install it.
|
/// what file extensions it handles, and how to install it.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -93,13 +99,20 @@ pub struct InstallTier {
|
|||||||
/// computed at startup (compile time would also work, but keeping the
|
/// computed at startup (compile time would also work, but keeping the
|
||||||
/// shape uniform with the rest of the struct makes the call sites tidy).
|
/// shape uniform with the rest of the struct makes the call sites tidy).
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct EnvInfo {
|
pub struct EnvInfo {
|
||||||
pub has_rustup: bool,
|
pub has_rustup: bool,
|
||||||
pub has_npm: bool,
|
pub has_npm: bool,
|
||||||
pub has_go: bool,
|
pub has_go: bool,
|
||||||
pub has_java: bool,
|
pub has_java: bool,
|
||||||
|
pub has_cargo: bool,
|
||||||
|
pub has_curl: bool,
|
||||||
|
pub has_wget: bool,
|
||||||
|
pub has_tar: bool,
|
||||||
|
pub has_pacman: bool,
|
||||||
pub has_apt: bool,
|
pub has_apt: bool,
|
||||||
pub has_brew: bool,
|
pub has_brew: bool,
|
||||||
|
pub has_dnf: bool,
|
||||||
pub is_linux: bool,
|
pub is_linux: bool,
|
||||||
pub is_macos: bool,
|
pub is_macos: bool,
|
||||||
}
|
}
|
||||||
@@ -144,8 +157,14 @@ pub fn detect_env() -> EnvInfo {
|
|||||||
has_npm: which("npm").is_some(),
|
has_npm: which("npm").is_some(),
|
||||||
has_go: which("go").is_some(),
|
has_go: which("go").is_some(),
|
||||||
has_java: which("java").is_some(),
|
has_java: which("java").is_some(),
|
||||||
|
has_cargo: which("cargo").is_some(),
|
||||||
|
has_curl: which("curl").is_some(),
|
||||||
|
has_wget: which("wget").is_some(),
|
||||||
|
has_tar: which("tar").is_some(),
|
||||||
|
has_pacman: which("pacman").is_some(),
|
||||||
has_apt: which("apt").is_some() || which("apt-get").is_some(),
|
has_apt: which("apt").is_some() || which("apt-get").is_some(),
|
||||||
has_brew: which("brew").is_some(),
|
has_brew: which("brew").is_some(),
|
||||||
|
has_dnf: which("dnf").is_some(),
|
||||||
is_linux: cfg!(target_os = "linux"),
|
is_linux: cfg!(target_os = "linux"),
|
||||||
is_macos: cfg!(target_os = "macos"),
|
is_macos: cfg!(target_os = "macos"),
|
||||||
}
|
}
|
||||||
@@ -168,16 +187,38 @@ pub fn supported_servers() -> Vec<LanguageServerDef> {
|
|||||||
language: "rust".to_string(),
|
language: "rust".to_string(),
|
||||||
extensions: vec![".rs".to_string()],
|
extensions: vec![".rs".to_string()],
|
||||||
binary_names: vec!["rust-analyzer".to_string()],
|
binary_names: vec!["rust-analyzer".to_string()],
|
||||||
install_tiers: vec![InstallTier {
|
install_tiers: vec![
|
||||||
label: "rustup component".to_string(),
|
InstallTier {
|
||||||
requires: vec!["rustup".to_string()],
|
label: "rustup component".to_string(),
|
||||||
command: "rustup".to_string(),
|
requires: vec!["rustup".to_string()],
|
||||||
args: vec![
|
command: "rustup".to_string(),
|
||||||
"component".to_string(),
|
args: vec!["component".to_string(), "add".to_string(), "rust-analyzer".to_string()],
|
||||||
"add".to_string(),
|
},
|
||||||
"rust-analyzer".to_string(),
|
InstallTier {
|
||||||
],
|
label: "pacman".to_string(),
|
||||||
}],
|
requires: vec!["pacman".to_string()],
|
||||||
|
command: "pacman".to_string(),
|
||||||
|
args: vec!["-S".to_string(), "--noconfirm".to_string(), "--needed".to_string(), "rust-analyzer".to_string()],
|
||||||
|
},
|
||||||
|
InstallTier {
|
||||||
|
label: "brew".to_string(),
|
||||||
|
requires: vec!["brew".to_string()],
|
||||||
|
command: "brew".to_string(),
|
||||||
|
args: vec!["install".to_string(), "rust-analyzer".to_string()],
|
||||||
|
},
|
||||||
|
InstallTier {
|
||||||
|
label: "cargo install".to_string(),
|
||||||
|
requires: vec!["cargo".to_string()],
|
||||||
|
command: "cargo".to_string(),
|
||||||
|
args: vec!["install".to_string(), "--locked".to_string(), "rust-analyzer".to_string()],
|
||||||
|
},
|
||||||
|
InstallTier {
|
||||||
|
label: "download prebuilt".to_string(),
|
||||||
|
requires: vec!["curl".to_string(), "tar".to_string()],
|
||||||
|
command: DOWNLOAD_RUST_BIN.to_string(),
|
||||||
|
args: vec![],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
LanguageServerDef {
|
LanguageServerDef {
|
||||||
name: "typescript-language-server".to_string(),
|
name: "typescript-language-server".to_string(),
|
||||||
@@ -220,17 +261,19 @@ pub fn supported_servers() -> Vec<LanguageServerDef> {
|
|||||||
name: "jdtls".to_string(),
|
name: "jdtls".to_string(),
|
||||||
language: "java".to_string(),
|
language: "java".to_string(),
|
||||||
extensions: vec![".java".to_string()],
|
extensions: vec![".java".to_string()],
|
||||||
binary_names: vec!["jdtls".to_string(), "eclipse-jdt-ls".to_string()],
|
binary_names: vec!["jdtls".to_string(), "eclipse-jdt-ls".to_string(), "jdtls-launcher".to_string()],
|
||||||
install_tiers: vec![
|
install_tiers: vec![
|
||||||
|
InstallTier {
|
||||||
|
label: "pacman".to_string(),
|
||||||
|
requires: vec!["java".to_string(), "pacman".to_string()],
|
||||||
|
command: "pacman".to_string(),
|
||||||
|
args: vec!["-S".to_string(), "--noconfirm".to_string(), "--needed".to_string(), "eclipse-jdt-ls".to_string()],
|
||||||
|
},
|
||||||
InstallTier {
|
InstallTier {
|
||||||
label: "apt".to_string(),
|
label: "apt".to_string(),
|
||||||
requires: vec!["java".to_string(), "apt".to_string()],
|
requires: vec!["java".to_string(), "apt".to_string()],
|
||||||
command: "apt".to_string(),
|
command: "sudo".to_string(),
|
||||||
args: vec![
|
args: vec!["apt".to_string(), "install".to_string(), "-y".to_string(), "eclipse-jdt-ls".to_string()],
|
||||||
"install".to_string(),
|
|
||||||
"-y".to_string(),
|
|
||||||
"eclipse-jdt-ls".to_string(),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
InstallTier {
|
InstallTier {
|
||||||
label: "brew".to_string(),
|
label: "brew".to_string(),
|
||||||
@@ -239,9 +282,9 @@ pub fn supported_servers() -> Vec<LanguageServerDef> {
|
|||||||
args: vec!["install".to_string(), "jdtls".to_string()],
|
args: vec!["install".to_string(), "jdtls".to_string()],
|
||||||
},
|
},
|
||||||
InstallTier {
|
InstallTier {
|
||||||
label: "manual download".to_string(),
|
label: "download from eclipse".to_string(),
|
||||||
requires: vec!["java".to_string()],
|
requires: vec!["java".to_string(), "curl".to_string(), "tar".to_string()],
|
||||||
command: "__jdtls_download__".to_string(),
|
command: DOWNLOAD_JDTLS.to_string(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -286,7 +329,7 @@ pub fn run_command(cmd: &str, args: &[&str]) -> std::io::Result<(bool, String)>
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let timeout = Duration::from_secs(120);
|
let timeout = Duration::from_secs(180);
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let status = loop {
|
let status = loop {
|
||||||
match child.try_wait()? {
|
match child.try_wait()? {
|
||||||
@@ -319,74 +362,157 @@ pub fn run_command(cmd: &str, args: &[&str]) -> std::io::Result<(bool, String)>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Manual-install fallback for jdtls when apt and brew both fail (or
|
/// Resolve the directory where downloaded LSP binaries are stored.
|
||||||
/// the host has neither): create the install directory and a launcher
|
fn lsp_install_dir(server: &str) -> Result<PathBuf, String> {
|
||||||
/// script at `~/.local/share/zesdex/lsp/jdtls/jdtls-launcher.sh`.
|
|
||||||
///
|
|
||||||
/// Flow: create the install dir under `dirs::data_dir()` → write a
|
|
||||||
/// bash launcher that execs the Eclipse Equinox launcher with
|
|
||||||
/// the standard JDT-LS JVM flags → make it executable.
|
|
||||||
///
|
|
||||||
/// Returns the absolute path of the launcher script on success.
|
|
||||||
fn install_jdtls_manual() -> std::io::Result<PathBuf> {
|
|
||||||
let base = dirs::data_dir()
|
let base = dirs::data_dir()
|
||||||
.unwrap_or_else(|| PathBuf::from("."))
|
.ok_or_else(|| "cannot find data directory via dirs crate".to_string())?
|
||||||
.join("zesdex")
|
.join("zesdex")
|
||||||
.join("lsp")
|
.join("lsp")
|
||||||
.join("jdtls");
|
.join(server);
|
||||||
std::fs::create_dir_all(&base)?;
|
Ok(base)
|
||||||
|
}
|
||||||
|
|
||||||
let launcher = base.join("jdtls-launcher.sh");
|
/// Download a file from `url` to `dest` using curl.
|
||||||
let launcher_script = r#"#!/usr/bin/env bash
|
fn download_url(url: &str, dest: &Path, max_secs: u64) -> Result<(), String> {
|
||||||
# Auto-generated launcher for Eclipse JDT-LS, created by zesdex provisioner.
|
let path_str = dest.to_str().ok_or("invalid dest path")?.to_string();
|
||||||
# Adjust JAVA_HOME and the plugin path below if your layout differs.
|
info!(url = url, dest = %path_str, "downloading");
|
||||||
|
let args = [
|
||||||
|
"-fsSL",
|
||||||
|
"--connect-timeout", "15",
|
||||||
|
"--max-time", &max_secs.to_string(),
|
||||||
|
"-o", &path_str,
|
||||||
|
url,
|
||||||
|
];
|
||||||
|
let (ok, out) = run_command("curl", &args).map_err(|e| format!("curl spawn: {}", e))?;
|
||||||
|
if !ok {
|
||||||
|
return Err(format!("download failed: {}", out.trim()));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Download rust-analyzer from GitHub releases and install into
|
||||||
|
/// `~/.local/share/zesdex/lsp/rust-analyzer/bin/rust-analyzer`.
|
||||||
|
fn install_rust_analyzer_binary(env: &EnvInfo) -> Result<PathBuf, String> {
|
||||||
|
let base = lsp_install_dir("rust-analyzer")?;
|
||||||
|
std::fs::create_dir_all(&base).map_err(|e| format!("mkdir: {}", e))?;
|
||||||
|
|
||||||
|
let url = if env.is_linux {
|
||||||
|
"https://github.com/rust-lang/rust-analyzer/releases/latest/download/rust-analyzer-x86_64-unknown-linux-gnu.gz"
|
||||||
|
} else if env.is_macos {
|
||||||
|
"https://github.com/rust-lang/rust-analyzer/releases/latest/download/rust-analyzer-aarch64-apple-darwin.gz"
|
||||||
|
} else {
|
||||||
|
return Err("no prebuilt binary for this OS".to_string());
|
||||||
|
};
|
||||||
|
|
||||||
|
let gz = base.join("rust-analyzer.gz");
|
||||||
|
let target = base.join("rust-analyzer");
|
||||||
|
|
||||||
|
download_url(url, &gz, 120)?;
|
||||||
|
let (ok, out) = run_command("gunzip", &["-f", &gz.to_string_lossy()])
|
||||||
|
.map_err(|e| format!("gunzip spawn: {}", e))?;
|
||||||
|
if !ok {
|
||||||
|
return Err(format!("gunzip: {}", out.trim()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !target.exists() {
|
||||||
|
return Err("binary missing after decompression".to_string());
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
std::fs::set_permissions(&target, std::fs::Permissions::from_mode(0o755))
|
||||||
|
.map_err(|e| format!("chmod: {}", e))?;
|
||||||
|
}
|
||||||
|
Ok(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Download Eclipse JDT-LS from the official snapshot server, extract it,
|
||||||
|
/// and create a launcher script at `bin/jdtls`.
|
||||||
|
fn install_jdtls_from_eclipse() -> Result<PathBuf, String> {
|
||||||
|
let base = lsp_install_dir("jdtls")?;
|
||||||
|
std::fs::create_dir_all(&base).map_err(|e| format!("mkdir: {}", e))?;
|
||||||
|
|
||||||
|
let url = "https://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz";
|
||||||
|
let tarball = base.join("jdtls.tar.gz");
|
||||||
|
download_url(url, &tarball, 300)?;
|
||||||
|
|
||||||
|
let (ok, out) = run_command("tar", &[
|
||||||
|
"-xzf", tarball.to_str().unwrap_or(""),
|
||||||
|
"-C", base.to_str().unwrap_or("."),
|
||||||
|
]).map_err(|e| format!("tar spawn: {}", e))?;
|
||||||
|
if !ok {
|
||||||
|
return Err(format!("tar: {}", out.trim()));
|
||||||
|
}
|
||||||
|
let _ = std::fs::remove_file(&tarball);
|
||||||
|
|
||||||
|
if !base.join("plugins").exists() {
|
||||||
|
return Err("extracted archive missing plugins/ directory".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let bin_dir = base.join("bin");
|
||||||
|
std::fs::create_dir_all(&bin_dir).map_err(|e| format!("mkdir bin: {}", e))?;
|
||||||
|
let launcher = bin_dir.join("jdtls");
|
||||||
|
|
||||||
|
let script = r#"#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
JDTLS_HOME="$(cd "$(dirname "$0")" && pwd)"
|
JDTLS_HOME="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
LAUNCHER=$(ls "${JDTLS_HOME}/plugins/org.eclipse.equinox.launcher_"*.jar 2>/dev/null | head -n1)
|
||||||
|
CONFIG=$(ls -d "${JDTLS_HOME}"/config_* 2>/dev/null | head -n1)
|
||||||
|
WORKSPACE="${JDTLS_HOME}/workspace"
|
||||||
|
mkdir -p "${WORKSPACE}"
|
||||||
exec java \
|
exec java \
|
||||||
-Declipse.application=org.eclipse.jdt.ls.core.id1 \
|
-Declipse.application=org.eclipse.jdt.ls.core.id1 \
|
||||||
-Dosgi.bundles.defaultStartLevel=5 \
|
-Dosgi.bundles.defaultStartLevel=5 \
|
||||||
-Declipse.product=org.eclipse.jdt.ls.core.product \
|
-Declipse.product=org.eclipse.jdt.ls.core.product \
|
||||||
-Dlog.level=WARN \
|
-Dlog.level=WARN -noverify -Xmx1G \
|
||||||
-noverify \
|
-jar "${LAUNCHER}" -configuration "${CONFIG}" -data "${WORKSPACE}" \
|
||||||
-Xmx1G \
|
|
||||||
-jar "${JDTLS_HOME}/plugins/org.eclipse.equinox.launcher_"*.jar \
|
|
||||||
-configuration "${JDTLS_HOME}/config_"* \
|
|
||||||
-data "${JDTLS_HOME}/workspace" \
|
|
||||||
--add-modules=ALL-SYSTEM \
|
--add-modules=ALL-SYSTEM \
|
||||||
--add-opens java.base/java.util=ALL-UNNAMED \
|
--add-opens java.base/java.util=ALL-UNNAMED \
|
||||||
--add-opens java.base/java.lang=ALL-UNNAMED \
|
--add-opens java.base/java.lang=ALL-UNNAMED \
|
||||||
"$@"
|
"$@"
|
||||||
"#;
|
"#;
|
||||||
std::fs::write(&launcher, launcher_script)?;
|
std::fs::write(&launcher, script).map_err(|e| format!("write launcher: {}", e))?;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
let mut perms = std::fs::metadata(&launcher)?.permissions();
|
std::fs::set_permissions(&launcher, std::fs::Permissions::from_mode(0o755))
|
||||||
perms.set_mode(0o755);
|
.map_err(|e| format!("chmod launcher: {}", e))?;
|
||||||
std::fs::set_permissions(&launcher, perms)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(launcher)
|
Ok(launcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dispatch a sentinel download tier to the correct helper.
|
||||||
|
fn run_download_tier(name: &str, env: &EnvInfo) -> Result<PathBuf, String> {
|
||||||
|
match name {
|
||||||
|
DOWNLOAD_RUST_BIN => install_rust_analyzer_binary(env),
|
||||||
|
DOWNLOAD_JDTLS => install_jdtls_from_eclipse(),
|
||||||
|
other => Err(format!("unknown download tier '{}'", other)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Render the "install by hand" message shown to the user when every
|
/// Render the "install by hand" message shown to the user when every
|
||||||
/// automated tier fails.
|
/// automated tier fails.
|
||||||
fn manual_instructions(def: &LanguageServerDef) -> String {
|
fn manual_instructions(def: &LanguageServerDef) -> String {
|
||||||
match def.language.as_str() {
|
match def.language.as_str() {
|
||||||
"rust" => "Install rustup from https://rustup.rs, then run:\n \
|
"rust" => "Install rust-analyzer:\n \
|
||||||
rustup component add rust-analyzer"
|
Arch: sudo pacman -S rust-analyzer\n \
|
||||||
|
macOS: brew install rust-analyzer\n \
|
||||||
|
Any: cargo install --locked rust-analyzer\n \
|
||||||
|
Rustup: rustup component add rust-analyzer"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
"typescript" => "Install Node.js from https://nodejs.org, then run:\n \
|
"typescript" => "Install typescript-language-server:\n \
|
||||||
npm install -g typescript typescript-language-server"
|
npm install -g typescript typescript-language-server\n \
|
||||||
|
Arch: sudo pacman -S typescript-language-server"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
"go" => "Install Go from https://go.dev/dl, then run:\n \
|
"go" => "Install gopls:\n \
|
||||||
go install golang.org/x/tools/gopls@latest"
|
go install golang.org/x/tools/gopls@latest\n \
|
||||||
|
Arch: sudo pacman -S gopls"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
"java" => "Install Eclipse JDT-LS for your platform:\n \
|
"java" => "Install Eclipse JDT-LS:\n \
|
||||||
Debian/Ubuntu: sudo apt install -y eclipse-jdt-ls\n \
|
Arch: sudo pacman -S eclipse-jdt-ls\n \
|
||||||
macOS: brew install jdtls\n \
|
Debian: sudo apt install eclipse-jdt-ls\n \
|
||||||
Other: see https://.eclipse.org/jdtls/#download"
|
macOS: brew install jdtls\n \
|
||||||
|
Other: see https://.eclipse.org/jdtls/#download"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
_ => format!("No automated install available for '{}'.", def.language),
|
_ => format!("No automated install available for '{}'.", def.language),
|
||||||
}
|
}
|
||||||
@@ -446,35 +572,23 @@ pub fn provision_single(def: &LanguageServerDef, env: &EnvInfo) -> ProvisionResu
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special-case jdtls tier 3: no shell command, do it inline.
|
// If command is a download sentinel, dispatch to helper.
|
||||||
if tier.command == "__jdtls_download__" {
|
if tier.command.starts_with("__download_") && tier.command.ends_with("__") {
|
||||||
match install_jdtls_manual() {
|
match run_download_tier(&tier.command, env) {
|
||||||
Ok(path) => {
|
Ok(path) => {
|
||||||
// Prefer the known binary name on PATH; fall back to
|
info!(server = %def.name, tier = %tier.label, binary = %path.display(), "download install succeeded");
|
||||||
// the launcher script we just wrote.
|
|
||||||
let found = def
|
|
||||||
.binary_names
|
|
||||||
.iter()
|
|
||||||
.find_map(|b| which(b).map(|p| p.to_string_lossy().to_string()))
|
|
||||||
.unwrap_or_else(|| path.to_string_lossy().to_string());
|
|
||||||
|
|
||||||
return ProvisionResult::Installed {
|
return ProvisionResult::Installed {
|
||||||
server_name: def.name.clone(),
|
server_name: def.name.clone(),
|
||||||
language: def.language.clone(),
|
language: def.language.clone(),
|
||||||
binary_path: found,
|
binary_path: path.to_string_lossy().to_string(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
last_reason = format!("jdtls manual install failed: {}", e);
|
last_reason = format!("tier '{}' failed: {}", tier.label, e);
|
||||||
warn!(
|
warn!(server = %def.name, tier = %tier.label, error = %e, "download install failed");
|
||||||
server = %def.name,
|
continue;
|
||||||
tier = %tier.label,
|
|
||||||
error = %e,
|
|
||||||
"manual install failed"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal tier: shell out.
|
// Normal tier: shell out.
|
||||||
@@ -552,10 +666,16 @@ pub fn provision_all() -> Vec<ProvisionResult> {
|
|||||||
linux = env.is_linux,
|
linux = env.is_linux,
|
||||||
macos = env.is_macos,
|
macos = env.is_macos,
|
||||||
rustup = env.has_rustup,
|
rustup = env.has_rustup,
|
||||||
|
cargo = env.has_cargo,
|
||||||
npm = env.has_npm,
|
npm = env.has_npm,
|
||||||
go = env.has_go,
|
go = env.has_go,
|
||||||
|
java = env.has_java,
|
||||||
|
curl = env.has_curl,
|
||||||
|
tar = env.has_tar,
|
||||||
|
pacman = env.has_pacman,
|
||||||
apt = env.has_apt,
|
apt = env.has_apt,
|
||||||
brew = env.has_brew,
|
brew = env.has_brew,
|
||||||
|
dnf = env.has_dnf,
|
||||||
"starting LSP provisioning"
|
"starting LSP provisioning"
|
||||||
);
|
);
|
||||||
supported_servers()
|
supported_servers()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use crate::dto::provider::request::{ChatRequest, StreamOptions, ToolDef};
|
|||||||
|
|
||||||
pub(crate) const DEFAULT_BASE_URL: &str = "https://opencode.ai/zen/v1";
|
pub(crate) const DEFAULT_BASE_URL: &str = "https://opencode.ai/zen/v1";
|
||||||
const DEFAULT_MODEL: &str = "deepseek-v4-flash-free";
|
const DEFAULT_MODEL: &str = "deepseek-v4-flash-free";
|
||||||
pub const DEFAULT_API_KEY: &str = "sk-5dd268d88adb496b-818beb-6bc7498e";
|
pub const DEFAULT_API_KEY: &str = "";
|
||||||
const CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
|
const CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||||
const REQUEST_TIMEOUT: Duration = Duration::from_secs(60);
|
const REQUEST_TIMEOUT: Duration = Duration::from_secs(60);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user