Skip to content

[Compatibility] Nested tools.apply_patch still uses decorated Begin Patch delimiters in code mode #2367

Description

@ArcSolver

Client or integration

Codex App

Provider or upstream service

xai / grok-4.6 through OpenCodex 2.29.0 (@bitkyc08/opencodex)

OpenCodex version

2.29.0

Endpoint or capability

Codex Desktop code mode: top-level freeform exec -> nested tools.apply_patch(input: string)

Current behaviour

In a Codex Desktop side conversation, the only top-level tool is freeform exec. File edits go through the nested helper await tools.apply_patch(string).

A nested helper call whose first line is *** Begin Patch *** is rejected by Codex before any file is touched:

apply_patch verification failed: invalid patch: The first line of the patch must be '*** Begin Patch'

The same helper succeeds when the first line is exactly *** Begin Patch with no trailing ***.

This is not the {input:string} JSON wrapper. Passing a raw string that starts with *** Begin Patch works. Passing a decorated *** Begin Patch *** envelope fails even when the rest of the patch is valid.

OpenCodex 2.29.0 does not include src/responses/apply-patch-envelope.ts. Open PR #2310 repairs decorated envelopes for top-level apply_patch custom-tool payloads, and it correctly leaves exec JavaScript byte-identical. Nested tools.apply_patch(...) is host-executed by Codex from inside that JavaScript, so the decorated delimiter never reaches #2310's repair and still fails.

Expected behaviour

Code-mode catalog guidance should tell routed models that nested tools.apply_patch(input) is host-executed and must begin exactly with *** Begin Patch / *** End Patch, with no trailing *** on those lines.

OpenCodex should not rewrite JavaScript inside exec. The nested helper body is Codex-owned. The proxy can only teach the correct delimiter, or repair a top-level apply_patch custom-tool payload as #2310 does.

Minimal redacted request or reproduction

From a Codex Desktop code-mode turn whose catalog lists only exec:

await tools.apply_patch("*** Begin Patch ***\n*** End Patch ***\n");
// rejected: first line of the patch must be '*** Begin Patch'

await tools.apply_patch("*** Begin Patch\n*** End Patch\n");
// accepted by the verifier (empty-patch rejection is a later, unrelated check)

Actual response or error

apply_patch verification failed: invalid patch: The first line of the patch must be '*** Begin Patch'

Upstream documentation

Codex apply_patch grammar requires the first line to be exactly *** Begin Patch (no trailing ***). OpenCodex already documents that for top-level custom tools in src/responses/parser.ts (begin exactly with *** Begin Patch (no trailing *** )). Nested helpers in code mode currently do not inherit that sentence.

https://github.com/lidge-jun/opencodex/blob/dev/src/responses/parser.ts

Related: #2310 repairs decorated top-level envelopes and leaves exec JavaScript untouched. #2111 covered missing exec tool events, not this delimiter mismatch.

Suggested mapping or implementation notes

Add the nested-helper delimiter rule to the shared non-OpenAI code-mode catalog nudge and the Cursor code-mode guidance. Keep exec JavaScript byte-identical. Do not invent an exec-body rewriter.

Additional context and attachments

Live observation was on Codex Desktop with OpenCodex 2.29.0 routing xai/grok-4.6. The nested helper is invoked from V8 isolate JavaScript, not as a top-level custom_tool_call named apply_patch.

Checks

  • I searched existing provider and compatibility issues.
  • The request and response were redacted.
  • The expected behaviour is based on an upstream specification or a concrete client requirement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    landed-via-maintainerOriginal PR closed after landing via a maintainer merge trainproviderProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reports

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions