# llm-diff-patcher

A TypeScript library for applying "fuzzy" diffs, particularly designed for LLM-generated code modifications where line numbers may not be accurate.

## Installation

```bash
npm install llm-diff-patcher
```

## Usage

```typescript
import { applyPatchToFiles } from 'llm-diff-patcher';

// Original source code
const sourceText = `function hello() {
  console.log("Hello, world!");
  return true;
}`;

// A diff to apply (in unified diff format)
const diffText = `@@ -1,4 +1,4 @@
 function hello() {
-  console.log("Hello, world!");
+  console.log("Hello, universe!");
   return true;
 }`;

// Apply the fuzzy diff
const result = applyDiff(sourceText, diffText);

console.log(result);
// Output:
// function hello() {
//   console.log("Hello, universe!");
//   return true;
// }

// For applying to files in a directory:
const patchResult = applyPatchToFiles(diffText, {
  basePath: '/path/to/project',
  dryRun: false
});

console.log(`Files: ${patchResult.successfulFiles}/${patchResult.totalFiles}, Hunks: ${patchResult.appliedHunks}/${patchResult.totalHunks}`);
```

## Configuration Options

You can customize the behavior with options:

```typescript
// When applying to files
const result = applyPatchToFiles(diffText, {
  // Base directory for resolving file paths
  basePath: '/path/to/project',
  
  // If true, doesn't actually write to files (default: false)
  dryRun: true,
  
  // Minimum number of context lines required for a match
  minContextLines: 2,
  
  // Options passed to the underlying diff library
  jsDiffApplyPatchOptions: {
    // Maximum Levenshtein distance between context in patch and actual file lines
    // Higher values allow more fuzzy matches (default: 0)
    fuzzFactor: 2,
    
    // Automatically handle different line endings between patch and source file
    // (default: true)
    autoConvertLineEndings: true,
    
    // Custom function to compare lines for equality when patching
    // Allows for very flexible fuzzy matching
    compareLine: (lineNumber, line, operation, patchContent) => {

      // Custom comparison logic here
      // Return true if lines should be considered equal, false otherwise
      return line.trim() === patchContent.trim(); // Example: ignore whitespace
    }
  }
});
```

## Why llm-diff-patcher?

Unlike traditional diff tools that require exact line numbers to match, `llm-diff-patcher` is designed to handle the imprecise nature of diffs generated by Large Language Models (LLMs). 

Key benefits:

1. **Fuzzy Matching**: Applies changes based on context even when line numbers are incorrect
2. **Robust Error Handling**: Provides detailed information about successful and failed patches
3. **Flexible Configuration**: Adjust matching strictness to your needs
4. **Dry Run Mode**: Test patches without modifying files

## Use Cases

- Applying code changes suggested by AI assistants like GPT, Claude, or other LLMs
- Implementing code modifications across slightly different versions of files
- Working with diffs that may not have perfect context or line numbers
- Automated code refactoring with LLM-generated patches

## API

The library provides several key functions:

- `applyPatchToFiles`: Apply patch to multiple files in a directory
- `applyDiff`: Apply a single diff to a string
- `parsePatch`: Parse a patch string into a structured format
- `cleanPatch`: Clean up and normalize patch text

## Error Handling

The library provides detailed error information to help you understand what went wrong:

```typescript
if (!patchResult.success) {
  console.error(`Failed to apply patch. Errors:`);
  patchResult.errors.forEach(error => {
    console.error(`- ${error.message} (${error.context})`);
  });
}
```

## License

MIT