agent: Add ability to interrupt current generation with a new message (#28762)

If you wanted to interrupt the current LLM response that's generating to
send a follow up message, you'd need to stop it first, type your new
message, and then send it. Now, you can just type your new message while
there's a response generating and send it. This will interrupt the
previous response generation and kick off a new one.

Release Notes:

- agent: Allow to send a new message while a response is generating,
interrupting the LLM to focus instead on the most recent prompt.
This commit is contained in:
Danilo Leal 2025-04-15 13:34:35 -03:00 committed by GitHub
parent 144fd0b00d
commit 8f52bb92b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -208,6 +208,7 @@ impl MessageEditor {
} }
if self.thread.read(cx).is_generating() { if self.thread.read(cx).is_generating() {
self.stop_current_and_send_new_message(window, cx);
return; return;
} }
@ -297,6 +298,17 @@ impl MessageEditor {
.detach(); .detach();
} }
fn stop_current_and_send_new_message(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let cancelled = self
.thread
.update(cx, |thread, cx| thread.cancel_last_completion(cx));
if cancelled {
self.set_editor_is_expanded(false, cx);
self.send_to_model(RequestKind::Chat, window, cx);
}
}
fn handle_context_strip_event( fn handle_context_strip_event(
&mut self, &mut self,
_context_strip: &Entity<ContextStrip>, _context_strip: &Entity<ContextStrip>,
@ -464,39 +476,76 @@ impl MessageEditor {
let focus_handle = focus_handle.clone(); let focus_handle = focus_handle.clone();
move |parent| { move |parent| {
if is_generating { if is_generating {
parent.child( parent
IconButton::new( .when(is_editor_empty, |parent| {
"stop-generation", parent.child(
IconName::StopFilled, IconButton::new(
) "stop-generation",
.icon_color(Color::Error) IconName::StopFilled,
.style(ButtonStyle::Tinted(ui::TintColor::Error)) )
.tooltip(move |window, cx| { .icon_color(Color::Error)
Tooltip::for_action( .style(ButtonStyle::Tinted(
"Stop Generation", ui::TintColor::Error,
&editor::actions::Cancel, ))
window, .tooltip(move |window, cx| {
cx, Tooltip::for_action(
"Stop Generation",
&editor::actions::Cancel,
window,
cx,
)
})
.on_click({
let focus_handle = focus_handle.clone();
move |_event, window, cx| {
focus_handle.dispatch_action(
&editor::actions::Cancel,
window,
cx,
);
}
})
.with_animation(
"pulsating-label",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(
0.4, 1.0,
)),
|icon_button, delta| {
icon_button.alpha(delta)
},
),
) )
}) })
.on_click({ .when(!is_editor_empty, |parent| {
let focus_handle = focus_handle.clone(); parent.child(
move |_event, window, cx| { IconButton::new("send-message", IconName::Send)
focus_handle.dispatch_action( .icon_color(Color::Accent)
&editor::actions::Cancel, .style(ButtonStyle::Filled)
window, .disabled(
cx, !is_model_selected
); || self
} .waiting_for_summaries_to_send,
)
.on_click({
let focus_handle = focus_handle.clone();
move |_event, window, cx| {
focus_handle.dispatch_action(
&Chat, window, cx,
);
}
})
.tooltip(move |window, cx| {
Tooltip::for_action(
"Stop and Send New Message",
&Chat,
window,
cx,
)
}),
)
}) })
.with_animation(
"pulsating-label",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(0.4, 1.0)),
|icon_button, delta| icon_button.alpha(delta),
),
)
} else { } else {
parent.child( parent.child(
IconButton::new("send-message", IconName::Send) IconButton::new("send-message", IconName::Send)