@@ -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);