Notify when tool is finished (#27459)
Now if a tool call finishes (or is blocked on confirmation) and the Zed window is not active, you get a notification popup. You can turn it off with a setting. <img width="420" alt="Screenshot 2025-03-25 at 5 19 25 PM" src="https://github.com/user-attachments/assets/bdf7b6b8-4428-4b46-8b09-e0be140f8a51" /> <img width="420 alt="Screenshot 2025-03-25 at 5 18 13 PM" src="https://github.com/user-attachments/assets/1325e7b8-cd5a-44b9-a82d-5db928ad3cfc" /> Release Notes: - N/A --------- Co-authored-by: Agus Zubiaga <hi@aguz.me> Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This commit is contained in:
parent
a605b66ce1
commit
931a6d6f40
8 changed files with 216 additions and 3 deletions
|
@ -4,8 +4,9 @@ use crate::thread::{
|
|||
};
|
||||
use crate::thread_store::ThreadStore;
|
||||
use crate::tool_use::{PendingToolUseStatus, ToolUse, ToolUseStatus};
|
||||
use crate::ui::ContextPill;
|
||||
use crate::ui::{ContextPill, ToolReadyPopUp, ToolReadyPopupEvent};
|
||||
|
||||
use assistant_settings::AssistantSettings;
|
||||
use collections::HashMap;
|
||||
use editor::{Editor, MultiBuffer};
|
||||
use gpui::{
|
||||
|
@ -13,6 +14,7 @@ use gpui::{
|
|||
Animation, AnimationExt, AnyElement, App, ClickEvent, DefiniteLength, EdgesRefinement, Empty,
|
||||
Entity, Focusable, Length, ListAlignment, ListOffset, ListState, ScrollHandle, StyleRefinement,
|
||||
Subscription, Task, TextStyleRefinement, Transformation, UnderlineStyle, WeakEntity,
|
||||
WindowHandle,
|
||||
};
|
||||
use language::{Buffer, LanguageRegistry};
|
||||
use language_model::{LanguageModelRegistry, LanguageModelToolUseId, Role};
|
||||
|
@ -42,6 +44,7 @@ pub struct ActiveThread {
|
|||
expanded_tool_uses: HashMap<LanguageModelToolUseId, bool>,
|
||||
expanded_thinking_segments: HashMap<(MessageId, usize), bool>,
|
||||
last_error: Option<ThreadError>,
|
||||
pop_ups: Vec<WindowHandle<ToolReadyPopUp>>,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
}
|
||||
|
||||
|
@ -244,6 +247,7 @@ impl ActiveThread {
|
|||
}),
|
||||
editing_message: None,
|
||||
last_error: None,
|
||||
pop_ups: Vec::new(),
|
||||
_subscriptions: subscriptions,
|
||||
};
|
||||
|
||||
|
@ -370,7 +374,14 @@ impl ActiveThread {
|
|||
ThreadEvent::StreamedCompletion | ThreadEvent::SummaryChanged => {
|
||||
self.save_thread(cx);
|
||||
}
|
||||
ThreadEvent::DoneStreaming => {}
|
||||
ThreadEvent::DoneStreaming => {
|
||||
if !self.thread().read(cx).is_generating() {
|
||||
self.show_notification("Your changes have been applied.", window, cx);
|
||||
}
|
||||
}
|
||||
ThreadEvent::ToolConfirmationNeeded => {
|
||||
self.show_notification("There's a tool confirmation needed.", window, cx);
|
||||
}
|
||||
ThreadEvent::StreamedAssistantText(message_id, text) => {
|
||||
if let Some(rendered_message) = self.rendered_messages_by_id.get_mut(&message_id) {
|
||||
rendered_message.append_text(text, window, cx);
|
||||
|
@ -497,6 +508,59 @@ impl ActiveThread {
|
|||
}
|
||||
}
|
||||
|
||||
fn show_notification(
|
||||
&mut self,
|
||||
caption: impl Into<SharedString>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<'_, ActiveThread>,
|
||||
) {
|
||||
if !window.is_window_active()
|
||||
&& self.pop_ups.is_empty()
|
||||
&& AssistantSettings::get_global(cx).notify_when_agent_waiting
|
||||
{
|
||||
let caption = caption.into();
|
||||
|
||||
for screen in cx.displays() {
|
||||
let options = ToolReadyPopUp::window_options(screen, cx);
|
||||
|
||||
if let Some(screen_window) = cx
|
||||
.open_window(options, |_, cx| {
|
||||
cx.new(|_| ToolReadyPopUp::new(caption.clone()))
|
||||
})
|
||||
.log_err()
|
||||
{
|
||||
if let Some(pop_up) = screen_window.entity(cx).log_err() {
|
||||
cx.subscribe_in(&pop_up, window, {
|
||||
|this, _, event, window, cx| match event {
|
||||
ToolReadyPopupEvent::Accepted => {
|
||||
let handle = window.window_handle();
|
||||
cx.activate(true); // Switch back to the Zed application
|
||||
|
||||
// If there are multiple Zed windows, activate the correct one.
|
||||
cx.defer(move |cx| {
|
||||
handle
|
||||
.update(cx, |_view, window, _cx| {
|
||||
window.activate_window();
|
||||
})
|
||||
.log_err();
|
||||
});
|
||||
|
||||
this.dismiss_notifications(cx);
|
||||
}
|
||||
ToolReadyPopupEvent::Dismissed => {
|
||||
this.dismiss_notifications(cx);
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
self.pop_ups.push(screen_window);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawns a task to save the active thread.
|
||||
///
|
||||
/// Only one task to save the thread will be in flight at a time.
|
||||
|
@ -1635,6 +1699,16 @@ impl ActiveThread {
|
|||
.into_any()
|
||||
})
|
||||
}
|
||||
|
||||
fn dismiss_notifications(&mut self, cx: &mut Context<'_, ActiveThread>) {
|
||||
for window in self.pop_ups.drain(..) {
|
||||
window
|
||||
.update(cx, |_, window, _| {
|
||||
window.remove_window();
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ActiveThread {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue