assistant2: Agent notification improvements (#27638)
- Show thread's summary in notification title - Improve thread's summary prompt so it's more descriptive - Make whole notification clickable  Release Notes: - N/A
This commit is contained in:
parent
82ce187bfc
commit
da47013e56
4 changed files with 156 additions and 108 deletions
|
@ -4,7 +4,7 @@ use crate::thread::{
|
|||
};
|
||||
use crate::thread_store::ThreadStore;
|
||||
use crate::tool_use::{PendingToolUseStatus, ToolUse, ToolUseStatus};
|
||||
use crate::ui::{ContextPill, ToolReadyPopUp, ToolReadyPopupEvent};
|
||||
use crate::ui::{AgentNotification, AgentNotificationEvent, ContextPill};
|
||||
use crate::AssistantPanel;
|
||||
use assistant_settings::AssistantSettings;
|
||||
use collections::HashMap;
|
||||
|
@ -45,9 +45,9 @@ 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>>,
|
||||
notifications: Vec<WindowHandle<AgentNotification>>,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
pop_up_subscriptions: HashMap<WindowHandle<ToolReadyPopUp>, Vec<Subscription>>,
|
||||
notification_subscriptions: HashMap<WindowHandle<AgentNotification>, Vec<Subscription>>,
|
||||
}
|
||||
|
||||
struct RenderedMessage {
|
||||
|
@ -252,9 +252,9 @@ impl ActiveThread {
|
|||
scrollbar_state: ScrollbarState::new(list_state),
|
||||
editing_message: None,
|
||||
last_error: None,
|
||||
pop_ups: Vec::new(),
|
||||
notifications: Vec::new(),
|
||||
_subscriptions: subscriptions,
|
||||
pop_up_subscriptions: HashMap::default(),
|
||||
notification_subscriptions: HashMap::default(),
|
||||
};
|
||||
|
||||
for message in thread.read(cx).messages().cloned().collect::<Vec<_>>() {
|
||||
|
@ -377,24 +377,23 @@ impl ActiveThread {
|
|||
self.save_thread(cx);
|
||||
}
|
||||
ThreadEvent::DoneStreaming => {
|
||||
if !self.thread().read(cx).is_generating() {
|
||||
let thread = self.thread.read(cx);
|
||||
|
||||
if !thread.is_generating() {
|
||||
self.show_notification(
|
||||
"The assistant response has concluded.",
|
||||
IconName::Check,
|
||||
Color::Success,
|
||||
if thread.used_tools_since_last_user_message() {
|
||||
"Finished running tools"
|
||||
} else {
|
||||
"New message"
|
||||
},
|
||||
IconName::ZedAssistant,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
ThreadEvent::ToolConfirmationNeeded => {
|
||||
self.show_notification(
|
||||
"There's a tool confirmation needed.",
|
||||
IconName::Info,
|
||||
Color::Muted,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
self.show_notification("Waiting for tool confirmation", IconName::Info, window, cx);
|
||||
}
|
||||
ThreadEvent::StreamedAssistantText(message_id, text) => {
|
||||
if let Some(rendered_message) = self.rendered_messages_by_id.get_mut(&message_id) {
|
||||
|
@ -526,85 +525,90 @@ impl ActiveThread {
|
|||
&mut self,
|
||||
caption: impl Into<SharedString>,
|
||||
icon: IconName,
|
||||
icon_color: Color,
|
||||
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
|
||||
if window.is_window_active()
|
||||
|| !self.notifications.is_empty()
|
||||
|| !AssistantSettings::get_global(cx).notify_when_agent_waiting
|
||||
{
|
||||
let caption = caption.into();
|
||||
return;
|
||||
}
|
||||
|
||||
for screen in cx.displays() {
|
||||
let options = ToolReadyPopUp::window_options(screen, cx);
|
||||
let caption = caption.into();
|
||||
|
||||
if let Some(screen_window) = cx
|
||||
.open_window(options, |_, cx| {
|
||||
cx.new(|_| ToolReadyPopUp::new(caption.clone(), icon, icon_color))
|
||||
})
|
||||
.log_err()
|
||||
{
|
||||
if let Some(pop_up) = screen_window.entity(cx).log_err() {
|
||||
self.pop_up_subscriptions
|
||||
.entry(screen_window)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(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
|
||||
let title = self
|
||||
.thread
|
||||
.read(cx)
|
||||
.summary()
|
||||
.unwrap_or("Agent Panel".into());
|
||||
|
||||
let workspace_handle = this.workspace.clone();
|
||||
for screen in cx.displays() {
|
||||
let options = AgentNotification::window_options(screen, cx);
|
||||
|
||||
// If there are multiple Zed windows, activate the correct one.
|
||||
cx.defer(move |cx| {
|
||||
handle
|
||||
.update(cx, |_view, window, _cx| {
|
||||
window.activate_window();
|
||||
if let Some(screen_window) = cx
|
||||
.open_window(options, |_, cx| {
|
||||
cx.new(|_| AgentNotification::new(title.clone(), caption.clone(), icon))
|
||||
})
|
||||
.log_err()
|
||||
{
|
||||
if let Some(pop_up) = screen_window.entity(cx).log_err() {
|
||||
self.notification_subscriptions
|
||||
.entry(screen_window)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(cx.subscribe_in(&pop_up, window, {
|
||||
|this, _, event, window, cx| match event {
|
||||
AgentNotificationEvent::Accepted => {
|
||||
let handle = window.window_handle();
|
||||
cx.activate(true); // Switch back to the Zed application
|
||||
|
||||
if let Some(workspace) =
|
||||
workspace_handle.upgrade()
|
||||
{
|
||||
workspace.update(_cx, |workspace, cx| {
|
||||
workspace
|
||||
.focus_panel::<AssistantPanel>(
|
||||
window, cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
.log_err();
|
||||
let workspace_handle = this.workspace.clone();
|
||||
|
||||
// If there are multiple Zed windows, activate the correct one.
|
||||
cx.defer(move |cx| {
|
||||
handle
|
||||
.update(cx, |_view, window, _cx| {
|
||||
window.activate_window();
|
||||
|
||||
if let Some(workspace) = workspace_handle.upgrade()
|
||||
{
|
||||
workspace.update(_cx, |workspace, cx| {
|
||||
workspace.focus_panel::<AssistantPanel>(
|
||||
window, cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
.log_err();
|
||||
});
|
||||
|
||||
this.dismiss_notifications(cx);
|
||||
}
|
||||
AgentNotificationEvent::Dismissed => {
|
||||
this.dismiss_notifications(cx);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
self.notifications.push(screen_window);
|
||||
|
||||
// If the user manually refocuses the original window, dismiss the popup.
|
||||
self.notification_subscriptions
|
||||
.entry(screen_window)
|
||||
.or_insert_with(Vec::new)
|
||||
.push({
|
||||
let pop_up_weak = pop_up.downgrade();
|
||||
|
||||
cx.observe_window_activation(window, move |_, window, cx| {
|
||||
if window.is_window_active() {
|
||||
if let Some(pop_up) = pop_up_weak.upgrade() {
|
||||
pop_up.update(cx, |_, cx| {
|
||||
cx.emit(AgentNotificationEvent::Dismissed);
|
||||
});
|
||||
|
||||
this.dismiss_notifications(cx);
|
||||
}
|
||||
ToolReadyPopupEvent::Dismissed => {
|
||||
this.dismiss_notifications(cx);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
self.pop_ups.push(screen_window);
|
||||
|
||||
// If the user manually refocuses the original window, dismiss the popup.
|
||||
self.pop_up_subscriptions
|
||||
.entry(screen_window)
|
||||
.or_insert_with(Vec::new)
|
||||
.push({
|
||||
let pop_up_weak = pop_up.downgrade();
|
||||
|
||||
cx.observe_window_activation(window, move |_, window, cx| {
|
||||
if window.is_window_active() {
|
||||
if let Some(pop_up) = pop_up_weak.upgrade() {
|
||||
pop_up.update(cx, |_, cx| {
|
||||
cx.emit(ToolReadyPopupEvent::Dismissed);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1764,14 +1768,14 @@ impl ActiveThread {
|
|||
}
|
||||
|
||||
fn dismiss_notifications(&mut self, cx: &mut Context<'_, ActiveThread>) {
|
||||
for window in self.pop_ups.drain(..) {
|
||||
for window in self.notifications.drain(..) {
|
||||
window
|
||||
.update(cx, |_, window, _| {
|
||||
window.remove_window();
|
||||
})
|
||||
.ok();
|
||||
|
||||
self.pop_up_subscriptions.remove(&window);
|
||||
self.notification_subscriptions.remove(&window);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue