From fa1cd28c9ea19398bc58bfb3c7790478e7111539 Mon Sep 17 00:00:00 2001 From: Dev Randalpura Date: Thu, 14 May 2026 13:01:40 -0400 Subject: [PATCH 1/2] Preserved new line at the end of the window --- packages/core/src/tools/edit.test.ts | 36 ++++++++++++++++++++++++++++ packages/core/src/tools/edit.ts | 14 ++++++----- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/packages/core/src/tools/edit.test.ts b/packages/core/src/tools/edit.test.ts index 4077a6cd414..84086bbd696 100644 --- a/packages/core/src/tools/edit.test.ts +++ b/packages/core/src/tools/edit.test.ts @@ -511,6 +511,42 @@ function doIt() { expect(result.newContent).toBe(expectedContent); }); + it('should preserve trailing newlines in flexible replacement (regression)', async () => { + const content = ' line1\n line2\n line3\n'; + const result = await calculateReplacement(mockConfig, { + params: { + file_path: 'test.txt', + old_string: 'line1\nline2', + new_string: 'line1-replaced\nline2-replaced', + }, + currentContent: content, + abortSignal, + }); + + expect(result.newContent).toBe( + ' line1-replaced\n line2-replaced\n line3\n', + ); + }); + + it('should correctly increment loop index in flexible replacement when allow_multiple is true (regression)', async () => { + const content = ' match1\n match2\n match1\n match2\n'; + const result = await calculateReplacement(mockConfig, { + params: { + file_path: 'test.txt', + old_string: 'match1\nmatch2', + new_string: 'replaced1\nreplaced2\nreplaced3', + allow_multiple: true, + }, + currentContent: content, + abortSignal, + }); + + expect(result.occurrences).toBe(2); + expect(result.newContent).toBe( + ' replaced1\n replaced2\n replaced3\n replaced1\n replaced2\n replaced3\n', + ); + }); + it('should correctly rebase indentation in flexible replacement without double-indenting', async () => { const content = ' if (a) {\n foo();\n }\n'; // old_string and new_string are unindented. They should be rebased to 4-space. diff --git a/packages/core/src/tools/edit.ts b/packages/core/src/tools/edit.ts index 3f6d5d9f622..40da86f9055 100644 --- a/packages/core/src/tools/edit.ts +++ b/packages/core/src/tools/edit.ts @@ -202,12 +202,14 @@ async function calculateFlexibleReplacement( const indentationMatch = firstLineInMatch.match(/^([ \t]*)/); const indentation = indentationMatch ? indentationMatch[1] : ''; const newBlockWithIndent = applyIndentation(replaceLines, indentation); - sourceLines.splice( - i, - searchLinesStripped.length, - newBlockWithIndent.join('\n'), - ); - i += replaceLines.length; + + let replacementText = newBlockWithIndent.join('\n'); + if (window[window.length - 1].endsWith('\n')) { + replacementText += '\n'; + } + + sourceLines.splice(i, searchLinesStripped.length, replacementText); + i += 1; } else { i++; } From 17c1215be4f4c86b13549a77bed93c3a585aba8f Mon Sep 17 00:00:00 2001 From: Dev Randalpura Date: Thu, 14 May 2026 14:14:46 -0400 Subject: [PATCH 2/2] Fixed cases where it would add the new line twice --- packages/core/src/tools/edit.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/core/src/tools/edit.ts b/packages/core/src/tools/edit.ts index 40da86f9055..c00ea4c0da0 100644 --- a/packages/core/src/tools/edit.ts +++ b/packages/core/src/tools/edit.ts @@ -204,15 +204,17 @@ async function calculateFlexibleReplacement( const newBlockWithIndent = applyIndentation(replaceLines, indentation); let replacementText = newBlockWithIndent.join('\n'); - if (window[window.length - 1].endsWith('\n')) { + if ( + new_string !== '' && + window[window.length - 1].endsWith('\n') && + !replacementText.endsWith('\n') + ) { replacementText += '\n'; } sourceLines.splice(i, searchLinesStripped.length, replacementText); - i += 1; - } else { - i++; } + i++; } if (flexibleOccurrences > 0) {