diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 362d6d15df..62bb7ec40a 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -5800,8 +5800,11 @@ impl ChatWidget { Some((cmd, rest, rest_offset)) } - fn is_builtin_slash_draft(&self, draft: &UserMessage) -> bool { - self.parse_builtin_slash_command(&draft.text).is_some() + fn is_known_slash_draft(&self, draft: &UserMessage) -> bool { + let Some((name, _, _)) = parse_slash_name(&draft.text) else { + return false; + }; + !name.contains('/') && SlashCommand::from_str(name).is_ok() } fn reject_unavailable_builtin_slash_command(&mut self, user_message: &UserMessage) -> bool { @@ -6909,7 +6912,7 @@ impl ChatWidget { let Some(queued_message) = self.queued_user_messages.pop_front() else { break; }; - let replay_control = if self.is_builtin_slash_draft(&queued_message) { + let replay_control = if self.is_known_slash_draft(&queued_message) { self.execute_serialized_slash_command(queued_message) } else { self.submit_user_message(queued_message); diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 5437f0aa72..009ff730d4 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -8909,6 +8909,28 @@ async fn serialized_disabled_fast_slash_draft_is_rejected_immediately() { ); } +#[tokio::test] +async fn queued_disabled_fast_slash_draft_is_rejected_on_replay() { + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await; + chat.thread_id = Some(ThreadId::new()); + chat.set_feature_enabled(Feature::FastMode, false); + chat.on_task_started(); + chat.queued_user_messages.push_back("/fast on".into()); + + chat.bottom_pane.set_task_running(false); + chat.drain_queued_inputs_until_blocked(); + + assert_no_submit_op(&mut op_rx); + assert!(chat.queued_user_messages.is_empty()); + assert_eq!(chat.bottom_pane.composer_text(), "/fast on"); + + let inserted = drain_insert_history(&mut rx); + assert_eq!(inserted.len(), 1); + assert!( + lines_to_single_string(&inserted[0]).contains("/fast is not available in this session.") + ); +} + #[tokio::test] async fn user_turn_carries_service_tier_after_fast_toggle() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;