applypatch

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: MIT, Apache-2.0 Imports: 9 Imported by: 0

README

applypatch

Go Reference License

Apply the patches OpenAI models write with the apply_patch tool, to strings in memory. It handles both the V4A update diffs of the Responses API apply_patch tool and the *** Begin Patch format of the Codex CLI, and it exports the Codex tool definition.

Install

go get github.com/fgn/applypatch

Usage

// One text and one update diff.
output, err := applypatch.Apply(input, diff)

// A Codex patch over several files: add, delete, update, move.
files, err := applypatch.Codex.ApplyFiles(files, patch)

// The tool to offer a model; send its input to ApplyFiles.
tool := applypatch.CodexTool()

Modes

  • Strict, the default, never guesses. Anchors, context, and removed lines must match byte for byte and exactly once, or the patch is an error the model can fix.
  • Codex does what the Codex CLI does with line-ending preservation on: first match, then fallbacks that ignore whitespace and Unicode punctuation, insertions without context at the end of the file, and a newline after every line. It is checked against the real Codex binary.

Development

Development tasks run through Task, which you can install from taskfile.dev/docs/installation. Run task to format, lint, and test, and task --list to see the rest, including the Codex parity, fuzz, and mutation tasks.

License

MIT, except the parts ported from OpenAI Codex, which are Apache-2.0; see NOTICE. Strict mode is a Go port of applyDiff from the OpenAI Agents SDK for JavaScript (MIT), and Codex mode, the patch parser, and the tool definition are a Go port of apply_patch from OpenAI Codex (Apache-2.0).

Documentation

Overview

Package applypatch applies the patches that OpenAI models write with the apply_patch tool, to strings in memory.

Two formats are supported. An update diff (V4A) edits one text, as in the diff of a Responses API apply_patch update_file operation:

@@ def greet():
-    print("Hi")
+    print("Hello")

A patch, as written for the Codex apply_patch tool (see CodexTool), wraps operations on several files:

*** Begin Patch
*** Add File: hello.txt
+Hello
*** Update File: greet.py
@@ def greet():
-    print("Hi")
+    print("Hello")
*** End Patch

A Mode decides how update diffs are matched. Strict, the default, never guesses: anchors, context, and removed lines must match byte for byte and exactly once. Codex follows the Codex CLI: first match, then fuzzy fallbacks for whitespace and Unicode punctuation.

Strict mode is a Go port of applyDiff from the OpenAI Agents SDK for JavaScript (MIT). Codex mode, the patch parser, and CodexTool are a Go port of apply_patch from OpenAI Codex (Apache-2.0).

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Apply

func Apply(input, diff string) (string, error)

Apply applies one update diff to input in Strict mode.

Example
package main

import (
	"fmt"

	"github.com/fgn/applypatch"
)

func main() {
	input := "def greet():\n    print(\"Hi\")\n"
	diff := "@@ def greet():\n-    print(\"Hi\")\n+    print(\"Hello\")"
	output, err := applypatch.Apply(input, diff)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Print(output)
}
Output:
def greet():
    print("Hello")

func ApplyBatch

func ApplyBatch(input string, diffs []string) (string, error)

ApplyBatch applies several update diffs to input in Strict mode.

Example
package main

import (
	"fmt"

	"github.com/fgn/applypatch"
)

func main() {
	input := "alpha\nbeta\ngamma\n"
	output, err := applypatch.ApplyBatch(input, []string{"-alpha\n+ALPHA", "-gamma\n+GAMMA"})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Print(output)
}
Output:
ALPHA
beta
GAMMA

func ApplyFiles

func ApplyFiles(files map[string]string, patch string) (map[string]string, error)

ApplyFiles applies an apply_patch patch to files in Strict mode.

Example
package main

import (
	"fmt"

	"github.com/fgn/applypatch"
)

func main() {
	files := map[string]string{"greet.py": "print(\"Hi\")\n"}
	patch := `*** Begin Patch
*** Add File: README.md
+# Greeter
*** Update File: greet.py
@@
-print("Hi")
+print("Hello")
*** End Patch`
	output, err := applypatch.Codex.ApplyFiles(files, patch)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%q\n%q\n", output["README.md"], output["greet.py"])
}
Output:
"# Greeter\n"
"print(\"Hello\")\n"

Types

type Mode

type Mode int

Mode selects how update diffs are parsed and matched against the text they patch. The zero value is Strict.

