commit bfa3c342d1f0c68a1fe9c0162a767a0d10e03d88
parent 5b8b01f91e44189515f7c1162e23795bac625735
Author: William Casarin <jb55@jb55.com>
Date: Tue, 24 Feb 2026 11:39:44 -0800
dave: allow message queuing while Claude is working
Previously the Ask button was replaced by Stop while Claude was
working, and handle_user_send() unconditionally dispatched to the
backend (overwriting the active stream). This meant users couldn't
send follow-up messages during a turn, and Shift+Enter while working
was a latent bug that would lose the current stream.
Now the Ask button is always visible (Stop shown alongside for local
sessions), and handle_user_send() skips backend dispatch when already
streaming. Queued messages stay in chat and are automatically
dispatched by the existing needs_redispatch_after_stream_end() logic
when the current turn finishes.
This also helps unstick remote sessions: sending a message from a
remote device forces the local side to re-evaluate session state,
and the message gets dispatched once the stream ends (or immediately
if the process had crashed and the channel disconnected).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
2 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/crates/notedeck_dave/src/lib.rs b/crates/notedeck_dave/src/lib.rs
@@ -2185,6 +2185,13 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr
if session.is_remote() {
return;
}
+
+ // If already streaming, queue the message in chat without dispatching.
+ // needs_redispatch_after_stream_end() will dispatch it when the
+ // current turn finishes.
+ if session.is_streaming() {
+ return;
+ }
}
self.send_user_message(app_ctx, ui.ctx());
}
diff --git a/crates/notedeck_dave/src/ui/dave.rs b/crates/notedeck_dave/src/ui/dave.rs
@@ -1086,8 +1086,25 @@ impl<'a> DaveUi<'a> {
ui.with_layout(Layout::right_to_left(Align::Max), |ui| {
let mut dave_response = DaveResponse::none();
- // Show Stop button when working, Ask button otherwise
- if self.flags.contains(DaveUiFlags::IsWorking) {
+ // Always show Ask button (messages queue while working)
+ if ui
+ .add(
+ egui::Button::new(tr!(
+ i18n,
+ "Ask",
+ "Button to send message to Dave AI assistant"
+ ))
+ .min_size(egui::vec2(60.0, 44.0)),
+ )
+ .clicked()
+ {
+ dave_response = DaveResponse::send();
+ }
+
+ // Show Stop button alongside Ask for local working sessions
+ if self.flags.contains(DaveUiFlags::IsWorking)
+ && !self.flags.contains(DaveUiFlags::IsRemote)
+ {
if ui
.add(
egui::Button::new(tr!(
@@ -1109,18 +1126,6 @@ impl<'a> DaveUi<'a> {
.color(ui.visuals().warn_fg_color),
);
}
- } else if ui
- .add(
- egui::Button::new(tr!(
- i18n,
- "Ask",
- "Button to send message to Dave AI assistant"
- ))
- .min_size(egui::vec2(60.0, 44.0)),
- )
- .clicked()
- {
- dave_response = DaveResponse::send();
}
let r = ui.add(