diff --git a/Cargo.toml b/Cargo.toml index a96dc5d4d57ac5e5be60ace099e42b6a8123c42e..2c8143756b33b35f892076c3e71d6bf458a47ea0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -848,6 +848,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 a9421723d125d27f3eb13c43fb17936f9078dae8..c60710eaeeff29040ea9e3d98b002b865c799857 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 c80ddb5c92ef4b670123433effe297da4cbbda23..3da63c281ef72765479d23cc508ef4ca50ff927c 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -1091,6 +1091,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"; @@ -1122,17 +1123,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 + } } }; @@ -2527,6 +2532,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"); @@ -2617,6 +2627,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| { @@ -2643,6 +2654,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(); @@ -2675,6 +2687,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();