(
input1: {
file_path: string
edits: FileEdit[]
},
input2: {
file_path: string
edits: FileEdit[]
},
)
| 730 | * Handles file edits (FileEditTool). |
| 731 | */ |
| 732 | export function areFileEditsInputsEquivalent( |
| 733 | input1: { |
| 734 | file_path: string |
| 735 | edits: FileEdit[] |
| 736 | }, |
| 737 | input2: { |
| 738 | file_path: string |
| 739 | edits: FileEdit[] |
| 740 | }, |
| 741 | ): boolean { |
| 742 | // Fast path: different files |
| 743 | if (input1.file_path !== input2.file_path) { |
| 744 | return false |
| 745 | } |
| 746 | |
| 747 | // Fast path: literal equality |
| 748 | if ( |
| 749 | input1.edits.length === input2.edits.length && |
| 750 | input1.edits.every((edit1, index) => { |
| 751 | const edit2 = input2.edits[index] |
| 752 | return ( |
| 753 | edit2 !== undefined && |
| 754 | edit1.old_string === edit2.old_string && |
| 755 | edit1.new_string === edit2.new_string && |
| 756 | edit1.replace_all === edit2.replace_all |
| 757 | ) |
| 758 | }) |
| 759 | ) { |
| 760 | return true |
| 761 | } |
| 762 | |
| 763 | // Semantic comparison (requires file read). If the file doesn't exist, |
| 764 | // compare against empty content (no TOCTOU pre-check). |
| 765 | let fileContent = '' |
| 766 | try { |
| 767 | fileContent = readFileSyncCached(input1.file_path) |
| 768 | } catch (error) { |
| 769 | if (!isENOENT(error)) { |
| 770 | throw error |
| 771 | } |
| 772 | } |
| 773 | |
| 774 | return areFileEditsEquivalent(input1.edits, input2.edits, fileContent) |
| 775 | } |
| 776 |
no test coverage detected