From 45aeced2046cc4cbd1bb54cc2d45390baf9fdd76 Mon Sep 17 00:00:00 2001 From: Edward Frazer Date: Thu, 7 May 2026 09:45:25 -0700 Subject: [PATCH] fix(tui): keep draining whitespace-only queued upload --- codex-rs/tui/src/chatwidget/slash_dispatch.rs | 4 +++ .../src/chatwidget/tests/slash_commands.rs | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/codex-rs/tui/src/chatwidget/slash_dispatch.rs b/codex-rs/tui/src/chatwidget/slash_dispatch.rs index 8cf21dcec7..7a85d3efc7 100644 --- a/codex-rs/tui/src/chatwidget/slash_dispatch.rs +++ b/codex-rs/tui/src/chatwidget/slash_dispatch.rs @@ -860,6 +860,10 @@ impl ChatWidget { let trimmed_start = rest.trim_start(); let leading_trimmed = rest.len().saturating_sub(trimmed_start.len()); let trimmed_rest = trimmed_start.trim_end(); + if cmd == SlashCommand::Upload && trimmed_rest.is_empty() { + self.dispatch_command(cmd); + return QueueDrain::Continue; + } let args_elements = Self::slash_command_args_elements( trimmed_rest, rest_offset + leading_trimmed, diff --git a/codex-rs/tui/src/chatwidget/tests/slash_commands.rs b/codex-rs/tui/src/chatwidget/tests/slash_commands.rs index 65acdf68c2..58cad9bd29 100644 --- a/codex-rs/tui/src/chatwidget/tests/slash_commands.rs +++ b/codex-rs/tui/src/chatwidget/tests/slash_commands.rs @@ -2107,6 +2107,36 @@ async fn queued_upload_without_args_keeps_draining() { } } +#[tokio::test] +async fn queued_upload_with_only_whitespace_keeps_draining() { + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.thread_id = Some(ThreadId::new()); + handle_turn_started(&mut chat, "turn-1"); + + queue_composer_text_with_tab(&mut chat, "/upload "); + queue_composer_text_with_tab(&mut chat, "after upload help"); + + complete_turn_with_message(&mut chat, "turn-1", Some("done")); + + let events = std::iter::from_fn(|| rx.try_recv().ok()).collect::>(); + assert!( + !events + .iter() + .any(|event| matches!(event, AppEvent::UploadLocalFile { .. })), + "whitespace-only queued /upload should not start an upload; events: {events:?}" + ); + match next_submit_op(&mut op_rx) { + Op::UserTurn { items, .. } => assert_eq!( + items, + vec![UserInput::Text { + text: "after upload help".to_string(), + text_elements: Vec::new(), + }] + ), + other => panic!("expected follow-up prompt after whitespace-only /upload, got {other:?}"), + } +} + #[tokio::test] async fn user_turn_sends_standard_override_after_fast_is_turned_off() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;