diff --git a/codex-rs/tui/src/bottom_pane/command_popup.rs b/codex-rs/tui/src/bottom_pane/command_popup.rs index 1c2291465e..f8ea0b41e1 100644 --- a/codex-rs/tui/src/bottom_pane/command_popup.rs +++ b/codex-rs/tui/src/bottom_pane/command_popup.rs @@ -464,7 +464,7 @@ mod tests { } #[test] - fn collab_command_hidden_when_collaboration_modes_disabled() { + fn plan_command_hidden_when_collaboration_modes_disabled() { let mut popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); popup.on_composer_text_change("/".to_string()); @@ -476,35 +476,12 @@ mod tests { CommandItem::UserPrompt(_) => None, }) .collect(); - assert!( - !cmds.contains(&"collab"), - "expected '/collab' to be hidden when collaboration modes are disabled, got {cmds:?}" - ); assert!( !cmds.contains(&"plan"), "expected '/plan' to be hidden when collaboration modes are disabled, got {cmds:?}" ); } - #[test] - fn collab_command_visible_when_collaboration_modes_enabled() { - let mut popup = CommandPopup::new( - Vec::new(), - CommandPopupFlags { - collaboration_modes_enabled: true, - connectors_enabled: false, - personality_command_enabled: true, - windows_degraded_sandbox_active: false, - }, - ); - popup.on_composer_text_change("/collab".to_string()); - - match popup.selected_item() { - Some(CommandItem::Builtin(cmd)) => assert_eq!(cmd.command(), "collab"), - other => panic!("expected collab to be selected for exact match, got {other:?}"), - } - } - #[test] fn plan_command_visible_when_collaboration_modes_enabled() { let mut popup = CommandPopup::new( diff --git a/codex-rs/tui/src/bottom_pane/slash_commands.rs b/codex-rs/tui/src/bottom_pane/slash_commands.rs index 4613161f2f..ae2b3731dc 100644 --- a/codex-rs/tui/src/bottom_pane/slash_commands.rs +++ b/codex-rs/tui/src/bottom_pane/slash_commands.rs @@ -20,7 +20,7 @@ pub(crate) fn builtins_for_input( .filter(|(_, cmd)| allow_elevate_sandbox || *cmd != SlashCommand::ElevateSandbox) .filter(|(_, cmd)| { collaboration_modes_enabled - || !matches!(*cmd, SlashCommand::Collab | SlashCommand::Plan) + || *cmd != SlashCommand::Plan }) .filter(|(_, cmd)| connectors_enabled || *cmd != SlashCommand::Apps) .filter(|(_, cmd)| personality_command_enabled || *cmd != SlashCommand::Personality) diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index dcbee999bc..3fe4546b5c 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -3299,22 +3299,18 @@ impl ChatWidget { ); return; } - if let Some(mask) = collaboration_modes::plan_mask(self.models_manager.as_ref()) { + if self.active_mode_kind() == ModeKind::Plan { + let Some(mask) = collaboration_modes::default_mask(self.models_manager.as_ref()) else { + self.add_info_message("Default mode unavailable right now.".to_string(), None); + return; + }; + self.set_collaboration_mask(mask); + } else if let Some(mask) = collaboration_modes::plan_mask(self.models_manager.as_ref()) { self.set_collaboration_mask(mask); } else { self.add_info_message("Plan mode unavailable right now.".to_string(), None); } } - SlashCommand::Collab => { - if !self.collaboration_modes_enabled() { - self.add_info_message( - "Collaboration modes are disabled.".to_string(), - Some("Enable collaboration modes to use /collab.".to_string()), - ); - return; - } - self.open_collaboration_modes_popup(); - } SlashCommand::Agent => { self.app_event_tx.send(AppEvent::OpenAgentPicker); } diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index f069db9160..52751b21b6 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -3578,35 +3578,32 @@ async fn collab_mode_shift_tab_cycles_only_when_enabled_and_idle() { } #[tokio::test] -async fn collab_slash_command_opens_picker_and_updates_mode() { +async fn plan_slash_command_toggles_plan_mode() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(None).await; - chat.thread_id = Some(ThreadId::new()); chat.set_feature_enabled(Feature::CollaborationModes, true); + let initial = chat.current_collaboration_mode().clone(); + let default = initial.clone(); - chat.dispatch_command(SlashCommand::Collab); - let popup = render_bottom_popup(&chat, 80); - assert!( - popup.contains("Select Collaboration Mode"), - "expected collaboration picker: {popup}" - ); + chat.dispatch_command(SlashCommand::Plan); - chat.handle_key_event(KeyEvent::from(KeyCode::Enter)); - let selected_mask = match rx.try_recv() { - Ok(AppEvent::UpdateCollaborationMode(mask)) => mask, - other => panic!("expected UpdateCollaborationMode event, got {other:?}"), - }; - chat.set_collaboration_mask(selected_mask); + assert!(rx.try_recv().is_err(), "plan should not emit an app event"); + assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Plan); + assert_eq!(chat.current_collaboration_mode(), &default); + + chat.dispatch_command(SlashCommand::Plan); + + assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Default); + assert_eq!(chat.current_collaboration_mode(), &initial); chat.bottom_pane .set_composer_text("hello".to_string(), Vec::new(), Vec::new()); chat.handle_key_event(KeyEvent::from(KeyCode::Enter)); match next_submit_op(&mut op_rx) { Op::UserTurn { - collaboration_mode: - Some(CollaborationMode { - mode: ModeKind::Default, - .. - }), + collaboration_mode: Some(CollaborationMode { + mode: ModeKind::Default, + .. + }), personality: Some(Personality::Pragmatic), .. } => {} @@ -3614,7 +3611,6 @@ async fn collab_slash_command_opens_picker_and_updates_mode() { panic!("expected Op::UserTurn with code collab mode, got {other:?}") } } - chat.bottom_pane .set_composer_text("follow up".to_string(), Vec::new(), Vec::new()); chat.handle_key_event(KeyEvent::from(KeyCode::Enter)); @@ -3632,6 +3628,8 @@ async fn collab_slash_command_opens_picker_and_updates_mode() { panic!("expected Op::UserTurn with code collab mode, got {other:?}") } } + assert_eq!(chat.current_collaboration_mode(), &initial); + assert_eq!(chat.active_mode_kind(), ModeKind::Default); } #[tokio::test] diff --git a/codex-rs/tui/src/slash_command.rs b/codex-rs/tui/src/slash_command.rs index 16e767f802..b5abb3c1e0 100644 --- a/codex-rs/tui/src/slash_command.rs +++ b/codex-rs/tui/src/slash_command.rs @@ -29,7 +29,6 @@ pub enum SlashCommand { Init, Compact, Plan, - Collab, Agent, // Undo, Diff, @@ -82,7 +81,6 @@ impl SlashCommand { SlashCommand::Model => "choose what model and reasoning effort to use", SlashCommand::Personality => "choose a communication style for Codex", SlashCommand::Plan => "switch to Plan mode", - SlashCommand::Collab => "change collaboration mode (experimental)", SlashCommand::Agent => "switch the active agent thread", SlashCommand::Approvals => "choose what Codex is allowed to do", SlashCommand::Permissions => "choose what Codex is allowed to do", @@ -152,7 +150,6 @@ impl SlashCommand { | SlashCommand::Exit => true, SlashCommand::Rollout => true, SlashCommand::TestApproval => true, - SlashCommand::Collab => true, SlashCommand::Agent => true, SlashCommand::Statusline => false, }