From 5f8984aa7d550955eb5f894d5c29adc2b9901da2 Mon Sep 17 00:00:00 2001 From: Dylan Date: Mon, 11 Aug 2025 13:11:04 -0700 Subject: [PATCH] [apply-patch] Support applypatch command string (#2186) ## Summary GPT-OSS and `gpt-5-mini` have training artifacts that cause the models to occasionally use `applypatch` instead of `apply_patch`. I think long-term we'll want to provide `apply_patch` as a first class tool, but for now let's silently handle this case to avoid hurting model performance ## Testing - [x] Added unit test --- codex-rs/apply-patch/src/lib.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/codex-rs/apply-patch/src/lib.rs b/codex-rs/apply-patch/src/lib.rs index 61b1b68f..262d219d 100644 --- a/codex-rs/apply-patch/src/lib.rs +++ b/codex-rs/apply-patch/src/lib.rs @@ -82,8 +82,9 @@ pub struct ApplyPatchArgs { } pub fn maybe_parse_apply_patch(argv: &[String]) -> MaybeApplyPatch { + const APPLY_PATCH_COMMANDS: [&str; 2] = ["apply_patch", "applypatch"]; match argv { - [cmd, body] if cmd == "apply_patch" => match parse_patch(body) { + [cmd, body] if APPLY_PATCH_COMMANDS.contains(&cmd.as_str()) => match parse_patch(body) { Ok(source) => MaybeApplyPatch::Body(source), Err(e) => MaybeApplyPatch::PatchParseError(e), }, @@ -722,6 +723,31 @@ mod tests { } } + #[test] + fn test_literal_applypatch() { + let args = strs_to_strings(&[ + "applypatch", + r#"*** Begin Patch +*** Add File: foo ++hi +*** End Patch +"#, + ]); + + match maybe_parse_apply_patch(&args) { + MaybeApplyPatch::Body(ApplyPatchArgs { hunks, patch: _ }) => { + assert_eq!( + hunks, + vec![Hunk::AddFile { + path: PathBuf::from("foo"), + contents: "hi\n".to_string() + }] + ); + } + result => panic!("expected MaybeApplyPatch::Body got {result:?}"), + } + } + #[test] fn test_heredoc() { let args = strs_to_strings(&[