From 2179be1855569a79280581e45c8be780c0c72778 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 13 Jan 2025 14:29:50 -0500 Subject: [PATCH] assistant2: Add an indicator when a response is streaming in (#23078) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR adds an indicator to the Assistant message to indicate that it is still streaming: Screenshot 2025-01-13 at 2 10 33 PM Release Notes: - N/A --- crates/assistant2/src/active_thread.rs | 38 ++++++++++++++++++++++++-- crates/assistant2/src/thread.rs | 4 +++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/crates/assistant2/src/active_thread.rs b/crates/assistant2/src/active_thread.rs index 7633d044a13b10643480c05ac0ffa85e08bfc579..58dc92ebe2cd3f667dde9bf5f4543eaecf020fb2 100644 --- a/crates/assistant2/src/active_thread.rs +++ b/crates/assistant2/src/active_thread.rs @@ -1,11 +1,13 @@ use std::sync::Arc; +use std::time::Duration; use assistant_tool::ToolWorkingSet; use collections::HashMap; use gpui::{ - list, AbsoluteLength, AnyElement, AppContext, DefiniteLength, EdgesRefinement, Empty, Length, - ListAlignment, ListOffset, ListState, Model, StyleRefinement, Subscription, - TextStyleRefinement, UnderlineStyle, View, WeakView, + list, percentage, AbsoluteLength, Animation, AnimationExt, AnyElement, AppContext, + DefiniteLength, EdgesRefinement, Empty, Length, ListAlignment, ListOffset, ListState, Model, + StyleRefinement, Subscription, TextStyleRefinement, Transformation, UnderlineStyle, View, + WeakView, }; use language::LanguageRegistry; use language_model::Role; @@ -248,6 +250,7 @@ impl ActiveThread { return Empty.into_any(); }; + let is_streaming_completion = self.thread.read(cx).is_streaming(); let context = self.thread.read(cx).context_for_message(message_id); let colors = cx.theme().colors(); @@ -290,6 +293,35 @@ impl ActiveThread { ), ) .child(div().p_2p5().text_ui(cx).child(markdown.clone())) + .when( + message.role == Role::Assistant && is_streaming_completion, + |parent| { + parent.child( + h_flex() + .gap_1() + .p_2p5() + .child( + Icon::new(IconName::ArrowCircle) + .size(IconSize::Small) + .color(Color::Muted) + .with_animation( + "arrow-circle", + Animation::new(Duration::from_secs(2)).repeat(), + |icon, delta| { + icon.transform(Transformation::rotate( + percentage(delta), + )) + }, + ), + ) + .child( + Label::new("Generating…") + .size(LabelSize::Small) + .color(Color::Muted), + ), + ) + }, + ) .when_some(context, |parent, context| { if !context.is_empty() { parent.child( diff --git a/crates/assistant2/src/thread.rs b/crates/assistant2/src/thread.rs index 707d8be514b09c9795ca9d7fdc95083055a9f199..b5a42da85b325a8829cdcd3977a1a08f38c9da35 100644 --- a/crates/assistant2/src/thread.rs +++ b/crates/assistant2/src/thread.rs @@ -132,6 +132,10 @@ impl Thread { self.messages.iter() } + pub fn is_streaming(&self) -> bool { + !self.pending_completions.is_empty() + } + pub fn tools(&self) -> &Arc { &self.tools }