const (
	// Strict applies an update diff only when every anchor, context line, and
	// removed line matches the input byte for byte and exactly once. It never
	// guesses: a diff that could apply in more than one place is an error.
	Strict Mode = iota
	// Codex applies patches the way the apply_patch tool of the OpenAI Codex
	// CLI does with line-ending preservation enabled. It takes the first
	// match, falls back to ignoring whitespace and Unicode punctuation
	// differences, appends insertions without context to the end of the file,
	// keeps each line's ending, and ends every line with a newline.
	Codex
)

func (Mode) Apply

func (m Mode) Apply(input, diff string) (string, error)

Apply applies one update diff to input and returns the patched text. The diff is the V4A body of an update, as in the diff of an apply_patch update_file operation, without "*** Update File:" or other patch headers. A final "\n" ends the last line rather than adding an empty one. Strict mode also accepts "\r\n" line breaks; Codex mode splits on "\n" only and keeps any "\r" as part of the line.

Example
package main

import (
	"fmt"

	"github.com/fgn/applypatch"
)

func main() {
	// Strict mode rejects a diff that only matches when whitespace is
	// ignored; Codex mode applies it like the Codex CLI would.
	input := "total  \n"
	diff := "-total\n+sum"
	_, err := applypatch.Strict.Apply(input, diff)
	fmt.Println("strict:", err)
	output, _ := applypatch.Codex.Apply(input, diff)
	fmt.Printf("codex: %q\n", output)
}
Output:
strict: target must match exactly once
codex: "sum\n"

func (Mode) ApplyBatch

func (m Mode) ApplyBatch(input string, diffs []string) (string, error)

ApplyBatch applies several update diffs to input. In Strict mode every diff targets the original input and overlapping edits fail the whole batch. In Codex mode the diffs apply one after another, like consecutive apply_patch calls on the same file.

func (Mode) ApplyFiles

func (m Mode) ApplyFiles(files map[string]string, patch string) (map[string]string, error)

ApplyFiles applies an apply_patch patch, "*** Begin Patch" through "*** End Patch", to files, a map from path to contents. It returns a new map and leaves files unchanged. Paths are map keys used exactly as written in the patch. Operations apply in order, and if any fails, ApplyFiles returns only the error.

func (Mode) String

func (m Mode) String() string

String returns "strict" or "codex".

type Operation

type Operation struct {
	Kind OperationKind
	Path string
	// MoveTo is the new path of an updated file, or empty.
	MoveTo string
	// Contents is the text of an added file: each "+" line of the patch
	// followed by a newline.
	Contents string
	// Diff is the update diff of an updated file: each line of the patch
	// followed by "\n". Mode.Apply(contents, Diff) applies it exactly as
	// ApplyFiles would.
	Diff string
}

Operation is one file operation of a patch.

type OperationKind

type OperationKind int

OperationKind says what an Operation does to its file.

const (
	// AddFile creates a file, replacing any file at the same path.
	AddFile OperationKind = iota + 1
	// DeleteFile removes an existing file.
	DeleteFile
	// UpdateFile applies an update diff to an existing file and can move it.
	UpdateFile
)

func (OperationKind) String

func (k OperationKind) String() string

String returns "add", "delete", or "update".

type Patch

type Patch struct {
	// EnvironmentID is the value of an optional "*** Environment ID:" line.
	EnvironmentID string
	Operations    []Operation
}

Patch is a parsed apply_patch patch.

func Parse

func Parse(patch string) (*Patch, error)

Parse parses an apply_patch patch the way Codex does: it accepts whitespace around the markers and a patch wrapped in a <<EOF heredoc. Parse checks the structure of the patch; the diffs of updates are checked when a Mode applies them.

type Tool

type Tool struct {
	Type        string     `json:"type"`
	Name        string     `json:"name"`
	Description string     `json:"description"`
	Format      ToolFormat `json:"format"`
}

Tool is a custom (freeform) tool definition for the OpenAI Responses API.

func CodexTool

func CodexTool() Tool

CodexTool returns the apply_patch tool that Codex gives GPT-5 models: a custom tool whose input must match a Lark grammar for the "*** Begin Patch" format. Pass the input of the model's custom_tool_call to Mode.ApplyFiles.

Example
package main

import (
	"fmt"

	"github.com/fgn/applypatch"
)

func main() {
	tool := applypatch.CodexTool()
	fmt.Println(tool.Type, tool.Name, tool.Format.Type, tool.Format.Syntax)
}
Output:
custom apply_patch grammar lark

type ToolFormat

type ToolFormat struct {
	Type       string `json:"type"`
	Syntax     string `json:"syntax"`
	Definition string `json:"definition"`
}

ToolFormat constrains the input of a custom tool.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL