diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 17afb9a185..617aba0f01 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -1270,7 +1270,16 @@ impl ChatWidget { SlashCommand::Mcp => { self.add_mcp_output(); } - #[cfg(debug_assertions)] + SlashCommand::Rollout => { + if let Some(path) = self.rollout_path() { + self.add_info_message( + format!("Current rollout path: {}", path.display()), + None, + ); + } else { + self.add_info_message("Rollout path is not available yet.".to_string(), None); + } + } SlashCommand::TestApproval => { use codex_core::protocol::EventMsg; use std::collections::HashMap; diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index eb53f90f77..d182467831 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -863,6 +863,42 @@ fn slash_undo_sends_op() { } } +#[test] +fn slash_rollout_displays_current_path() { + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(); + let rollout_path = PathBuf::from("/tmp/codex-test-rollout.jsonl"); + chat.current_rollout_path = Some(rollout_path.clone()); + + chat.dispatch_command(SlashCommand::Rollout); + + let cells = drain_insert_history(&mut rx); + assert_eq!(cells.len(), 1, "expected info message for rollout path"); + let rendered = lines_to_single_string(&cells[0]); + assert!( + rendered.contains(&rollout_path.display().to_string()), + "expected rollout path to be shown: {rendered}" + ); +} + +#[test] +fn slash_rollout_handles_missing_path() { + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(); + + chat.dispatch_command(SlashCommand::Rollout); + + let cells = drain_insert_history(&mut rx); + assert_eq!( + cells.len(), + 1, + "expected info message explaining missing path" + ); + let rendered = lines_to_single_string(&cells[0]); + assert!( + rendered.contains("not available"), + "expected missing rollout path message: {rendered}" + ); +} + #[test] fn undo_success_events_render_info_messages() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(); diff --git a/codex-rs/tui/src/slash_command.rs b/codex-rs/tui/src/slash_command.rs index bb3be33099..cfe7102ca1 100644 --- a/codex-rs/tui/src/slash_command.rs +++ b/codex-rs/tui/src/slash_command.rs @@ -26,7 +26,7 @@ pub enum SlashCommand { Logout, Quit, Feedback, - #[cfg(debug_assertions)] + Rollout, TestApproval, } @@ -48,7 +48,7 @@ impl SlashCommand { SlashCommand::Approvals => "choose what Codex can do without approval", SlashCommand::Mcp => "list configured MCP tools", SlashCommand::Logout => "log out of Codex", - #[cfg(debug_assertions)] + SlashCommand::Rollout => "print the rollout file path", SlashCommand::TestApproval => "test approval request", } } @@ -76,14 +76,23 @@ impl SlashCommand { | SlashCommand::Mcp | SlashCommand::Feedback | SlashCommand::Quit => true, - - #[cfg(debug_assertions)] + SlashCommand::Rollout => true, SlashCommand::TestApproval => true, } } + + fn is_visible(self) -> bool { + match self { + SlashCommand::Rollout | SlashCommand::TestApproval => cfg!(debug_assertions), + _ => true, + } + } } /// Return all built-in commands in a Vec paired with their command string. pub fn built_in_slash_commands() -> Vec<(&'static str, SlashCommand)> { - SlashCommand::iter().map(|c| (c.command(), c)).collect() + SlashCommand::iter() + .filter(|command| command.is_visible()) + .map(|c| (c.command(), c)) + .collect() }