Update models.json (#18586)

- Replace the active models-manager catalog with the deleted core
catalog contents.
- Replace stale hardcoded test model slugs with current bundled model
slugs.
- Keep this as a stacked change on top of the cleanup PR.
This commit is contained in:
Ahmed Ibrahim
2026-04-20 10:27:01 -07:00
committed by GitHub
Unverified
parent 5d5d610740
commit 316cf0e90b
63 changed files with 540 additions and 1016 deletions
@@ -21,8 +21,8 @@ use tempfile::TempDir;
use tokio::time::timeout;
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
const REQUESTED_MODEL: &str = "gpt-5.1-codex-max";
const SERVER_MODEL: &str = "gpt-5.2-codex";
const REQUESTED_MODEL: &str = "gpt-5.4";
const SERVER_MODEL: &str = "gpt-5.3-codex";
#[tokio::test]
async fn openai_model_header_mismatch_emits_model_rerouted_notification_v2() -> Result<()> {
@@ -125,7 +125,7 @@ stream_max_retries = 0
async fn start_thread(mcp: &mut McpProcess) -> Result<String> {
let req_id = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1".to_string()),
model: Some("gpt-5.2".to_string()),
..Default::default()
})
.await?;
@@ -131,7 +131,7 @@ async fn thread_resume_rejects_unmaterialized_thread() -> Result<()> {
// Start a thread.
let start_id = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
..Default::default()
})
.await?;
@@ -207,7 +207,7 @@ async fn thread_resume_tracks_thread_initialized_analytics() -> Result<()> {
let payload = wait_for_analytics_payload(&server, DEFAULT_READ_TIMEOUT).await?;
let event = thread_initialized_event(&payload)?;
assert_basic_thread_initialized_event(event, &thread.id, "gpt-5.2-codex", "resumed");
assert_basic_thread_initialized_event(event, &thread.id, "gpt-5.3-codex", "resumed");
Ok(())
}
@@ -556,7 +556,7 @@ async fn thread_resume_prefers_persisted_git_metadata_for_local_threads() -> Res
&config_toml,
format!(
r#"
model = "gpt-5.2-codex"
model = "gpt-5.3-codex"
approval_policy = "never"
sandbox_mode = "read-only"
@@ -922,7 +922,7 @@ async fn thread_resume_keeps_in_flight_turn_streaming() -> Result<()> {
let start_id = primary
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
..Default::default()
})
.await?;
@@ -1029,7 +1029,7 @@ async fn thread_resume_rejects_history_when_thread_is_running() -> Result<()> {
let start_id = primary
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
..Default::default()
})
.await?;
@@ -1145,7 +1145,7 @@ async fn thread_resume_rejects_mismatched_path_when_thread_is_running() -> Resul
let start_id = primary
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
..Default::default()
})
.await?;
@@ -1251,7 +1251,7 @@ async fn thread_resume_rejoins_running_thread_even_with_override_mismatch() -> R
let start_id = primary
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
..Default::default()
})
.await?;
@@ -1320,7 +1320,7 @@ async fn thread_resume_rejoins_running_thread_even_with_override_mismatch() -> R
.await??;
let ThreadResumeResponse { thread, model, .. } =
to_response::<ThreadResumeResponse>(resume_resp)?;
assert_eq!(model, "gpt-5.1-codex-max");
assert_eq!(model, "gpt-5.4");
// The running-thread resume response is queued onto the thread listener task.
// If the in-flight turn completes before that queued command runs, the response
// can legitimately observe the thread as idle.
@@ -1364,7 +1364,7 @@ async fn thread_resume_replays_pending_command_execution_request_approval() -> R
let start_id = primary
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
..Default::default()
})
.await?;
@@ -1501,7 +1501,7 @@ async fn thread_resume_replays_pending_file_change_request_approval() -> Result<
let start_id = primary
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
cwd: Some(workspace.to_string_lossy().into_owned()),
..Default::default()
})
@@ -1851,7 +1851,7 @@ async fn thread_resume_prefers_path_over_thread_id() -> Result<()> {
let start_id = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
..Default::default()
})
.await?;
@@ -1971,7 +1971,7 @@ async fn start_materialized_thread_and_restart(
let start_id = first_mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
..Default::default()
})
.await?;
@@ -2045,7 +2045,7 @@ async fn thread_resume_accepts_personality_override() -> Result<()> {
let start_id = primary
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.2-codex".to_string()),
model: Some("gpt-5.3-codex".to_string()),
..Default::default()
})
.await?;
@@ -2083,7 +2083,7 @@ async fn thread_resume_accepts_personality_override() -> Result<()> {
let resume_id = secondary
.send_thread_resume_request(ThreadResumeParams {
thread_id: thread.id,
model: Some("gpt-5.2-codex".to_string()),
model: Some("gpt-5.3-codex".to_string()),
personality: Some(Personality::Friendly),
..Default::default()
})
@@ -2145,7 +2145,7 @@ fn create_config_toml(codex_home: &std::path::Path, server_uri: &str) -> std::io
config_toml,
format!(
r#"
model = "gpt-5.2-codex"
model = "gpt-5.3-codex"
approval_policy = "never"
sandbox_mode = "read-only"
@@ -2182,7 +2182,7 @@ fn create_config_toml_with_chatgpt_base_url(
config_toml,
format!(
r#"
model = "gpt-5.2-codex"
model = "gpt-5.3-codex"
approval_policy = "never"
sandbox_mode = "read-only"
chatgpt_base_url = "{chatgpt_base_url}"
@@ -2213,7 +2213,7 @@ fn create_config_toml_with_required_broken_mcp(
config_toml,
format!(
r#"
model = "gpt-5.2-codex"
model = "gpt-5.3-codex"
approval_policy = "never"
sandbox_mode = "read-only"
@@ -64,7 +64,7 @@ async fn thread_start_creates_thread_and_emits_started() -> Result<()> {
// Start a v2 thread with an explicit model override.
let req_id = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1".to_string()),
model: Some("gpt-5.2".to_string()),
..Default::default()
})
.await?;
@@ -414,7 +414,7 @@ async fn thread_start_ephemeral_remains_pathless() -> Result<()> {
let req_id = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.1".to_string()),
model: Some("gpt-5.2".to_string()),
ephemeral: Some(true),
..Default::default()
})
@@ -894,7 +894,7 @@ async fn turn_start_accepts_collaboration_mode_override_v2() -> Result<()> {
let thread_req = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.2-codex".to_string()),
model: Some("gpt-5.3-codex".to_string()),
..Default::default()
})
.await?;
@@ -977,7 +977,7 @@ async fn turn_start_uses_thread_feature_overrides_for_collaboration_mode_instruc
let thread_req = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.2-codex".to_string()),
model: Some("gpt-5.3-codex".to_string()),
config: Some(HashMap::from([(
"features.default_mode_request_user_input".to_string(),
json!(true),
@@ -1268,7 +1268,7 @@ async fn turn_start_uses_migrated_pragmatic_personality_without_override_v2() ->
let thread_req = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.2-codex".to_string()),
model: Some("gpt-5.3-codex".to_string()),
..Default::default()
})
.await?;
@@ -2033,7 +2033,7 @@ async fn turn_start_emits_spawn_agent_item_with_model_metadata_v2() -> Result<()
const CHILD_PROMPT: &str = "child: do work";
const PARENT_PROMPT: &str = "spawn a child and continue";
const SPAWN_CALL_ID: &str = "spawn-call-1";
const REQUESTED_MODEL: &str = "gpt-5.1";
const REQUESTED_MODEL: &str = "gpt-5.2";
const REQUESTED_REASONING_EFFORT: ReasoningEffort = ReasoningEffort::Low;
let server = responses::start_mock_server().await;
@@ -2088,7 +2088,7 @@ async fn turn_start_emits_spawn_agent_item_with_model_metadata_v2() -> Result<()
let thread_req = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.2-codex".to_string()),
model: Some("gpt-5.3-codex".to_string()),
..Default::default()
})
.await?;
@@ -2227,9 +2227,9 @@ async fn turn_start_emits_spawn_agent_item_with_effective_role_model_metadata_v2
const CHILD_PROMPT: &str = "child: do work";
const PARENT_PROMPT: &str = "spawn a child and continue";
const SPAWN_CALL_ID: &str = "spawn-call-1";
const REQUESTED_MODEL: &str = "gpt-5.1";
const REQUESTED_MODEL: &str = "gpt-5.2";
const REQUESTED_REASONING_EFFORT: ReasoningEffort = ReasoningEffort::Low;
const ROLE_MODEL: &str = "gpt-5.1-codex-max";
const ROLE_MODEL: &str = "gpt-5.4";
const ROLE_REASONING_EFFORT: ReasoningEffort = ReasoningEffort::High;
let server = responses::start_mock_server().await;
@@ -2302,7 +2302,7 @@ config_file = "./custom-role.toml"
let thread_req = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("gpt-5.2-codex".to_string()),
model: Some("gpt-5.3-codex".to_string()),
..Default::default()
})
.await?;
+1 -1
View File
@@ -83,7 +83,7 @@ async fn apply_explorer_role_sets_model_and_adds_session_flags_layer() {
.await
.expect("explorer role should apply");
assert_eq!(config.model.as_deref(), Some("gpt-5.1-codex-mini"));
assert_eq!(config.model.as_deref(), Some("gpt-5.4-mini"));
assert_eq!(config.model_reasoning_effort, Some(ReasoningEffort::Medium));
assert_eq!(session_flags_layer_count(&config), before_layers + 1);
}
+4 -4
View File
@@ -13,7 +13,7 @@ fn serializes_text_verbosity_when_set() {
let input: Vec<ResponseItem> = vec![];
let tools: Vec<serde_json::Value> = vec![];
let req = ResponsesApiRequest {
model: "gpt-5.1".to_string(),
model: "gpt-5.4".to_string(),
instructions: "i".to_string(),
input,
tools,
@@ -57,7 +57,7 @@ fn serializes_text_schema_with_strict_format() {
.expect("text controls");
let req = ResponsesApiRequest {
model: "gpt-5.1".to_string(),
model: "gpt-5.4".to_string(),
instructions: "i".to_string(),
input,
tools,
@@ -95,7 +95,7 @@ fn omits_text_when_not_set() {
let input: Vec<ResponseItem> = vec![];
let tools: Vec<serde_json::Value> = vec![];
let req = ResponsesApiRequest {
model: "gpt-5.1".to_string(),
model: "gpt-5.4".to_string(),
instructions: "i".to_string(),
input,
tools,
@@ -118,7 +118,7 @@ fn omits_text_when_not_set() {
#[test]
fn serializes_flex_service_tier_when_set() {
let req = ResponsesApiRequest {
model: "gpt-5.1".to_string(),
model: "gpt-5.4".to_string(),
instructions: "i".to_string(),
input: vec![],
tools: vec![],
+24 -24
View File
@@ -232,7 +232,7 @@ max_rollout_age_days = 42
max_rollouts_per_startup = 9
min_rollout_idle_hours = 24
extract_model = "gpt-5-mini"
consolidation_model = "gpt-5"
consolidation_model = "gpt-5.2"
"#;
let memories_cfg =
toml::from_str::<ConfigToml>(memories).expect("TOML deserialization should succeed");
@@ -247,7 +247,7 @@ consolidation_model = "gpt-5"
max_rollouts_per_startup: Some(9),
min_rollout_idle_hours: Some(24),
extract_model: Some("gpt-5-mini".to_string()),
consolidation_model: Some("gpt-5".to_string()),
consolidation_model: Some("gpt-5.2".to_string()),
}),
memories_cfg.memories
);
@@ -271,7 +271,7 @@ consolidation_model = "gpt-5"
max_rollouts_per_startup: 9,
min_rollout_idle_hours: 24,
extract_model: Some("gpt-5-mini".to_string()),
consolidation_model: Some("gpt-5".to_string()),
consolidation_model: Some("gpt-5.2".to_string()),
}
);
@@ -3229,14 +3229,14 @@ async fn set_model_updates_defaults() -> anyhow::Result<()> {
let codex_home = TempDir::new()?;
ConfigEditsBuilder::new(codex_home.path())
.set_model(Some("gpt-5.1-codex"), Some(ReasoningEffort::High))
.set_model(Some("gpt-5.4"), Some(ReasoningEffort::High))
.apply()
.await?;
let serialized = tokio::fs::read_to_string(codex_home.path().join(CONFIG_TOML_FILE)).await?;
let parsed: ConfigToml = toml::from_str(&serialized)?;
assert_eq!(parsed.model.as_deref(), Some("gpt-5.1-codex"));
assert_eq!(parsed.model.as_deref(), Some("gpt-5.4"));
assert_eq!(parsed.model_reasoning_effort, Some(ReasoningEffort::High));
Ok(())
@@ -3250,7 +3250,7 @@ async fn set_model_overwrites_existing_model() -> anyhow::Result<()> {
tokio::fs::write(
&config_path,
r#"
model = "gpt-5.1-codex"
model = "gpt-5.4"
model_reasoning_effort = "medium"
[profiles.dev]
@@ -3286,7 +3286,7 @@ async fn set_model_updates_profile() -> anyhow::Result<()> {
ConfigEditsBuilder::new(codex_home.path())
.with_profile(Some("dev"))
.set_model(Some("gpt-5.1-codex"), Some(ReasoningEffort::Medium))
.set_model(Some("gpt-5.4"), Some(ReasoningEffort::Medium))
.apply()
.await?;
@@ -3297,7 +3297,7 @@ async fn set_model_updates_profile() -> anyhow::Result<()> {
.get("dev")
.expect("profile should be created");
assert_eq!(profile.model.as_deref(), Some("gpt-5.1-codex"));
assert_eq!(profile.model.as_deref(), Some("gpt-5.4"));
assert_eq!(
profile.model_reasoning_effort,
Some(ReasoningEffort::Medium)
@@ -3319,7 +3319,7 @@ model = "gpt-4"
model_reasoning_effort = "medium"
[profiles.prod]
model = "gpt-5.1-codex"
model = "gpt-5.4"
"#,
)
.await?;
@@ -3348,7 +3348,7 @@ model = "gpt-5.1-codex"
.profiles
.get("prod")
.and_then(|profile| profile.model.as_deref()),
Some("gpt-5.1-codex"),
Some("gpt-5.4"),
);
Ok(())
@@ -3713,7 +3713,7 @@ async fn agent_role_file_metadata_overrides_config_toml_metadata() -> std::io::R
description = "Role metadata from file"
nickname_candidates = ["Hypatia"]
developer_instructions = "Research carefully"
model = "gpt-5"
model = "gpt-5.2"
"#,
)
.await?;
@@ -3775,7 +3775,7 @@ trust_level = "trusted"
r#"
name = "researcher"
description = "Role metadata from file"
model = "gpt-5"
model = "gpt-5.2"
"#,
)
.await?;
@@ -3785,7 +3785,7 @@ model = "gpt-5"
name = "reviewer"
description = "Review role"
developer_instructions = "Review carefully"
model = "gpt-5"
model = "gpt-5.2"
"#,
)
.await?;
@@ -3830,7 +3830,7 @@ async fn legacy_agent_role_config_file_allows_missing_developer_instructions() -
tokio::fs::write(
&role_config_path,
r#"
model = "gpt-5"
model = "gpt-5.2"
model_reasoning_effort = "high"
"#,
)
@@ -3882,7 +3882,7 @@ async fn agent_role_without_description_after_merge_is_dropped_with_warning() ->
&role_config_path,
r#"
developer_instructions = "Research carefully"
model = "gpt-5"
model = "gpt-5.2"
"#,
)
.await?;
@@ -4001,7 +4001,7 @@ async fn agent_role_file_name_takes_precedence_over_config_key() -> std::io::Res
name = "archivist"
description = "Role metadata from file"
developer_instructions = "Research carefully"
model = "gpt-5"
model = "gpt-5.2"
"#,
)
.await?;
@@ -4286,7 +4286,7 @@ nickname_candidates = ["Ada"]
home_agents_dir.join("researcher.toml"),
r#"
developer_instructions = "Research carefully"
model = "gpt-5"
model = "gpt-5.2"
"#,
)
.await?;
@@ -4319,7 +4319,7 @@ name = "writer"
description = "Writer role from file"
nickname_candidates = ["Sagan"]
developer_instructions = "Write carefully"
model = "gpt-5"
model = "gpt-5.2"
"#,
)
.await?;
@@ -4426,7 +4426,7 @@ config_file = "./agents/researcher.toml"
home_agents_dir.join("researcher.toml"),
r#"
developer_instructions = "Research carefully"
model = "gpt-5"
model = "gpt-5.2"
"#,
)
.await?;
@@ -4725,7 +4725,7 @@ approval_policy = "on-failure"
enabled = false
[profiles.gpt5]
model = "gpt-5.1"
model = "gpt-5.4"
model_provider = "openai"
approval_policy = "on-failure"
model_reasoning_effort = "high"
@@ -5248,7 +5248,7 @@ async fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> {
)
.await?;
let expected_gpt5_profile_config = Config {
model: Some("gpt-5.1".to_string()),
model: Some("gpt-5.4".to_string()),
review_model: None,
model_context_window: None,
model_auto_compact_token_limit: None,
@@ -5898,7 +5898,7 @@ fn config_toml_deserializes_mcp_oauth_callback_url() {
async fn config_loads_mcp_oauth_callback_port_from_toml() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let toml = r#"
model = "gpt-5.1"
model = "gpt-5.4"
mcp_oauth_callback_port = 5678
"#;
let cfg: ConfigToml =
@@ -5920,7 +5920,7 @@ async fn config_loads_allow_login_shell_from_toml() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let cfg: ConfigToml = toml::from_str(
r#"
model = "gpt-5.1"
model = "gpt-5.4"
allow_login_shell = false
"#,
)
@@ -5941,7 +5941,7 @@ allow_login_shell = false
async fn config_loads_mcp_oauth_callback_url_from_toml() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let toml = r#"
model = "gpt-5.1"
model = "gpt-5.4"
mcp_oauth_callback_url = "https://example.com/callback"
"#;
let cfg: ConfigToml =
+14 -14
View File
@@ -18,14 +18,14 @@ fn blocking_set_model_top_level() {
codex_home,
/*profile*/ None,
&[ConfigEdit::SetModel {
model: Some("gpt-5.1-codex".to_string()),
model: Some("gpt-5.4".to_string()),
effort: Some(ReasoningEffort::High),
}],
)
.expect("persist");
let contents = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config");
let expected = r#"model = "gpt-5.1-codex"
let expected = r#"model = "gpt-5.4"
model_reasoning_effort = "high"
"#;
assert_eq!(contents, expected);
@@ -197,7 +197,7 @@ fn blocking_set_model_writes_through_symlink_chain() {
codex_home,
/*profile*/ None,
&[ConfigEdit::SetModel {
model: Some("gpt-5.1-codex".to_string()),
model: Some("gpt-5.4".to_string()),
effort: Some(ReasoningEffort::High),
}],
)
@@ -207,7 +207,7 @@ fn blocking_set_model_writes_through_symlink_chain() {
assert!(meta.file_type().is_symlink());
let contents = std::fs::read_to_string(&target_path).expect("read target");
let expected = r#"model = "gpt-5.1-codex"
let expected = r#"model = "gpt-5.4"
model_reasoning_effort = "high"
"#;
assert_eq!(contents, expected);
@@ -230,7 +230,7 @@ fn blocking_set_model_replaces_symlink_on_cycle() {
codex_home,
/*profile*/ None,
&[ConfigEdit::SetModel {
model: Some("gpt-5.1-codex".to_string()),
model: Some("gpt-5.4".to_string()),
effort: None,
}],
)
@@ -240,7 +240,7 @@ fn blocking_set_model_replaces_symlink_on_cycle() {
assert!(!meta.file_type().is_symlink());
let contents = std::fs::read_to_string(&config_path).expect("read config");
let expected = r#"model = "gpt-5.1-codex"
let expected = r#"model = "gpt-5.4"
"#;
assert_eq!(contents, expected);
}
@@ -381,7 +381,7 @@ fn blocking_set_model_with_explicit_profile() {
std::fs::write(
codex_home.join(CONFIG_TOML_FILE),
r#"[profiles."team a"]
model = "gpt-5.1-codex"
model = "gpt-5.4"
"#,
)
.expect("seed");
@@ -536,8 +536,8 @@ existing = "value"
codex_home,
/*profile*/ None,
&[ConfigEdit::RecordModelMigrationSeen {
from: "gpt-5".to_string(),
to: "gpt-5.1".to_string(),
from: "gpt-5.2".to_string(),
to: "gpt-5.4".to_string(),
}],
)
.expect("persist");
@@ -547,7 +547,7 @@ existing = "value"
existing = "value"
[notice.model_migrations]
gpt-5 = "gpt-5.1"
gpt-5 = "gpt-5.4"
"#;
assert_eq!(contents, expected);
}
@@ -1102,13 +1102,13 @@ async fn async_builder_set_model_persists() {
let codex_home = tmp.path().to_path_buf();
ConfigEditsBuilder::new(&codex_home)
.set_model(Some("gpt-5.1-codex"), Some(ReasoningEffort::High))
.set_model(Some("gpt-5.4"), Some(ReasoningEffort::High))
.apply()
.await
.expect("persist");
let contents = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config");
let expected = r#"model = "gpt-5.1-codex"
let expected = r#"model = "gpt-5.4"
model_reasoning_effort = "high"
"#;
assert_eq!(contents, expected);
@@ -1130,11 +1130,11 @@ model_reasoning_effort = "low"
std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config");
assert_eq!(contents, initial_expected);
let updated_expected = r#"model = "gpt-5.1-codex"
let updated_expected = r#"model = "gpt-5.4"
model_reasoning_effort = "high"
"#;
ConfigEditsBuilder::new(codex_home)
.set_model(Some("gpt-5.1-codex"), Some(ReasoningEffort::High))
.set_model(Some("gpt-5.4"), Some(ReasoningEffort::High))
.apply_blocking()
.expect("persist update");
contents = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE)).expect("read config");
+3 -3
View File
@@ -62,7 +62,7 @@ X-Doc = "42"
async fn write_value_preserves_comments_and_order() -> Result<()> {
let tmp = tempdir().expect("tempdir");
let original = r#"# Codex user configuration
model = "gpt-5"
model = "gpt-5.2"
approval_policy = "on-request"
[notice]
@@ -88,7 +88,7 @@ unified_exec = true
let updated = std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE)).expect("read config");
let expected = r#"# Codex user configuration
model = "gpt-5"
model = "gpt-5.2"
approval_policy = "on-request"
[notice]
@@ -390,7 +390,7 @@ async fn version_conflict_rejected() {
.write_value(ConfigValueWriteParams {
file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),
key_path: "model".to_string(),
value: serde_json::json!("gpt-5"),
value: serde_json::json!("gpt-5.2"),
merge_strategy: MergeStrategy::Replace,
expected_version: Some("sha256:bogus".to_string()),
})
+1 -1
View File
@@ -94,7 +94,7 @@ fn numbered_mcp_tools(count: usize) -> HashMap<String, ToolInfo> {
async fn tools_config_for_mcp_tool_exposure(search_tool: bool) -> ToolsConfig {
let config = test_config().await;
let model_info = ModelsManager::construct_model_info_offline_for_tests(
"gpt-5-codex",
"gpt-5.4",
&config.to_models_manager_config(),
);
let features = Features::with_defaults();
+2 -2
View File
@@ -10,7 +10,7 @@ use tokio::fs as tokio_fs;
#[test]
fn build_stage_one_input_message_truncates_rollout_using_model_context_window() {
let input = format!("{}{}{}", "a".repeat(700_000), "middle", "z".repeat(700_000));
let mut model_info = model_info_from_slug("gpt-5.2-codex");
let mut model_info = model_info_from_slug("gpt-5.3-codex");
model_info.context_window = Some(123_000);
let expected_rollout_token_limit = usize::try_from(
((123_000_i64 * model_info.effective_context_window_percent) / 100)
@@ -39,7 +39,7 @@ fn build_stage_one_input_message_truncates_rollout_using_model_context_window()
#[test]
fn build_stage_one_input_message_uses_default_limit_when_model_context_window_missing() {
let input = format!("{}{}{}", "a".repeat(700_000), "middle", "z".repeat(700_000));
let mut model_info = model_info_from_slug("gpt-5.2-codex");
let mut model_info = model_info_from_slug("gpt-5.3-codex");
model_info.context_window = None;
model_info.max_context_window = None;
let expected_truncated = truncate_text(
+1 -1
View File
@@ -35,7 +35,7 @@ fn stored_thread(cwd: &str, title: &str, first_user_message: &str) -> StoredThre
preview: first_user_message.to_string(),
name: (!title.is_empty()).then(|| title.to_string()),
model_provider: "test-provider".to_string(),
model: Some("gpt-5".to_string()),
model: Some("gpt-5.2".to_string()),
reasoning_effort: None,
created_at: Utc
.timestamp_opt(1_709_251_100, 0)
+17 -17
View File
@@ -202,8 +202,8 @@ fn test_session_telemetry_without_metadata() -> SessionTelemetry {
.expect("in-memory metrics client");
SessionTelemetry::new(
ThreadId::new(),
"gpt-5.1",
"gpt-5.1",
"gpt-5.4",
"gpt-5.4",
/*account_id*/ None,
/*account_email*/ None,
/*auth_mode*/ None,
@@ -455,7 +455,7 @@ async fn preview_session_start_hooks(
session_id: ThreadId::new(),
cwd: config.cwd.clone(),
transcript_path: None,
model: "gpt-5".to_string(),
model: "gpt-5.2".to_string(),
permission_mode: "default".to_string(),
source: codex_hooks::SessionStartSource::Startup,
}),
@@ -1042,19 +1042,19 @@ async fn get_base_instructions_no_user_content() {
};
let test_cases = vec![
InstructionsTestCase {
slug: "gpt-5",
slug: "gpt-5.4",
expects_apply_patch_description: false,
},
InstructionsTestCase {
slug: "gpt-5.1",
slug: "gpt-5.4-mini",
expects_apply_patch_description: false,
},
InstructionsTestCase {
slug: "gpt-5.1-codex",
slug: "gpt-5.3-codex",
expects_apply_patch_description: false,
},
InstructionsTestCase {
slug: "gpt-5.1-codex-max",
slug: "gpt-5.2",
expects_apply_patch_description: false,
},
];
@@ -2538,19 +2538,19 @@ async fn turn_context_with_model_updates_model_fields() {
let (session, mut turn_context) = make_session_and_context().await;
turn_context.reasoning_effort = Some(ReasoningEffortConfig::Minimal);
let updated = turn_context
.with_model("gpt-5.1".to_string(), &session.services.models_manager)
.with_model("gpt-5.4".to_string(), &session.services.models_manager)
.await;
let expected_model_info = session
.services
.models_manager
.get_model_info(
"gpt-5.1",
"gpt-5.4",
&updated.config.as_ref().to_models_manager_config(),
)
.await;
assert_eq!(updated.config.model.as_deref(), Some("gpt-5.1"));
assert_eq!(updated.collaboration_mode.model(), "gpt-5.1");
assert_eq!(updated.config.model.as_deref(), Some("gpt-5.4"));
assert_eq!(updated.collaboration_mode.model(), "gpt-5.4");
assert_eq!(updated.model_info, expected_model_info);
assert_eq!(
updated.reasoning_effort,
@@ -5303,10 +5303,10 @@ async fn record_context_updates_and_set_reference_context_item_reinjects_full_co
async fn record_context_updates_and_set_reference_context_item_persists_baseline_without_emitting_diffs()
{
let (session, previous_context) = make_session_and_context().await;
let next_model = if previous_context.model_info.slug == "gpt-5.1" {
"gpt-5"
let next_model = if previous_context.model_info.slug == "gpt-5.4" {
"gpt-5.2"
} else {
"gpt-5.1"
"gpt-5.4"
};
let turn_context = previous_context
.with_model(next_model.to_string(), &session.services.models_manager)
@@ -5455,10 +5455,10 @@ async fn build_initial_context_prepends_model_switch_message() {
async fn record_context_updates_and_set_reference_context_item_persists_full_reinjection_to_rollout()
{
let (session, previous_context) = make_session_and_context().await;
let next_model = if previous_context.model_info.slug == "gpt-5.1" {
"gpt-5"
let next_model = if previous_context.model_info.slug == "gpt-5.4" {
"gpt-5.2"
} else {
"gpt-5.1"
"gpt-5.4"
};
let turn_context = previous_context
.with_model(next_model.to_string(), &session.services.models_manager)
+2 -2
View File
@@ -25,8 +25,8 @@ fn test_session_telemetry() -> SessionTelemetry {
.expect("in-memory metrics client");
SessionTelemetry::new(
ThreadId::new(),
"gpt-5.1",
"gpt-5.1",
"gpt-5.4",
"gpt-5.4",
/*account_id*/ None,
/*account_email*/ None,
/*auth_mode*/ None,
+23 -22
View File
@@ -109,7 +109,7 @@ fn discoverable_connector(id: &str, name: &str, description: &str) -> Discoverab
async fn search_capable_model_info() -> ModelInfo {
let config = test_config().await;
let mut model_info = construct_model_info_offline("gpt-5-codex", &config);
let mut model_info = construct_model_info_offline("gpt-5.4", &config);
model_info.supports_search_tool = true;
model_info
}
@@ -218,7 +218,7 @@ fn find_namespace_function_tool<'a>(
async fn multi_agent_v2_tools_config() -> ToolsConfig {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.enable(Feature::Collab);
features.enable(Feature::MultiAgentV2);
@@ -297,7 +297,7 @@ fn build_specs_with_unavailable_tools(
#[tokio::test]
async fn model_provided_unified_exec_is_blocked_for_windows_sandboxed_policies() {
let mut model_info = model_info_from_models_json("gpt-5-codex").await;
let mut model_info = model_info_from_models_json("gpt-5.4").await;
model_info.shell_type = ConfigShellToolType::UnifiedExec;
let features = Features::with_defaults();
let available_models = Vec::new();
@@ -323,7 +323,7 @@ async fn model_provided_unified_exec_is_blocked_for_windows_sandboxed_policies()
#[tokio::test]
async fn get_memory_requires_feature_flag() {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.disable(Feature::MemoryTool);
let available_models = Vec::new();
@@ -408,7 +408,7 @@ async fn assert_default_model_tools(
async fn test_build_specs_gpt5_codex_default() {
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5-codex",
"gpt-5.4",
&features,
Some(WebSearchMode::Cached),
"shell_command",
@@ -433,7 +433,7 @@ async fn test_build_specs_gpt5_codex_default() {
async fn test_build_specs_gpt51_codex_default() {
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5.1-codex",
"gpt-5.4",
&features,
Some(WebSearchMode::Cached),
"shell_command",
@@ -459,7 +459,7 @@ async fn test_build_specs_gpt5_codex_unified_exec_web_search() {
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
assert_model_tools(
"gpt-5-codex",
"gpt-5.4",
&features,
Some(WebSearchMode::Live),
&[
@@ -486,7 +486,7 @@ async fn test_build_specs_gpt51_codex_unified_exec_web_search() {
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
assert_model_tools(
"gpt-5.1-codex",
"gpt-5.4",
&features,
Some(WebSearchMode::Live),
&[
@@ -512,7 +512,7 @@ async fn test_build_specs_gpt51_codex_unified_exec_web_search() {
async fn test_gpt_5_1_codex_max_defaults() {
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5.1-codex-max",
"gpt-5.4",
&features,
Some(WebSearchMode::Cached),
"shell_command",
@@ -537,7 +537,7 @@ async fn test_gpt_5_1_codex_max_defaults() {
async fn test_codex_5_1_mini_defaults() {
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5.1-codex-mini",
"gpt-5.4-mini",
&features,
Some(WebSearchMode::Cached),
"shell_command",
@@ -562,13 +562,14 @@ async fn test_codex_5_1_mini_defaults() {
async fn test_gpt_5_defaults() {
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5",
"gpt-5.2",
&features,
Some(WebSearchMode::Cached),
"shell",
"shell_command",
&[
"update_plan",
"request_user_input",
"apply_patch",
"web_search",
"image_generation",
"view_image",
@@ -586,7 +587,7 @@ async fn test_gpt_5_defaults() {
async fn test_gpt_5_1_defaults() {
let features = Features::with_defaults();
assert_default_model_tools(
"gpt-5.1",
"gpt-5.4",
&features,
Some(WebSearchMode::Cached),
"shell_command",
@@ -612,7 +613,7 @@ async fn test_gpt_5_1_codex_max_unified_exec_web_search() {
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
assert_model_tools(
"gpt-5.1-codex-max",
"gpt-5.4",
&features,
Some(WebSearchMode::Live),
&[
@@ -998,7 +999,7 @@ async fn search_tool_registers_namespaced_mcp_tool_aliases() {
#[tokio::test]
async fn direct_mcp_tools_register_namespaced_handlers() {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
let available_models = Vec::new();
@@ -1035,7 +1036,7 @@ async fn direct_mcp_tools_register_namespaced_handlers() {
#[tokio::test]
async fn unavailable_mcp_tools_are_exposed_as_dummy_function_tools() {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
let available_models = Vec::new();
@@ -1084,7 +1085,7 @@ async fn unavailable_mcp_tools_are_exposed_as_dummy_function_tools() {
#[tokio::test]
async fn test_mcp_tool_property_missing_type_defaults_to_string() {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
let available_models = Vec::new();
@@ -1147,7 +1148,7 @@ async fn test_mcp_tool_property_missing_type_defaults_to_string() {
#[tokio::test]
async fn test_mcp_tool_preserves_integer_schema() {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
let available_models = Vec::new();
@@ -1208,7 +1209,7 @@ async fn test_mcp_tool_preserves_integer_schema() {
#[tokio::test]
async fn test_mcp_tool_array_without_items_gets_default_string_items() {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
features.enable(Feature::ApplyPatchFreeform);
@@ -1273,7 +1274,7 @@ async fn test_mcp_tool_array_without_items_gets_default_string_items() {
#[tokio::test]
async fn test_mcp_tool_anyof_defaults_to_string() {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
let available_models = Vec::new();
@@ -1342,7 +1343,7 @@ async fn test_mcp_tool_anyof_defaults_to_string() {
#[tokio::test]
async fn test_get_openai_tools_mcp_tools_with_additional_properties_schema() {
let config = test_config().await;
let model_info = construct_model_info_offline("gpt-5-codex", &config);
let model_info = construct_model_info_offline("gpt-5.4", &config);
let mut features = Features::with_defaults();
features.enable(Feature::UnifiedExec);
let available_models = Vec::new();
@@ -1461,7 +1462,7 @@ async fn code_mode_only_restricts_model_tools_to_exec_tools() {
features.enable(Feature::CodeModeOnly);
assert_model_tools(
"gpt-5.1-codex",
"gpt-5.4",
&features,
Some(WebSearchMode::Live),
&["exec", "wait"],
+1 -1
View File
@@ -20,7 +20,7 @@ fn feedback_tags_macro_compiles() {
#[derive(Debug)]
struct OnlyDebug;
feedback_tags!(model = "gpt-5", cached = true, debug_only = OnlyDebug);
feedback_tags!(model = "gpt-5.2", cached = true, debug_only = OnlyDebug);
}
#[derive(Default)]
+1 -1
View File
@@ -601,7 +601,7 @@ data: {"type":"response.completed","response":{"id":"resp-1"}}
let url = format!("{}/v1/responses", server.uri());
let payload = serde_json::json!({
"model": "gpt-5.1",
"model": "gpt-5.4",
"instructions": "test",
"input": [{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "hello"}]}],
"stream": true
+2 -2
View File
@@ -516,9 +516,9 @@ fn ensure_test_model_catalog(config: &mut Config) -> Result<()> {
let mut model = bundled_models
.models
.iter()
.find(|candidate| candidate.slug == "gpt-5.1-codex")
.find(|candidate| candidate.slug == "gpt-5.2")
.cloned()
.unwrap_or_else(|| panic!("missing bundled model gpt-5.1-codex"));
.unwrap_or_else(|| panic!("missing bundled model gpt-5.2"));
model.slug = TEST_MODEL_WITH_EXPERIMENTAL_TOOLS.to_string();
model.display_name = TEST_MODEL_WITH_EXPERIMENTAL_TOOLS.to_string();
model.experimental_supported_tools = vec!["test_sync_tool".to_string()];
+3 -3
View File
@@ -37,7 +37,7 @@ async fn interrupt_long_running_tool_emits_turn_aborted() {
mount_sse_once(&server, body).await;
let codex = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.build(&server)
.await
.unwrap()
@@ -93,7 +93,7 @@ async fn interrupt_tool_records_history_entries() {
let response_mock = mount_sse_sequence(&server, vec![first_body, follow_up_body]).await;
let fixture = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.build(&server)
.await
.unwrap();
@@ -193,7 +193,7 @@ async fn interrupt_persists_turn_aborted_marker_in_next_request() {
let response_mock = mount_sse_sequence(&server, vec![first_body, follow_up_body]).await;
let fixture = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.build(&server)
.await
.unwrap();
+5 -5
View File
@@ -146,7 +146,7 @@ async fn apply_patch_cli_multiple_operations_integration(
) -> Result<()> {
skip_if_no_network!(Ok(()));
let harness = apply_patch_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = apply_patch_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
// Seed workspace state
harness.write_file("modify.txt", "line1\nline2\n").await?;
@@ -761,7 +761,7 @@ async fn apply_patch_cli_verification_failure_has_no_side_effects(
async fn apply_patch_shell_command_heredoc_with_cd_updates_relative_workdir() -> Result<()> {
skip_if_no_network!(Ok(()));
let harness = apply_patch_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = apply_patch_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
// Prepare a file inside a subdir; update it via cd && apply_patch heredoc form.
harness.write_file("sub/in_sub.txt", "before\n").await?;
@@ -801,7 +801,7 @@ async fn apply_patch_cli_can_use_shell_command_output_as_patch_input() -> Result
);
let harness =
apply_patch_harness_with(|builder| builder.with_model("gpt-5.1").with_windows_cmd_shell())
apply_patch_harness_with(|builder| builder.with_model("gpt-5.4").with_windows_cmd_shell())
.await?;
let source_contents = "line1\nnaïve café\nline3\n";
@@ -1065,7 +1065,7 @@ async fn apply_patch_shell_command_heredoc_with_cd_emits_turn_diff() -> Result<(
"TurnDiffTracker currently reads the test-runner filesystem, not the remote executor filesystem",
);
let harness = apply_patch_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = apply_patch_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let test = harness.test();
let codex = test.codex.clone();
@@ -1150,7 +1150,7 @@ async fn apply_patch_shell_command_failure_propagates_error_and_skips_diff() ->
"TurnDiffTracker currently reads the test-runner filesystem, not the remote executor filesystem",
);
let harness = apply_patch_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = apply_patch_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let test = harness.test();
let codex = test.codex.clone();
+40 -40
View File
@@ -782,7 +782,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::FileCreated {
target: TargetPath::OutsideWorkspace("dfa_on_request.txt"),
@@ -799,7 +799,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::FileCreated {
target: TargetPath::OutsideWorkspace("dfa_on_request_5_1.txt"),
@@ -816,7 +816,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::NetworkSuccess {
body_contains: "danger-network-ok",
@@ -832,7 +832,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::NetworkSuccessNoExitCode {
body_contains: "danger-network-ok",
@@ -847,7 +847,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::CommandSuccess {
stdout_contains: "trusted-unless",
@@ -862,7 +862,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::CommandSuccessNoExitCode {
stdout_contains: "trusted-unless",
@@ -877,7 +877,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Denied,
expected_reason: None,
@@ -895,7 +895,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::RequireEscalated,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Denied,
expected_reason: None,
@@ -914,7 +914,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::FileCreated {
target: TargetPath::OutsideWorkspace("dfa_on_failure.txt"),
@@ -931,7 +931,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::FileCreatedNoExitCode {
target: TargetPath::OutsideWorkspace("dfa_on_failure_5_1.txt"),
@@ -948,7 +948,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -968,7 +968,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -988,7 +988,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::FileCreated {
target: TargetPath::OutsideWorkspace("dfa_never.txt"),
@@ -1005,7 +1005,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::FileCreatedNoExitCode {
target: TargetPath::OutsideWorkspace("dfa_never_5_1.txt"),
@@ -1022,7 +1022,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::RequireEscalated,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1042,7 +1042,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::RequireEscalated,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1061,7 +1061,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::CommandSuccess {
stdout_contains: "trusted-read-only",
@@ -1076,7 +1076,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::CommandSuccessNoExitCode {
stdout_contains: "trusted-read-only",
@@ -1127,7 +1127,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: Some("command failed; retry without sandbox?"),
@@ -1148,7 +1148,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: Some("command failed; retry without sandbox?"),
@@ -1168,7 +1168,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::RequireEscalated,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1187,7 +1187,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::RequireEscalated,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1226,7 +1226,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1-codex"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::PatchApplied {
target: TargetPath::Workspace("apply_patch_function.txt"),
@@ -1243,7 +1243,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![Feature::ApplyPatchFreeform],
model_override: Some("gpt-5.1-codex"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::PatchApplied {
target: TargetPath::OutsideWorkspace("apply_patch_function_danger.txt"),
@@ -1260,7 +1260,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1-codex"),
model_override: Some("gpt-5.4"),
outcome: Outcome::PatchApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1280,7 +1280,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1-codex"),
model_override: Some("gpt-5.4"),
outcome: Outcome::PatchApproval {
decision: ReviewDecision::Denied,
expected_reason: None,
@@ -1320,7 +1320,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1-codex"),
model_override: Some("gpt-5.4"),
outcome: Outcome::PatchApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1340,7 +1340,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1-codex"),
model_override: Some("gpt-5.4"),
outcome: Outcome::Auto,
expectation: Expectation::FileNotCreated {
target: TargetPath::OutsideWorkspace("apply_patch_function_never.txt"),
@@ -1359,7 +1359,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1379,7 +1379,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5.1"),
model_override: Some("gpt-5.4"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1422,7 +1422,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::CommandSuccess {
stdout_contains: "trusted-never",
@@ -1438,7 +1438,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::FileCreated {
target: TargetPath::Workspace("ww_on_request.txt"),
@@ -1469,7 +1469,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::RequireEscalated,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1489,7 +1489,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::NetworkSuccess {
body_contains: "workspace-network-ok",
@@ -1506,7 +1506,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: Some("command failed; retry without sandbox?"),
@@ -1526,7 +1526,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: None,
@@ -1570,7 +1570,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::UseDefault,
features: vec![Feature::UnifiedExec],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::Auto,
expectation: Expectation::CommandSuccess {
stdout_contains: "hello unified exec",
@@ -1588,7 +1588,7 @@ fn scenarios() -> Vec<ScenarioSpec> {
},
sandbox_permissions: SandboxPermissions::RequireEscalated,
features: vec![Feature::UnifiedExec],
model_override: Some("gpt-5"),
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApproval {
decision: ReviewDecision::Approved,
expected_reason: Some(DEFAULT_UNIFIED_EXEC_JUSTIFICATION),
@@ -1675,7 +1675,7 @@ async fn run_scenario(scenario: &ScenarioSpec) -> Result<()> {
let sandbox_policy = scenario.sandbox_policy.clone();
let features = scenario.features.clone();
let model_override = scenario.model_override;
let model = model_override.unwrap_or("gpt-5.1");
let model = model_override.unwrap_or("gpt-5.4");
let mut builder = test_codex().with_model(model).with_config(move |config| {
config.permissions.approval_policy = Constrained::allow_any(approval_policy);
@@ -1804,7 +1804,7 @@ async fn approving_apply_patch_for_session_skips_future_prompts_for_same_file()
let sandbox_policy_for_config = sandbox_policy.clone();
let mut builder = test_codex()
.with_model("gpt-5.1-codex")
.with_model("gpt-5.4")
.with_config(move |config| {
config.permissions.approval_policy = Constrained::allow_any(approval_policy);
config.permissions.sandbox_policy = Constrained::allow_any(sandbox_policy_for_config);
+19 -25
View File
@@ -537,7 +537,7 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() {
.await;
let codex_home = Arc::new(TempDir::new().unwrap());
let mut builder = test_codex().with_model("gpt-5.1");
let mut builder = test_codex().with_model("gpt-5.4");
let test = builder
.resume(&server, codex_home, session_path.clone())
.await
@@ -688,7 +688,7 @@ async fn resume_replays_image_tool_outputs_with_detail() {
.await;
let codex_home = Arc::new(TempDir::new().unwrap());
let mut builder = test_codex().with_model("gpt-5.1");
let mut builder = test_codex().with_model("gpt-5.4");
let test = builder
.resume(&server, codex_home, session_path.clone())
.await
@@ -1493,7 +1493,7 @@ async fn includes_configured_effort_in_request() -> anyhow::Result<()> {
)
.await;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5.1-codex")
.with_model("gpt-5.4")
.with_config(|config| {
config.model_reasoning_effort = Some(ReasoningEffort::Medium);
})
@@ -1538,10 +1538,7 @@ async fn includes_no_effort_in_request() -> anyhow::Result<()> {
sse(vec![ev_response_created("resp1"), ev_completed("resp1")]),
)
.await;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5.1-codex")
.build(&server)
.await?;
let TestCodex { codex, .. } = test_codex().with_model("gpt-5.4").build(&server).await?;
codex
.submit(Op::UserInput {
@@ -1582,7 +1579,7 @@ async fn includes_default_reasoning_effort_in_request_when_defined_by_model_info
sse(vec![ev_response_created("resp1"), ev_completed("resp1")]),
)
.await;
let TestCodex { codex, .. } = test_codex().with_model("gpt-5.1").build(&server).await?;
let TestCodex { codex, .. } = test_codex().with_model("gpt-5.4").build(&server).await?;
codex
.submit(Op::UserInput {
@@ -1627,15 +1624,12 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
config,
session_configured,
..
} = test_codex()
.with_model("gpt-5.1-codex")
.build(&server)
.await?;
} = test_codex().with_model("gpt-5.4").build(&server).await?;
let collaboration_mode = CollaborationMode {
mode: ModeKind::Default,
settings: Settings {
model: "gpt-5.1".to_string(),
model: "gpt-5.4".to_string(),
reasoning_effort: Some(ReasoningEffort::High),
developer_instructions: None,
},
@@ -1668,7 +1662,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
let request_body = resp_mock.single_request().body_json();
assert_eq!(request_body["model"].as_str(), Some("gpt-5.1"));
assert_eq!(request_body["model"].as_str(), Some("gpt-5.4"));
assert_eq!(
request_body
.get("reasoning")
@@ -1742,8 +1736,8 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default()
let model = model_catalog
.models
.iter_mut()
.find(|model| model.slug == "gpt-5.1")
.expect("gpt-5.1 exists in bundled models.json");
.find(|model| model.slug == "gpt-5.4")
.expect("gpt-5.4 exists in bundled models.json");
model.supports_reasoning_summaries = true;
model.default_reasoning_summary = ReasoningSummary::Detailed;
@@ -1753,7 +1747,7 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default()
session_configured,
..
} = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.with_config(move |config| {
config.model_catalog = Some(model_catalog);
})
@@ -1856,13 +1850,13 @@ async fn reasoning_summary_none_overrides_model_catalog_default() -> anyhow::Res
let model = model_catalog
.models
.iter_mut()
.find(|model| model.slug == "gpt-5.1")
.expect("gpt-5.1 exists in bundled models.json");
.find(|model| model.slug == "gpt-5.4")
.expect("gpt-5.4 exists in bundled models.json");
model.supports_reasoning_summaries = true;
model.default_reasoning_summary = ReasoningSummary::Detailed;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.with_config(move |config| {
config.model_reasoning_summary = Some(ReasoningSummary::None);
config.model_catalog = Some(model_catalog);
@@ -1905,7 +1899,7 @@ async fn includes_default_verbosity_in_request() -> anyhow::Result<()> {
sse(vec![ev_response_created("resp1"), ev_completed("resp1")]),
)
.await;
let TestCodex { codex, .. } = test_codex().with_model("gpt-5.1").build(&server).await?;
let TestCodex { codex, .. } = test_codex().with_model("gpt-5.4").build(&server).await?;
codex
.submit(Op::UserInput {
@@ -1946,7 +1940,7 @@ async fn configured_verbosity_not_sent_for_models_without_support() -> anyhow::R
)
.await;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5.1-codex")
.with_model("test-no-verbosity")
.with_config(|config| {
config.model_verbosity = Some(Verbosity::High);
})
@@ -1991,7 +1985,7 @@ async fn configured_verbosity_is_sent() -> anyhow::Result<()> {
)
.await;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.with_config(|config| {
config.model_verbosity = Some(Verbosity::High);
})
@@ -2412,7 +2406,7 @@ async fn token_count_includes_rate_limits_snapshot() {
"reasoning_output_tokens": 0,
"total_tokens": 123
},
// Default model is gpt-5.1-codex-max in tests → 95% usable context window
// Default model is gpt-5.4 in tests → 95% usable context window
"model_context_window": 258400
},
"rate_limits": {
@@ -2577,7 +2571,7 @@ async fn context_window_error_sets_total_tokens_to_model_window() -> anyhow::Res
let TestCodex { codex, .. } = test_codex()
.with_config(|config| {
config.model = Some("gpt-5.1".to_string());
config.model = Some("gpt-5.4".to_string());
config.model_context_window = Some(272_000);
})
.build(&server)
@@ -51,7 +51,7 @@ use tempfile::TempDir;
use tracing::Instrument;
use tracing_test::traced_test;
const MODEL: &str = "gpt-5.2-codex";
const MODEL: &str = "gpt-5.3-codex";
const OPENAI_BETA_HEADER: &str = "OpenAI-Beta";
const WS_V2_BETA_HEADER_VALUE: &str = "responses_websockets=2026-02-06";
const X_CLIENT_REQUEST_ID_HEADER: &str = "x-client-request-id";
+4 -5
View File
@@ -413,16 +413,15 @@ if (!tool) {
.features
.enable(Feature::CodeModeOnly)
.expect("test config should allow feature update");
config.chatgpt_base_url = apps_base_url;
config.model = Some("gpt-5-codex".to_string());
let mut model_catalog = bundled_models_response()
.unwrap_or_else(|err| panic!("bundled models.json should parse: {err}"));
let model = model_catalog
.models
.iter_mut()
.find(|model| model.slug == "gpt-5-codex")
.expect("gpt-5-codex exists in bundled models.json");
.find(|model| model.slug == "gpt-5.4")
.expect("gpt-5.4 exists in bundled models.json");
config.chatgpt_base_url = apps_base_url;
config.model = Some("gpt-5.4".to_string());
model.supports_search_tool = true;
config.model_catalog = Some(model_catalog);
});
+2 -2
View File
@@ -62,7 +62,7 @@ async fn codex_delegate_forwards_exec_approval_and_proceeds_on_approval() {
// Build a conversation configured to require approvals so the delegate
// routes ExecApprovalRequest via the parent.
let mut builder = test_codex().with_model("gpt-5.1").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config.permissions.approval_policy = Constrained::allow_any(AskForApproval::OnRequest);
config.permissions.sandbox_policy =
Constrained::allow_any(SandboxPolicy::new_read_only_policy());
@@ -144,7 +144,7 @@ async fn codex_delegate_forwards_patch_approval_and_proceeds_on_decision() {
let server = start_mock_server().await;
mount_sse_sequence(&server, vec![sse1, sse2]).await;
let mut builder = test_codex().with_model("gpt-5.1").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config.permissions.approval_policy = Constrained::allow_any(AskForApproval::OnRequest);
// Use a restricted sandbox so patch approval is required
config.permissions.sandbox_policy =
@@ -25,7 +25,7 @@ fn collab_mode_with_mode_and_instructions(
CollaborationMode {
mode,
settings: Settings {
model: "gpt-5.1".to_string(),
model: "gpt-5.4".to_string(),
reasoning_effort: None,
developer_instructions: instructions.map(str::to_string),
},
+6 -6
View File
@@ -1711,8 +1711,8 @@ async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() {
skip_if_no_network!();
let server = MockServer::start().await;
let previous_model = "gpt-5.2-codex";
let next_model = "gpt-5.1-codex-max";
let previous_model = "gpt-5.3-codex";
let next_model = "gpt-5.2";
let models_mock = mount_models_once(
&server,
@@ -1837,8 +1837,8 @@ async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() {
skip_if_no_network!();
let server = MockServer::start().await;
let previous_model = "gpt-5.2-codex";
let next_model = "gpt-5.1-codex-max";
let previous_model = "gpt-5.3-codex";
let next_model = "gpt-5.2";
let models_mock = mount_models_once(
&server,
@@ -3124,8 +3124,8 @@ async fn snapshot_request_shape_pre_turn_compaction_strips_incoming_model_switch
skip_if_no_network!();
let server = start_mock_server().await;
let previous_model = "gpt-5.1-codex-max";
let next_model = "gpt-5.2-codex";
let previous_model = "gpt-5.4";
let next_model = "gpt-5.3-codex";
let request_log = mount_sse_sequence(
&server,
+2 -2
View File
@@ -2130,8 +2130,8 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_strips_incoming_model
-> Result<()> {
skip_if_no_network!(Ok(()));
let previous_model = "gpt-5.1-codex-max";
let next_model = "gpt-5.2-codex";
let previous_model = "gpt-5.4";
let next_model = "gpt-5.3-codex";
let harness = TestCodexHarness::with_builder(
test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
@@ -158,7 +158,7 @@ async fn compact_resume_and_fork_preserve_model_history_view() {
// 1. Arrange mocked SSE responses for the initial compact/resume/fork flow.
let server = MockServer::start().await;
let request_log = mount_initial_flow(&server).await;
let expected_model = "gpt-5.1-codex";
let expected_model = "gpt-5.4";
// 2. Start a new conversation and drive it through the compact/resume/fork steps.
let (_home, config, manager, base) =
start_test_conversation(&server, Some(expected_model)).await;
@@ -538,7 +538,7 @@ async fn snapshot_rollback_followup_turn_trims_context_updates() -> Result<()> {
return Ok(());
}
const MODEL: &str = "gpt-5.1-codex";
const MODEL: &str = "gpt-5.4";
const TURN_ONE_USER: &str = "turn 1 user";
const TURN_TWO_USER: &str = "turn 2 user";
const FOLLOWUP_USER: &str = "follow-up user";
+4 -4
View File
@@ -168,7 +168,7 @@ async fn execpolicy_blocks_shell_invocation() -> Result<()> {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn shell_command_empty_script_with_collaboration_mode_does_not_panic() -> Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config
.features
.enable(Feature::CollaborationModes)
@@ -223,7 +223,7 @@ async fn shell_command_empty_script_with_collaboration_mode_does_not_panic() ->
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn unified_exec_empty_script_with_collaboration_mode_does_not_panic() -> Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config
.features
.enable(Feature::UnifiedExec)
@@ -282,7 +282,7 @@ async fn unified_exec_empty_script_with_collaboration_mode_does_not_panic() -> R
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn shell_command_whitespace_script_with_collaboration_mode_does_not_panic() -> Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config
.features
.enable(Feature::CollaborationModes)
@@ -337,7 +337,7 @@ async fn shell_command_whitespace_script_with_collaboration_mode_does_not_panic(
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn unified_exec_whitespace_script_with_collaboration_mode_does_not_panic() -> Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config
.features
.enable(Feature::UnifiedExec)
+1 -1
View File
@@ -1018,7 +1018,7 @@ async fn blocked_queued_prompt_does_not_strand_earlier_accepted_prompt() -> Resu
start_streaming_sse_server(vec![first_chunks, second_chunks]).await;
let mut builder = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.with_pre_build_hook(|home| {
if let Err(error) =
write_user_prompt_submit_hook(home, "blocked queued prompt", BLOCKED_PROMPT_CONTEXT)
+2 -2
View File
@@ -30,12 +30,12 @@ const SCHEMA: &str = r#"
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn codex_returns_json_result_for_gpt5() -> anyhow::Result<()> {
codex_returns_json_result("gpt-5.1".to_string()).await
codex_returns_json_result("gpt-5.4".to_string()).await
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn codex_returns_json_result_for_gpt5_codex() -> anyhow::Result<()> {
codex_returns_json_result("gpt-5.1-codex".to_string()).await
codex_returns_json_result("gpt-5.4".to_string()).await
}
async fn codex_returns_json_result(model: String) -> anyhow::Result<()> {
+3 -3
View File
@@ -115,9 +115,9 @@ async fn model_change_appends_model_instructions_developer_message() -> Result<(
)
.await;
let mut builder = test_codex().with_model("gpt-5.2-codex");
let mut builder = test_codex().with_model("gpt-5.3-codex");
let test = builder.build(&server).await?;
let next_model = "gpt-5.1-codex-max";
let next_model = "gpt-5.4";
test.codex
.submit(Op::UserTurn {
@@ -206,7 +206,7 @@ async fn model_and_personality_change_only_appends_model_instructions() -> Resul
.await;
let mut builder = test_codex()
.with_model("gpt-5.2-codex")
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
@@ -100,7 +100,7 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> {
.await;
let mut builder = test_codex()
.with_model("gpt-5.2-codex")
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
@@ -200,7 +200,7 @@ async fn snapshot_model_visible_layout_cwd_change_does_not_refresh_agents() -> R
)
.await;
let mut builder = test_codex().with_model("gpt-5.2-codex");
let mut builder = test_codex().with_model("gpt-5.3-codex");
let test = builder.build(&server).await?;
let cwd_one = test.cwd_path().join("agents_one");
let cwd_two = test.cwd_path().join("agents_two");
@@ -339,7 +339,7 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul
.await;
let mut resume_builder = test_codex().with_config(|config| {
config.model = Some("gpt-5.2-codex".to_string());
config.model = Some("gpt-5.3-codex".to_string());
config
.features
.enable(Feature::Personality)
@@ -439,7 +439,7 @@ async fn snapshot_model_visible_layout_resume_override_matches_rollout_model() -
.await;
let mut resume_builder = test_codex().with_config(|config| {
config.model = Some("gpt-5.2-codex".to_string());
config.model = Some("gpt-5.3-codex".to_string());
});
let resumed = resume_builder.resume(&server, home, rollout_path).await?;
let resume_override_cwd = resumed.cwd_path().join(PRETURN_CONTEXT_DIFF_CWD);
@@ -57,7 +57,7 @@ async fn renews_cache_ttl_on_matching_models_etag() -> Result<()> {
let mut builder = test_codex().with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing());
builder = builder.with_config(|config| {
config.model = Some("gpt-5".to_string());
config.model = Some("gpt-5.2".to_string());
config.model_provider.request_max_retries = Some(0);
config.model_provider.stream_max_retries = Some(1);
});
@@ -46,7 +46,7 @@ async fn refresh_models_on_models_etag_mismatch_and_avoid_duplicate_models_fetch
let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing();
let mut builder = test_codex()
.with_auth(auth)
.with_model("gpt-5")
.with_model("gpt-5.2")
.with_config(|config| {
// Keep this test deterministic: no request retries, and a small stream retry budget.
config.model_provider.request_max_retries = Some(0);
@@ -26,7 +26,7 @@ fn collab_mode_with_instructions(instructions: Option<&str>) -> CollaborationMod
CollaborationMode {
mode: ModeKind::Default,
settings: Settings {
model: "gpt-5.1".to_string(),
model: "gpt-5.4".to_string(),
reasoning_effort: None,
developer_instructions: instructions.map(str::to_string),
},
+5 -5
View File
@@ -85,7 +85,7 @@ fn response_completed_chunks(response_id: &str) -> Vec<StreamingSseChunk> {
async fn build_codex(server: &StreamingSseServer) -> Arc<CodexThread> {
test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.build_with_streaming_server(server)
.await
.unwrap_or_else(|err| panic!("build streaming Codex test session: {err}"))
@@ -264,7 +264,7 @@ async fn injected_user_input_triggers_follow_up_request_with_deltas() {
start_streaming_sse_server(vec![first_chunks, second_chunks]).await;
let codex = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.build_with_streaming_server(&server)
.await
.unwrap()
@@ -530,7 +530,7 @@ async fn steered_user_input_waits_for_model_continuation_after_mid_turn_compact(
.await;
let codex = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.with_config(|config| {
config.model_provider.name = "OpenAI (test)".to_string();
config.model_provider.supports_websockets = false;
@@ -617,7 +617,7 @@ async fn steered_user_input_follows_compact_when_only_the_steer_needs_follow_up(
.await;
let codex = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.with_config(|config| {
config.model_provider.name = "OpenAI (test)".to_string();
config.model_provider.supports_websockets = false;
@@ -724,7 +724,7 @@ async fn steered_user_input_waits_when_tool_output_triggers_compact_before_next_
.await;
let test = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.with_config(|config| {
config.model_provider.name = "OpenAI (test)".to_string();
config.model_provider.supports_websockets = false;
+8 -8
View File
@@ -50,7 +50,7 @@ async fn personality_does_not_mutate_base_instructions_without_template() {
.expect("test config should allow feature update");
config.personality = Some(Personality::Friendly);
let model_info = codex_core::test_support::construct_model_info_offline("gpt-5.1", &config);
let model_info = codex_core::test_support::construct_model_info_offline("gpt-5.4", &config);
assert_eq!(
model_info.get_model_instructions(config.personality),
model_info.base_instructions
@@ -69,7 +69,7 @@ async fn base_instructions_override_disables_personality_template() {
config.base_instructions = Some("override instructions".to_string());
let model_info =
codex_core::test_support::construct_model_info_offline("gpt-5.2-codex", &config);
codex_core::test_support::construct_model_info_offline("gpt-5.3-codex", &config);
assert_eq!(model_info.base_instructions, "override instructions");
assert_eq!(
@@ -85,7 +85,7 @@ async fn user_turn_personality_none_does_not_add_update_message() -> anyhow::Res
let server = start_mock_server().await;
let resp_mock = mount_sse_once(&server, sse_completed("resp-1")).await;
let mut builder = test_codex()
.with_model("gpt-5.2-codex")
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
@@ -135,7 +135,7 @@ async fn config_personality_some_sets_instructions_template() -> anyhow::Result<
let server = start_mock_server().await;
let resp_mock = mount_sse_once(&server, sse_completed("resp-1")).await;
let mut builder = test_codex()
.with_model("gpt-5.2-codex")
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
@@ -193,7 +193,7 @@ async fn config_personality_none_sends_no_personality() -> anyhow::Result<()> {
let server = start_mock_server().await;
let resp_mock = mount_sse_once(&server, sse_completed("resp-1")).await;
let mut builder = test_codex()
.with_model("gpt-5.2-codex")
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
@@ -258,7 +258,7 @@ async fn default_personality_is_pragmatic_without_config_toml() -> anyhow::Resul
let server = start_mock_server().await;
let resp_mock = mount_sse_once(&server, sse_completed("resp-1")).await;
let mut builder = test_codex()
.with_model("gpt-5.2-codex")
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
@@ -513,7 +513,7 @@ async fn instructions_uses_base_if_feature_disabled() -> anyhow::Result<()> {
config.personality = Some(Personality::Friendly);
let model_info =
codex_core::test_support::construct_model_info_offline("gpt-5.2-codex", &config);
codex_core::test_support::construct_model_info_offline("gpt-5.3-codex", &config);
assert_eq!(
model_info.get_model_instructions(config.personality),
model_info.base_instructions
@@ -814,7 +814,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() -
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.model = Some("gpt-5.2-codex".to_string());
config.model = Some("gpt-5.3-codex".to_string());
});
let test = builder.build(&server).await?;
@@ -191,14 +191,14 @@ async fn no_marker_sessions_sets_personality() -> io::Result<()> {
async fn no_marker_sessions_preserves_existing_config_fields() -> io::Result<()> {
let temp = TempDir::new()?;
write_session_with_user_event(temp.path()).await?;
tokio::fs::write(temp.path().join("config.toml"), "model = \"gpt-5-codex\"\n").await?;
tokio::fs::write(temp.path().join("config.toml"), "model = \"gpt-5.4\"\n").await?;
let config_toml = read_config_toml(temp.path()).await?;
let status = maybe_migrate_personality(temp.path(), &config_toml).await?;
assert_eq!(status, PersonalityMigrationStatus::Applied);
let persisted = read_config_toml(temp.path()).await?;
assert_eq!(persisted.model, Some("gpt-5-codex".to_string()));
assert_eq!(persisted.model, Some("gpt-5.4".to_string()));
assert_eq!(persisted.personality, Some(Personality::Pragmatic));
Ok(())
}
+2 -2
View File
@@ -118,7 +118,7 @@ async fn build_analytics_plugin_test_codex(
let mut builder = test_codex()
.with_home(codex_home)
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_model("gpt-5")
.with_model("gpt-5.2")
.with_config(move |config| {
config.chatgpt_base_url = chatgpt_base_url;
});
@@ -396,7 +396,7 @@ async fn explicit_plugin_mentions_track_plugin_used_analytics() -> Result<()> {
event["event_params"]["product_client_id"],
serde_json::json!(codex_login::default_client::originator().value)
);
assert_eq!(event["event_params"]["model_slug"], "gpt-5");
assert_eq!(event["event_params"]["model_slug"], "gpt-5.2");
assert!(event["event_params"]["thread_id"].as_str().is_some());
assert!(event["event_params"]["turn_id"].as_str().is_some());
+5 -5
View File
@@ -119,7 +119,7 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> {
} = test_codex()
.with_config(|config| {
config.user_instructions = Some("be consistent and helpful".to_string());
config.model = Some("gpt-5.1-codex-max".to_string());
config.model = Some("gpt-5.2".to_string());
// Keep tool expectations stable when the default web_search mode changes.
config
.web_search_mode
@@ -237,7 +237,7 @@ async fn gpt_5_tools_without_apply_patch_append_apply_patch_instructions() -> an
.features
.enable(Feature::CollaborationModes)
.expect("test config should allow feature update");
config.model = Some("gpt-5".to_string());
config.model = Some("gpt-5.2".to_string());
})
.build(&server)
.await?;
@@ -509,7 +509,7 @@ async fn override_before_first_turn_emits_environment_context() -> anyhow::Resul
let collaboration_mode = CollaborationMode {
mode: ModeKind::Default,
settings: Settings {
model: "gpt-5.1".to_string(),
model: "gpt-5.4".to_string(),
reasoning_effort: Some(ReasoningEffort::High),
developer_instructions: None,
},
@@ -522,7 +522,7 @@ async fn override_before_first_turn_emits_environment_context() -> anyhow::Resul
approvals_reviewer: None,
sandbox_policy: None,
windows_sandbox_level: None,
model: Some("gpt-5.1-codex".to_string()),
model: Some("gpt-5.4".to_string()),
effort: Some(Some(ReasoningEffort::Low)),
summary: None,
service_tier: None,
@@ -545,7 +545,7 @@ async fn override_before_first_turn_emits_environment_context() -> anyhow::Resul
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
let body = req.single_request().body_json();
assert_eq!(body["model"].as_str(), Some("gpt-5.1"));
assert_eq!(body["model"].as_str(), Some("gpt-5.4"));
assert_eq!(
body.get("reasoning")
.and_then(|reasoning| reasoning.get("effort"))
@@ -2833,7 +2833,7 @@ async fn delegated_turn_user_role_echo_does_not_redelegate_and_still_forwards_au
]])
.await;
let mut builder = test_codex().with_model("gpt-5.1").with_config({
let mut builder = test_codex().with_model("gpt-5.4").with_config({
let realtime_base_url = realtime_server.uri().to_string();
move |config| {
config.experimental_realtime_ws_base_url = Some(realtime_base_url);
@@ -2979,7 +2979,7 @@ async fn inbound_handoff_request_does_not_block_realtime_event_forwarding() -> R
]]])
.await;
let mut builder = test_codex().with_model("gpt-5.1").with_config({
let mut builder = test_codex().with_model("gpt-5.4").with_config({
let realtime_base_url = realtime_server.uri().to_string();
move |config| {
config.experimental_realtime_ws_base_url = Some(realtime_base_url);
@@ -3110,7 +3110,7 @@ async fn inbound_handoff_request_steers_active_turn() -> Result<()> {
]])
.await;
let mut builder = test_codex().with_model("gpt-5.1").with_config({
let mut builder = test_codex().with_model("gpt-5.4").with_config({
let realtime_base_url = realtime_server.uri().to_string();
move |config| {
config.experimental_realtime_ws_base_url = Some(realtime_base_url);
@@ -3260,7 +3260,7 @@ async fn inbound_handoff_request_starts_turn_and_does_not_block_realtime_audio()
]]])
.await;
let mut builder = test_codex().with_model("gpt-5.1").with_config({
let mut builder = test_codex().with_model("gpt-5.4").with_config({
let realtime_base_url = realtime_server.uri().to_string();
move |config| {
config.experimental_realtime_ws_base_url = Some(realtime_base_url);
+5 -5
View File
@@ -556,7 +556,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> {
let mut builder = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config.model = Some("gpt-5.1".to_string());
config.model = Some("gpt-5.4".to_string());
});
let TestCodex {
codex,
@@ -680,7 +680,7 @@ async fn remote_models_truncation_policy_without_override_preserves_remote() ->
let mut builder = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config.model = Some("gpt-5.1".to_string());
config.model = Some("gpt-5.4".to_string());
});
let test = builder.build(&server).await?;
@@ -726,7 +726,7 @@ async fn remote_models_truncation_policy_with_tool_output_override() -> Result<(
let mut builder = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config.model = Some("gpt-5.1".to_string());
config.model = Some("gpt-5.4".to_string());
config.tool_output_token_limit = Some(50);
});
let test = builder.build(&server).await?;
@@ -815,7 +815,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> {
let mut builder = test_codex()
.with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config.model = Some("gpt-5.1".to_string());
config.model = Some("gpt-5.2".to_string());
});
let TestCodex {
codex,
@@ -867,7 +867,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> {
wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await;
let base_model_info = models_manager
.get_model_info("gpt-5.1", &config.to_models_manager_config())
.get_model_info("gpt-5.2", &config.to_models_manager_config())
.await;
let body = response_mock.single_request().body_json();
let instructions = body["instructions"].as_str().unwrap();
+3 -3
View File
@@ -297,7 +297,7 @@ async fn resume_switches_models_preserves_base_instructions() -> Result<()> {
.await;
let mut resume_builder = test_codex().with_config(|config| {
config.model = Some("gpt-5.2-codex".to_string());
config.model = Some("gpt-5.3-codex".to_string());
});
let resumed = resume_builder.resume(&server, home, rollout_path).await?;
resumed
@@ -412,7 +412,7 @@ async fn resume_model_switch_is_not_duplicated_after_pre_turn_override() -> Resu
.await;
let mut resume_builder = test_codex().with_config(|config| {
config.model = Some("gpt-5.2-codex".to_string());
config.model = Some("gpt-5.3-codex".to_string());
});
let resumed = resume_builder.resume(&server, home, rollout_path).await?;
resumed
@@ -423,7 +423,7 @@ async fn resume_model_switch_is_not_duplicated_after_pre_turn_override() -> Resu
approvals_reviewer: None,
sandbox_policy: None,
windows_sandbox_level: None,
model: Some("gpt-5.1-codex-max".to_string()),
model: Some("gpt-5.4".to_string()),
effort: None,
summary: None,
service_tier: None,
+2 -2
View File
@@ -400,7 +400,7 @@ async fn review_uses_custom_review_model_from_config() {
// Choose a review model different from the main model; ensure it is used.
let codex = new_conversation_for_server(&server, codex_home.clone(), |cfg| {
cfg.model = Some("gpt-4.1".to_string());
cfg.review_model = Some("gpt-5.1".to_string());
cfg.review_model = Some("gpt-5.4".to_string());
})
.await;
@@ -433,7 +433,7 @@ async fn review_uses_custom_review_model_from_config() {
let request = request_log.single_request();
assert_eq!(request.path(), "/v1/responses");
let body = request.body_json();
assert_eq!(body["model"].as_str().unwrap(), "gpt-5.1");
assert_eq!(body["model"].as_str().unwrap(), "gpt-5.4");
let _codex_home_guard = codex_home;
server.verify().await;
+3 -4
View File
@@ -99,15 +99,14 @@ fn tool_search_output_tools(request: &ResponsesRequest, call_id: &str) -> Vec<Va
}
fn configure_search_capable_model(config: &mut Config) {
config.model = Some("gpt-5-codex".to_string());
let mut model_catalog = bundled_models_response()
.unwrap_or_else(|err| panic!("bundled models.json should parse: {err}"));
let model = model_catalog
.models
.iter_mut()
.find(|model| model.slug == "gpt-5-codex")
.expect("gpt-5-codex exists in bundled models.json");
.find(|model| model.slug == "gpt-5.4")
.expect("gpt-5.4 exists in bundled models.json");
config.model = Some("gpt-5.4".to_string());
model.supports_search_tool = true;
config.model_catalog = Some(model_catalog);
}
+7 -7
View File
@@ -109,7 +109,7 @@ fn assert_shell_command_output(output: &str, expected: &str) -> Result<()> {
async fn shell_command_works() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let call_id = "shell-command-call";
mount_shell_responses(
@@ -131,7 +131,7 @@ async fn shell_command_works() -> anyhow::Result<()> {
async fn output_with_login() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let call_id = "shell-command-call-login-true";
mount_shell_responses(&harness, call_id, "echo 'hello, world'", Some(true)).await;
@@ -147,7 +147,7 @@ async fn output_with_login() -> anyhow::Result<()> {
async fn output_without_login() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let call_id = "shell-command-call-login-false";
mount_shell_responses(&harness, call_id, "echo 'hello, world'", Some(false)).await;
@@ -163,7 +163,7 @@ async fn output_without_login() -> anyhow::Result<()> {
async fn multi_line_output_with_login() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let call_id = "shell-command-call-first-extra-login";
mount_shell_responses(
@@ -186,7 +186,7 @@ async fn pipe_output_with_login() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
skip_if_windows!(Ok(()));
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let call_id = "shell-command-call-second-extra-no-login";
mount_shell_responses(
@@ -209,7 +209,7 @@ async fn pipe_output_without_login() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
skip_if_windows!(Ok(()));
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let call_id = "shell-command-call-third-extra-login-false";
mount_shell_responses(&harness, call_id, "echo 'hello, world' | cat", Some(false)).await;
@@ -225,7 +225,7 @@ async fn pipe_output_without_login() -> anyhow::Result<()> {
async fn shell_command_times_out_with_timeout_ms() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.1")).await?;
let harness = shell_command_harness_with(|builder| builder.with_model("gpt-5.4")).await?;
let call_id = "shell-command-timeout";
let command = if cfg!(windows) {
"timeout /t 5"
@@ -105,10 +105,10 @@ fn configure_shell_model(
) -> TestCodexBuilder {
let builder = match (output_type, include_apply_patch_tool) {
(ShellModelOutput::ShellCommand, _) => builder.with_model("test-gpt-5-codex"),
(ShellModelOutput::LocalShell, true) => builder.with_model("gpt-5.1-codex"),
(ShellModelOutput::Shell, true) => builder.with_model("gpt-5.1-codex"),
(ShellModelOutput::LocalShell, false) => builder.with_model("codex-mini-latest"),
(ShellModelOutput::Shell, false) => builder.with_model("gpt-5"),
(ShellModelOutput::LocalShell, true) => builder.with_model("gpt-5.4"),
(ShellModelOutput::Shell, true) => builder.with_model("gpt-5.4"),
(ShellModelOutput::LocalShell, false) => builder.with_model("test-local-shell-json"),
(ShellModelOutput::Shell, false) => builder.with_model("test-shell-json"),
};
builder.with_config(move |config| {
@@ -717,7 +717,7 @@ async fn shell_output_is_structured_for_nonzero_exit(output_type: ShellModelOutp
let server = start_mock_server().await;
let mut builder = test_codex()
.with_model("gpt-5.1-codex")
.with_model("gpt-5.4")
.with_config(move |config| {
config.include_apply_patch_tool = true;
});
@@ -808,7 +808,7 @@ async fn shell_command_output_is_not_truncated_under_10k_bytes() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5.1");
let mut builder = test_codex().with_model("gpt-5.4");
let test = builder.build(&server).await?;
let call_id = "shell-command";
@@ -859,7 +859,7 @@ async fn shell_command_output_is_not_truncated_over_10k_bytes() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5.1");
let mut builder = test_codex().with_model("gpt-5.2");
let test = builder.build(&server).await?;
let call_id = "shell-command";
@@ -910,11 +910,9 @@ async fn local_shell_call_output_is_structured() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex()
.with_model("gpt-5.1-codex")
.with_config(|config| {
config.include_apply_patch_tool = true;
});
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config.include_apply_patch_tool = true;
});
let test = builder.build(&server).await?;
let call_id = "local-shell-call";
@@ -31,11 +31,11 @@ const TURN_0_FORK_PROMPT: &str = "seed fork context";
const TURN_1_PROMPT: &str = "spawn a child and continue";
const TURN_2_NO_WAIT_PROMPT: &str = "follow up without wait";
const CHILD_PROMPT: &str = "child: do work";
const INHERITED_MODEL: &str = "gpt-5.2-codex";
const INHERITED_MODEL: &str = "gpt-5.3-codex";
const INHERITED_REASONING_EFFORT: ReasoningEffort = ReasoningEffort::XHigh;
const REQUESTED_MODEL: &str = "gpt-5.1";
const REQUESTED_MODEL: &str = "gpt-5.4";
const REQUESTED_REASONING_EFFORT: ReasoningEffort = ReasoningEffort::Low;
const ROLE_MODEL: &str = "gpt-5.1-codex-max";
const ROLE_MODEL: &str = "gpt-5.4";
const ROLE_REASONING_EFFORT: ReasoningEffort = ReasoningEffort::High;
const SPAWNED_AGENT_DEVELOPER_INSTRUCTIONS: &str = "You are a newly spawned agent in a team of agents collaborating to complete a task. You can spawn sub-agents to handle subtasks, and those sub-agents can spawn their own sub-agents. You are responsible for returning the response to your assigned task in the final channel. When you give your response, the contents of your response in the final channel will be immediately delivered back to your parent agent. The prior conversation history was forked from your parent agent. Treat the next user message as your assigned task, and use the forked history only as background context.";
@@ -701,7 +701,7 @@ async fn spawn_agent_tool_description_mentions_role_locked_settings() -> Result<
role_block(&agent_type_description, "custom").expect("custom role description");
assert_eq!(
custom_role_description,
"custom: {\nCustom role\n- This role's model is set to `gpt-5.1-codex-max` and its reasoning effort is set to `high`. These settings cannot be changed.\n}"
"custom: {\nCustom role\n- This role's model is set to `gpt-5.4` and its reasoning effort is set to `high`. These settings cannot be changed.\n}"
);
Ok(())
+1 -1
View File
@@ -51,7 +51,7 @@ async fn shell_tool_executes_command_and_streams_output() -> anyhow::Result<()>
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5");
let mut builder = test_codex().with_model("test-local-shell-json");
let TestCodex {
codex,
cwd,
@@ -145,7 +145,7 @@ async fn shell_tools_run_in_parallel() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5.1");
let mut builder = test_codex().with_model("gpt-5.4");
let test = builder.build(&server).await?;
let shell_args = json!({
@@ -344,7 +344,7 @@ async fn shell_tools_start_before_response_completed_when_stream_delayed() -> an
])
.await;
let mut builder = test_codex().with_model("gpt-5.1");
let mut builder = test_codex().with_model("gpt-5.4");
let test = builder
.build_with_streaming_server(&streaming_server)
.await?;
+8 -9
View File
@@ -71,20 +71,19 @@ fn configure_apps_without_search_tool(config: &mut Config, apps_base_url: &str)
.features
.enable(Feature::ToolSuggest)
.expect("test config should allow feature update");
config.chatgpt_base_url = apps_base_url.to_string();
config.model = Some("gpt-5-codex".to_string());
config.tool_suggest.discoverables = vec![ToolSuggestDiscoverable {
kind: ToolSuggestDiscoverableType::Connector,
id: DISCOVERABLE_GMAIL_ID.to_string(),
}];
let mut model_catalog = bundled_models_response()
.unwrap_or_else(|err| panic!("bundled models.json should parse: {err}"));
let model = model_catalog
.models
.iter_mut()
.find(|model| model.slug == "gpt-5-codex")
.expect("gpt-5-codex exists in bundled models.json");
.find(|model| model.slug == "gpt-5.4")
.expect("gpt-5.4 exists in bundled models.json");
config.chatgpt_base_url = apps_base_url.to_string();
config.model = Some("gpt-5.4".to_string());
config.tool_suggest.discoverables = vec![ToolSuggestDiscoverable {
kind: ToolSuggestDiscoverableType::Connector,
id: DISCOVERABLE_GMAIL_ID.to_string(),
}];
model.supports_search_tool = false;
config.model_catalog = Some(model_catalog);
}
+7 -7
View File
@@ -143,7 +143,7 @@ async fn historical_unavailable_mcp_call_is_exposed_as_placeholder_tool() -> Res
};
let codex_home = Arc::new(TempDir::new()?);
let mut builder = test_codex()
.with_model("gpt-5.1")
.with_model("gpt-5.4")
.with_home(Arc::clone(&codex_home))
.with_config(move |config| {
config
@@ -232,7 +232,7 @@ async fn historical_unavailable_mcp_call_is_exposed_as_placeholder_tool() -> Res
)
.await;
let mut resume_builder = test_codex().with_model("gpt-5.1").with_config(|config| {
let mut resume_builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config
.features
.enable(Feature::UnavailableDummyTools)
@@ -270,7 +270,7 @@ async fn shell_escalated_permissions_rejected_then_ok() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5");
let mut builder = test_codex().with_model("test-shell-json");
let test = builder.build(&server).await?;
let command = ["/bin/echo", "shell ok"];
@@ -367,7 +367,7 @@ async fn sandbox_denied_shell_returns_original_output() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5.1-codex");
let mut builder = test_codex().with_model("gpt-5.4");
let fixture = builder.build(&server).await?;
let call_id = "sandbox-denied-shell";
@@ -464,7 +464,7 @@ async fn shell_enforces_glob_deny_read_policy() -> Result<()> {
let read_only_policy = SandboxPolicy::new_read_only_policy();
let read_only_policy_for_config = read_only_policy.clone();
let mut builder = test_codex()
.with_model("gpt-5.1-codex")
.with_model("gpt-5.4")
.with_config(move |config| {
config.permissions.sandbox_policy = Constrained::allow_any(read_only_policy_for_config);
let mut file_system_sandbox_policy = FileSystemSandboxPolicy::default();
@@ -626,7 +626,7 @@ async fn shell_timeout_includes_timeout_prefix_and_metadata() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5");
let mut builder = test_codex().with_model("test-shell-json");
let test = builder.build(&server).await?;
let call_id = "shell-timeout";
@@ -697,7 +697,7 @@ async fn shell_timeout_handles_background_grandchild_stdout() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5.1").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config
.permissions
.sandbox_policy
+11 -15
View File
@@ -45,7 +45,7 @@ async fn tool_call_output_configured_limit_chars_type() -> Result<()> {
let server = start_mock_server().await;
// Use a model that exposes the shell_command tool.
let mut builder = test_codex().with_model("gpt-5.1").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config.tool_output_token_limit = Some(100_000);
});
@@ -121,7 +121,7 @@ async fn tool_call_output_exceeds_limit_truncated_chars_limit() -> Result<()> {
let server = start_mock_server().await;
// Use a model that exposes the shell_command tool.
let mut builder = test_codex().with_model("gpt-5.1");
let mut builder = test_codex().with_model("gpt-5.2");
let fixture = builder.build(&server).await?;
@@ -195,7 +195,7 @@ async fn tool_call_output_exceeds_limit_truncated_for_model() -> Result<()> {
let server = start_mock_server().await;
// Use a model that exposes the shell_command tool.
let mut builder = test_codex().with_model("gpt-5.1-codex");
let mut builder = test_codex().with_model("gpt-5.4");
let fixture = builder.build(&server).await?;
let call_id = "shell-too-large";
@@ -271,7 +271,7 @@ async fn tool_call_output_truncated_only_once() -> Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5.1-codex");
let mut builder = test_codex().with_model("gpt-5.4");
let fixture = builder.build(&server).await?;
let call_id = "shell-single-truncation";
let command = if cfg!(windows) {
@@ -545,11 +545,9 @@ async fn token_policy_marker_reports_tokens() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex()
.with_model("gpt-5.1-codex")
.with_config(|config| {
config.tool_output_token_limit = Some(50); // small budget to force truncation
});
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config.tool_output_token_limit = Some(50); // small budget to force truncation
});
let fixture = builder.build(&server).await?;
let call_id = "shell-token-marker";
@@ -598,7 +596,7 @@ async fn byte_policy_marker_reports_bytes() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5.1").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config.tool_output_token_limit = Some(50); // ~200 byte cap
});
let fixture = builder.build(&server).await?;
@@ -649,11 +647,9 @@ async fn shell_command_output_not_truncated_with_custom_limit() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let mut builder = test_codex()
.with_model("gpt-5.1-codex")
.with_config(|config| {
config.tool_output_token_limit = Some(50_000); // ample budget
});
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config.tool_output_token_limit = Some(50_000); // ample budget
});
let fixture = builder.build(&server).await?;
let call_id = "shell-no-trunc";
+1 -1
View File
@@ -27,7 +27,7 @@ use pretty_assertions::assert_eq;
#[allow(clippy::expect_used)]
async fn undo_harness() -> Result<TestCodexHarness> {
let builder = test_codex().with_model("gpt-5.1").with_config(|config| {
let builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config.include_apply_patch_tool = true;
config
.features
+3 -3
View File
@@ -345,7 +345,7 @@ async fn unified_exec_emits_exec_command_begin_event() -> Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config.use_experimental_unified_exec_tool = true;
config
.features
@@ -404,7 +404,7 @@ async fn unified_exec_resolves_relative_workdir() -> Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config.use_experimental_unified_exec_tool = true;
config
.features
@@ -473,7 +473,7 @@ async fn unified_exec_respects_workdir_override() -> Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5").with_config(|config| {
let mut builder = test_codex().with_model("gpt-5.2").with_config(|config| {
config.use_experimental_unified_exec_tool = true;
config
.features
+4 -6
View File
@@ -141,7 +141,7 @@ async fn user_shell_cmd_can_be_interrupted() {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn user_shell_command_does_not_replace_active_turn() -> anyhow::Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex().with_model("gpt-5.1");
let mut builder = test_codex().with_model("gpt-5.4");
let fixture = builder.build(&server).await?;
let call_id = "active-turn-shell-call";
@@ -439,11 +439,9 @@ async fn user_shell_command_is_truncated_only_once() -> anyhow::Result<()> {
let server = start_mock_server().await;
let mut builder = test_codex()
.with_model("gpt-5.1-codex")
.with_config(|config| {
config.tool_output_token_limit = Some(100);
});
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config.tool_output_token_limit = Some(100);
});
let fixture = builder.build(&server).await?;
let call_id = "user-shell-double-truncation";
+45 -53
View File
@@ -33,14 +33,12 @@ async fn web_search_mode_cached_sets_external_web_access_false() {
]);
let resp_mock = responses::mount_sse_once(&server, sse).await;
let mut builder = test_codex()
.with_model("gpt-5-codex")
.with_config(|config| {
config
.web_search_mode
.set(WebSearchMode::Cached)
.expect("test web_search_mode should satisfy constraints");
});
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config
.web_search_mode
.set(WebSearchMode::Cached)
.expect("test web_search_mode should satisfy constraints");
});
let test = builder
.build(&server)
.await
@@ -73,18 +71,16 @@ async fn web_search_mode_takes_precedence_over_legacy_flags() {
]);
let resp_mock = responses::mount_sse_once(&server, sse).await;
let mut builder = test_codex()
.with_model("gpt-5-codex")
.with_config(|config| {
config
.features
.enable(Feature::WebSearchRequest)
.expect("test config should allow feature update");
config
.web_search_mode
.set(WebSearchMode::Cached)
.expect("test web_search_mode should satisfy constraints");
});
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config
.features
.enable(Feature::WebSearchRequest)
.expect("test config should allow feature update");
config
.web_search_mode
.set(WebSearchMode::Cached)
.expect("test web_search_mode should satisfy constraints");
});
let test = builder
.build(&server)
.await
@@ -117,22 +113,20 @@ async fn web_search_mode_defaults_to_cached_when_features_disabled() {
]);
let resp_mock = responses::mount_sse_once(&server, sse).await;
let mut builder = test_codex()
.with_model("gpt-5-codex")
.with_config(|config| {
config
.web_search_mode
.set(WebSearchMode::Cached)
.expect("test web_search_mode should satisfy constraints");
config
.features
.disable(Feature::WebSearchCached)
.expect("test config should allow feature update");
config
.features
.disable(Feature::WebSearchRequest)
.expect("test config should allow feature update");
});
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config
.web_search_mode
.set(WebSearchMode::Cached)
.expect("test web_search_mode should satisfy constraints");
config
.features
.disable(Feature::WebSearchCached)
.expect("test config should allow feature update");
config
.features
.disable(Feature::WebSearchRequest)
.expect("test config should allow feature update");
});
let test = builder
.build(&server)
.await
@@ -174,22 +168,20 @@ async fn web_search_mode_updates_between_turns_with_sandbox_policy() {
)
.await;
let mut builder = test_codex()
.with_model("gpt-5-codex")
.with_config(|config| {
config
.web_search_mode
.set(WebSearchMode::Cached)
.expect("test web_search_mode should satisfy constraints");
config
.features
.disable(Feature::WebSearchCached)
.expect("test config should allow feature update");
config
.features
.disable(Feature::WebSearchRequest)
.expect("test config should allow feature update");
});
let mut builder = test_codex().with_model("gpt-5.4").with_config(|config| {
config
.web_search_mode
.set(WebSearchMode::Cached)
.expect("test web_search_mode should satisfy constraints");
config
.features
.disable(Feature::WebSearchCached)
.expect("test config should allow feature update");
config
.features
.disable(Feature::WebSearchRequest)
.expect("test config should allow feature update");
});
let test = builder
.build(&server)
.await
@@ -250,7 +242,7 @@ location = { country = "US", city = "New York", timezone = "America/New_York" }
)
.expect("write config.toml");
let mut builder = test_codex().with_model("gpt-5-codex").with_home(home);
let mut builder = test_codex().with_model("gpt-5.3-codex").with_home(home);
let test = builder
.build(&server)
.await
File diff suppressed because one or more lines are too long
@@ -21,7 +21,7 @@ async fn offline_model_info_without_tool_output_override() {
CollaborationModesConfig::default(),
);
let model_info = manager.get_model_info("gpt-5.1", &config).await;
let model_info = manager.get_model_info("gpt-5.2", &config).await;
assert_eq!(
model_info.truncation_policy,
@@ -45,7 +45,7 @@ async fn offline_model_info_with_tool_output_override() {
CollaborationModesConfig::default(),
);
let model_info = manager.get_model_info("gpt-5.1-codex", &config).await;
let model_info = manager.get_model_info("gpt-5.4", &config).await;
assert_eq!(
model_info.truncation_policy,
+1 -1
View File
@@ -471,7 +471,7 @@ fn is_standard_tool_call(parsed_cmd: &[ParsedCommand]) -> bool {
}
const RATE_LIMIT_WARNING_THRESHOLDS: [f64; 3] = [75.0, 90.0, 95.0];
const NUDGE_MODEL_SLUG: &str = "gpt-5.1-codex-mini";
const NUDGE_MODEL_SLUG: &str = "gpt-5.4-mini";
const RATE_LIMIT_SWITCH_PROMPT_THRESHOLD: f64 = 90.0;
#[derive(Default)]