From 2f2b6774d3f00cf7d6ea9f01e50146c483ba7961 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 8 May 2026 10:14:45 +0300 Subject: [PATCH 1/5] Enable apply_patch freeform by default --- codex-rs/features/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codex-rs/features/src/lib.rs b/codex-rs/features/src/lib.rs index 6c8ce49894de..ec6c24004a25 100644 --- a/codex-rs/features/src/lib.rs +++ b/codex-rs/features/src/lib.rs @@ -819,7 +819,7 @@ pub const FEATURES: &[FeatureSpec] = &[ id: Feature::ApplyPatchFreeform, key: "apply_patch_freeform", stage: Stage::UnderDevelopment, - default_enabled: false, + default_enabled: true, }, FeatureSpec { id: Feature::ApplyPatchStreamingEvents, From b64fab69aa9cfd1e782d9fbb03b8245930edd896 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 8 May 2026 10:20:38 +0300 Subject: [PATCH 2/5] Mark apply_patch freeform as stable --- codex-rs/features/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codex-rs/features/src/lib.rs b/codex-rs/features/src/lib.rs index ec6c24004a25..721069a5bde7 100644 --- a/codex-rs/features/src/lib.rs +++ b/codex-rs/features/src/lib.rs @@ -818,7 +818,7 @@ pub const FEATURES: &[FeatureSpec] = &[ FeatureSpec { id: Feature::ApplyPatchFreeform, key: "apply_patch_freeform", - stage: Stage::UnderDevelopment, + stage: Stage::Stable, default_enabled: true, }, FeatureSpec { From 8e30ec84bd83eb2d4f9ca3089f14116b1f802dee Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 8 May 2026 10:56:36 +0300 Subject: [PATCH 3/5] codex: fix CI failure on PR #21687 --- codex-rs/core/src/config/config_tests.rs | 8 ++++---- codex-rs/features/src/tests.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/codex-rs/core/src/config/config_tests.rs b/codex-rs/core/src/config/config_tests.rs index 9b785ff3373f..2a12e5b16ede 100644 --- a/codex-rs/core/src/config/config_tests.rs +++ b/codex-rs/core/src/config/config_tests.rs @@ -7056,7 +7056,7 @@ async fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> { commit_attribution: None, forced_chatgpt_workspace_id: None, forced_login_method: None, - include_apply_patch_tool: false, + include_apply_patch_tool: true, web_search_mode: Constrained::allow_any(WebSearchMode::Cached), web_search_config: None, use_experimental_unified_exec_tool: !cfg!(windows), @@ -7315,7 +7315,7 @@ async fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> { commit_attribution: None, forced_chatgpt_workspace_id: None, forced_login_method: None, - include_apply_patch_tool: false, + include_apply_patch_tool: true, web_search_mode: Constrained::allow_any(WebSearchMode::Cached), web_search_config: None, use_experimental_unified_exec_tool: !cfg!(windows), @@ -7473,7 +7473,7 @@ async fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> { commit_attribution: None, forced_chatgpt_workspace_id: None, forced_login_method: None, - include_apply_patch_tool: false, + include_apply_patch_tool: true, web_search_mode: Constrained::allow_any(WebSearchMode::Cached), web_search_config: None, use_experimental_unified_exec_tool: !cfg!(windows), @@ -7616,7 +7616,7 @@ async fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> { commit_attribution: None, forced_chatgpt_workspace_id: None, forced_login_method: None, - include_apply_patch_tool: false, + include_apply_patch_tool: true, web_search_mode: Constrained::allow_any(WebSearchMode::Cached), web_search_config: None, use_experimental_unified_exec_tool: !cfg!(windows), diff --git a/codex-rs/features/src/tests.rs b/codex-rs/features/src/tests.rs index 5464fa7a61a4..55d2d8ba2790 100644 --- a/codex-rs/features/src/tests.rs +++ b/codex-rs/features/src/tests.rs @@ -578,7 +578,7 @@ fn materialize_resolved_enabled_writes_all_features_and_preserves_custom_config( FeatureConfigSource::default(), FeatureOverrides::default(), ); - assert_eq!(replayed.enabled(Feature::ApplyPatchFreeform), false); + assert_eq!(replayed.enabled(Feature::ApplyPatchFreeform), true); } #[test] From 0e53d9c8e33d0b697105bd93f4825b096cab74bf Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 8 May 2026 15:19:46 +0300 Subject: [PATCH 4/5] codex: fix CI failure on PR #21687 Co-authored-by: Codex --- codex-rs/core/tests/suite/tools.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/codex-rs/core/tests/suite/tools.rs b/codex-rs/core/tests/suite/tools.rs index b85607454061..7ba76eaa4d09 100644 --- a/codex-rs/core/tests/suite/tools.rs +++ b/codex-rs/core/tests/suite/tools.rs @@ -772,6 +772,20 @@ async fn shell_timeout_includes_timeout_prefix_and_metadata() -> Result<()> { "timeout output missing `command timed out`: {stdout}" ); } else { + let normalized_output = output_str + .replace("\r\n", "\n") + .replace('\r', "\n") + .trim_end_matches('\n') + .to_string(); + + let shell_output_pattern = r"(?s)^Exit code: 124\nWall time: [0-9]+(?:\.[0-9]+)? seconds\nOutput:\ncommand timed out after [0-9]+ milliseconds\n(?:.*)?$"; + if Regex::new(shell_output_pattern) + .expect("shell timeout output regex should compile") + .is_match(&normalized_output) + { + return Ok(()); + } + // Fallback: accept the signal classification path to deflake the test. let signal_pattern = r"(?is)^execution error:.*signal.*$"; assert_regex_match(signal_pattern, output_str); From 102cd4836a34565b57ca1842ebcd10479abe0848 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 8 May 2026 15:48:53 +0300 Subject: [PATCH 5/5] codex: fix CI failure on PR #21687 Co-authored-by: Codex --- codex-rs/tools/src/tool_config.rs | 2 +- codex-rs/tools/src/tool_config_tests.rs | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/codex-rs/tools/src/tool_config.rs b/codex-rs/tools/src/tool_config.rs index 0bb4b8b156f1..2ebf0540f784 100644 --- a/codex-rs/tools/src/tool_config.rs +++ b/codex-rs/tools/src/tool_config.rs @@ -222,7 +222,7 @@ impl ToolsConfig { let apply_patch_tool_type = match model_info.apply_patch_tool_type { Some(ApplyPatchToolType::Freeform) => Some(ApplyPatchToolType::Freeform), Some(ApplyPatchToolType::Function) => Some(ApplyPatchToolType::Function), - None => include_apply_patch_tool.then_some(ApplyPatchToolType::Freeform), + None => include_apply_patch_tool.then_some(ApplyPatchToolType::Function), }; let agent_jobs_worker_tools = include_agent_jobs diff --git a/codex-rs/tools/src/tool_config_tests.rs b/codex-rs/tools/src/tool_config_tests.rs index 34c871cac327..3d1829c4e554 100644 --- a/codex-rs/tools/src/tool_config_tests.rs +++ b/codex-rs/tools/src/tool_config_tests.rs @@ -4,6 +4,7 @@ use codex_features::Features; use codex_protocol::config_types::WebSearchMode; use codex_protocol::config_types::WindowsSandboxLevel; use codex_protocol::models::PermissionProfile; +use codex_protocol::openai_models::ApplyPatchToolType; use codex_protocol::openai_models::ConfigShellToolType; use codex_protocol::openai_models::InputModality; use codex_protocol::openai_models::ModelInfo; @@ -154,6 +155,29 @@ fn shell_zsh_fork_prefers_shell_command_over_unified_exec() { ); } +#[test] +fn fallback_apply_patch_models_use_function_tool_by_default() { + let model_info = model_info(); + let features = Features::with_defaults(); + + let available_models = Vec::new(); + let tools_config = ToolsConfig::new(&ToolsConfigParams { + model_info: &model_info, + available_models: &available_models, + features: &features, + image_generation_tool_auth_allowed: true, + web_search_mode: Some(WebSearchMode::Cached), + session_source: SessionSource::Cli, + permission_profile: &PermissionProfile::Disabled, + windows_sandbox_level: WindowsSandboxLevel::Disabled, + }); + + assert_eq!( + tools_config.apply_patch_tool_type, + Some(ApplyPatchToolType::Function) + ); +} + #[test] fn subagents_keep_request_user_input_config_and_agent_jobs_workers_opt_in_by_label() { let model_info = model_info();