Compare commits

...

1 Commits

Author SHA1 Message Date
Charles Cunningham
bacd398f31 Reduce collaboration modes to plan/default with legacy aliases 2026-02-02 17:25:33 -08:00
34 changed files with 148 additions and 251 deletions

View File

@@ -1042,10 +1042,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},

View File

@@ -686,7 +686,7 @@
"$ref": "#/definitions/ModeKind"
}
],
"default": "code"
"default": "default"
},
"model_context_window": {
"format": "int64",
@@ -3280,10 +3280,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},
@@ -5433,7 +5430,7 @@
"$ref": "#/definitions/ModeKind"
}
],
"default": "code"
"default": "default"
},
"model_context_window": {
"format": "int64",

View File

@@ -1264,7 +1264,7 @@
"$ref": "#/definitions/ModeKind"
}
],
"default": "code"
"default": "default"
},
"model_context_window": {
"format": "int64",
@@ -4061,10 +4061,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},

View File

@@ -2526,7 +2526,7 @@
"$ref": "#/definitions/v2/ModeKind"
}
],
"default": "code"
"default": "default"
},
"model_context_window": {
"format": "int64",
@@ -6008,10 +6008,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},
@@ -12273,10 +12270,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},

View File

@@ -686,7 +686,7 @@
"$ref": "#/definitions/ModeKind"
}
],
"default": "code"
"default": "default"
},
"model_context_window": {
"format": "int64",
@@ -3280,10 +3280,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},

View File

@@ -686,7 +686,7 @@
"$ref": "#/definitions/ModeKind"
}
],
"default": "code"
"default": "default"
},
"model_context_window": {
"format": "int64",
@@ -3280,10 +3280,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},

View File

@@ -686,7 +686,7 @@
"$ref": "#/definitions/ModeKind"
}
],
"default": "code"
"default": "default"
},
"model_context_window": {
"format": "int64",
@@ -3280,10 +3280,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},

View File

@@ -53,10 +53,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},

View File

@@ -5,4 +5,4 @@
/**
* Initial collaboration mode to use when the TUI starts.
*/
export type ModeKind = "plan" | "code" | "pair_programming" | "execute" | "custom";
export type ModeKind = "plan" | "default";

View File

