diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index c319b7c6ae9f22fdc8d9ac266e01745115648214..be7a2ff8c1be9c2b91fd4ae6dabfdbc550784a91 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -308,7 +308,7 @@ "shift-alt-y": "agent::KeepAll", "shift-alt-z": "agent::RejectAll", "ctrl-enter": "agent::ChatWithFollow", - "ctrl-shift-enter": "agent::QueueMessage", + "ctrl-shift-enter": "agent::SendImmediately", "ctrl-shift-alt-enter": "agent::SendNextQueuedMessage", "ctrl-shift-backspace": "agent::ClearMessageQueue", "ctrl-shift-v": "agent::PasteRaw", diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 8fe72ecbc6bb14bf3dcf800ca9e1c73ef60dff67..a0bd957bdab86241ad6e5ef6d0af6394fea6463a 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -356,7 +356,7 @@ "shift-alt-y": "agent::KeepAll", "shift-alt-z": "agent::RejectAll", "cmd-enter": "agent::ChatWithFollow", - "cmd-shift-enter": "agent::QueueMessage", + "cmd-shift-enter": "agent::SendImmediately", "cmd-shift-alt-enter": "agent::SendNextQueuedMessage", "cmd-shift-backspace": "agent::ClearMessageQueue", "cmd-shift-v": "agent::PasteRaw", diff --git a/assets/keymaps/default-windows.json b/assets/keymaps/default-windows.json index 637bc66f0cf9dbcc357a30276bd3a015518eb4fb..05a65626d0bd3afa74ab174a565ec2ec3e2f1020 100644 --- a/assets/keymaps/default-windows.json +++ b/assets/keymaps/default-windows.json @@ -310,7 +310,7 @@ "shift-alt-y": "agent::KeepAll", "shift-alt-z": "agent::RejectAll", "ctrl-enter": "agent::ChatWithFollow", - "ctrl-shift-enter": "agent::QueueMessage", + "ctrl-shift-enter": "agent::SendImmediately", "ctrl-shift-alt-enter": "agent::SendNextQueuedMessage", "ctrl-shift-backspace": "agent::ClearMessageQueue", "ctrl-shift-v": "agent::PasteRaw", diff --git a/crates/agent_ui/src/acp/message_editor.rs b/crates/agent_ui/src/acp/message_editor.rs index 81a3ba715d725dc4d966228ecc7a236f988afe06..ee25811e6c543eb5c135d6b76655df2e7633270f 100644 --- a/crates/agent_ui/src/acp/message_editor.rs +++ b/crates/agent_ui/src/acp/message_editor.rs @@ -1,4 +1,4 @@ -use crate::QueueMessage; +use crate::SendImmediately; use crate::acp::AcpThreadHistory; use crate::{ ChatWithFollow, @@ -53,7 +53,7 @@ pub struct MessageEditor { #[derive(Clone, Copy, Debug)] pub enum MessageEditorEvent { Send, - Queue, + SendImmediately, Cancel, Focus, LostFocus, @@ -508,18 +508,6 @@ impl MessageEditor { cx.emit(MessageEditorEvent::Send) } - pub fn queue(&mut self, cx: &mut Context) { - if self.is_empty(cx) { - return; - } - - self.editor.update(cx, |editor, cx| { - editor.clear_inlay_hints(cx); - }); - - cx.emit(MessageEditorEvent::Queue) - } - pub fn trigger_completion_menu(&mut self, window: &mut Window, cx: &mut Context) { let editor = self.editor.clone(); @@ -563,8 +551,16 @@ impl MessageEditor { self.send(cx); } - fn queue_message(&mut self, _: &QueueMessage, _: &mut Window, cx: &mut Context) { - self.queue(cx); + fn send_immediately(&mut self, _: &SendImmediately, _: &mut Window, cx: &mut Context) { + if self.is_empty(cx) { + return; + } + + self.editor.update(cx, |editor, cx| { + editor.clear_inlay_hints(cx); + }); + + cx.emit(MessageEditorEvent::SendImmediately) } fn chat_with_follow( @@ -1009,7 +1005,7 @@ impl Render for MessageEditor { div() .key_context("MessageEditor") .on_action(cx.listener(Self::chat)) - .on_action(cx.listener(Self::queue_message)) + .on_action(cx.listener(Self::send_immediately)) .on_action(cx.listener(Self::chat_with_follow)) .on_action(cx.listener(Self::cancel)) .on_action(cx.listener(Self::paste_raw)) diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs index 1378a9f02d1eb201d658b8ba7f325fb17530455c..f1d70741e83fbaed3906bc63cb1b08cfa8899131 100644 --- a/crates/agent_ui/src/acp/thread_view.rs +++ b/crates/agent_ui/src/acp/thread_view.rs @@ -73,7 +73,7 @@ use crate::ui::{AgentNotification, AgentNotificationEvent, BurnModeTooltip, Usag use crate::{ AgentDiffPane, AgentPanel, AllowAlways, AllowOnce, ClearMessageQueue, ContinueThread, ContinueWithBurnMode, CycleFavoriteModels, CycleModeSelector, ExpandMessageEditor, Follow, - KeepAll, NewThread, OpenAgentDiff, OpenHistory, QueueMessage, RejectAll, RejectOnce, + KeepAll, NewThread, OpenAgentDiff, OpenHistory, RejectAll, RejectOnce, SendImmediately, SendNextQueuedMessage, ToggleBurnMode, ToggleProfileSelector, }; @@ -1204,7 +1204,7 @@ impl AcpThreadView { ) { match event { MessageEditorEvent::Send => self.send(window, cx), - MessageEditorEvent::Queue => self.queue_message(window, cx), + MessageEditorEvent::SendImmediately => self.interrupt_and_send(window, cx), MessageEditorEvent::Cancel => self.cancel_generation(cx), MessageEditorEvent::Focus => { self.cancel_editing(&Default::default(), window, cx); @@ -1256,7 +1256,7 @@ impl AcpThreadView { } } } - ViewEvent::MessageEditorEvent(_editor, MessageEditorEvent::Queue) => {} + ViewEvent::MessageEditorEvent(_editor, MessageEditorEvent::SendImmediately) => {} ViewEvent::MessageEditorEvent(editor, MessageEditorEvent::Send) => { self.regenerate(event.entry_index, editor.clone(), window, cx); } @@ -1300,7 +1300,7 @@ impl AcpThreadView { } if thread.read(cx).status() != ThreadStatus::Idle { - self.stop_current_and_send_new_message(window, cx); + self.queue_message(window, cx); return; } @@ -1344,6 +1344,23 @@ impl AcpThreadView { self.send_impl(self.message_editor.clone(), window, cx) } + fn interrupt_and_send(&mut self, window: &mut Window, cx: &mut Context) { + let Some(thread) = self.thread() else { + return; + }; + + if self.is_loading_contents { + return; + } + + if thread.read(cx).status() == ThreadStatus::Idle { + self.send_impl(self.message_editor.clone(), window, cx); + return; + } + + self.stop_current_and_send_new_message(window, cx); + } + fn stop_current_and_send_new_message(&mut self, window: &mut Window, cx: &mut Context) { let Some(thread) = self.thread().cloned() else { return; @@ -5617,13 +5634,7 @@ impl AcpThreadView { .tooltip(move |_window, cx| { if is_editor_empty && !is_generating { Tooltip::for_action("Type to Send", &Chat, cx) - } else { - let title = if is_generating { - "Stop and Send Message" - } else { - "Send" - }; - + } else if is_generating { let focus_handle = focus_handle.clone(); Tooltip::element(move |_window, cx| { @@ -5633,7 +5644,7 @@ impl AcpThreadView { h_flex() .gap_2() .justify_between() - .child(Label::new(title)) + .child(Label::new("Queue and Send")) .child(KeyBinding::for_action_in(&Chat, &focus_handle, cx)), ) .child( @@ -5643,15 +5654,17 @@ impl AcpThreadView { .justify_between() .border_t_1() .border_color(cx.theme().colors().border_variant) - .child(Label::new("Queue Message")) + .child(Label::new("Send Immediately")) .child(KeyBinding::for_action_in( - &QueueMessage, + &SendImmediately, &focus_handle, cx, )), ) .into_any_element() })(_window, cx) + } else { + Tooltip::for_action("Send Message", &Chat, cx) } }) .on_click(cx.listener(|this, _, window, cx| { @@ -8846,7 +8859,7 @@ pub(crate) mod tests { editor.set_text("Message 2", window, cx); }); thread_view.update_in(cx, |thread_view, window, cx| { - thread_view.send(window, cx); + thread_view.interrupt_and_send(window, cx); }); cx.update(|_, cx| { diff --git a/crates/agent_ui/src/agent_ui.rs b/crates/agent_ui/src/agent_ui.rs index bd8f9eb6ecda35ee2d3804406c07fb7637ee5557..d13257ce5fc0d58e96b8bfd04c81183514b498ce 100644 --- a/crates/agent_ui/src/agent_ui.rs +++ b/crates/agent_ui/src/agent_ui.rs @@ -123,8 +123,8 @@ actions!( ContinueWithBurnMode, /// Toggles burn mode for faster responses. ToggleBurnMode, - /// Queues a message to be sent when generation completes. - QueueMessage, + /// Interrupts the current generation and sends the message immediately. + SendImmediately, /// Sends the next queued message immediately. SendNextQueuedMessage, /// Clears all messages from the queue.