mirror of
https://github.com/openai/codex.git
synced 2026-05-02 02:17:22 +00:00
change collaboration mode to struct (#9793)
Shouldn't cause behavioral change
This commit is contained in:
@@ -910,7 +910,7 @@ impl ChatWidget {
|
||||
if !self.queued_user_messages.is_empty() {
|
||||
return;
|
||||
}
|
||||
if !matches!(self.stored_collaboration_mode, CollaborationMode::Plan(_)) {
|
||||
if self.stored_collaboration_mode.mode != ModeKind::Plan {
|
||||
return;
|
||||
}
|
||||
let has_message = last_agent_message.is_some_and(|message| !message.trim().is_empty());
|
||||
@@ -1943,7 +1943,10 @@ impl ChatWidget {
|
||||
config.experimental_mode,
|
||||
)
|
||||
} else {
|
||||
CollaborationMode::Custom(fallback_custom)
|
||||
CollaborationMode {
|
||||
mode: ModeKind::Custom,
|
||||
settings: fallback_custom,
|
||||
}
|
||||
};
|
||||
|
||||
let active_cell = Some(Self::placeholder_session_header_cell(&config));
|
||||
@@ -2061,7 +2064,10 @@ impl ChatWidget {
|
||||
config.experimental_mode,
|
||||
)
|
||||
} else {
|
||||
CollaborationMode::Custom(fallback_custom)
|
||||
CollaborationMode {
|
||||
mode: ModeKind::Custom,
|
||||
settings: fallback_custom,
|
||||
}
|
||||
};
|
||||
|
||||
let active_cell = Some(Self::placeholder_session_header_cell(&config));
|
||||
@@ -2182,7 +2188,10 @@ impl ChatWidget {
|
||||
config.experimental_mode,
|
||||
)
|
||||
} else {
|
||||
CollaborationMode::Custom(fallback_custom)
|
||||
CollaborationMode {
|
||||
mode: ModeKind::Custom,
|
||||
settings: fallback_custom,
|
||||
}
|
||||
};
|
||||
|
||||
let mut widget = Self {
|
||||
@@ -3552,11 +3561,11 @@ impl ChatWidget {
|
||||
let items: Vec<SelectionItem> = presets
|
||||
.into_iter()
|
||||
.map(|preset| {
|
||||
let name = match preset {
|
||||
CollaborationMode::Plan(_) => "Plan",
|
||||
CollaborationMode::PairProgramming(_) => "Pair Programming",
|
||||
CollaborationMode::Execute(_) => "Execute",
|
||||
CollaborationMode::Custom(_) => "Custom",
|
||||
let name = match preset.mode {
|
||||
ModeKind::Plan => "Plan",
|
||||
ModeKind::PairProgramming => "Pair Programming",
|
||||
ModeKind::Execute => "Execute",
|
||||
ModeKind::Custom => "Custom",
|
||||
};
|
||||
let is_current =
|
||||
collaboration_modes::same_variant(&self.stored_collaboration_mode, &preset);
|
||||
@@ -4538,12 +4547,7 @@ impl ChatWidget {
|
||||
}
|
||||
if feature == Feature::CollaborationModes {
|
||||
self.bottom_pane.set_collaboration_modes_enabled(enabled);
|
||||
let settings = match &self.stored_collaboration_mode {
|
||||
CollaborationMode::Plan(settings)
|
||||
| CollaborationMode::PairProgramming(settings)
|
||||
| CollaborationMode::Execute(settings)
|
||||
| CollaborationMode::Custom(settings) => settings.clone(),
|
||||
};
|
||||
let settings = self.stored_collaboration_mode.settings.clone();
|
||||
let fallback_custom = settings.clone();
|
||||
self.stored_collaboration_mode = if enabled {
|
||||
initial_collaboration_mode(
|
||||
@@ -4552,7 +4556,10 @@ impl ChatWidget {
|
||||
self.config.experimental_mode,
|
||||
)
|
||||
} else {
|
||||
CollaborationMode::Custom(settings)
|
||||
CollaborationMode {
|
||||
mode: ModeKind::Custom,
|
||||
settings,
|
||||
}
|
||||
};
|
||||
self.update_collaboration_mode_indicator();
|
||||
}
|
||||
@@ -4632,11 +4639,11 @@ impl ChatWidget {
|
||||
if !self.collaboration_modes_enabled() {
|
||||
return None;
|
||||
}
|
||||
match &self.stored_collaboration_mode {
|
||||
CollaborationMode::Plan(_) => Some("Plan"),
|
||||
CollaborationMode::PairProgramming(_) => Some("Pair Programming"),
|
||||
CollaborationMode::Execute(_) => Some("Execute"),
|
||||
CollaborationMode::Custom(_) => None,
|
||||
match self.stored_collaboration_mode.mode {
|
||||
ModeKind::Plan => Some("Plan"),
|
||||
ModeKind::PairProgramming => Some("Pair Programming"),
|
||||
ModeKind::Execute => Some("Execute"),
|
||||
ModeKind::Custom => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4644,13 +4651,11 @@ impl ChatWidget {
|
||||
if !self.collaboration_modes_enabled() {
|
||||
return None;
|
||||
}
|
||||
match &self.stored_collaboration_mode {
|
||||
CollaborationMode::Plan(_) => Some(CollaborationModeIndicator::Plan),
|
||||
CollaborationMode::PairProgramming(_) => {
|
||||
Some(CollaborationModeIndicator::PairProgramming)
|
||||
}
|
||||
CollaborationMode::Execute(_) => Some(CollaborationModeIndicator::Execute),
|
||||
CollaborationMode::Custom(_) => None,
|
||||
match self.stored_collaboration_mode.mode {
|
||||
ModeKind::Plan => Some(CollaborationModeIndicator::Plan),
|
||||
ModeKind::PairProgramming => Some(CollaborationModeIndicator::PairProgramming),
|
||||
ModeKind::Execute => Some(CollaborationModeIndicator::Execute),
|
||||
ModeKind::Custom => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4681,7 +4686,8 @@ impl ChatWidget {
|
||||
if !self.collaboration_modes_enabled() {
|
||||
return;
|
||||
}
|
||||
|
||||
let old_model = self.stored_collaboration_mode.model().to_string();
|
||||
let mode = mode.with_updates(Some(old_model), None, None);
|
||||
self.stored_collaboration_mode = mode;
|
||||
self.update_collaboration_mode_indicator();
|
||||
self.request_redraw();
|
||||
@@ -5304,15 +5310,20 @@ fn initial_collaboration_mode(
|
||||
) -> CollaborationMode {
|
||||
if let Some(kind) = desired_mode {
|
||||
if kind == ModeKind::Custom {
|
||||
return CollaborationMode::Custom(fallback_custom);
|
||||
return CollaborationMode {
|
||||
mode: ModeKind::Custom,
|
||||
settings: fallback_custom,
|
||||
};
|
||||
}
|
||||
if let Some(mode) = collaboration_modes::mode_for_kind(models_manager, kind) {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
|
||||
collaboration_modes::default_mode(models_manager)
|
||||
.unwrap_or(CollaborationMode::Custom(fallback_custom))
|
||||
collaboration_modes::default_mode(models_manager).unwrap_or(CollaborationMode {
|
||||
mode: ModeKind::Custom,
|
||||
settings: fallback_custom,
|
||||
})
|
||||
}
|
||||
|
||||
async fn fetch_rate_limits(base_url: String, auth: CodexAuth) -> Option<RateLimitSnapshot> {
|
||||
|
||||
@@ -64,6 +64,8 @@ use codex_otel::OtelManager;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::account::PlanType;
|
||||
use codex_protocol::config_types::CollaborationMode;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Settings;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ReasoningEffortPreset;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
@@ -779,18 +781,24 @@ async fn make_chatwidget_manual(
|
||||
let reasoning_effort = None;
|
||||
let stored_collaboration_mode = if collaboration_modes_enabled {
|
||||
collaboration_modes::default_mode(models_manager.as_ref()).unwrap_or_else(|| {
|
||||
CollaborationMode::Custom(Settings {
|
||||
CollaborationMode {
|
||||
mode: ModeKind::Custom,
|
||||
settings: Settings {
|
||||
model: resolved_model.clone(),
|
||||
reasoning_effort,
|
||||
developer_instructions: None,
|
||||
},
|
||||
}
|
||||
})
|
||||
} else {
|
||||
CollaborationMode {
|
||||
mode: ModeKind::Custom,
|
||||
settings: Settings {
|
||||
model: resolved_model.clone(),
|
||||
reasoning_effort,
|
||||
developer_instructions: None,
|
||||
})
|
||||
})
|
||||
} else {
|
||||
CollaborationMode::Custom(Settings {
|
||||
model: resolved_model.clone(),
|
||||
reasoning_effort,
|
||||
developer_instructions: None,
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
let widget = ChatWidget {
|
||||
app_event_tx,
|
||||
@@ -1206,7 +1214,7 @@ async fn plan_implementation_popup_yes_emits_submit_message_event() {
|
||||
panic!("expected SubmitUserMessageWithMode, got {event:?}");
|
||||
};
|
||||
assert_eq!(text, PLAN_IMPLEMENTATION_EXECUTE_MESSAGE);
|
||||
assert!(matches!(collaboration_mode, CollaborationMode::Execute(_)));
|
||||
assert_eq!(collaboration_mode.mode, ModeKind::Execute);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -1221,7 +1229,11 @@ async fn submit_user_message_with_mode_sets_execute_collaboration_mode() {
|
||||
|
||||
match next_submit_op(&mut op_rx) {
|
||||
Op::UserTurn {
|
||||
collaboration_mode: Some(CollaborationMode::Execute(_)),
|
||||
collaboration_mode:
|
||||
Some(CollaborationMode {
|
||||
mode: ModeKind::Execute,
|
||||
..
|
||||
}),
|
||||
personality: None,
|
||||
..
|
||||
} => {}
|
||||
@@ -1235,11 +1247,14 @@ async fn submit_user_message_with_mode_sets_execute_collaboration_mode() {
|
||||
async fn plan_implementation_popup_skips_replayed_turn_complete() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await;
|
||||
chat.set_feature_enabled(Feature::CollaborationModes, true);
|
||||
chat.stored_collaboration_mode = CollaborationMode::Plan(Settings {
|
||||
model: chat.current_model().to_string(),
|
||||
reasoning_effort: None,
|
||||
developer_instructions: None,
|
||||
});
|
||||
chat.stored_collaboration_mode = CollaborationMode {
|
||||
mode: ModeKind::Plan,
|
||||
settings: Settings {
|
||||
model: chat.current_model().to_string(),
|
||||
reasoning_effort: None,
|
||||
developer_instructions: None,
|
||||
},
|
||||
};
|
||||
|
||||
chat.replay_initial_messages(vec![EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
last_agent_message: Some("Plan details".to_string()),
|
||||
@@ -1256,11 +1271,14 @@ async fn plan_implementation_popup_skips_replayed_turn_complete() {
|
||||
async fn plan_implementation_popup_skips_when_messages_queued() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await;
|
||||
chat.set_feature_enabled(Feature::CollaborationModes, true);
|
||||
chat.stored_collaboration_mode = CollaborationMode::Plan(Settings {
|
||||
model: chat.current_model().to_string(),
|
||||
reasoning_effort: None,
|
||||
developer_instructions: None,
|
||||
});
|
||||
chat.stored_collaboration_mode = CollaborationMode {
|
||||
mode: ModeKind::Plan,
|
||||
settings: Settings {
|
||||
model: chat.current_model().to_string(),
|
||||
reasoning_effort: None,
|
||||
developer_instructions: None,
|
||||
},
|
||||
};
|
||||
chat.bottom_pane.set_task_running(true);
|
||||
chat.queue_user_message("Queued message".into());
|
||||
|
||||
@@ -1277,11 +1295,14 @@ async fn plan_implementation_popup_skips_when_messages_queued() {
|
||||
async fn plan_implementation_popup_shows_on_plan_update_without_message() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await;
|
||||
chat.set_feature_enabled(Feature::CollaborationModes, true);
|
||||
chat.stored_collaboration_mode = CollaborationMode::Plan(Settings {
|
||||
model: chat.current_model().to_string(),
|
||||
reasoning_effort: None,
|
||||
developer_instructions: None,
|
||||
});
|
||||
chat.stored_collaboration_mode = CollaborationMode {
|
||||
mode: ModeKind::Plan,
|
||||
settings: Settings {
|
||||
model: chat.current_model().to_string(),
|
||||
reasoning_effort: None,
|
||||
developer_instructions: None,
|
||||
},
|
||||
};
|
||||
|
||||
chat.on_task_started();
|
||||
chat.on_plan_update(UpdatePlanArgs {
|
||||
@@ -1306,11 +1327,14 @@ async fn plan_implementation_popup_skips_when_rate_limit_prompt_pending() {
|
||||
chat.auth_manager =
|
||||
AuthManager::from_auth_for_testing(CodexAuth::create_dummy_chatgpt_auth_for_testing());
|
||||
chat.set_feature_enabled(Feature::CollaborationModes, true);
|
||||
chat.stored_collaboration_mode = CollaborationMode::Plan(Settings {
|
||||
model: chat.current_model().to_string(),
|
||||
reasoning_effort: None,
|
||||
developer_instructions: None,
|
||||
});
|
||||
chat.stored_collaboration_mode = CollaborationMode {
|
||||
mode: ModeKind::Plan,
|
||||
settings: Settings {
|
||||
model: chat.current_model().to_string(),
|
||||
reasoning_effort: None,
|
||||
developer_instructions: None,
|
||||
},
|
||||
};
|
||||
|
||||
chat.on_task_started();
|
||||
chat.on_plan_update(UpdatePlanArgs {
|
||||
@@ -2205,16 +2229,10 @@ async fn collab_mode_shift_tab_cycles_only_when_enabled_and_idle() {
|
||||
chat.set_feature_enabled(Feature::CollaborationModes, true);
|
||||
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::BackTab));
|
||||
assert!(matches!(
|
||||
chat.stored_collaboration_mode,
|
||||
CollaborationMode::Execute(_)
|
||||
));
|
||||
assert_eq!(chat.stored_collaboration_mode.mode, ModeKind::Execute);
|
||||
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::BackTab));
|
||||
assert!(matches!(
|
||||
chat.stored_collaboration_mode,
|
||||
CollaborationMode::Plan(_)
|
||||
));
|
||||
assert_eq!(chat.stored_collaboration_mode.mode, ModeKind::Plan);
|
||||
|
||||
chat.on_task_started();
|
||||
let before = chat.stored_collaboration_mode.clone();
|
||||
@@ -2247,7 +2265,11 @@ async fn collab_slash_command_opens_picker_and_updates_mode() {
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::Enter));
|
||||
match next_submit_op(&mut op_rx) {
|
||||
Op::UserTurn {
|
||||
collaboration_mode: Some(CollaborationMode::PairProgramming(_)),
|
||||
collaboration_mode:
|
||||
Some(CollaborationMode {
|
||||
mode: ModeKind::PairProgramming,
|
||||
..
|
||||
}),
|
||||
personality: None,
|
||||
..
|
||||
} => {}
|
||||
@@ -2261,7 +2283,11 @@ async fn collab_slash_command_opens_picker_and_updates_mode() {
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::Enter));
|
||||
match next_submit_op(&mut op_rx) {
|
||||
Op::UserTurn {
|
||||
collaboration_mode: Some(CollaborationMode::PairProgramming(_)),
|
||||
collaboration_mode:
|
||||
Some(CollaborationMode {
|
||||
mode: ModeKind::PairProgramming,
|
||||
..
|
||||
}),
|
||||
personality: None,
|
||||
..
|
||||
} => {}
|
||||
@@ -2282,7 +2308,11 @@ async fn collab_mode_defaults_to_pair_programming_when_enabled() {
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::Enter));
|
||||
match next_submit_op(&mut op_rx) {
|
||||
Op::UserTurn {
|
||||
collaboration_mode: Some(CollaborationMode::PairProgramming(_)),
|
||||
collaboration_mode:
|
||||
Some(CollaborationMode {
|
||||
mode: ModeKind::PairProgramming,
|
||||
..
|
||||
}),
|
||||
personality: None,
|
||||
..
|
||||
} => {}
|
||||
@@ -2296,10 +2326,10 @@ async fn collab_mode_defaults_to_pair_programming_when_enabled() {
|
||||
async fn collab_mode_enabling_sets_pair_programming_default() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await;
|
||||
chat.set_feature_enabled(Feature::CollaborationModes, true);
|
||||
assert!(matches!(
|
||||
chat.stored_collaboration_mode,
|
||||
CollaborationMode::PairProgramming(_)
|
||||
));
|
||||
assert_eq!(
|
||||
chat.stored_collaboration_mode.mode,
|
||||
ModeKind::PairProgramming
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -3,19 +3,14 @@ use codex_protocol::config_types::CollaborationMode;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
|
||||
fn mode_kind(mode: &CollaborationMode) -> ModeKind {
|
||||
match mode {
|
||||
CollaborationMode::Plan(_) => ModeKind::Plan,
|
||||
CollaborationMode::PairProgramming(_) => ModeKind::PairProgramming,
|
||||
CollaborationMode::Execute(_) => ModeKind::Execute,
|
||||
CollaborationMode::Custom(_) => ModeKind::Custom,
|
||||
}
|
||||
mode.mode
|
||||
}
|
||||
|
||||
pub(crate) fn default_mode(models_manager: &ModelsManager) -> Option<CollaborationMode> {
|
||||
let presets = models_manager.list_collaboration_modes();
|
||||
presets
|
||||
.iter()
|
||||
.find(|preset| matches!(preset, CollaborationMode::PairProgramming(_)))
|
||||
.find(|preset| preset.mode == ModeKind::PairProgramming)
|
||||
.cloned()
|
||||
.or_else(|| presets.into_iter().next())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user