@@ -1,8 +1,8 @@
//! Validates that the collaboration mode list endpoint returns the expected default presets.
//!
//! The test drives the app server through the MCP harness and asserts that the list response
//! includes the plan, coding, pair programming, and execute modes with their default model and reasoning
//! effort settings, which keeps the API contract visible in one place.
//! includes the plan and default modes with their default model and reasoning effort
//! settings, which keeps the API contract visible in one place.
#![allow(clippy::unwrap_used)]
@@ -45,23 +45,8 @@ async fn list_collaboration_modes_returns_presets() -> Result<()> {
let CollaborationModeListResponse { data: items } =
to_response::<CollaborationModeListResponse>(response)?;
let expected = [
plan_preset(),
code_preset(),
pair_programming_preset(),
execute_preset(),
];
assert_eq!(expected.len(), items.len());
for (expected_mask, actual_mask) in expected.iter().zip(items.iter()) {
assert_eq!(expected_mask.name, actual_mask.name);
assert_eq!(expected_mask.mode, actual_mask.mode);
assert_eq!(expected_mask.model, actual_mask.model);
assert_eq!(expected_mask.reasoning_effort, actual_mask.reasoning_effort);
assert_eq!(
expected_mask.developer_instructions,
actual_mask.developer_instructions
);
}
let expected = vec![plan_preset(), default_preset()];
assert_eq!(expected, items);
Ok(())
}
@@ -77,35 +62,11 @@ fn plan_preset() -> CollaborationModeMask {
.unwrap()
}
/// Builds the pair programming preset that the list response is expected to return.
///
/// The helper keeps the expected model and reasoning defaults co-located with the test
/// so that mismatches point directly at the API contract being exercised.
fn pair_programming_preset() -> CollaborationModeMask {
/// Builds the default preset that the list response is expected to return.
fn default_preset() -> CollaborationModeMask {
let presets = test_builtin_collaboration_mode_presets();
presets
.into_iter()
.find(|p| p.mode == Some(ModeKind::PairProgramming))
.unwrap()
}
/// Builds the code preset that the list response is expected to return.
fn code_preset() -> CollaborationModeMask {
let presets = test_builtin_collaboration_mode_presets();
presets
.into_iter()
.find(|p| p.mode == Some(ModeKind::Code))
.unwrap()
}
/// Builds the execute preset that the list response is expected to return.
///
/// The execute preset uses a different reasoning effort to capture the higher-effort
/// execution contract the server currently exposes.
fn execute_preset() -> CollaborationModeMask {
let presets = test_builtin_collaboration_mode_presets();
presets
.into_iter()
.find(|p| p.mode == Some(ModeKind::Execute))
.find(|p| p.mode == Some(ModeKind::Default))
.unwrap()
}

View File

@@ -365,7 +365,7 @@ async fn turn_start_accepts_collaboration_mode_override_v2() -> Result<()> {
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(thread_resp)?;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model: "mock-model-collab".to_string(),
reasoning_effort: Some(ReasoningEffort::High),

View File

@@ -378,10 +378,7 @@
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
"plan",
"code",
"pair_programming",
"execute",
"custom"
"default"
],
"type": "string"
},
@@ -1021,7 +1018,7 @@
}
],
"default": null,
"description": "Start the TUI in the specified collaboration mode (plan/execute/etc.). Defaults to unset."
"description": "Start the TUI in the specified collaboration mode (plan/default). Defaults to unset."
},
"notification_method": {
"allOf": [

View File

@@ -232,7 +232,7 @@ mod tests {
async fn on_event_updates_status_from_task_started() {
let status = agent_status_from_event(&EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}));
assert_eq!(status, Some(AgentStatus::Running));
}

View File

@@ -370,7 +370,7 @@ impl Codex {
// TODO (aibrahim): Consolidate config.model and config.model_reasoning_effort into config.collaboration_mode
// to avoid extracting these fields separately and constructing CollaborationMode here.
let collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model: model.clone(),
reasoning_effort: config.model_reasoning_effort,
@@ -2628,7 +2628,7 @@ mod handlers {
} => {
let collaboration_mode = collaboration_mode.or_else(|| {
Some(CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model: model.clone(),
reasoning_effort: effort,
@@ -4942,7 +4942,7 @@ mod tests {
let model_info = ModelsManager::construct_model_info_offline(model.as_str(), &config);
let reasoning_effort = config.model_reasoning_effort;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model,
reasoning_effort,
@@ -5025,7 +5025,7 @@ mod tests {
let model_info = ModelsManager::construct_model_info_offline(model.as_str(), &config);
let reasoning_effort = config.model_reasoning_effort;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model,
reasoning_effort,
@@ -5292,7 +5292,7 @@ mod tests {
let model_info = ModelsManager::construct_model_info_offline(model.as_str(), &config);
let reasoning_effort = config.model_reasoning_effort;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model,
reasoning_effort,
@@ -5412,7 +5412,7 @@ mod tests {
let model_info = ModelsManager::construct_model_info_offline(model.as_str(), &config);
let reasoning_effort = config.model_reasoning_effort;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model,
reasoning_effort,

View File

@@ -212,7 +212,7 @@ pub struct Config {
/// Show startup tooltips in the TUI welcome screen.
pub show_tooltips: bool,
/// Start the TUI in the specified collaboration mode (plan/execute/etc.).
/// Start the TUI in the specified collaboration mode (plan/default).
pub experimental_mode: Option<ModeKind>,
/// Controls whether the TUI uses the terminal's alternate screen buffer.

View File

@@ -471,7 +471,7 @@ pub struct Tui {
#[serde(default = "default_true")]
pub show_tooltips: bool,
/// Start the TUI in the specified collaboration mode (plan/execute/etc.).
/// Start the TUI in the specified collaboration mode (plan/default).
/// Defaults to unset.
#[serde(default)]
pub experimental_mode: Option<ModeKind>,

View File

@@ -121,7 +121,7 @@ pub enum Feature {
SkillEnvVarDependencyPrompt,
/// Steer feature flag - when enabled, Enter submits immediately instead of queuing.
Steer,
/// Enable collaboration modes (Plan, Code, Pair Programming, Execute).
/// Enable collaboration modes (Plan, Default).
CollaborationModes,
/// Enable personality selection in the TUI.
Personality,

View File

@@ -3,19 +3,11 @@ use codex_protocol::config_types::ModeKind;
use codex_protocol::openai_models::ReasoningEffort;
const COLLABORATION_MODE_PLAN: &str = include_str!("../../templates/collaboration_mode/plan.md");
const COLLABORATION_MODE_CODE: &str = include_str!("../../templates/collaboration_mode/code.md");
const COLLABORATION_MODE_PAIR_PROGRAMMING: &str =
include_str!("../../templates/collaboration_mode/pair_programming.md");
const COLLABORATION_MODE_EXECUTE: &str =
include_str!("../../templates/collaboration_mode/execute.md");
const COLLABORATION_MODE_DEFAULT: &str =
include_str!("../../templates/collaboration_mode/default.md");
pub(super) fn builtin_collaboration_mode_presets() -> Vec<CollaborationModeMask> {
vec![
plan_preset(),
code_preset(),
pair_programming_preset(),
execute_preset(),
]
vec![plan_preset(), default_preset()]
}
#[cfg(any(test, feature = "test-support"))]
@@ -33,32 +25,12 @@ fn plan_preset() -> CollaborationModeMask {
}
}
fn code_preset() -> CollaborationModeMask {
fn default_preset() -> CollaborationModeMask {
CollaborationModeMask {
name: "Code".to_string(),
mode: Some(ModeKind::Code),
name: "Default".to_string(),
mode: Some(ModeKind::Default),
model: None,
reasoning_effort: None,
developer_instructions: Some(Some(COLLABORATION_MODE_CODE.to_string())),
}
}
fn pair_programming_preset() -> CollaborationModeMask {
CollaborationModeMask {
name: "Pair Programming".to_string(),
mode: Some(ModeKind::PairProgramming),
model: None,
reasoning_effort: Some(Some(ReasoningEffort::Medium)),
developer_instructions: Some(Some(COLLABORATION_MODE_PAIR_PROGRAMMING.to_string())),
}
}
fn execute_preset() -> CollaborationModeMask {
CollaborationModeMask {
name: "Execute".to_string(),
mode: Some(ModeKind::Execute),
model: None,
reasoning_effort: Some(Some(ReasoningEffort::High)),
developer_instructions: Some(Some(COLLABORATION_MODE_EXECUTE.to_string())),
developer_instructions: Some(Some(COLLABORATION_MODE_DEFAULT.to_string())),
}
}

View File

@@ -37,12 +37,10 @@ impl ToolHandler for RequestUserInputHandler {
};
let mode = session.collaboration_mode().await.mode;
if !matches!(mode, ModeKind::Plan | ModeKind::PairProgramming) {
if !matches!(mode, ModeKind::Plan) {
let mode_name = match mode {
ModeKind::Code => "Code",
ModeKind::Execute => "Execute",
ModeKind::Custom => "Custom",
ModeKind::Plan | ModeKind::PairProgramming => unreachable!(),
ModeKind::Default | ModeKind::PairProgramming | ModeKind::Execute => "Default",
ModeKind::Plan => unreachable!(),
};
return Err(FunctionCallError::RespondToModel(format!(
"request_user_input is unavailable in {mode_name} mode"

View File

@@ -1 +0,0 @@
you are now in code mode.

View File

@@ -0,0 +1 @@
you are now in default mode.

View File

@@ -824,7 +824,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
.await?;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model: "gpt-5.1".to_string(),
reasoning_effort: Some(ReasoningEffort::High),

View File

@@ -37,7 +37,7 @@ fn collab_mode_with_mode_and_instructions(
}
fn collab_mode_with_instructions(instructions: Option<&str>) -> CollaborationMode {
collab_mode_with_mode_and_instructions(ModeKind::Custom, instructions)
collab_mode_with_mode_and_instructions(ModeKind::Default, instructions)
}
fn developer_texts(input: &[Value]) -> Vec<String> {
@@ -427,7 +427,7 @@ async fn collaboration_mode_update_emits_new_instruction_message_when_mode_chang
let req2 = mount_sse_once(&server, sse_completed("resp-2")).await;
let test = test_codex().build(&server).await?;
let code_text = "code mode instructions";
let default_text = "default mode instructions";
let plan_text = "plan mode instructions";
test.codex
@@ -440,8 +440,8 @@ async fn collaboration_mode_update_emits_new_instruction_message_when_mode_chang
effort: None,
summary: None,
collaboration_mode: Some(collab_mode_with_mode_and_instructions(
ModeKind::Code,
Some(code_text),
ModeKind::Default,
Some(default_text),
)),
personality: None,
})
@@ -488,9 +488,9 @@ async fn collaboration_mode_update_emits_new_instruction_message_when_mode_chang
let input = req2.single_request().input();
let dev_texts = developer_texts(&input);
let code_text = collab_xml(code_text);
let default_text = collab_xml(default_text);
let plan_text = collab_xml(plan_text);
assert_eq!(count_exact(&dev_texts, &code_text), 1);
assert_eq!(count_exact(&dev_texts, &default_text), 1);
assert_eq!(count_exact(&dev_texts, &plan_text), 1);
Ok(())
@@ -517,7 +517,7 @@ async fn collaboration_mode_update_noop_does_not_append_when_mode_is_unchanged()
effort: None,
summary: None,
collaboration_mode: Some(collab_mode_with_mode_and_instructions(
ModeKind::Code,
ModeKind::Default,
Some(collab_text),
)),
personality: None,
@@ -545,7 +545,7 @@ async fn collaboration_mode_update_noop_does_not_append_when_mode_is_unchanged()
effort: None,
summary: None,
collaboration_mode: Some(collab_mode_with_mode_and_instructions(
ModeKind::Code,
ModeKind::Default,
Some(collab_text),
)),
personality: None,

View File

@@ -24,7 +24,7 @@ use tempfile::TempDir;
fn collab_mode_with_instructions(instructions: Option<&str>) -> CollaborationMode {
CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model: "gpt-5.1".to_string(),
reasoning_effort: None,

View File

@@ -412,7 +412,7 @@ async fn override_before_first_turn_emits_environment_context() -> anyhow::Resul
let TestCodex { codex, .. } = test_codex().build(&server).await?;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model: "gpt-5.1".to_string(),
reasoning_effort: Some(ReasoningEffort::High),

View File

@@ -273,8 +273,8 @@ where
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn request_user_input_rejected_in_execute_mode() -> anyhow::Result<()> {
assert_request_user_input_rejected("Execute", |model| CollaborationMode {
async fn request_user_input_rejected_in_legacy_execute_mode_alias() -> anyhow::Result<()> {
assert_request_user_input_rejected("Default", |model| CollaborationMode {
mode: ModeKind::Execute,
settings: Settings {
model,
@@ -286,22 +286,9 @@ async fn request_user_input_rejected_in_execute_mode() -> anyhow::Result<()> {
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn request_user_input_rejected_in_code_mode() -> anyhow::Result<()> {
assert_request_user_input_rejected("Code", |model| CollaborationMode {
mode: ModeKind::Code,
settings: Settings {
model,
reasoning_effort: None,
developer_instructions: None,
},
})
.await
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn request_user_input_rejected_in_custom_mode() -> anyhow::Result<()> {
assert_request_user_input_rejected("Custom", |model| CollaborationMode {
mode: ModeKind::Custom,
async fn request_user_input_rejected_in_default_mode() -> anyhow::Result<()> {
assert_request_user_input_rejected("Default", |model| CollaborationMode {
mode: ModeKind::Default,
settings: Settings {
model,
reasoning_effort: None,

View File

@@ -118,7 +118,7 @@ fn task_started_produces_turn_started_event() {
"t1",
EventMsg::TurnStarted(codex_core::protocol::TurnStartedEvent {
model_context_window: Some(32_000),
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
));

View File

@@ -173,10 +173,23 @@ pub enum AltScreenMode {
pub enum ModeKind {
Plan,
#[default]
Code,
#[serde(
alias = "code",
alias = "pair_programming",
alias = "execute",
alias = "custom"
)]
Default,
#[doc(hidden)]
#[serde(skip_serializing, skip_deserializing)]
#[schemars(skip)]
#[ts(skip)]
PairProgramming,
#[doc(hidden)]
#[serde(skip_serializing, skip_deserializing)]
#[schemars(skip)]
#[ts(skip)]
Execute,
Custom,
}
/// Collaboration mode for a Codex session.
@@ -276,7 +289,7 @@ mod tests {
#[test]
fn apply_mask_can_clear_optional_fields() {
let mode = CollaborationMode {
mode: ModeKind::Code,
mode: ModeKind::Default,
settings: Settings {
model: "gpt-5.2-codex".to_string(),
reasoning_effort: Some(ReasoningEffort::High),
@@ -292,7 +305,7 @@ mod tests {
};
let expected = CollaborationMode {
mode: ModeKind::Code,
mode: ModeKind::Default,
settings: Settings {
model: "gpt-5.2-codex".to_string(),
reasoning_effort: None,
@@ -301,4 +314,13 @@ mod tests {
};
assert_eq!(expected, mode.apply_mask(&mask));
}
#[test]
fn mode_kind_deserializes_legacy_values_to_default() {
for legacy in ["code", "pair_programming", "execute", "custom"] {
let json = format!("\"{legacy}\"");
let mode: ModeKind = serde_json::from_str(&json).expect("deserialize mode");
assert_eq!(ModeKind::Default, mode);
}
}
}

View File

@@ -73,8 +73,6 @@ pub(crate) struct FooterProps {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum CollaborationModeIndicator {
Plan,
PairProgramming,
Execute,
}
const MODE_CYCLE_HINT: &str = "shift+tab to cycle";
@@ -89,10 +87,6 @@ impl CollaborationModeIndicator {
};
match self {
CollaborationModeIndicator::Plan => format!("Plan mode{suffix}"),
CollaborationModeIndicator::PairProgramming => {
format!("Pair Programming mode{suffix}")
}
CollaborationModeIndicator::Execute => format!("Execute mode{suffix}"),
}
}
@@ -100,8 +94,6 @@ impl CollaborationModeIndicator {
let label = self.label(show_cycle_hint);
match self {
CollaborationModeIndicator::Plan => Span::from(label).magenta(),
CollaborationModeIndicator::PairProgramming => Span::from(label).cyan(),
CollaborationModeIndicator::Execute => Span::from(label).dim(),
}
}
}

View File

@@ -467,7 +467,7 @@ pub(crate) struct ChatWidget {
/// where the overlay may briefly treat new tail content as already cached.
active_cell_revision: u64,
config: Config,
/// The unmasked collaboration mode settings (always Custom mode).
/// The unmasked collaboration mode settings (always Default mode).
///
/// Masks are applied on top of this base mode to derive the effective mode.
current_collaboration_mode: CollaborationMode,
@@ -1108,8 +1108,8 @@ impl ChatWidget {
}
fn open_plan_implementation_prompt(&mut self) {
let code_mask = collaboration_modes::code_mask(self.models_manager.as_ref());
let (implement_actions, implement_disabled_reason) = match code_mask {
let default_mask = collaboration_modes::default_mode_mask(self.models_manager.as_ref());
let (implement_actions, implement_disabled_reason) = match default_mask {
Some(mask) => {
let user_text = PLAN_IMPLEMENTATION_CODING_MESSAGE.to_string();
let actions: Vec<SelectionAction> = vec![Box::new(move |tx| {
@@ -1120,13 +1120,13 @@ impl ChatWidget {
})];
(actions, None)
}
None => (Vec::new(), Some("Code mode unavailable".to_string())),
None => (Vec::new(), Some("Default mode unavailable".to_string())),
};
let items = vec![
SelectionItem {
name: PLAN_IMPLEMENTATION_YES.to_string(),
description: Some("Switch to Code and start coding.".to_string()),
description: Some("Switch to Default and start coding.".to_string()),
selected_description: None,
is_current: false,
actions: implement_actions,
@@ -2216,15 +2216,15 @@ impl ChatWidget {
.as_ref()
.and_then(|mask| mask.model.clone())
.unwrap_or_else(|| model_for_header.clone());
let fallback_custom = Settings {
let fallback_default = Settings {
model: header_model.clone(),
reasoning_effort: None,
developer_instructions: None,
};
// Collaboration modes start in Custom mode (not activated).
// Collaboration modes start in Default mode.
let current_collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
settings: fallback_custom,
mode: ModeKind::Default,
settings: fallback_default,
};
let active_cell = Some(Self::placeholder_session_header_cell(&config));
@@ -2361,15 +2361,15 @@ impl ChatWidget {
.as_ref()
.and_then(|mask| mask.model.clone())
.unwrap_or_else(|| model_for_header.clone());
let fallback_custom = Settings {
let fallback_default = Settings {
model: header_model.clone(),
reasoning_effort: None,
developer_instructions: None,
};
// Collaboration modes start in Custom mode (not activated).
// Collaboration modes start in Default mode.
let current_collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
settings: fallback_custom,
mode: ModeKind::Default,
settings: fallback_default,
};
let active_cell = Some(Self::placeholder_session_header_cell(&config));
@@ -2497,15 +2497,15 @@ impl ChatWidget {
let codex_op_tx =
spawn_agent_from_existing(conversation, session_configured, app_event_tx.clone());
let fallback_custom = Settings {
let fallback_default = Settings {
model: header_model.clone(),
reasoning_effort: None,
developer_instructions: None,
};
// Collaboration modes start in Custom mode (not activated).
// Collaboration modes start in Default mode.
let current_collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
settings: fallback_custom,
mode: ModeKind::Default,
settings: fallback_default,
};
let mut widget = Self {
@@ -5166,7 +5166,7 @@ impl ChatWidget {
self.bottom_pane.set_collaboration_modes_enabled(enabled);
let settings = self.current_collaboration_mode.settings.clone();
self.current_collaboration_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings,
};
self.active_collaboration_mask = None;
@@ -5319,7 +5319,7 @@ impl ChatWidget {
self.active_collaboration_mask
.as_ref()
.and_then(|mask| mask.mode)
.unwrap_or(ModeKind::Custom)
.unwrap_or(ModeKind::Default)
}
fn effective_reasoning_effort(&self) -> Option<ReasoningEffortConfig> {
@@ -5364,10 +5364,8 @@ impl ChatWidget {
}
match self.active_mode_kind() {
ModeKind::Plan => Some("Plan"),
ModeKind::Code => Some("Code"),
ModeKind::PairProgramming => Some("Pair Programming"),
ModeKind::Execute => Some("Execute"),
ModeKind::Custom => None,
ModeKind::Default => Some("Default"),
ModeKind::PairProgramming | ModeKind::Execute => None,
}
}
@@ -5377,10 +5375,7 @@ impl ChatWidget {
}
match self.active_mode_kind() {
ModeKind::Plan => Some(CollaborationModeIndicator::Plan),
ModeKind::Code => None,
ModeKind::PairProgramming => Some(CollaborationModeIndicator::PairProgramming),
ModeKind::Execute => Some(CollaborationModeIndicator::Execute),
ModeKind::Custom => None,
ModeKind::Default | ModeKind::PairProgramming | ModeKind::Execute => None,
}
}
@@ -5403,7 +5398,7 @@ impl ChatWidget {
}
}
/// Cycle to the next collaboration mode variant (Plan -> Code -> Plan).
/// Cycle to the next collaboration mode variant (Plan -> Default -> Plan).
fn cycle_collaboration_mode(&mut self) {
if !self.collaboration_modes_enabled() {
return;
@@ -5419,7 +5414,7 @@ impl ChatWidget {
/// Update the active collaboration mask.
///
/// When collaboration modes are enabled and a preset is selected (not Custom),
/// When collaboration modes are enabled and a preset is selected,
/// the current mode is attached to submissions as `Op::UserTurn { collaboration_mode: Some(...) }`.
pub(crate) fn set_collaboration_mask(&mut self, mask: CollaborationModeMask) {
if !self.collaboration_modes_enabled() {

View File

@@ -4,7 +4,7 @@ expression: popup
---
Implement this plan?
1. Yes, implement this plan Switch to Code and start coding.
1. Yes, implement this plan Switch to Default and start coding.
2. No, stay in Plan mode Continue planning with the model.
Press enter to confirm or esc to go back

View File

@@ -4,7 +4,7 @@ expression: popup
---
Implement this plan?
1. Yes, implement this plan Switch to Code and start coding.
1. Yes, implement this plan Switch to Default and start coding.
2. No, stay in Plan mode Continue planning with the model.
Press enter to confirm or esc to go back

View File

@@ -780,7 +780,7 @@ async fn make_chatwidget_manual(
let models_manager = Arc::new(ModelsManager::new(codex_home, auth_manager.clone()));
let reasoning_effort = None;
let base_mode = CollaborationMode {
mode: ModeKind::Custom,
mode: ModeKind::Default,
settings: Settings {
model: resolved_model.clone(),
reasoning_effort,
@@ -1211,7 +1211,7 @@ async fn plan_implementation_popup_yes_emits_submit_message_event() {
panic!("expected SubmitUserMessageWithMode, got {event:?}");
};
assert_eq!(text, PLAN_IMPLEMENTATION_CODING_MESSAGE);
assert_eq!(collaboration_mode.mode, Some(ModeKind::Code));
assert_eq!(collaboration_mode.mode, Some(ModeKind::Default));
}
#[tokio::test]
@@ -1220,22 +1220,22 @@ async fn submit_user_message_with_mode_sets_coding_collaboration_mode() {
chat.thread_id = Some(ThreadId::new());
chat.set_feature_enabled(Feature::CollaborationModes, true);
let code_mode = collaboration_modes::code_mask(chat.models_manager.as_ref())
.expect("expected code collaboration mode");
chat.submit_user_message_with_mode("Implement the plan.".to_string(), code_mode);
let default_mode = collaboration_modes::default_mode_mask(chat.models_manager.as_ref())
.expect("expected default collaboration mode");
chat.submit_user_message_with_mode("Implement the plan.".to_string(), default_mode);
match next_submit_op(&mut op_rx) {
Op::UserTurn {
collaboration_mode:
Some(CollaborationMode {
mode: ModeKind::Code,
mode: ModeKind::Default,
..
}),
personality: None,
..
} => {}
other => {
panic!("expected Op::UserTurn with code collab mode, got {other:?}")
panic!("expected Op::UserTurn with default collab mode, got {other:?}")
}
}
}
@@ -1982,7 +1982,7 @@ async fn unified_exec_wait_after_final_agent_message_snapshot() {
id: "turn-1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
@@ -2017,7 +2017,7 @@ async fn unified_exec_wait_before_streamed_agent_message_snapshot() {
id: "turn-1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
@@ -2228,7 +2228,7 @@ async fn collab_mode_shift_tab_cycles_only_when_enabled_and_idle() {
let initial = chat.current_collaboration_mode().clone();
chat.handle_key_event(KeyEvent::from(KeyCode::BackTab));
assert_eq!(chat.current_collaboration_mode(), &initial);
assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Custom);
assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Default);
chat.set_feature_enabled(Feature::CollaborationModes, true);
@@ -2237,7 +2237,7 @@ async fn collab_mode_shift_tab_cycles_only_when_enabled_and_idle() {
assert_eq!(chat.current_collaboration_mode(), &initial);
chat.handle_key_event(KeyEvent::from(KeyCode::BackTab));
assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Code);
assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Default);
assert_eq!(chat.current_collaboration_mode(), &initial);
chat.on_task_started();
@@ -2273,7 +2273,7 @@ async fn collab_slash_command_opens_picker_and_updates_mode() {
Op::UserTurn {
collaboration_mode:
Some(CollaborationMode {
mode: ModeKind::Code,
mode: ModeKind::Default,
..
}),
personality: None,
@@ -2291,7 +2291,7 @@ async fn collab_slash_command_opens_picker_and_updates_mode() {
Op::UserTurn {
collaboration_mode:
Some(CollaborationMode {
mode: ModeKind::Code,
mode: ModeKind::Default,
..
}),
personality: None,
@@ -2395,7 +2395,7 @@ async fn collaboration_modes_defaults_to_code_on_startup() {
};
let chat = ChatWidget::new(init, thread_manager);
assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Code);
assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Default);
assert_eq!(chat.current_model(), resolved_model);
}
@@ -2501,8 +2501,8 @@ async fn collab_mode_is_not_sent_until_selected() {
async fn collab_mode_enabling_keeps_custom_until_selected() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await;
chat.set_feature_enabled(Feature::CollaborationModes, true);
assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Custom);
assert_eq!(chat.current_collaboration_mode().mode, ModeKind::Custom);
assert_eq!(chat.active_collaboration_mode_kind(), ModeKind::Default);
assert_eq!(chat.current_collaboration_mode().mode, ModeKind::Default);
}
#[tokio::test]
@@ -2850,7 +2850,7 @@ async fn interrupted_turn_error_message_snapshot() {
id: "task-1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
@@ -3865,7 +3865,7 @@ async fn interrupt_clears_unified_exec_wait_streak_snapshot() {
id: "turn-1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
@@ -3939,7 +3939,7 @@ async fn ui_snapshots_small_heights_task_running() {
id: "task-1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
chat.handle_codex_event(Event {
@@ -3971,7 +3971,7 @@ async fn status_widget_and_approval_modal_snapshot() {
id: "task-1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
// Provide a deterministic header for the status line.
@@ -4024,7 +4024,7 @@ async fn status_widget_active_snapshot() {
id: "task-1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
// Provide a deterministic header via a bold reasoning chunk.
@@ -4074,7 +4074,7 @@ async fn mcp_startup_complete_does_not_clear_running_task() {
id: "task-1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
@@ -4631,7 +4631,7 @@ async fn stream_recovery_restores_previous_status_header() {
id: "task".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
drain_insert_history(&mut rx);
@@ -4669,7 +4669,7 @@ async fn multiple_agent_messages_in_single_turn_emit_multiple_headers() {
id: "s1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
@@ -4864,7 +4864,7 @@ async fn chatwidget_exec_and_status_layout_vt100_snapshot() {
id: "t1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
chat.handle_codex_event(Event {
@@ -4912,7 +4912,7 @@ async fn chatwidget_markdown_code_blocks_vt100_snapshot() {
id: "t1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
// Build a vt100 visual from the history insertions only (no UI overlay)
@@ -5002,7 +5002,7 @@ async fn chatwidget_tall() {
id: "t1".into(),
msg: EventMsg::TurnStarted(TurnStartedEvent {
model_context_window: None,
collaboration_mode_kind: ModeKind::Custom,
collaboration_mode_kind: ModeKind::Default,
}),
});
for i in 0..30 {

View File

@@ -3,7 +3,7 @@ use codex_protocol::config_types::CollaborationModeMask;
use codex_protocol::config_types::ModeKind;
fn is_tui_mode(kind: ModeKind) -> bool {
matches!(kind, ModeKind::Plan | ModeKind::Code)
matches!(kind, ModeKind::Plan | ModeKind::Default)
}
fn filtered_presets(models_manager: &ModelsManager) -> Vec<CollaborationModeMask> {
@@ -22,7 +22,7 @@ pub(crate) fn default_mask(models_manager: &ModelsManager) -> Option<Collaborati
let presets = filtered_presets(models_manager);
presets
.iter()
.find(|mask| mask.mode == Some(ModeKind::Code))
.find(|mask| mask.mode == Some(ModeKind::Default))
.cloned()
.or_else(|| presets.into_iter().next())
}
@@ -56,8 +56,8 @@ pub(crate) fn next_mask(
presets.get(next_index).cloned()
}
pub(crate) fn code_mask(models_manager: &ModelsManager) -> Option<CollaborationModeMask> {
mask_for_kind(models_manager, ModeKind::Code)
pub(crate) fn default_mode_mask(models_manager: &ModelsManager) -> Option<CollaborationModeMask> {
mask_for_kind(models_manager, ModeKind::Default)
}
pub(crate) fn plan_mask(models_manager: &ModelsManager) -> Option<CollaborationModeMask> {