diff --git a/Cargo.toml b/Cargo.toml index 5ea1db1c6fc52ac9c346a19e744ed60a883469d6..ae119718167e929a0f116deb49ea36a70f91644c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -842,6 +842,9 @@ too_many_arguments = "allow" # We often have large enum variants yet we rarely actually bother with splitting them up. large_enum_variant = "allow" +# Boolean expressions can be hard to read, requiring only the minimal form gets in the way +nonminimal_bol = "allow" + [workspace.metadata.cargo-machete] ignored = [ "bindgen", diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs index c039826c83affe53d8354bf2c744bbe40b1015b8..1bb9b92602ca4cdc1d0426ec84685b0f587e5eef 100644 --- a/crates/agent_ui/src/acp/thread_view.rs +++ b/crates/agent_ui/src/acp/thread_view.rs @@ -8,7 +8,7 @@ use action_log::ActionLog; use agent_client_protocol::{self as acp, PromptCapabilities}; use agent_servers::{AgentServer, AgentServerDelegate, ClaudeCode}; use agent_settings::{AgentProfileId, AgentSettings, CompletionMode, NotifyWhenAgentWaiting}; -use agent2::{DbThreadMetadata, HistoryEntry, HistoryEntryId, HistoryStore}; +use agent2::{DbThreadMetadata, HistoryEntry, HistoryEntryId, HistoryStore, NativeAgentServer}; use anyhow::{Context as _, Result, anyhow, bail}; use audio::{Audio, Sound}; use buffer_diff::BufferDiff; @@ -418,6 +418,13 @@ impl AcpThreadView { window: &mut Window, cx: &mut Context, ) -> ThreadState { + if project.read(cx).is_via_collab() + && agent.clone().downcast::().is_none() + { + return ThreadState::LoadError(LoadError::Other( + "External agents are not yet supported for remote projects.".into(), + )); + } let root_dir = project .read(cx) .visible_worktrees(cx) diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index ff795b98c7015b580dd6fc71fd07118a8e06bc87..abb9f8e5ec6e9aebb4d5f2228f68d0621047c419 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -1075,6 +1075,7 @@ impl AgentPanel { let workspace = self.workspace.clone(); let project = self.project.clone(); let fs = self.fs.clone(); + let is_via_collab = self.project.read(cx).is_via_collab(); const LAST_USED_EXTERNAL_AGENT_KEY: &str = "agent_panel__last_used_external_agent"; @@ -1106,17 +1107,21 @@ impl AgentPanel { agent } None => { - cx.background_spawn(async move { - KEY_VALUE_STORE.read_kvp(LAST_USED_EXTERNAL_AGENT_KEY) - }) - .await - .log_err() - .flatten() - .and_then(|value| { - serde_json::from_str::(&value).log_err() - }) - .unwrap_or_default() - .agent + if is_via_collab { + ExternalAgent::NativeAgent + } else { + cx.background_spawn(async move { + KEY_VALUE_STORE.read_kvp(LAST_USED_EXTERNAL_AGENT_KEY) + }) + .await + .log_err() + .flatten() + .and_then(|value| { + serde_json::from_str::(&value).log_err() + }) + .unwrap_or_default() + .agent + } } }; @@ -2504,6 +2509,11 @@ impl AgentPanel { .with_handle(self.new_thread_menu_handle.clone()) .menu({ let workspace = self.workspace.clone(); + let is_via_collab = workspace + .update(cx, |workspace, cx| { + workspace.project().read(cx).is_via_collab() + }) + .unwrap_or_default(); move |window, cx| { telemetry::event!("New Thread Clicked"); @@ -2594,6 +2604,7 @@ impl AgentPanel { ContextMenuEntry::new("New Gemini CLI Thread") .icon(IconName::AiGemini) .icon_color(Color::Muted) + .disabled(is_via_collab) .handler({ let workspace = workspace.clone(); move |window, cx| { @@ -2620,6 +2631,7 @@ impl AgentPanel { menu.item( ContextMenuEntry::new("New Claude Code Thread") .icon(IconName::AiClaude) + .disabled(is_via_collab) .icon_color(Color::Muted) .handler({ let workspace = workspace.clone(); @@ -2652,6 +2664,7 @@ impl AgentPanel { ContextMenuEntry::new(format!("New {} Thread", agent_name)) .icon(IconName::Terminal) .icon_color(Color::Muted) + .disabled(is_via_collab) .handler({ let workspace = workspace.clone(); let agent_name = agent_name.clone();