From 879d96f5a489424edab7c19c4d7b0fa76eae301c Mon Sep 17 00:00:00 2001 From: xintaofei Date: Tue, 17 Mar 2026 18:10:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BD=BB=E5=BA=95=E5=88=A0=E9=99=A4=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E4=B8=8D=E5=AE=8C=E6=95=B4=E7=9A=84Agent=E5=92=8C?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=87=8F=E8=BD=BB?= =?UTF-8?q?=E7=BB=B4=E6=8A=A4=E5=B7=A5=E4=BD=9C=E9=87=8F=EF=BC=8C=E7=AD=89?= =?UTF-8?q?=E5=90=8E=E7=BB=AD=E7=9C=9F=E6=AD=A3=E9=80=82=E9=85=8D=E5=A5=BD?= =?UTF-8?q?=E4=BA=86=E5=86=8D=E5=8A=A0=E5=9B=9E=E6=9D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/acp/connection.rs | 16 - src-tauri/src/acp/preflight.rs | 80 ---- src-tauri/src/acp/registry.rs | 353 ------------------ src-tauri/src/commands/acp.rs | 174 +-------- src-tauri/src/commands/conversations.rs | 7 - src-tauri/src/lib.rs | 1 - src-tauri/src/models/agent.rs | 30 -- src/components/agent-icon.tsx | 201 +--------- .../settings/acp-agent-settings.tsx | 125 +------ src/lib/tauri.ts | 10 - src/lib/types.ts | 60 --- 11 files changed, 19 insertions(+), 1038 deletions(-) diff --git a/src-tauri/src/acp/connection.rs b/src-tauri/src/acp/connection.rs index e4659c7..ef63c20 100644 --- a/src-tauri/src/acp/connection.rs +++ b/src-tauri/src/acp/connection.rs @@ -169,22 +169,6 @@ async fn build_agent( let refs: Vec<&str> = parts.iter().map(|s| s.as_str()).collect(); AcpAgent::from_args(&refs).map_err(|e| AcpError::SpawnFailed(e.to_string())) } - AgentDistribution::Uvx { - package, args, env, .. - } => { - let merged_env = merge_agent_env(env, runtime_env); - let mut parts: Vec = Vec::new(); - for (k, v) in &merged_env { - parts.push(format!("{k}={v}")); - } - parts.push("uvx".into()); - parts.push(package.into()); - for a in args { - parts.push((*a).into()); - } - let refs: Vec<&str> = parts.iter().map(|s| s.as_str()).collect(); - AcpAgent::from_args(&refs).map_err(|e| AcpError::SpawnFailed(e.to_string())) - } AgentDistribution::Binary { version, cmd, diff --git a/src-tauri/src/acp/preflight.rs b/src-tauri/src/acp/preflight.rs index bb04473..e67052f 100644 --- a/src-tauri/src/acp/preflight.rs +++ b/src-tauri/src/acp/preflight.rs @@ -9,10 +9,6 @@ use crate::models::agent::AgentType; /// Stores `Some(checks)` after a successful (all-pass) run; /// stays `None` if checks failed so they are retried next time. static NPX_ENV_CACHE: Mutex>> = Mutex::new(None); -/// Cache for UVX environment check results. -/// Stores `Some(checks)` after a successful (all-pass) run; -/// stays `None` if checks failed so they are retried next time. -static UVX_ENV_CACHE: Mutex>> = Mutex::new(None); #[derive(Debug, Clone, Serialize)] #[serde(rename_all = "snake_case")] @@ -57,7 +53,6 @@ pub async fn run_preflight(agent_type: AgentType) -> PreflightResult { debug_assert_eq!(meta.agent_type, agent_type); let checks = match &meta.distribution { AgentDistribution::Npx { node_required, .. } => check_npx_environment(*node_required).await, - AgentDistribution::Uvx { .. } => check_uvx_environment().await, AgentDistribution::Binary { version, cmd, @@ -259,81 +254,6 @@ fn build_node_version_check(current_version: Option<&str>, required: &str) -> Ch } } -async fn check_uvx_environment() -> Vec { - // Return cached result if a previous check passed - let cached = UVX_ENV_CACHE.lock().unwrap().clone(); - if let Some(cached) = cached { - return cached; - } - - // Run uv and uvx checks in parallel - let (uv_result, uvx_result) = tokio::join!( - crate::process::tokio_command("uv") - .arg("--version") - .output(), - crate::process::tokio_command("uvx") - .arg("--version") - .output(), - ); - - let install_fix = vec![FixAction { - label: "Install uv".into(), - kind: FixActionKind::OpenUrl, - payload: "https://docs.astral.sh/uv/getting-started/installation/".into(), - }]; - - let uv_check = match uv_result { - Ok(output) if output.status.success() => { - let version = String::from_utf8_lossy(&output.stdout).trim().to_string(); - CheckItem { - check_id: "uv_available".into(), - label: "uv".into(), - status: CheckStatus::Pass, - message: format!("uv {version} available"), - fixes: vec![], - } - } - _ => CheckItem { - check_id: "uv_available".into(), - label: "uv".into(), - status: CheckStatus::Fail, - message: "uv is not installed or not in PATH".into(), - fixes: install_fix.clone(), - }, - }; - - let uvx_check = match uvx_result { - Ok(output) if output.status.success() => { - let version = String::from_utf8_lossy(&output.stdout).trim().to_string(); - CheckItem { - check_id: "uvx_available".into(), - label: "uvx".into(), - status: CheckStatus::Pass, - message: format!("uvx {version} available"), - fixes: vec![], - } - } - _ => CheckItem { - check_id: "uvx_available".into(), - label: "uvx".into(), - status: CheckStatus::Fail, - message: "uvx is not installed or not in PATH".into(), - fixes: install_fix, - }, - }; - - let checks = vec![uv_check, uvx_check]; - - let all_passed = checks - .iter() - .all(|c| !matches!(c.status, CheckStatus::Fail)); - if all_passed { - *UVX_ENV_CACHE.lock().unwrap() = Some(checks.clone()); - } - - checks -} - async fn check_binary_environment( agent_type: AgentType, version: &str, diff --git a/src-tauri/src/acp/registry.rs b/src-tauri/src/acp/registry.rs index 356b118..21dffa5 100644 --- a/src-tauri/src/acp/registry.rs +++ b/src-tauri/src/acp/registry.rs @@ -10,12 +10,6 @@ pub enum AgentDistribution { /// Minimum Node.js version required, e.g. "22.12.0". None means no specific requirement. node_required: Option<&'static str>, }, - Uvx { - version: &'static str, - package: &'static str, - args: &'static [&'static str], - env: &'static [(&'static str, &'static str)], - }, Binary { version: &'static str, cmd: &'static str, @@ -43,7 +37,6 @@ impl AcpAgentMeta { pub fn registry_version(&self) -> Option<&'static str> { match &self.distribution { AgentDistribution::Npx { version, .. } - | AgentDistribution::Uvx { version, .. } | AgentDistribution::Binary { version, .. } => Some(*version), } } @@ -78,76 +71,31 @@ pub fn current_platform() -> &'static str { pub fn all_acp_agents() -> Vec { vec![ - AgentType::Auggie, - AgentType::Autohand, AgentType::ClaudeCode, - AgentType::Cline, - AgentType::CodebuddyCode, AgentType::Codex, - AgentType::CorustAgent, - AgentType::FactoryDroid, AgentType::Gemini, - AgentType::GithubCopilot, - AgentType::Goose, - AgentType::Junie, - AgentType::Kimi, - AgentType::MinionCode, - AgentType::MistralVibe, AgentType::OpenClaw, AgentType::OpenCode, - AgentType::Qoder, - AgentType::QwenCode, - AgentType::Stakpak, ] } pub fn registry_id_for(agent_type: AgentType) -> &'static str { match agent_type { - AgentType::Auggie => "auggie", - AgentType::Autohand => "autohand", AgentType::ClaudeCode => "claude-acp", - AgentType::Cline => "cline", - AgentType::CodebuddyCode => "codebuddy-code", AgentType::Codex => "codex-acp", - AgentType::CorustAgent => "corust-agent", - AgentType::FactoryDroid => "factory-droid", AgentType::Gemini => "gemini", - AgentType::GithubCopilot => "github-copilot-cli", - AgentType::Goose => "goose", - AgentType::Junie => "junie", - AgentType::Kimi => "kimi", - AgentType::MinionCode => "minion-code", - AgentType::MistralVibe => "mistral-vibe", AgentType::OpenClaw => "openclaw-acp", AgentType::OpenCode => "opencode", - AgentType::Qoder => "qoder", - AgentType::QwenCode => "qwen-code", - AgentType::Stakpak => "stakpak", } } pub fn from_registry_id(id: &str) -> Option { match id { - "auggie" => Some(AgentType::Auggie), - "autohand" => Some(AgentType::Autohand), "claude-acp" => Some(AgentType::ClaudeCode), - "cline" => Some(AgentType::Cline), - "codebuddy-code" => Some(AgentType::CodebuddyCode), "codex-acp" => Some(AgentType::Codex), - "corust-agent" => Some(AgentType::CorustAgent), - "factory-droid" => Some(AgentType::FactoryDroid), "gemini" => Some(AgentType::Gemini), - "github-copilot-cli" | "github-copilot" => Some(AgentType::GithubCopilot), - "goose" => Some(AgentType::Goose), - "junie" | "junie-acp" => Some(AgentType::Junie), - "kimi" => Some(AgentType::Kimi), - "minion-code" => Some(AgentType::MinionCode), - "mistral-vibe" => Some(AgentType::MistralVibe), "openclaw-acp" => Some(AgentType::OpenClaw), "opencode" => Some(AgentType::OpenCode), - "qoder" => Some(AgentType::Qoder), - "qwen-code" => Some(AgentType::QwenCode), - "stakpak" => Some(AgentType::Stakpak), _ => None, } } @@ -158,30 +106,6 @@ pub fn get_agent_meta(agent_type: AgentType) -> AcpAgentMeta { Some(agent_type) ); match agent_type { - AgentType::Auggie => AcpAgentMeta { - agent_type, - name: "Auggie CLI", - description: "Augment Code's powerful software agent, backed by industry-leading context engine", - distribution: AgentDistribution::Npx { - version: "0.19.0", - package: "@augmentcode/auggie@0.19.0", - args: &["--acp"], - env: &[("AUGMENT_DISABLE_AUTO_UPDATE", "1")], - node_required: None, - }, - }, - AgentType::Autohand => AcpAgentMeta { - agent_type, - name: "Autohand Code", - description: "Autohand Code - AI coding agent powered by Autohand AI", - distribution: AgentDistribution::Npx { - version: "0.2.1", - package: "@autohandai/autohand-acp@0.2.1", - args: &[], - env: &[], - node_required: None, - }, - }, AgentType::ClaudeCode => AcpAgentMeta { agent_type, name: "Claude Code", @@ -194,30 +118,6 @@ pub fn get_agent_meta(agent_type: AgentType) -> AcpAgentMeta { node_required: None, }, }, - AgentType::Cline => AcpAgentMeta { - agent_type, - name: "Cline", - description: "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more", - distribution: AgentDistribution::Npx { - version: "2.8.0", - package: "cline@2.8.0", - args: &["--acp"], - env: &[], - node_required: None, - }, - }, - AgentType::CodebuddyCode => AcpAgentMeta { - agent_type, - name: "Codebuddy Code", - description: "Tencent Cloud's official intelligent coding tool", - distribution: AgentDistribution::Npx { - version: "2.63.1", - package: "@tencent-ai/codebuddy-code@2.63.1", - args: &["--acp"], - env: &[], - node_required: None, - }, - }, AgentType::Codex => AcpAgentMeta { agent_type, name: "Codex CLI", @@ -255,47 +155,6 @@ pub fn get_agent_meta(agent_type: AgentType) -> AcpAgentMeta { ], }, }, - AgentType::CorustAgent => AcpAgentMeta { - agent_type, - name: "Corust Agent", - description: "Co-building with a seasoned Rust partner.", - distribution: AgentDistribution::Binary { - version: "0.3.8", - cmd: "corust-agent-acp", - args: &[], - env: &[], - platforms: &[ - PlatformBinary { - platform: "darwin-aarch64", - url: "https://github.com/Corust-ai/corust-agent-release/releases/download/v0.3.8/agent-darwin-arm64.tar.gz", - }, - PlatformBinary { - platform: "darwin-x86_64", - url: "https://github.com/Corust-ai/corust-agent-release/releases/download/v0.3.8/agent-darwin-x64.tar.gz", - }, - PlatformBinary { - platform: "linux-x86_64", - url: "https://github.com/Corust-ai/corust-agent-release/releases/download/v0.3.8/agent-linux-x64.tar.gz", - }, - PlatformBinary { - platform: "windows-x86_64", - url: "https://github.com/Corust-ai/corust-agent-release/releases/download/v0.3.8/agent-windows-x64.zip", - }, - ], - }, - }, - AgentType::FactoryDroid => AcpAgentMeta { - agent_type, - name: "Factory Droid", - description: "Factory Droid - AI coding agent powered by Factory AI", - distribution: AgentDistribution::Npx { - version: "0.76.0", - package: "droid@0.76.0", - args: &["exec", "--output-format", "acp"], - env: &[("DROID_DISABLE_AUTO_UPDATE", "true"), ("FACTORY_DROID_AUTO_UPDATE_ENABLED", "false")], - node_required: None, - }, - }, AgentType::Gemini => AcpAgentMeta { agent_type, name: "Gemini CLI", @@ -308,161 +167,6 @@ pub fn get_agent_meta(agent_type: AgentType) -> AcpAgentMeta { node_required: None, }, }, - AgentType::GithubCopilot => AcpAgentMeta { - agent_type, - name: "GitHub Copilot", - description: "GitHub's AI pair programmer", - distribution: AgentDistribution::Npx { - version: "1.0.6", - package: "@github/copilot@1.0.6", - args: &["--acp"], - env: &[], - node_required: None, - }, - }, - AgentType::Goose => AcpAgentMeta { - agent_type, - name: "goose", - description: "A local, extensible, open source AI agent that automates engineering tasks", - distribution: AgentDistribution::Binary { - version: "1.27.2", - cmd: "goose", - args: &["acp"], - env: &[], - platforms: &[ - PlatformBinary { - platform: "darwin-aarch64", - url: "https://github.com/block/goose/releases/download/v1.27.2/goose-aarch64-apple-darwin.tar.bz2", - }, - PlatformBinary { - platform: "darwin-x86_64", - url: "https://github.com/block/goose/releases/download/v1.27.2/goose-x86_64-apple-darwin.tar.bz2", - }, - PlatformBinary { - platform: "linux-aarch64", - url: "https://github.com/block/goose/releases/download/v1.27.2/goose-aarch64-unknown-linux-gnu.tar.bz2", - }, - PlatformBinary { - platform: "linux-x86_64", - url: "https://github.com/block/goose/releases/download/v1.27.2/goose-x86_64-unknown-linux-gnu.tar.bz2", - }, - PlatformBinary { - platform: "windows-x86_64", - url: "https://github.com/block/goose/releases/download/v1.27.2/goose-x86_64-pc-windows-msvc.zip", - }, - ], - }, - }, - AgentType::Junie => AcpAgentMeta { - agent_type, - name: "Junie", - description: "AI Coding Agent by JetBrains", - distribution: AgentDistribution::Binary { - version: "888.195.0", - cmd: "junie", - args: &["--acp=true"], - env: &[], - platforms: &[ - PlatformBinary { - platform: "darwin-aarch64", - url: "https://github.com/JetBrains/junie/releases/download/888.195/junie-release-888.195-macos-aarch64.zip", - }, - PlatformBinary { - platform: "darwin-x86_64", - url: "https://github.com/JetBrains/junie/releases/download/888.195/junie-release-888.195-macos-amd64.zip", - }, - PlatformBinary { - platform: "linux-aarch64", - url: "https://github.com/JetBrains/junie/releases/download/888.195/junie-release-888.195-linux-aarch64.zip", - }, - PlatformBinary { - platform: "linux-x86_64", - url: "https://github.com/JetBrains/junie/releases/download/888.195/junie-release-888.195-linux-amd64.zip", - }, - PlatformBinary { - platform: "windows-x86_64", - url: "https://github.com/JetBrains/junie/releases/download/888.195/junie-release-888.195-windows-amd64.zip", - }, - ], - }, - }, - AgentType::Kimi => AcpAgentMeta { - agent_type, - name: "Kimi CLI", - description: "Moonshot AI's coding assistant", - distribution: AgentDistribution::Binary { - version: "1.22.0", - cmd: "kimi", - args: &["acp"], - env: &[], - platforms: &[ - PlatformBinary { - platform: "darwin-aarch64", - url: "https://github.com/MoonshotAI/kimi-cli/releases/download/1.22.0/kimi-1.22.0-aarch64-apple-darwin.tar.gz", - }, - PlatformBinary { - platform: "linux-aarch64", - url: "https://github.com/MoonshotAI/kimi-cli/releases/download/1.22.0/kimi-1.22.0-aarch64-unknown-linux-gnu.tar.gz", - }, - PlatformBinary { - platform: "linux-x86_64", - url: "https://github.com/MoonshotAI/kimi-cli/releases/download/1.22.0/kimi-1.22.0-x86_64-unknown-linux-gnu.tar.gz", - }, - PlatformBinary { - platform: "windows-x86_64", - url: "https://github.com/MoonshotAI/kimi-cli/releases/download/1.22.0/kimi-1.22.0-x86_64-pc-windows-msvc.zip", - }, - ], - }, - }, - AgentType::MinionCode => AcpAgentMeta { - agent_type, - name: "Minion Code", - description: "An enhanced AI code assistant built on the Minion framework with rich development tools", - distribution: AgentDistribution::Uvx { - version: "0.1.44", - package: "minion-code@0.1.44", - args: &["acp"], - env: &[], - }, - }, - AgentType::MistralVibe => AcpAgentMeta { - agent_type, - name: "Mistral Vibe", - description: "Mistral's open-source coding assistant", - distribution: AgentDistribution::Binary { - version: "2.5.0", - cmd: "vibe-acp", - args: &[], - env: &[], - platforms: &[ - PlatformBinary { - platform: "darwin-aarch64", - url: "https://github.com/mistralai/mistral-vibe/releases/download/v2.5.0/vibe-acp-darwin-aarch64-2.5.0.zip", - }, - PlatformBinary { - platform: "darwin-x86_64", - url: "https://github.com/mistralai/mistral-vibe/releases/download/v2.5.0/vibe-acp-darwin-x86_64-2.5.0.zip", - }, - PlatformBinary { - platform: "linux-aarch64", - url: "https://github.com/mistralai/mistral-vibe/releases/download/v2.5.0/vibe-acp-linux-aarch64-2.5.0.zip", - }, - PlatformBinary { - platform: "linux-x86_64", - url: "https://github.com/mistralai/mistral-vibe/releases/download/v2.5.0/vibe-acp-linux-x86_64-2.5.0.zip", - }, - PlatformBinary { - platform: "windows-aarch64", - url: "https://github.com/mistralai/mistral-vibe/releases/download/v2.5.0/vibe-acp-windows-aarch64-2.5.0.zip", - }, - PlatformBinary { - platform: "windows-x86_64", - url: "https://github.com/mistralai/mistral-vibe/releases/download/v2.5.0/vibe-acp-windows-x86_64-2.5.0.zip", - }, - ], - }, - }, AgentType::OpenClaw => AcpAgentMeta { agent_type, name: "OpenClaw", @@ -508,62 +212,5 @@ pub fn get_agent_meta(agent_type: AgentType) -> AcpAgentMeta { ], }, }, - AgentType::Qoder => AcpAgentMeta { - agent_type, - name: "Qoder CLI", - description: "AI coding assistant with agentic capabilities", - distribution: AgentDistribution::Npx { - version: "0.1.31", - package: "@qoder-ai/qodercli@0.1.31", - args: &["--acp"], - env: &[], - node_required: None, - }, - }, - AgentType::QwenCode => AcpAgentMeta { - agent_type, - name: "Qwen Code", - description: "Alibaba's Qwen coding assistant", - distribution: AgentDistribution::Npx { - version: "0.12.5", - package: "@qwen-code/qwen-code@0.12.5", - args: &["--acp", "--experimental-skills"], - env: &[], - node_required: None, - }, - }, - AgentType::Stakpak => AcpAgentMeta { - agent_type, - name: "Stakpak", - description: "Open-source DevOps agent in Rust with enterprise-grade security", - distribution: AgentDistribution::Binary { - version: "0.3.68", - cmd: "stakpak", - args: &["acp"], - env: &[], - platforms: &[ - PlatformBinary { - platform: "darwin-aarch64", - url: "https://github.com/stakpak/agent/releases/download/v0.3.68/stakpak-darwin-aarch64.tar.gz", - }, - PlatformBinary { - platform: "darwin-x86_64", - url: "https://github.com/stakpak/agent/releases/download/v0.3.68/stakpak-darwin-x86_64.tar.gz", - }, - PlatformBinary { - platform: "linux-aarch64", - url: "https://github.com/stakpak/agent/releases/download/v0.3.68/stakpak-linux-aarch64.tar.gz", - }, - PlatformBinary { - platform: "linux-x86_64", - url: "https://github.com/stakpak/agent/releases/download/v0.3.68/stakpak-linux-x86_64.tar.gz", - }, - PlatformBinary { - platform: "windows-x86_64", - url: "https://github.com/stakpak/agent/releases/download/v0.3.68/stakpak-windows-x86_64.zip", - }, - ], - }, - }, } } diff --git a/src-tauri/src/commands/acp.rs b/src-tauri/src/commands/acp.rs index 2f5d03e..a515c57 100644 --- a/src-tauri/src/commands/acp.rs +++ b/src-tauri/src/commands/acp.rs @@ -38,46 +38,6 @@ fn emit_acp_agents_updated( ); } -fn parse_version_output(output: &std::process::Output) -> Option { - let stdout = String::from_utf8_lossy(&output.stdout); - let stderr = String::from_utf8_lossy(&output.stderr); - let mut first_non_empty: Option = None; - - for raw_line in stdout.lines().chain(stderr.lines()) { - let line = raw_line.trim(); - if line.is_empty() { - continue; - } - if first_non_empty.is_none() { - first_non_empty = Some(line.to_string()); - } - - for raw_token in line.split_whitespace() { - let token = raw_token.trim_matches(|c: char| { - !(c.is_ascii_alphanumeric() || c == '.' || c == '@' || c == '-' || c == '_') - }); - if token.is_empty() { - continue; - } - - let candidate = token - .rsplit('@') - .next() - .unwrap_or(token) - .trim_matches(|c: char| !c.is_ascii_alphanumeric() && c != '.' && c != '-') - .trim_start_matches('v'); - - let is_version_like = - candidate.chars().any(|c| c.is_ascii_digit()) && candidate.contains('.'); - if is_version_like { - return Some(candidate.to_string()); - } - } - } - - first_non_empty -} - fn is_version_like(value: &str) -> bool { value.chars().any(|c| c.is_ascii_digit()) && value.contains('.') } @@ -260,28 +220,12 @@ async fn detect_npx_cached_version(package: &str) -> Option { detected } -async fn detect_uvx_cached_version(package: &str) -> Option { - let output = crate::process::tokio_command("uvx") - .arg(package) - .arg("--version") - .output() - .await - .ok()?; - if !output.status.success() { - return None; - } - parse_version_output(&output).and_then(|value| normalize_version_candidate(&value)) -} - async fn detect_local_version(agent_type: AgentType) -> Option { let meta = registry::get_agent_meta(agent_type); match meta.distribution { registry::AgentDistribution::Npx { package, .. } => { detect_npx_cached_version(package).await } - registry::AgentDistribution::Uvx { package, .. } => detect_uvx_cached_version(package) - .await - .or_else(|| version_from_package_spec(package)), registry::AgentDistribution::Binary { cmd, .. } => { binary_cache::detect_installed_version(agent_type, cmd) .ok() @@ -320,27 +264,6 @@ async fn prepare_npx_package(package: &str) -> Result<(), AcpError> { Ok(()) } -async fn prepare_uvx_package(package: &str) -> Result<(), AcpError> { - let output = crate::process::tokio_command("uvx") - .arg(package) - .arg("--version") - .output() - .await - .map_err(|e| AcpError::protocol(format!("failed to run uvx: {e}")))?; - - if !output.status.success() { - let err = String::from_utf8_lossy(&output.stderr).trim().to_string(); - let msg = if err.is_empty() { - "failed to prepare uvx package".to_string() - } else { - format!("failed to prepare uvx package: {err}") - }; - return Err(AcpError::protocol(msg)); - } - - Ok(()) -} - async fn npm_cache_dir() -> Option { let output = crate::process::tokio_command("npm") .arg("config") @@ -414,29 +337,6 @@ async fn uninstall_npx_package(package: &str) -> Result<(), AcpError> { Ok(()) } -async fn uninstall_uvx_package(package: &str) -> Result<(), AcpError> { - let package_name = package_name_from_spec(package); - if package_name.is_empty() { - return Ok(()); - } - - // Best effort: remove package cache and any explicitly installed tool. - let _ = crate::process::tokio_command("uv") - .arg("cache") - .arg("clean") - .arg(&package_name) - .output() - .await; - let _ = crate::process::tokio_command("uv") - .arg("tool") - .arg("uninstall") - .arg(&package_name) - .output() - .await; - - Ok(()) -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum SkillStorageKind { SkillDirectoryOnly, @@ -983,7 +883,6 @@ fn skill_storage_spec(agent_type: AgentType) -> Option { global_dirs: vec![home_dir_or_default().join(".openclaw").join("skills")], project_rel_dirs: vec!["skills"], }), - _ => None, } } @@ -1444,11 +1343,6 @@ pub async fn acp_list_agents( "npx", setting.and_then(|m| m.installed_version.clone()), ), - registry::AgentDistribution::Uvx { .. } => ( - true, - "uvx", - setting.and_then(|m| m.installed_version.clone()), - ), registry::AgentDistribution::Binary { platforms, cmd, .. } => { let detected = binary_cache::detect_installed_version(agent_type, cmd) .ok() @@ -1684,7 +1578,7 @@ pub async fn acp_download_agent_binary( emit_acp_agents_updated(&app, "binary_downloaded", Some(agent_type)); Ok(()) } - registry::AgentDistribution::Npx { .. } | registry::AgentDistribution::Uvx { .. } => Err( + registry::AgentDistribution::Npx { .. } => Err( AcpError::protocol("download is only supported for binary agents"), ), } @@ -1770,69 +1664,6 @@ pub async fn acp_prepare_npx_agent( registry::AgentDistribution::Binary { .. } => Err(AcpError::protocol( "prepare is only supported for npx agents", )), - registry::AgentDistribution::Uvx { .. } => Err(AcpError::protocol( - "prepare is only supported for npx agents", - )), - } -} - -#[tauri::command] -pub async fn acp_prepare_uvx_agent( - agent_type: AgentType, - registry_version: Option, - db: State<'_, AppDatabase>, - app: tauri::AppHandle, -) -> Result { - let meta = registry::get_agent_meta(agent_type); - match meta.distribution { - registry::AgentDistribution::Uvx { package, .. } => { - let default = agent_setting_service::AgentDefaultInput { - agent_type, - registry_id: registry::registry_id_for(agent_type).to_string(), - default_sort_order: i32::MAX / 2, - }; - agent_setting_service::ensure_defaults(&db.conn, &[default]) - .await - .map_err(|e| AcpError::protocol(e.to_string()))?; - - let existing = agent_setting_service::get_by_agent_type(&db.conn, agent_type) - .await - .ok() - .flatten() - .and_then(|m| m.installed_version); - - prepare_uvx_package(package).await?; - let resolved = detect_local_version(agent_type) - .await - .or_else(|| version_from_package_spec(package)) - .or_else(|| { - registry_version - .as_deref() - .and_then(normalize_version_candidate) - }) - .or(existing) - .ok_or_else(|| { - AcpError::protocol( - "uvx install succeeded but failed to determine local version", - ) - })?; - - agent_setting_service::set_installed_version( - &db.conn, - agent_type, - Some(resolved.clone()), - ) - .await - .map_err(|e| AcpError::protocol(e.to_string()))?; - emit_acp_agents_updated(&app, "uvx_prepared", Some(agent_type)); - Ok(resolved) - } - registry::AgentDistribution::Npx { .. } => Err(AcpError::protocol( - "prepare is only supported for uvx agents", - )), - registry::AgentDistribution::Binary { .. } => Err(AcpError::protocol( - "prepare is only supported for uvx agents", - )), } } @@ -1850,9 +1681,6 @@ pub async fn acp_uninstall_agent( registry::AgentDistribution::Npx { package, .. } => { uninstall_npx_package(package).await?; } - registry::AgentDistribution::Uvx { package, .. } => { - uninstall_uvx_package(package).await?; - } } agent_setting_service::set_installed_version(&db.conn, agent_type, None) diff --git a/src-tauri/src/commands/conversations.rs b/src-tauri/src/commands/conversations.rs index b694062..8eeac7e 100644 --- a/src-tauri/src/commands/conversations.rs +++ b/src-tauri/src/commands/conversations.rs @@ -142,12 +142,6 @@ pub async fn get_conversation( AgentType::OpenCode => Box::new(OpenCodeParser::new()), AgentType::Gemini => Box::new(GeminiParser::new()), AgentType::OpenClaw => Box::new(OpenClawParser::new()), - _ => { - return Err(AppCommandError::invalid_input( - "Conversation parsing is not supported for this agent", - ) - .with_detail(format!("agent_type={agent_type}"))) - } }; parser @@ -280,7 +274,6 @@ pub async fn get_folder_conversation( AgentType::OpenCode => Box::new(OpenCodeParser::new()), AgentType::Gemini => Box::new(GeminiParser::new()), AgentType::OpenClaw => Box::new(OpenClawParser::new()), - _ => return Ok((vec![], None, None)), }; match parser.get_conversation(&eid) { Ok(d) => Ok((d.turns, d.session_stats, None)), diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 646d046..c1406e7 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -279,7 +279,6 @@ pub fn run() { acp_commands::acp_download_agent_binary, acp_commands::acp_detect_agent_local_version, acp_commands::acp_prepare_npx_agent, - acp_commands::acp_prepare_uvx_agent, acp_commands::acp_uninstall_agent, acp_commands::acp_update_agent_preferences, acp_commands::acp_reorder_agents, diff --git a/src-tauri/src/models/agent.rs b/src-tauri/src/models/agent.rs index 272d812..449f64a 100644 --- a/src-tauri/src/models/agent.rs +++ b/src-tauri/src/models/agent.rs @@ -7,23 +7,8 @@ pub enum AgentType { ClaudeCode, Codex, OpenCode, - Auggie, - Autohand, - Cline, - CodebuddyCode, - CorustAgent, Gemini, - GithubCopilot, - Goose, - Junie, - Qoder, - QwenCode, - FactoryDroid, - Kimi, - MinionCode, - MistralVibe, OpenClaw, - Stakpak, } impl fmt::Display for AgentType { @@ -32,23 +17,8 @@ impl fmt::Display for AgentType { AgentType::ClaudeCode => write!(f, "Claude Code"), AgentType::Codex => write!(f, "Codex CLI"), AgentType::OpenCode => write!(f, "OpenCode"), - AgentType::Auggie => write!(f, "Auggie"), - AgentType::Autohand => write!(f, "Autohand"), - AgentType::Cline => write!(f, "Cline"), - AgentType::CodebuddyCode => write!(f, "Codebuddy Code"), - AgentType::CorustAgent => write!(f, "Corust Agent"), AgentType::Gemini => write!(f, "Gemini CLI"), - AgentType::GithubCopilot => write!(f, "GitHub Copilot"), - AgentType::Goose => write!(f, "goose"), - AgentType::Junie => write!(f, "Junie"), - AgentType::Qoder => write!(f, "Qoder CLI"), - AgentType::QwenCode => write!(f, "Qwen Code"), - AgentType::FactoryDroid => write!(f, "Factory Droid"), - AgentType::Kimi => write!(f, "Kimi CLI"), - AgentType::MinionCode => write!(f, "Minion Code"), - AgentType::MistralVibe => write!(f, "Mistral Vibe"), AgentType::OpenClaw => write!(f, "OpenClaw"), - AgentType::Stakpak => write!(f, "Stakpak"), } } } diff --git a/src/components/agent-icon.tsx b/src/components/agent-icon.tsx index 2353ad7..8178de8 100644 --- a/src/components/agent-icon.tsx +++ b/src/components/agent-icon.tsx @@ -3,13 +3,7 @@ import { AGENT_COLORS } from "@/lib/types" import { cn } from "@/lib/utils" import ClaudeColor from "@lobehub/icons/es/Claude/components/Color" -import ClineMono from "@lobehub/icons/es/Cline/components/Mono" import GeminiColor from "@lobehub/icons/es/Gemini/components/Color" -import GithubCopilotMono from "@lobehub/icons/es/GithubCopilot/components/Mono" -import GooseMono from "@lobehub/icons/es/Goose/components/Mono" -import QwenColor from "@lobehub/icons/es/Qwen/components/Color" -import KimiColor from "@lobehub/icons/es/Kimi/components/Color" -import MistralColor from "@lobehub/icons/es/Mistral/components/Color" import OpenClawColor from "@lobehub/icons/es/OpenClaw/components/Color" import { OpenAI, OpenCode } from "@lobehub/icons" @@ -24,200 +18,17 @@ type AnyIcon = React.ComponentType const COLOR_ICONS: Partial> = { claude_code: ClaudeColor, gemini: GeminiColor, - qwen_code: QwenColor, - kimi: KimiColor, - mistral_vibe: MistralColor, open_claw: OpenClawColor, } const MONO_ICONS: Partial> = { codex: OpenAI, open_code: OpenCode, - github_copilot: GithubCopilotMono, - cline: ClineMono, - goose: GooseMono, } -// Text-color versions for Mono icons and SVG fallbacks +// Text-color versions for Mono icons const AGENT_TEXT_COLORS: Partial> = { open_code: "text-blue-500", - auggie: "text-purple-500", - autohand: "text-emerald-500", - cline: "text-rose-500", - codebuddy_code: "text-violet-500", - corust_agent: "text-amber-500", - github_copilot: "text-gray-700 dark:text-gray-300", - goose: "text-lime-500", - junie: "text-pink-500", - minion_code: "text-fuchsia-500", - qoder: "text-teal-500", - factory_droid: "text-yellow-600", - stakpak: "text-slate-500", -} - -function FallbackIcon({ - agentType, - className, -}: { - agentType: AgentType - className?: string -}) { - const cls = cn("shrink-0", AGENT_TEXT_COLORS[agentType], className) - - switch (agentType) { - case "auggie": - return ( - - - - ) - case "junie": - return ( - - - - ) - case "qoder": - return ( - - - - ) - case "factory_droid": - return ( - - - - - ) - case "autohand": - return ( - - - - ) - case "codebuddy_code": - return ( - - - - ) - case "corust_agent": - return ( - - - - ) - case "minion_code": - return ( - - - - - - - ) - case "stakpak": - return ( - - - - - - ) - default: - return ( - - ) - } } export function AgentIcon({ agentType, className }: AgentIconProps) { @@ -245,5 +56,13 @@ export function AgentIcon({ agentType, className }: AgentIconProps) { ) } - return + return ( + + ) } diff --git a/src/components/settings/acp-agent-settings.tsx b/src/components/settings/acp-agent-settings.tsx index 16809c1..dd4f001 100644 --- a/src/components/settings/acp-agent-settings.tsx +++ b/src/components/settings/acp-agent-settings.tsx @@ -61,7 +61,6 @@ import { acpListAgents, acpPreflight, acpPrepareNpxAgent, - acpPrepareUvxAgent, acpReorderAgents, acpUninstallAgent, acpUpdateAgentPreferences, @@ -115,11 +114,8 @@ type RunningActionKind = | "upgrade_binary" | "install_npx" | "upgrade_npx" - | "install_uvx" - | "upgrade_uvx" | "uninstall_binary" | "uninstall_npx" - | "uninstall_uvx" | "redownload_binary" type UiFixAction = @@ -131,11 +127,8 @@ type UiFixAction = | "upgrade_binary" | "install_npx" | "upgrade_npx" - | "install_uvx" - | "upgrade_uvx" | "uninstall_binary" | "uninstall_npx" - | "uninstall_uvx" payload: string } @@ -2049,8 +2042,7 @@ function hasComparableVersion( function buildVersionCheck(agent: AcpAgentInfo): UiCheckItem | null { if ( agent.distribution_type !== "binary" && - agent.distribution_type !== "npx" && - agent.distribution_type !== "uvx" + agent.distribution_type !== "npx" ) return null @@ -2063,23 +2055,11 @@ function buildVersionCheck(agent: AcpAgentInfo): UiCheckItem | null { { remoteVersion, localVersion } ) const installAction: RunningActionKind = - agent.distribution_type === "binary" - ? "download_binary" - : agent.distribution_type === "uvx" - ? "install_uvx" - : "install_npx" + agent.distribution_type === "binary" ? "download_binary" : "install_npx" const upgradeAction: RunningActionKind = - agent.distribution_type === "binary" - ? "upgrade_binary" - : agent.distribution_type === "uvx" - ? "upgrade_uvx" - : "upgrade_npx" + agent.distribution_type === "binary" ? "upgrade_binary" : "upgrade_npx" const uninstallAction: RunningActionKind = - agent.distribution_type === "binary" - ? "uninstall_binary" - : agent.distribution_type === "uvx" - ? "uninstall_uvx" - : "uninstall_npx" + agent.distribution_type === "binary" ? "uninstall_binary" : "uninstall_npx" if (!agent.available) { return { @@ -2739,78 +2719,6 @@ export function AcpAgentSettings() { [runPreflight, t] ) - const runUvxAction = useCallback( - async (agent: AcpAgentInfo, mode: "install" | "upgrade") => { - if (busyActionRef.current.has(agent.agent_type)) return - busyActionRef.current.add(agent.agent_type) - setBusyBinaryAction((prev) => ({ ...prev, [agent.agent_type]: true })) - setRunningActionKind((prev) => ({ - ...prev, - [agent.agent_type]: mode === "install" ? "install_uvx" : "upgrade_uvx", - })) - try { - const installedVersion = await acpPrepareUvxAgent( - agent.agent_type, - agent.registry_version - ) - setAgents((prev) => - prev.map((item) => - item.agent_type === agent.agent_type - ? { ...item, installed_version: installedVersion } - : item - ) - ) - await runPreflight(agent.agent_type) - const detectedVersion = await acpDetectAgentLocalVersion( - agent.agent_type - ) - if (detectedVersion && detectedVersion !== installedVersion) { - setAgents((prev) => - prev.map((item) => - item.agent_type === agent.agent_type - ? { ...item, installed_version: detectedVersion } - : item - ) - ) - } - const finalVersion = detectedVersion ?? installedVersion - toast.success( - t("toasts.agentActionCompleted", { - name: agent.name, - action: - mode === "upgrade" ? t("actions.upgrade") : t("actions.install"), - }), - { - description: finalVersion - ? t("toasts.localVersion", { version: finalVersion }) - : t("toasts.installCompletedVersionLater"), - } - ) - } catch (err) { - const message = err instanceof Error ? err.message : String(err) - toast.error( - t("toasts.agentActionFailed", { - name: agent.name, - action: - mode === "upgrade" ? t("actions.upgrade") : t("actions.install"), - }), - { - description: message, - } - ) - throw err - } finally { - busyActionRef.current.delete(agent.agent_type) - setBusyBinaryAction((prev) => ({ ...prev, [agent.agent_type]: false })) - setRunningActionKind((prev) => ({ - ...prev, - [agent.agent_type]: undefined, - })) - } - }, - [runPreflight, t] - ) - const runUninstallAction = useCallback( async (agent: AcpAgentInfo) => { if (busyActionRef.current.has(agent.agent_type)) return @@ -2821,9 +2729,7 @@ export function AcpAgentSettings() { [agent.agent_type]: agent.distribution_type === "binary" ? "uninstall_binary" - : agent.distribution_type === "uvx" - ? "uninstall_uvx" - : "uninstall_npx", + : "uninstall_npx", })) try { await acpUninstallAgent(agent.agent_type) @@ -2883,18 +2789,9 @@ export function AcpAgentSettings() { await runNpxAction(agent, "upgrade") return } - if (action.kind === "install_uvx") { - await runUvxAction(agent, "install") - return - } - if (action.kind === "upgrade_uvx") { - await runUvxAction(agent, "upgrade") - return - } if ( action.kind === "uninstall_binary" || - action.kind === "uninstall_npx" || - action.kind === "uninstall_uvx" + action.kind === "uninstall_npx" ) { setUninstallConfirmAgent(agent) return @@ -3001,11 +2898,8 @@ export function AcpAgentSettings() { "upgrade_binary", "install_npx", "upgrade_npx", - "install_uvx", - "upgrade_uvx", "uninstall_binary", "uninstall_npx", - "uninstall_uvx", "redownload_binary", ].includes(fix.kind) } @@ -3018,17 +2912,14 @@ export function AcpAgentSettings() { {runningActionKind[agent.agent_type] === fix.kind ? ( ) : fix.kind === "download_binary" || - fix.kind === "install_npx" || - fix.kind === "install_uvx" ? ( + fix.kind === "install_npx" ? ( ) : fix.kind === "upgrade_binary" || fix.kind === "upgrade_npx" || - fix.kind === "upgrade_uvx" || fix.kind === "redownload_binary" ? ( ) : fix.kind === "uninstall_binary" || - fix.kind === "uninstall_npx" || - fix.kind === "uninstall_uvx" ? ( + fix.kind === "uninstall_npx" ? ( ) : null} {fix.label} diff --git a/src/lib/tauri.ts b/src/lib/tauri.ts index 92c18eb..b8769ef 100644 --- a/src/lib/tauri.ts +++ b/src/lib/tauri.ts @@ -179,16 +179,6 @@ export async function acpPrepareNpxAgent( }) } -export async function acpPrepareUvxAgent( - agentType: AgentType, - registryVersion?: string | null -): Promise { - return invoke("acp_prepare_uvx_agent", { - agentType, - registryVersion: registryVersion ?? null, - }) -} - export async function acpUninstallAgent(agentType: AgentType): Promise { return invoke("acp_uninstall_agent", { agentType }) } diff --git a/src/lib/types.ts b/src/lib/types.ts index ecc1dbf..8341f82 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -2,23 +2,8 @@ export type AgentType = | "claude_code" | "codex" | "open_code" - | "auggie" - | "autohand" - | "cline" - | "codebuddy_code" - | "corust_agent" | "gemini" - | "github_copilot" - | "goose" - | "junie" - | "qoder" - | "qwen_code" - | "factory_droid" - | "kimi" - | "minion_code" - | "mistral_vibe" | "open_claw" - | "stakpak" export type AppErrorCode = | "invalid_input" @@ -219,23 +204,8 @@ export const AGENT_DISPLAY_ORDER: AgentType[] = [ "codex", "claude_code", "open_code", - "auggie", - "autohand", - "cline", - "codebuddy_code", - "corust_agent", "gemini", - "github_copilot", - "goose", - "junie", - "qoder", - "qwen_code", - "factory_droid", - "kimi", - "minion_code", - "mistral_vibe", "open_claw", - "stakpak", ] const AGENT_DISPLAY_ORDER_INDEX = new Map( @@ -252,46 +222,16 @@ export const AGENT_LABELS: Record = { claude_code: "Claude Code", codex: "Codex", open_code: "OpenCode", - auggie: "Auggie", - autohand: "Autohand Code", - cline: "Cline", - codebuddy_code: "Codebuddy Code", - corust_agent: "Corust Agent", gemini: "Gemini CLI", - github_copilot: "GitHub Copilot", - goose: "goose", - junie: "Junie", - qoder: "Qoder", - qwen_code: "Qwen Code", - factory_droid: "Factory Droid", - kimi: "Kimi", - minion_code: "Minion Code", - mistral_vibe: "Mistral Vibe", open_claw: "OpenClaw", - stakpak: "Stakpak", } export const AGENT_COLORS: Record = { claude_code: "bg-orange-500", codex: "bg-green-500", open_code: "bg-blue-500", - auggie: "bg-purple-500", - autohand: "bg-emerald-500", - cline: "bg-rose-500", - codebuddy_code: "bg-violet-500", - corust_agent: "bg-amber-500", gemini: "bg-blue-400", - github_copilot: "bg-gray-700", - goose: "bg-lime-500", - junie: "bg-pink-500", - qoder: "bg-teal-500", - qwen_code: "bg-indigo-500", - factory_droid: "bg-yellow-600", - kimi: "bg-cyan-500", - minion_code: "bg-fuchsia-500", - mistral_vibe: "bg-red-500", open_claw: "bg-emerald-600", - stakpak: "bg-slate-600", } // ACP connection status (matches Rust ConnectionStatus)