diff --git a/crates/agent_ui/src/agent_configuration.rs b/crates/agent_ui/src/agent_configuration.rs index aa4cbc8e5b261d1953a91fb090e7ecd28b4e3a31..327f699b4dbf5512a60637d8fce2edfba75280f0 100644 --- a/crates/agent_ui/src/agent_configuration.rs +++ b/crates/agent_ui/src/agent_configuration.rs @@ -977,7 +977,10 @@ impl AgentConfiguration { } else { AgentIcon::Name(IconName::Ai) }; - (name, icon) + let display_name = agent_server_store + .agent_display_name(&name) + .unwrap_or_else(|| name.0.clone()); + (name, icon, display_name) }) .collect(); @@ -1084,6 +1087,7 @@ impl AgentConfiguration { .child(self.render_agent_server( AgentIcon::Name(IconName::AiClaude), "Claude Code", + "Claude Code", false, cx, )) @@ -1091,6 +1095,7 @@ impl AgentConfiguration { .child(self.render_agent_server( AgentIcon::Name(IconName::AiOpenAi), "Codex CLI", + "Codex CLI", false, cx, )) @@ -1098,16 +1103,23 @@ impl AgentConfiguration { .child(self.render_agent_server( AgentIcon::Name(IconName::AiGemini), "Gemini CLI", + "Gemini CLI", false, cx, )) .map(|mut parent| { - for (name, icon) in user_defined_agents { + for (name, icon, display_name) in user_defined_agents { parent = parent .child( Divider::horizontal().color(DividerColor::BorderFaded), ) - .child(self.render_agent_server(icon, name, true, cx)); + .child(self.render_agent_server( + icon, + name, + display_name, + true, + cx, + )); } parent }), @@ -1118,11 +1130,13 @@ impl AgentConfiguration { fn render_agent_server( &self, icon: AgentIcon, - name: impl Into, + id: impl Into, + display_name: impl Into, external: bool, cx: &mut Context, ) -> impl IntoElement { - let name = name.into(); + let id = id.into(); + let display_name = display_name.into(); let icon = match icon { AgentIcon::Name(icon_name) => Icon::new(icon_name) .size(IconSize::Small) @@ -1132,12 +1146,15 @@ impl AgentConfiguration { .color(Color::Muted), }; - let tooltip_id = SharedString::new(format!("agent-source-{}", name)); - let tooltip_message = format!("The {} agent was installed from an extension.", name); + let tooltip_id = SharedString::new(format!("agent-source-{}", id)); + let tooltip_message = format!( + "The {} agent was installed from an extension.", + display_name + ); - let agent_server_name = ExternalAgentServerName(name.clone()); + let agent_server_name = ExternalAgentServerName(id.clone()); - let uninstall_btn_id = SharedString::from(format!("uninstall-{}", name)); + let uninstall_btn_id = SharedString::from(format!("uninstall-{}", id)); let uninstall_button = IconButton::new(uninstall_btn_id, IconName::Trash) .icon_color(Color::Muted) .icon_size(IconSize::Small) @@ -1161,7 +1178,7 @@ impl AgentConfiguration { h_flex() .gap_1p5() .child(icon) - .child(Label::new(name)) + .child(Label::new(display_name)) .when(external, |this| { this.child( div() diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index 18e8f1e731defa82e865dd45e66389634992037c..d5dd0a25c818600226eb8a894f73dffcba86b797 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -2083,8 +2083,11 @@ impl AgentPanel { for agent_name in agent_names { let icon_path = agent_server_store.agent_icon(&agent_name); + let display_name = agent_server_store + .agent_display_name(&agent_name) + .unwrap_or_else(|| agent_name.0.clone()); - let mut entry = ContextMenuEntry::new(agent_name.clone()); + let mut entry = ContextMenuEntry::new(display_name); if let Some(icon_path) = icon_path { entry = entry.custom_icon_svg(icon_path); diff --git a/crates/project/src/agent_server_store.rs b/crates/project/src/agent_server_store.rs index 6524cc6d22a0bf7c5d7a5c4ad6ae0e86d795be28..a2cc57beae9702e4d5b495a135e7c357c638c17a 100644 --- a/crates/project/src/agent_server_store.rs +++ b/crates/project/src/agent_server_store.rs @@ -137,6 +137,7 @@ pub struct AgentServerStore { state: AgentServerStoreState, external_agents: HashMap>, agent_icons: HashMap, + agent_display_names: HashMap, } pub struct AgentServersUpdated; @@ -155,6 +156,7 @@ mod ext_agent_tests { state: AgentServerStoreState::Collab, external_agents: HashMap::default(), agent_icons: HashMap::default(), + agent_display_names: HashMap::default(), } } @@ -258,6 +260,7 @@ impl AgentServerStore { self.external_agents.retain(|name, agent| { if agent.downcast_mut::().is_some() { self.agent_icons.remove(name); + self.agent_display_names.remove(name); false } else { // Keep the hardcoded external agents that don't come from extensions @@ -275,6 +278,12 @@ impl AgentServerStore { for (ext_id, manifest) in manifests { for (agent_name, agent_entry) in &manifest.agent_servers { // Store absolute icon path if provided, resolving symlinks for dev extensions + // Store display name from manifest + self.agent_display_names.insert( + ExternalAgentServerName(agent_name.clone().into()), + SharedString::from(agent_entry.name.clone()), + ); + let icon_path = if let Some(icon) = &agent_entry.icon { let icon_path = extensions_dir.join(ext_id).join(icon); // Canonicalize to resolve symlinks (dev extensions are symlinked) @@ -310,6 +319,12 @@ impl AgentServerStore { let mut agents = vec![]; for (ext_id, manifest) in manifests { for (agent_name, agent_entry) in &manifest.agent_servers { + // Store display name from manifest + self.agent_display_names.insert( + ExternalAgentServerName(agent_name.clone().into()), + SharedString::from(agent_entry.name.clone()), + ); + // Store absolute icon path if provided, resolving symlinks for dev extensions let icon = if let Some(icon) = &agent_entry.icon { let icon_path = extensions_dir.join(ext_id).join(icon); @@ -369,6 +384,10 @@ impl AgentServerStore { self.agent_icons.get(name).cloned() } + pub fn agent_display_name(&self, name: &ExternalAgentServerName) -> Option { + self.agent_display_names.get(name).cloned() + } + pub fn init_remote(session: &AnyProtoClient) { session.add_entity_message_handler(Self::handle_external_agents_updated); session.add_entity_message_handler(Self::handle_loading_status_updated); @@ -559,6 +578,7 @@ impl AgentServerStore { }, external_agents: Default::default(), agent_icons: Default::default(), + agent_display_names: Default::default(), }; if let Some(_events) = extension::ExtensionEvents::try_global(cx) {} this.agent_servers_settings_changed(cx); @@ -609,6 +629,7 @@ impl AgentServerStore { }, external_agents: external_agents.into_iter().collect(), agent_icons: HashMap::default(), + agent_display_names: HashMap::default(), } } @@ -617,6 +638,7 @@ impl AgentServerStore { state: AgentServerStoreState::Collab, external_agents: Default::default(), agent_icons: Default::default(), + agent_display_names: Default::default(), } } @@ -2040,6 +2062,7 @@ mod extension_agent_tests { state: AgentServerStoreState::Collab, external_agents: HashMap::default(), agent_icons: HashMap::default(), + agent_display_names: HashMap::default(), }; // Seed with extension agents (contain ": ") and custom agents (don't contain ": ")