From 9b2522505bae5b7bd5f9ecac5c5949443703980c Mon Sep 17 00:00:00 2001 From: xintaofei Date: Wed, 18 Mar 2026 10:16:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96agent=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/commands/acp.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/commands/acp.rs b/src-tauri/src/commands/acp.rs index 1e1549d..4756e5c 100644 --- a/src-tauri/src/commands/acp.rs +++ b/src-tauri/src/commands/acp.rs @@ -91,6 +91,25 @@ async fn detect_global_cmd_version(cmd: &str) -> Option { normalize_version_candidate(&raw) } +/// Check whether a command is available on the system PATH. +/// Uses `which` on unix and `where` on windows — lightweight and does not +/// invoke the target binary itself, avoiding side-effects or slow startups. +async fn is_cmd_available(cmd: &str) -> bool { + #[cfg(unix)] + let check_cmd = "which"; + #[cfg(windows)] + let check_cmd = "where"; + + crate::process::tokio_command(check_cmd) + .arg(cmd) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .status() + .await + .map(|s| s.success()) + .unwrap_or(false) +} + async fn detect_local_version(agent_type: AgentType) -> Option { let meta = registry::get_agent_meta(agent_type); match meta.distribution { @@ -1036,9 +1055,12 @@ pub async fn acp_connect( runtime_env.insert("OPENCLAW_RESET_SESSION".into(), "1".into()); } - if let registry::AgentDistribution::Npx { cmd, package, .. } = meta.distribution { - if detect_global_cmd_version(cmd).await.is_none() { - install_npm_global_package(package).await?; + if let registry::AgentDistribution::Npx { cmd, .. } = meta.distribution { + if !is_cmd_available(cmd).await { + return Err(AcpError::protocol(format!( + "{} SDK is not installed. Please install it in Agent Settings.", + meta.name + ))); } }