Do not send "finished" agent notification when about to send a queued message (#56157)

I wait for an agent it takes time/thinks, but I notice some odd error in
its work that I want to correct: I write a message, knowing that e.g.
Claude can read that later at some point and continue normally, and
focus away from Zed.

At some point, I get the notification I need to react to, only to
understand that the generation is ongoing still due to that delayed
message sent.

Release Notes:

- Fixed agent "finished" notification appearing right before the queued
message is sent
This commit is contained in:
Kirill Bulatov authored and GitHub committed 2026-05-08 17:13:58 +00:00
1 parent be83c952f6
commit 40d87a8c1f
1 file changed
+82 -13
+82 -13
View File
@@ -1507,18 +1507,6 @@ impl ConversationView {
return;
}
let used_tools = thread.read(cx).used_tools_since_last_user_message();
self.notify_with_sound(
if used_tools {
"Finished running tools"
} else {
"New message"
},
IconName::ZedAssistant,
window,
cx,
);
let should_send_queued = if let Some(active) = self.root_thread_view() {
active.update(cx, |active, cx| {
if active.skip_queue_processing_count > 0 {
@@ -1542,7 +1530,23 @@ impl ConversationView {
} else {
false
};
if should_send_queued {
// Skip notifying when a queued message is about to be auto-sent: the agent
// is not actually idle and a notification here would fire just before the
// next turn starts.
if !should_send_queued {
let used_tools = thread.read(cx).used_tools_since_last_user_message();
self.notify_with_sound(
if used_tools {
"Finished running tools"
} else {
"New message"
},
IconName::ZedAssistant,
window,
cx,
);
} else {
self.send_queued_message_at_index(0, false, window, cx);
}
}
@@ -3072,6 +3076,71 @@ pub(crate) mod tests {
);
}
#[gpui::test]
async fn test_no_notification_when_queued_message_will_be_auto_sent(cx: &mut TestAppContext) {
init_test(cx);
let connection = StubAgentConnection::new();
let (conversation_view, cx) =
setup_conversation_view(StubAgentServer::new(connection.clone()), cx).await;
add_to_workspace(conversation_view.clone(), cx);
let message_editor = message_editor(&conversation_view, cx);
message_editor.update_in(cx, |editor, window, cx| {
editor.set_text("first", window, cx);
});
active_thread(&conversation_view, cx)
.update_in(cx, |view, window, cx| view.send(window, cx));
cx.run_until_parked();
let session_id = conversation_view.read_with(cx, |view, cx| {
view.active_thread()
.unwrap()
.read(cx)
.thread
.read(cx)
.session_id()
.clone()
});
active_thread(&conversation_view, cx).update_in(cx, |thread, _window, cx| {
thread.add_to_queue(
vec![acp::ContentBlock::Text(acp::TextContent::new(
"queued".to_string(),
))],
vec![],
cx,
);
});
cx.deactivate_window();
cx.run_until_parked();
cx.update(|_, cx| {
connection.send_update(
session_id.clone(),
acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk::new(
"first response".into(),
)),
cx,
);
connection.end_turn(session_id, acp::StopReason::EndTurn);
});
cx.run_until_parked();
assert_eq!(
cx.windows()
.iter()
.filter(|window| window.downcast::<AgentNotification>().is_some())
.count(),
0,
"No notification should fire when a queued message will be auto-sent on Stopped"
);
}
#[gpui::test]
async fn test_notification_for_error(cx: &mut TestAppContext) {
init_test(cx);