From 90946aeb2a138b51ead3378110771933b236daee Mon Sep 17 00:00:00 2001 From: Bennet Bo Fenner Date: Thu, 21 Aug 2025 11:25:00 +0200 Subject: [PATCH] agent2: Allow expanding terminals individually (#36670) Release Notes: - N/A --- crates/agent_ui/src/acp/entry_view_state.rs | 10 ++++-- crates/agent_ui/src/acp/thread_view.rs | 36 ++++++++++++++------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/crates/agent_ui/src/acp/entry_view_state.rs b/crates/agent_ui/src/acp/entry_view_state.rs index 67acbb8b5b..fb15d8bed8 100644 --- a/crates/agent_ui/src/acp/entry_view_state.rs +++ b/crates/agent_ui/src/acp/entry_view_state.rs @@ -121,14 +121,19 @@ impl EntryViewState { for terminal in terminals { views.entry(terminal.entity_id()).or_insert_with(|| { - create_terminal( + let element = create_terminal( self.workspace.clone(), self.project.clone(), terminal.clone(), window, cx, ) - .into_any() + .into_any(); + cx.emit(EntryViewEvent { + entry_index: index, + view_event: ViewEvent::NewTerminal(terminal.entity_id()), + }); + element }); } @@ -187,6 +192,7 @@ pub struct EntryViewEvent { } pub enum ViewEvent { + NewTerminal(EntityId), MessageEditorEvent(Entity, MessageEditorEvent), } diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs index 12a33d022e..432ba4e0e8 100644 --- a/crates/agent_ui/src/acp/thread_view.rs +++ b/crates/agent_ui/src/acp/thread_view.rs @@ -20,11 +20,11 @@ use file_icons::FileIcons; use fs::Fs; use gpui::{ Action, Animation, AnimationExt, AnyView, App, BorderStyle, ClickEvent, ClipboardItem, - EdgesRefinement, ElementId, Empty, Entity, FocusHandle, Focusable, Hsla, Length, ListOffset, - ListState, MouseButton, PlatformDisplay, SharedString, Stateful, StyleRefinement, Subscription, - Task, TextStyle, TextStyleRefinement, Transformation, UnderlineStyle, WeakEntity, Window, - WindowHandle, div, ease_in_out, linear_color_stop, linear_gradient, list, percentage, point, - prelude::*, pulsating_between, + EdgesRefinement, ElementId, Empty, Entity, EntityId, FocusHandle, Focusable, Hsla, Length, + ListOffset, ListState, MouseButton, PlatformDisplay, SharedString, Stateful, StyleRefinement, + Subscription, Task, TextStyle, TextStyleRefinement, Transformation, UnderlineStyle, WeakEntity, + Window, WindowHandle, div, ease_in_out, linear_color_stop, linear_gradient, list, percentage, + point, prelude::*, pulsating_between, }; use language::Buffer; @@ -256,10 +256,10 @@ pub struct AcpThreadView { auth_task: Option>, expanded_tool_calls: HashSet, expanded_thinking_blocks: HashSet<(usize, usize)>, + expanded_terminals: HashSet, edits_expanded: bool, plan_expanded: bool, editor_expanded: bool, - terminal_expanded: bool, editing_message: Option, _cancel_task: Option>, _subscriptions: [Subscription; 3], @@ -354,11 +354,11 @@ impl AcpThreadView { auth_task: None, expanded_tool_calls: HashSet::default(), expanded_thinking_blocks: HashSet::default(), + expanded_terminals: HashSet::default(), editing_message: None, edits_expanded: false, plan_expanded: false, editor_expanded: false, - terminal_expanded: true, history_store, hovered_recent_history_item: None, _subscriptions: subscriptions, @@ -677,6 +677,11 @@ impl AcpThreadView { cx: &mut Context, ) { match &event.view_event { + ViewEvent::NewTerminal(terminal_id) => { + if AgentSettings::get_global(cx).expand_terminal_card { + self.expanded_terminals.insert(*terminal_id); + } + } ViewEvent::MessageEditorEvent(_editor, MessageEditorEvent::Focus) => { if let Some(thread) = self.thread() && let Some(AgentThreadEntry::UserMessage(user_message)) = @@ -2009,6 +2014,8 @@ impl AcpThreadView { .map(|path| format!("{}", path.display())) .unwrap_or_else(|| "current directory".to_string()); + let is_expanded = self.expanded_terminals.contains(&terminal.entity_id()); + let header = h_flex() .id(SharedString::from(format!( "terminal-tool-header-{}", @@ -2142,12 +2149,19 @@ impl AcpThreadView { "terminal-tool-disclosure-{}", terminal.entity_id() )), - self.terminal_expanded, + is_expanded, ) .opened_icon(IconName::ChevronUp) .closed_icon(IconName::ChevronDown) - .on_click(cx.listener(move |this, _event, _window, _cx| { - this.terminal_expanded = !this.terminal_expanded; + .on_click(cx.listener({ + let terminal_id = terminal.entity_id(); + move |this, _event, _window, _cx| { + if is_expanded { + this.expanded_terminals.remove(&terminal_id); + } else { + this.expanded_terminals.insert(terminal_id); + } + } })), ); @@ -2156,7 +2170,7 @@ impl AcpThreadView { .read(cx) .entry(entry_ix) .and_then(|entry| entry.terminal(terminal)); - let show_output = self.terminal_expanded && terminal_view.is_some(); + let show_output = is_expanded && terminal_view.is_some(); v_flex() .mb_2()