mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 04:11:10 -05:00
Merge pull request #126 from RooVetGit/delete_line_numbers_in_diff
Delete line numbers in diff
This commit is contained in:
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,21 +1,9 @@
|
|||||||
# Roo Cline Changelog
|
# Roo Cline Changelog
|
||||||
|
|
||||||
## [2.2.9]
|
## [2.2.6 - 2.2.10]
|
||||||
|
|
||||||
- Fix a bug where Gemini was including line numbers in the search/replace content
|
|
||||||
|
|
||||||
## [2.2.8]
|
|
||||||
|
|
||||||
- More work on diff editing (better matching, indentation, logging)
|
|
||||||
|
|
||||||
## [2.2.7]
|
|
||||||
|
|
||||||
- More fixes to search/replace diffs
|
- More fixes to search/replace diffs
|
||||||
|
|
||||||
## [2.2.6]
|
|
||||||
|
|
||||||
- Add a fuzzy match tolerance when applying diffs
|
|
||||||
|
|
||||||
## [2.2.5]
|
## [2.2.5]
|
||||||
|
|
||||||
- Allow MCP servers to be enabled/disabled
|
- Allow MCP servers to be enabled/disabled
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "roo-cline",
|
"name": "roo-cline",
|
||||||
"version": "2.2.9",
|
"version": "2.2.10",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "roo-cline",
|
"name": "roo-cline",
|
||||||
"version": "2.2.9",
|
"version": "2.2.10",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/bedrock-sdk": "^0.10.2",
|
"@anthropic-ai/bedrock-sdk": "^0.10.2",
|
||||||
"@anthropic-ai/sdk": "^0.26.0",
|
"@anthropic-ai/sdk": "^0.26.0",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"displayName": "Roo Cline",
|
"displayName": "Roo Cline",
|
||||||
"description": "A fork of Cline, an autonomous coding agent, with some added experimental configuration and automation features.",
|
"description": "A fork of Cline, an autonomous coding agent, with some added experimental configuration and automation features.",
|
||||||
"publisher": "RooVeterinaryInc",
|
"publisher": "RooVeterinaryInc",
|
||||||
"version": "2.2.9",
|
"version": "2.2.10",
|
||||||
"icon": "assets/icons/rocket.png",
|
"icon": "assets/icons/rocket.png",
|
||||||
"galleryBanner": {
|
"galleryBanner": {
|
||||||
"color": "#617A91",
|
"color": "#617A91",
|
||||||
|
|||||||
@@ -564,6 +564,153 @@ this.init();
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('line number stripping', () => {
|
||||||
|
describe('line number stripping', () => {
|
||||||
|
let strategy: SearchReplaceDiffStrategy
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
strategy = new SearchReplaceDiffStrategy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should strip line numbers from both search and replace sections', () => {
|
||||||
|
const originalContent = 'function test() {\n return true;\n}\n'
|
||||||
|
const diffContent = `test.ts
|
||||||
|
<<<<<<< SEARCH
|
||||||
|
1 | function test() {
|
||||||
|
2 | return true;
|
||||||
|
3 | }
|
||||||
|
=======
|
||||||
|
1 | function test() {
|
||||||
|
2 | return false;
|
||||||
|
3 | }
|
||||||
|
>>>>>>> REPLACE`
|
||||||
|
|
||||||
|
const result = strategy.applyDiff(originalContent, diffContent)
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.content).toBe('function test() {\n return false;\n}\n')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not strip when not all lines have numbers in either section', () => {
|
||||||
|
const originalContent = 'function test() {\n return true;\n}\n'
|
||||||
|
const diffContent = `test.ts
|
||||||
|
<<<<<<< SEARCH
|
||||||
|
1 | function test() {
|
||||||
|
2 | return true;
|
||||||
|
3 | }
|
||||||
|
=======
|
||||||
|
1 | function test() {
|
||||||
|
return false;
|
||||||
|
3 | }
|
||||||
|
>>>>>>> REPLACE`
|
||||||
|
|
||||||
|
const result = strategy.applyDiff(originalContent, diffContent)
|
||||||
|
expect(result.success).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should preserve content that naturally starts with pipe', () => {
|
||||||
|
const originalContent = '|header|another|\n|---|---|\n|data|more|\n'
|
||||||
|
const diffContent = `test.ts
|
||||||
|
<<<<<<< SEARCH
|
||||||
|
1 | |header|another|
|
||||||
|
2 | |---|---|
|
||||||
|
3 | |data|more|
|
||||||
|
=======
|
||||||
|
1 | |header|another|
|
||||||
|
2 | |---|---|
|
||||||
|
3 | |data|updated|
|
||||||
|
>>>>>>> REPLACE`
|
||||||
|
|
||||||
|
const result = strategy.applyDiff(originalContent, diffContent)
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.content).toBe('|header|another|\n|---|---|\n|data|updated|\n')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should preserve indentation when stripping line numbers', () => {
|
||||||
|
const originalContent = ' function test() {\n return true;\n }\n'
|
||||||
|
const diffContent = `test.ts
|
||||||
|
<<<<<<< SEARCH
|
||||||
|
1 | function test() {
|
||||||
|
2 | return true;
|
||||||
|
3 | }
|
||||||
|
=======
|
||||||
|
1 | function test() {
|
||||||
|
2 | return false;
|
||||||
|
3 | }
|
||||||
|
>>>>>>> REPLACE`
|
||||||
|
|
||||||
|
const result = strategy.applyDiff(originalContent, diffContent)
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.content).toBe(' function test() {\n return false;\n }\n')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle different line numbers between sections', () => {
|
||||||
|
const originalContent = 'function test() {\n return true;\n}\n'
|
||||||
|
const diffContent = `test.ts
|
||||||
|
<<<<<<< SEARCH
|
||||||
|
10 | function test() {
|
||||||
|
11 | return true;
|
||||||
|
12 | }
|
||||||
|
=======
|
||||||
|
20 | function test() {
|
||||||
|
21 | return false;
|
||||||
|
22 | }
|
||||||
|
>>>>>>> REPLACE`
|
||||||
|
|
||||||
|
const result = strategy.applyDiff(originalContent, diffContent)
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.content).toBe('function test() {\n return false;\n}\n')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not strip content that starts with pipe but no line number', () => {
|
||||||
|
const originalContent = '| Pipe\n|---|\n| Data\n'
|
||||||
|
const diffContent = `test.ts
|
||||||
|
<<<<<<< SEARCH
|
||||||
|
| Pipe
|
||||||
|
|---|
|
||||||
|
| Data
|
||||||
|
=======
|
||||||
|
| Pipe
|
||||||
|
|---|
|
||||||
|
| Updated
|
||||||
|
>>>>>>> REPLACE`
|
||||||
|
|
||||||
|
const result = strategy.applyDiff(originalContent, diffContent)
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.content).toBe('| Pipe\n|---|\n| Updated\n')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle mix of line-numbered and pipe-only content', () => {
|
||||||
|
const originalContent = '| Pipe\n|---|\n| Data\n'
|
||||||
|
const diffContent = `test.ts
|
||||||
|
<<<<<<< SEARCH
|
||||||
|
| Pipe
|
||||||
|
|---|
|
||||||
|
| Data
|
||||||
|
=======
|
||||||
|
1 | | Pipe
|
||||||
|
2 | |---|
|
||||||
|
3 | | NewData
|
||||||
|
>>>>>>> REPLACE`
|
||||||
|
|
||||||
|
const result = strategy.applyDiff(originalContent, diffContent)
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.content).toBe('1 | | Pipe\n2 | |---|\n3 | | NewData\n')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
describe('fuzzy matching', () => {
|
describe('fuzzy matching', () => {
|
||||||
let strategy: SearchReplaceDiffStrategy
|
let strategy: SearchReplaceDiffStrategy
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ The tool will maintain proper indentation and formatting while making changes.
|
|||||||
Only a single operation is allowed per tool use.
|
Only a single operation is allowed per tool use.
|
||||||
The SEARCH section must exactly match existing content including whitespace and indentation.
|
The SEARCH section must exactly match existing content including whitespace and indentation.
|
||||||
If you're not confident in the exact content to search for, use the read_file tool first to get the exact content.
|
If you're not confident in the exact content to search for, use the read_file tool first to get the exact content.
|
||||||
IMPORTANT: The read_file tool returns the file content with line numbers prepended to each line. However, DO NOT include line numbers in the SEARCH and REPLACE sections of the diff content.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- path: (required) The path of the file to modify (relative to the current working directory ${cwd})
|
- path: (required) The path of the file to modify (relative to the current working directory ${cwd})
|
||||||
@@ -132,10 +131,25 @@ Your search/replace content here
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const [_, searchContent, replaceContent] = match;
|
let [_, searchContent, replaceContent] = match;
|
||||||
|
|
||||||
// Detect line ending from original content
|
// Detect line ending from original content
|
||||||
const lineEnding = originalContent.includes('\r\n') ? '\r\n' : '\n';
|
const lineEnding = originalContent.includes('\r\n') ? '\r\n' : '\n';
|
||||||
|
|
||||||
|
// Strip line numbers from search and replace content if every line starts with a line number
|
||||||
|
const hasLineNumbers = (content: string) => {
|
||||||
|
const lines = content.split(/\r?\n/);
|
||||||
|
return lines.length > 0 && lines.every(line => /^\d+\s+\|(?!\|)/.test(line));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (hasLineNumbers(searchContent) && hasLineNumbers(replaceContent)) {
|
||||||
|
const stripLineNumbers = (content: string) => {
|
||||||
|
return content.replace(/^\d+\s+\|(?!\|)/gm, '')
|
||||||
|
};
|
||||||
|
|
||||||
|
searchContent = stripLineNumbers(searchContent);
|
||||||
|
replaceContent = stripLineNumbers(replaceContent);
|
||||||
|
}
|
||||||
|
|
||||||
// Split content into lines, handling both \n and \r\n
|
// Split content into lines, handling both \n and \r\n
|
||||||
const searchLines = searchContent.split(/\r?\n/);
|
const searchLines = searchContent.split(/\r?\n/);
|
||||||
|
|||||||
Reference in New Issue
Block a user