
Security News
Opengrep Adds Apex Support and New Rule Controls in Latest Updates
The latest Opengrep releases add Apex scanning, precision rule tuning, and performance gains for open source static code analysis.
This library provides a powerful and resilient toolkit for applying code modifications, specifically designed for use in AI-powered developer agents and automated coding systems. It moves beyond simple patch application by offering multiple intelligent strategies to find the correct location for a change and apply it, even if the source file has been slightly modified.
This enhanced reliability reduces failed operations and provides detailed feedback, enabling AI agents to self-correct and perform more complex coding tasks successfully.
diff -U
patch applicator for standard, unmodified diff files.getToolDescription
method, providing ready-to-use descriptions for LLM agent frameworks (like function calling).The library is built around the concept of "strategies," each providing a different way to interpret and apply a diff.
newUnifiedDiffStrategyService
(Recommended): The most advanced strategy. It doesn't rely on strict line numbers. Instead, it analyzes the content of the diff (context, additions, and removals) and searches for the best matching location in the source file. This is the most resilient and flexible option.multiSearchReplaceService
: Ideal for targeted replacements. The LLM provides one or more SEARCH
blocks and corresponding REPLACE
blocks. The library finds the exact SEARCH
content and replaces it. It can use line numbers as hints to narrow the search.unifiedDiffService
: A wrapper around a traditional unified diff library. It requires a standard diff -U
format with correct headers and line numbers. It is fast and efficient but brittle—it will fail if the source file has changed at all.The newUnifiedDiffStrategyService
calculates a confidence
score (from 0.0 to 1.0) for every potential patch location. This score is based on multiple factors, including string similarity, context validation, and the uniqueness of the search content within the file. A patch is only applied if the confidence meets a configurable threshold (e.g., 0.95
), preventing incorrect applications.
A core design principle is providing feedback for failure. Instead of a generic "patch failed" message, the DiffResult
object contains specific error details:
# Using npm
npm install diff-apply
# Using yarn
yarn add diff-apply
# Using bun
bun add diff-apply
Here’s a simple example of using the recommended Advanced Unified Diff strategy to apply a change.
import { newUnifiedDiffStrategyService } from 'advanced-diff-patcher';
import * as fs from 'fs';
// 1. The original content of the file.
const originalContent = fs.readFileSync('src/utils.ts', 'utf-8');
// 2. The diff generated by an LLM. Note the '...' in the @@ line,
// as this strategy doesn't need exact line numbers.
const llmGeneratedDiff = `--- src/utils.ts
+++ src/utils.ts
@@ ... @@
function calculateTotal(items: number[]): number {
- return items.reduce((sum, item) => {
- return sum + item;
- }, 0);
+ const total = items.reduce((sum, item) => {
+ return sum + item * 1.1; // Add 10% markup
+ }, 0);
+ return Math.round(total * 100) / 100; // Round to 2 decimal places
}`;
// 3. Create an instance of the strategy with a desired confidence threshold.
const strategy = newUnifiedDiffStrategyService.create(0.95); // 95% confidence required
async function applyChange() {
const result = await strategy.applyDiff({
originalContent,
diffContent: llmGeneratedDiff,
});
if (result.success) {
fs.writeFileSync('src/utils.ts', result.content);
console.log("Patch applied successfully!");
console.log("New content:\n", result.content);
} else {
// The agent can use this detailed error to self-correct.
console.error("Failed to apply patch:", result.error);
}
}
applyChange();
newUnifiedDiffStrategyService
for: Most general-purpose coding tasks, refactoring, adding features, and fixing bugs. Its resilience makes it the best default choice.multiSearchReplaceService
for: Very precise, targeted changes where the exact content to be replaced is known. Good for simple variable renames or string literal changes across a file.unifiedDiffService
for: Systems where you can guarantee the diff is generated against the exact same version of the file that it will be applied to.To integrate this library into an AI agent, provide the getToolDescription()
output of one or more strategies in your system prompt. The LLM can then choose the appropriate format and generate a diff.
System Prompt Example:
You are an expert AI programmer. When you need to modify a file, you must use the
apply_diff
tool. You must carefully read the format requirements for the diff and generate your response accordingly.
new-unified
)This is the most powerful and recommended strategy. It focuses on the content of the change, not strict line numbers.
Tool Description (for the LLM):
# apply_diff Tool - Generate Precise Code Changes
Generate a unified diff that can be cleanly applied to modify code files.
## Step-by-Step Instructions:
1. Start with file headers:
- First line: "--- {original_file_path}"
- Second line: "+++ {new_file_path}"
2. For each change section:
- Begin with "@@ ... @@" separator line without line numbers
- Include 2-3 lines of context before and after changes
- Mark removed lines with "-"
- Mark added lines with "+"
- Preserve exact indentation
3. Group related changes:
- Keep related modifications in the same hunk
- Start new hunks for logically separate changes
- When modifying functions/methods, include the entire block
## Requirements:
1. MUST include exact indentation
2. MUST include sufficient context for unique matching
3. MUST group related changes together
4. MUST use proper unified diff format
5. MUST NOT include timestamps in file headers
6. MUST NOT include line numbers in the @@ header
## Examples:
✅ Good diff (follows all requirements):
\`\`\`diff
--- src/utils.ts
+++ src/utils.ts
@@ ... @@
def calculate_total(items):
- total = 0
- for item in items:
- total += item.price
+ return sum(item.price for item in items)
\`\`\`
Example LLM Interaction:
User:
Refactor the
greet
function inmain.js
to say "Hello, Universe!" instead of "Hello, World!".
LLM apply_diff
call:
<apply_diff>
<path>main.js</path>
<diff>
--- main.js
+++ main.js
@@ ... @@
function greet() {
- console.log("Hello, World!");
+ console.log("Hello, Universe!");
}
</diff>
</apply_diff>
multi-search-replace
)Use this for precise replacements.
Tool Description (for the LLM):
## apply_diff
Description: Request to replace existing code using search and replace blocks. This tool allows for precise, surgical replacements to files by specifying what content to search for and what to replace it with. It supports single or multiple replacements in one call. The SEARCH section must exactly match existing content including whitespace and indentation.
Parameters:
- path: (required) The path of the file to modify.
- diff: (required) The search/replace block(s) defining the changes.
- start_line: (optional) The line number where the search block starts.
- end_line: (optional) The line number where the search block ends.
Diff format:
<<<<<<< SEARCH
:start_line: (optional)
:end_line: (optional)
-------
[exact content to find including whitespace]
=======
[new content to replace with]
>>>>>>> REPLACE
... more blocks ...
Example LLM Interaction:
User:
In
config.js
, change thePORT
from3000
to8080
and theHOST
from"localhost"
to"0.0.0.0"
.
LLM apply_diff
call:
<apply_diff>
<path>config.js</path>
<diff>
<<<<<<< SEARCH
:start_line: 5
:end_line: 5
-------
const PORT = 3000;
=======
const PORT = 8080;
>>>>>>> REPLACE
<<<<<<< SEARCH
:start_line: 6
:end_line: 6
-------
const HOST = "localhost";
=======
const HOST = "0.0.0.0";
>>>>>>> REPLACE
</diff>
</apply_diff>
unified
)Use this only when diffs are generated against a guaranteed-to-be-identical file.
Tool Description (for the LLM):
## apply_diff
Description: Apply a unified diff to a file. This tool requires a strict unified diff format (diff -U3) with correct file headers and hunk headers (e.g., @@ -1,5 +1,6 @@).
Parameters:
- path: (required) The path of the file to apply the diff to.
- diff: (required) The diff content in strict unified format.
Format Requirements:
1. Header: Must include `--- path/to/file` and `+++ path/to/file`.
2. Hunks: Must include `@@ -start,count +start,count @@` with correct line numbers.
Example LLM Interaction:
User:
I have a patch file to fix a bug in
calculator.js
. Please apply it.
LLM apply_diff
call:
<apply_diff>
<path>src/calculator.js</path>
<diff>
--- src/calculator.js
+++ src/calculator.js
@@ -5,7 +5,7 @@
function add(a, b) {
- return a - b; // Bug here
+ return a + b;
}
export { add };
</diff>
</apply_diff>
When an applyDiff
call fails, the error
message in the DiffResult
is your feedback loop.
Example Failure Scenario:
LLM Task: "In app.js
, add logging to the processRequest
function."
LLM generates a diff with too little context:
--- app.js
+++ app.js
@@ ... @@
- process(data);
+ console.log('Processing request...');
+ process(data);
Library returns a failure:
{
"success": false,
"error": "Failed to find a matching location in the file (68% confidence, needs 95%)\n\nPossible Issues:\n- Not enough context lines to uniquely identify the location\n- Add a few more lines of unchanged code around your changes"
}
Agent's next step: The agent should feed this error back to the LLM.
Prompt to LLM:
The previous attempt to modify
app.js
failed. The tool reported: "Failed to find a matching location... Not enough context lines...". Please read the file content forapp.js
again and generate a new diff with more surrounding context to ensure a unique match.
LLM generates a better diff:
--- app.js
+++ app.js
@@ ... @@
if (!req.body) {
return res.status(400).send('Bad Request');
}
- process(req.body);
+ console.log('Processing request...');
+ process(req.body);
res.status(200).send('OK');
}
This attempt succeeds because the additional context makes the location unambiguous.
DiffStrategy
: The interface that all strategies implement.
getToolDescription(args)
: Returns a markdown string to be used in an LLM prompt.applyDiff(params: ApplyDiffParams)
: Applies the diff.ApplyDiffParams
:
originalContent: string
: The source content of the file.diffContent: string
: The diff content generated by the LLM.startLine?: number
, endLine?: number
: Optional line hints.DiffResult
:
success: true
, content: string
: On success.success: false
, error: string
, details?: object
: On failure.Contributions are welcome! Please open an issue to discuss your ideas or submit a pull request. Ensure that all new features are accompanied by tests.
This project is licensed under the MIT License.
FAQs
A utility for applying file diffs programmatically
The npm package diff-apply receives a total of 3,859 weekly downloads. As such, diff-apply popularity was classified as popular.
We found that diff-apply demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The latest Opengrep releases add Apex scanning, precision rule tuning, and performance gains for open source static code analysis.
Security News
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.