diff --git a/crates/agent_ui/src/agent_connection_store.rs b/crates/agent_ui/src/agent_connection_store.rs index 2d0e4d2e6ef635dbdcc62e8f8922dcf3db94ace4..ed0bb94dd23edebd4846d4ff54b7e316b3d48c26 100644 --- a/crates/agent_ui/src/agent_connection_store.rs +++ b/crates/agent_ui/src/agent_connection_store.rs @@ -10,7 +10,7 @@ use gpui::{AppContext, Context, Entity, EventEmitter, SharedString, Subscription use project::{AgentServerStore, AgentServersUpdated, Project}; use watch::Receiver; -use crate::{ExternalAgent, ThreadHistory}; +use crate::{Agent, ThreadHistory}; use project::ExternalAgentServerName; pub enum AgentConnectionEntry { @@ -55,7 +55,7 @@ impl EventEmitter for AgentConnectionEntry {} pub struct AgentConnectionStore { project: Entity, thread_store: Entity, - entries: HashMap>, + entries: HashMap>, _subscriptions: Vec, } @@ -75,13 +75,13 @@ impl AgentConnectionStore { } } - pub fn entry(&self, key: &ExternalAgent) -> Option<&Entity> { + pub fn entry(&self, key: &Agent) -> Option<&Entity> { self.entries.get(key) } pub fn request_connection( &mut self, - agent: ExternalAgent, + agent: Agent, cx: &mut Context, ) -> Entity { self.entries.get(&agent).cloned().unwrap_or_else(|| { @@ -154,8 +154,8 @@ impl AgentConnectionStore { ) { let store = store.read(cx); self.entries.retain(|key, _| match key { - ExternalAgent::NativeAgent => true, - ExternalAgent::Custom { name } => store + Agent::NativeAgent => true, + Agent::Custom { name } => store .external_agents .contains_key(&ExternalAgentServerName(name.clone())), }); diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index ccd891da11a74e0086b4323cba8af09a5868b5c2..1fec3427678c134f7a264a4c10a6b2756de46881 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -42,7 +42,7 @@ use crate::{ ui::EndTrialUpsell, }; use crate::{ - AgentInitialContent, ExternalAgent, ExternalSourcePrompt, NewExternalAgentThread, + Agent, AgentInitialContent, ExternalSourcePrompt, NewExternalAgentThread, NewNativeAgentThreadFromSummary, }; use crate::{ @@ -738,11 +738,11 @@ impl AgentType { } } -impl From for AgentType { - fn from(value: ExternalAgent) -> Self { +impl From for AgentType { + fn from(value: Agent) -> Self { match value { - ExternalAgent::Custom { name } => Self::Custom { name }, - ExternalAgent::NativeAgent => Self::NativeAgent, + Agent::Custom { name } => Self::Custom { name }, + Agent::NativeAgent => Self::NativeAgent, } } } @@ -1284,7 +1284,7 @@ impl AgentPanel { cx: &mut Context, ) { self.external_thread( - Some(crate::ExternalAgent::NativeAgent), + Some(crate::Agent::NativeAgent), Some(session_id), cwd, title, @@ -1336,7 +1336,7 @@ impl AgentPanel { window: &mut Window, cx: &mut Context, ) { - let agent = ExternalAgent::NativeAgent; + let agent = Agent::NativeAgent; let session_id = action.from_session_id.clone(); @@ -1417,7 +1417,7 @@ impl AgentPanel { fn external_thread( &mut self, - agent_choice: Option, + agent_choice: Option, resume_session_id: Option, cwd: Option, title: Option, @@ -1435,7 +1435,7 @@ impl AgentPanel { #[derive(Serialize, Deserialize)] struct LastUsedExternalAgent { - agent: crate::ExternalAgent, + agent: crate::Agent, } let thread_store = self.thread_store.clone(); @@ -1473,7 +1473,7 @@ impl AgentPanel { } else { cx.spawn_in(window, async move |this, cx| { let ext_agent = if is_via_collab { - ExternalAgent::NativeAgent + Agent::NativeAgent } else { cx.background_spawn(async move { KEY_VALUE_STORE.read_kvp(LAST_USED_EXTERNAL_AGENT_KEY) @@ -1485,7 +1485,7 @@ impl AgentPanel { serde_json::from_str::(&value).log_err() }) .map(|agent| agent.agent) - .unwrap_or(ExternalAgent::NativeAgent) + .unwrap_or(Agent::NativeAgent) }; let server = ext_agent.server(fs, thread_store); @@ -1554,7 +1554,7 @@ impl AgentPanel { match &self.selected_agent { AgentType::TextThread | AgentType::NativeAgent => true, AgentType::Custom { name } => { - let agent = ExternalAgent::Custom { name: name.clone() }; + let agent = Agent::Custom { name: name.clone() }; self.connection_store .read(cx) .entry(&agent) @@ -1574,7 +1574,7 @@ impl AgentPanel { let history = self .connection_store .read(cx) - .entry(&ExternalAgent::NativeAgent)? + .entry(&Agent::NativeAgent)? .read(cx) .history()? .clone(); @@ -1584,7 +1584,7 @@ impl AgentPanel { }) } AgentType::Custom { name } => { - let agent = ExternalAgent::Custom { name: name.clone() }; + let agent = Agent::Custom { name: name.clone() }; let history = self .connection_store .read(cx) @@ -2376,10 +2376,10 @@ impl AgentPanel { cx.notify(); } - fn selected_external_agent(&self) -> Option { + fn selected_external_agent(&self) -> Option { match &self.selected_agent { - AgentType::NativeAgent => Some(ExternalAgent::NativeAgent), - AgentType::Custom { name } => Some(ExternalAgent::Custom { name: name.clone() }), + AgentType::NativeAgent => Some(Agent::NativeAgent), + AgentType::Custom { name } => Some(Agent::Custom { name: name.clone() }), AgentType::TextThread => None, } } @@ -2448,7 +2448,7 @@ impl AgentPanel { window.dispatch_action(NewTextThread.boxed_clone(), cx); } AgentType::NativeAgent => self.external_thread( - Some(crate::ExternalAgent::NativeAgent), + Some(crate::Agent::NativeAgent), None, None, None, @@ -2458,7 +2458,7 @@ impl AgentPanel { cx, ), AgentType::Custom { name } => self.external_thread( - Some(crate::ExternalAgent::Custom { name }), + Some(crate::Agent::Custom { name }), None, None, None, @@ -2544,7 +2544,7 @@ impl AgentPanel { initial_content: Option, workspace: WeakEntity, project: Entity, - ext_agent: ExternalAgent, + ext_agent: Agent, focus: bool, window: &mut Window, cx: &mut Context, @@ -4976,7 +4976,7 @@ impl rules_library::InlineAssistDelegate for PromptLibraryInlineAssist { .read(cx) .connection_store() .read(cx) - .entry(&crate::ExternalAgent::NativeAgent) + .entry(&crate::Agent::NativeAgent) .and_then(|s| s.read(cx).history()) else { log::error!("No connection entry found for native agent"); @@ -5158,7 +5158,7 @@ impl AgentPanel { let workspace = self.workspace.clone(); let project = self.project.clone(); - let ext_agent = ExternalAgent::Custom { + let ext_agent = Agent::Custom { name: server.name(), }; diff --git a/crates/agent_ui/src/agent_ui.rs b/crates/agent_ui/src/agent_ui.rs index 52ce6f0bd7a312966b6602fb43be4074d7f3e620..fbf47615cb23b75eaeff1f785ada8bf8605556d3 100644 --- a/crates/agent_ui/src/agent_ui.rs +++ b/crates/agent_ui/src/agent_ui.rs @@ -205,7 +205,7 @@ pub struct NewThread; #[serde(deny_unknown_fields)] pub struct NewExternalAgentThread { /// Which agent to use for the conversation. - agent: Option, + agent: Option, } #[derive(Clone, PartialEq, Deserialize, JsonSchema, Action)] @@ -218,7 +218,7 @@ pub struct NewNativeAgentThreadFromSummary { // TODO unify this with AgentType #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, JsonSchema)] #[serde(rename_all = "snake_case")] -pub enum ExternalAgent { +pub enum Agent { NativeAgent, Custom { name: SharedString }, } @@ -227,7 +227,7 @@ pub enum ExternalAgent { // the registry: "claude_code" -> Custom { name: "claude-acp" }, "codex" -> Custom { name: // "codex-acp" }, "gemini" -> Custom { name: "gemini" }. // Can be removed at some point in the future and go back to #[derive(Deserialize)]. -impl<'de> serde::Deserialize<'de> for ExternalAgent { +impl<'de> serde::Deserialize<'de> for Agent { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -280,7 +280,7 @@ impl<'de> serde::Deserialize<'de> for ExternalAgent { } } -impl ExternalAgent { +impl Agent { pub fn server( &self, fs: Arc, @@ -752,20 +752,20 @@ mod tests { use project::agent_server_store::{CLAUDE_AGENT_NAME, CODEX_NAME, GEMINI_NAME}; assert_eq!( - serde_json::from_str::(r#""claude_code""#).unwrap(), - ExternalAgent::Custom { + serde_json::from_str::(r#""claude_code""#).unwrap(), + Agent::Custom { name: CLAUDE_AGENT_NAME.into(), }, ); assert_eq!( - serde_json::from_str::(r#""codex""#).unwrap(), - ExternalAgent::Custom { + serde_json::from_str::(r#""codex""#).unwrap(), + Agent::Custom { name: CODEX_NAME.into(), }, ); assert_eq!( - serde_json::from_str::(r#""gemini""#).unwrap(), - ExternalAgent::Custom { + serde_json::from_str::(r#""gemini""#).unwrap(), + Agent::Custom { name: GEMINI_NAME.into(), }, ); @@ -774,12 +774,12 @@ mod tests { #[test] fn test_deserialize_current_external_agent_variants() { assert_eq!( - serde_json::from_str::(r#""native_agent""#).unwrap(), - ExternalAgent::NativeAgent, + serde_json::from_str::(r#""native_agent""#).unwrap(), + Agent::NativeAgent, ); assert_eq!( - serde_json::from_str::(r#"{"custom":{"name":"my-agent"}}"#).unwrap(), - ExternalAgent::Custom { + serde_json::from_str::(r#"{"custom":{"name":"my-agent"}}"#).unwrap(), + Agent::Custom { name: "my-agent".into(), }, ); diff --git a/crates/agent_ui/src/connection_view.rs b/crates/agent_ui/src/connection_view.rs index ae4a3d8aef9ae37673816360f9fdc56ffbb5e19a..59c3647d7c200422a46e91f75dcbd692f21b59a7 100644 --- a/crates/agent_ui/src/connection_view.rs +++ b/crates/agent_ui/src/connection_view.rs @@ -76,9 +76,9 @@ use crate::message_editor::{MessageEditor, MessageEditorEvent}; use crate::profile_selector::{ProfileProvider, ProfileSelector}; use crate::ui::{AgentNotification, AgentNotificationEvent}; use crate::{ - AgentDiffPane, AgentInitialContent, AgentPanel, AllowAlways, AllowOnce, AuthorizeToolCall, - ClearMessageQueue, CycleFavoriteModels, CycleModeSelector, CycleThinkingEffort, - EditFirstQueuedMessage, ExpandMessageEditor, ExternalAgent, Follow, KeepAll, NewThread, + Agent, AgentDiffPane, AgentInitialContent, AgentPanel, AllowAlways, AllowOnce, + AuthorizeToolCall, ClearMessageQueue, CycleFavoriteModels, CycleModeSelector, + CycleThinkingEffort, EditFirstQueuedMessage, ExpandMessageEditor, Follow, KeepAll, NewThread, OpenAddContextMenu, OpenAgentDiff, OpenHistory, RejectAll, RejectOnce, RemoveFirstQueuedMessage, SendImmediately, SendNextQueuedMessage, ToggleFastMode, ToggleProfileSelector, ToggleThinkingEffortMenu, ToggleThinkingMode, UndoLastReject, @@ -307,9 +307,9 @@ pub enum AcpServerViewEvent { impl EventEmitter for ConnectionView {} pub struct ConnectionView { - agent: Rc, + agent_server: Rc, connection_store: Entity, - connection_key: ExternalAgent, + agent: Agent, agent_server_store: Entity, workspace: WeakEntity, project: Entity, @@ -475,9 +475,9 @@ impl ConnectedServerState { impl ConnectionView { pub fn new( - agent: Rc, + agent_server: Rc, connection_store: Entity, - connection_key: ExternalAgent, + agent: Agent, resume_session_id: Option, cwd: Option, title: Option, @@ -515,18 +515,18 @@ impl ConnectionView { .detach(); Self { - agent: agent.clone(), + agent_server: agent_server.clone(), connection_store: connection_store.clone(), - connection_key: connection_key.clone(), + agent: agent.clone(), agent_server_store, workspace, project: project.clone(), thread_store, prompt_store, server_state: Self::initial_state( - agent.clone(), + agent_server.clone(), connection_store, - connection_key, + agent, resume_session_id, cwd, title, @@ -567,9 +567,9 @@ impl ConnectionView { .unwrap_or((None, None, None)); let state = Self::initial_state( - self.agent.clone(), + self.agent_server.clone(), self.connection_store.clone(), - self.connection_key.clone(), + self.agent.clone(), resume_session_id, cwd, title, @@ -595,9 +595,9 @@ impl ConnectionView { } fn initial_state( - agent: Rc, + agent_server: Rc, connection_store: Entity, - connection_key: ExternalAgent, + agent: Agent, resume_session_id: Option, cwd: Option, title: Option, @@ -607,7 +607,10 @@ impl ConnectionView { cx: &mut Context, ) -> ServerState { if project.read(cx).is_via_collab() - && agent.clone().downcast::().is_none() + && agent_server + .clone() + .downcast::() + .is_none() { return ServerState::LoadError { error: LoadError::Other( @@ -655,7 +658,7 @@ impl ConnectionView { .unwrap_or_else(|| paths::home_dir().as_path().into()); let connection_entry = - connection_store.update(cx, |store, cx| store.request_connection(connection_key, cx)); + connection_store.update(cx, |store, cx| store.request_connection(agent, cx)); let connection_entry_subscription = cx.subscribe(&connection_entry, |this, _entry, event, cx| match event { @@ -737,7 +740,7 @@ impl ConnectionView { Self::handle_auth_required( this, err, - agent.name(), + agent_server.name(), connection, window, cx, @@ -825,7 +828,7 @@ impl ConnectionView { window: &mut Window, cx: &mut Context, ) -> Entity { - let agent_name = self.agent.name(); + let agent_name = self.agent_server.name(); let prompt_capabilities = Rc::new(RefCell::new(acp::PromptCapabilities::default())); let available_commands = Rc::new(RefCell::new(vec![])); @@ -842,7 +845,7 @@ impl ConnectionView { self.prompt_store.clone(), prompt_capabilities.clone(), available_commands.clone(), - self.agent.name(), + self.agent_server.name(), ) }); @@ -877,7 +880,7 @@ impl ConnectionView { let model_selector; if let Some(config_options) = config_options_provider { // Use config options - don't create mode_selector or model_selector - let agent_server = self.agent.clone(); + let agent_server = self.agent_server.clone(); let fs = self.project.read(cx).fs().clone(); config_options_view = Some(cx.new(|cx| { @@ -889,7 +892,7 @@ impl ConnectionView { // Fall back to legacy mode/model selectors config_options_view = None; model_selector = connection.model_selector(&session_id).map(|selector| { - let agent_server = self.agent.clone(); + let agent_server = self.agent_server.clone(); let fs = self.project.read(cx).fs().clone(); cx.new(|cx| { ModelSelectorPopover::new( @@ -908,7 +911,7 @@ impl ConnectionView { .session_modes(&session_id, cx) .map(|session_modes| { let fs = self.project.read(cx).fs().clone(); - cx.new(|_cx| ModeSelector::new(session_modes, self.agent.clone(), fs)) + cx.new(|_cx| ModeSelector::new(session_modes, self.agent_server.clone(), fs)) }); } @@ -968,16 +971,16 @@ impl ConnectionView { .agent_display_name(&ExternalAgentServerName(agent_name.clone())) .unwrap_or_else(|| agent_name.clone()); - let agent_icon = self.agent.logo(); + let agent_icon = self.agent_server.logo(); let agent_icon_from_external_svg = self .agent_server_store .read(cx) - .agent_icon(&ExternalAgentServerName(self.agent.name())) + .agent_icon(&ExternalAgentServerName(self.agent_server.name())) .or_else(|| { project::AgentRegistryStore::try_global(cx).and_then(|store| { store .read(cx) - .agent(self.agent.name().as_ref()) + .agent(self.agent_server.name().as_ref()) .and_then(|a| a.icon_path().cloned()) }) }); @@ -1162,12 +1165,14 @@ impl ConnectionView { ServerState::Connected(_) => "New Thread".into(), ServerState::Loading(_) => "Loading…".into(), ServerState::LoadError { error, .. } => match error { - LoadError::Unsupported { .. } => format!("Upgrade {}", self.agent.name()).into(), + LoadError::Unsupported { .. } => { + format!("Upgrade {}", self.agent_server.name()).into() + } LoadError::FailedToInstall(_) => { - format!("Failed to Install {}", self.agent.name()).into() + format!("Failed to Install {}", self.agent_server.name()).into() } - LoadError::Exited { .. } => format!("{} Exited", self.agent.name()).into(), - LoadError::Other(_) => format!("Error Loading {}", self.agent.name()).into(), + LoadError::Exited { .. } => format!("{} Exited", self.agent_server.name()).into(), + LoadError::Other(_) => format!("Error Loading {}", self.agent_server.name()).into(), }, } } @@ -1445,8 +1450,8 @@ impl ConnectionView { let agent_display_name = self .agent_server_store .read(cx) - .agent_display_name(&ExternalAgentServerName(self.agent.name())) - .unwrap_or_else(|| self.agent.name()); + .agent_display_name(&ExternalAgentServerName(self.agent_server.name())) + .unwrap_or_else(|| self.agent_server.name()); if let Some(active) = self.active_thread() { let new_placeholder = @@ -1870,8 +1875,8 @@ impl ConnectionView { let agent_display_name = self .agent_server_store .read(cx) - .agent_display_name(&ExternalAgentServerName(self.agent.name())) - .unwrap_or_else(|| self.agent.name()); + .agent_display_name(&ExternalAgentServerName(self.agent_server.name())) + .unwrap_or_else(|| self.agent_server.name()); let show_fallback_description = auth_methods.len() > 1 && configuration_view.is_none() @@ -2032,7 +2037,7 @@ impl ConnectionView { LoadError::Other(_) => "other", }; - let agent_name = self.agent.name(); + let agent_name = self.agent_server.name(); telemetry::event!( "Agent Panel Error Shown", @@ -2091,7 +2096,7 @@ impl ConnectionView { cx: &mut Context, ) -> AnyElement { let (heading_label, description_label) = ( - format!("Upgrade {} to work with Zed", self.agent.name()), + format!("Upgrade {} to work with Zed", self.agent_server.name()), if version.is_empty() { format!( "Currently using {}, which does not report a valid --version", @@ -2211,7 +2216,7 @@ impl ConnectionView { let needed_count = self.queued_messages_len(cx); let queued_messages = self.queued_message_contents(cx); - let agent_name = self.agent.name(); + let agent_name = self.agent_server.name(); let workspace = self.workspace.clone(); let project = self.project.downgrade(); let Some(connected) = self.as_connected() else { @@ -2390,7 +2395,7 @@ impl ConnectionView { } // TODO: Change this once we have title summarization for external agents. - let title = self.agent.name(); + let title = self.agent_server.name(); match settings.notify_when_agent_waiting { NotifyWhenAgentWaiting::PrimaryScreen => { @@ -2579,7 +2584,7 @@ impl ConnectionView { .unwrap_or_else(|| SharedString::from("The model")) } else { // ACP agent - use the agent name (e.g., "Claude Agent", "Gemini CLI") - self.agent.name() + self.agent_server.name() } } @@ -2590,7 +2595,7 @@ impl ConnectionView { } pub(crate) fn reauthenticate(&mut self, window: &mut Window, cx: &mut Context) { - let agent_name = self.agent.name(); + let agent_name = self.agent_server.name(); if let Some(active) = self.active_thread() { active.update(cx, |active, cx| active.clear_thread_error(cx)); } @@ -2918,7 +2923,7 @@ pub(crate) mod tests { ConnectionView::new( Rc::new(StubAgentServer::default_response()), connection_store, - ExternalAgent::Custom { + Agent::Custom { name: "Test".into(), }, None, @@ -3031,7 +3036,7 @@ pub(crate) mod tests { ConnectionView::new( Rc::new(StubAgentServer::new(ResumeOnlyAgentConnection)), connection_store, - ExternalAgent::Custom { + Agent::Custom { name: "Test".into(), }, Some(SessionId::new("resume-session")), @@ -3089,7 +3094,7 @@ pub(crate) mod tests { ConnectionView::new( Rc::new(StubAgentServer::new(connection)), connection_store, - ExternalAgent::Custom { + Agent::Custom { name: "Test".into(), }, Some(SessionId::new("session-1")), @@ -3145,7 +3150,7 @@ pub(crate) mod tests { ConnectionView::new( Rc::new(StubAgentServer::new(connection)), connection_store, - ExternalAgent::Custom { + Agent::Custom { name: "Test".into(), }, Some(SessionId::new("session-1")), @@ -3201,7 +3206,7 @@ pub(crate) mod tests { ConnectionView::new( Rc::new(StubAgentServer::new(connection)), connection_store, - ExternalAgent::Custom { + Agent::Custom { name: "Test".into(), }, Some(SessionId::new("session-1")), @@ -3519,7 +3524,7 @@ pub(crate) mod tests { ConnectionView::new( Rc::new(agent), connection_store, - ExternalAgent::Custom { + Agent::Custom { name: "Test".into(), }, None, @@ -3735,7 +3740,7 @@ pub(crate) mod tests { cx.new(|cx| AgentConnectionStore::new(project.clone(), thread_store.clone(), cx)) }); - let agent_key = ExternalAgent::Custom { + let agent_key = Agent::Custom { name: "Test".into(), }; @@ -4486,7 +4491,7 @@ pub(crate) mod tests { ConnectionView::new( Rc::new(StubAgentServer::new(connection.as_ref().clone())), connection_store, - ExternalAgent::Custom { + Agent::Custom { name: "Test".into(), }, None, diff --git a/crates/agent_ui/src/inline_assistant.rs b/crates/agent_ui/src/inline_assistant.rs index 8fde876183db385c019e6ccb1f2e5a0d4b121892..1fc66f6079fa146440a1f5a594d9f160e4580ab2 100644 --- a/crates/agent_ui/src/inline_assistant.rs +++ b/crates/agent_ui/src/inline_assistant.rs @@ -281,7 +281,7 @@ impl InlineAssistant { let Some(history) = agent_panel .connection_store() .read(cx) - .entry(&crate::ExternalAgent::NativeAgent) + .entry(&crate::Agent::NativeAgent) .and_then(|s| s.read(cx).history().cloned()) else { log::error!("No connection entry found for native agent"); @@ -1981,7 +1981,7 @@ impl CodeActionProvider for AssistantCodeActionProvider { let history = panel .connection_store() .read(cx) - .entry(&crate::ExternalAgent::NativeAgent) + .entry(&crate::Agent::NativeAgent) .and_then(|e| e.read(cx).history()) .context("no history found for native agent")? .downgrade();