Skip to content

Commit 5e0c9a7

Browse files
KJ7LNWEric Wheeler
andauthored
fix: clamp negative line numbers when reading files (#2337)
Improve handling of AI-generated line numbers: - Clamp negative startLine values to 0 instead of throwing errors - Convert non-integer line numbers to integers automatically - Only reject when line numbers aren't numbers at all These changes prevent unnecessary model retries by handling imperfect AI-generated line numbers gracefully, making the system more robust when interacting with AI models. Signed-off-by: Eric Wheeler <[email protected]> Co-authored-by: Eric Wheeler <[email protected]>
1 parent 7261efb commit 5e0c9a7

File tree

2 files changed

+26
-21
lines changed

2 files changed

+26
-21
lines changed

src/integrations/misc/__tests__/read-lines.test.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,21 @@ describe("nthline", () => {
3333

3434
it("should throw error for negative to_line", async () => {
3535
await expect(readLines(testFile, -3)).rejects.toThrow(
36-
"Invalid endLine: -3. Line numbers must be non-negative integers.",
36+
"startLine (0) must be less than or equal to endLine (-3)",
3737
)
3838
})
3939

40-
it("should throw error for negative from_line", async () => {
41-
await expect(readLines(testFile, 3, -1)).rejects.toThrow(
42-
"Invalid startLine: -1. Line numbers must be non-negative integers.",
43-
)
40+
it("should handle negative from_line by clamping to 0", async () => {
41+
const lines = await readLines(testFile, 3, -1)
42+
expect(lines).toEqual(["Line 1", "Line 2", "Line 3", "Line 4"].join("\n"))
4443
})
4544

46-
it("should throw error for non-integer line numbers", async () => {
47-
await expect(readLines(testFile, 3, 1.5)).rejects.toThrow(
48-
"Invalid startLine: 1.5. Line numbers must be non-negative integers.",
49-
)
50-
await expect(readLines(testFile, 3.5)).rejects.toThrow(
51-
"Invalid endLine: 3.5. Line numbers must be non-negative integers.",
52-
)
45+
it("should floor non-integer line numbers", async () => {
46+
const linesWithNonIntegerStart = await readLines(testFile, 3, 1.5)
47+
expect(linesWithNonIntegerStart).toEqual(["Line 2", "Line 3", "Line 4"].join("\n"))
48+
49+
const linesWithNonIntegerEnd = await readLines(testFile, 3.5)
50+
expect(linesWithNonIntegerEnd).toEqual(["Line 1", "Line 2", "Line 3", "Line 4"].join("\n"))
5351
})
5452

5553
it("should throw error when from_line > to_line", async () => {

src/integrations/misc/read-lines.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,24 @@ const outOfRangeError = (filepath: string, n: number) => {
2424
*/
2525
export function readLines(filepath: string, endLine?: number, startLine?: number): Promise<string> {
2626
return new Promise((resolve, reject) => {
27-
// Validate input parameters
28-
// Check startLine validity if provided
29-
if (startLine !== undefined && (startLine < 0 || startLine % 1 !== 0)) {
30-
return reject(
31-
new RangeError(`Invalid startLine: ${startLine}. Line numbers must be non-negative integers.`),
32-
)
27+
// Reject if startLine is defined but not a number
28+
if (startLine !== undefined && typeof startLine !== "number") {
29+
return reject(new RangeError(`Invalid startLine: ${startLine}. Line numbers must be numbers.`))
30+
}
31+
32+
// Force startLine to be an integer and clamp to 0 if negative
33+
if (startLine !== undefined) {
34+
startLine = Math.max(0, Math.floor(startLine))
35+
}
36+
37+
// Reject if endLine is defined but not a number
38+
if (endLine !== undefined && typeof endLine !== "number") {
39+
return reject(new RangeError(`Invalid endLine: ${endLine}. Line numbers must be numbers.`))
3340
}
3441

35-
// Check endLine validity if provided
36-
if (endLine !== undefined && (endLine < 0 || endLine % 1 !== 0)) {
37-
return reject(new RangeError(`Invalid endLine: ${endLine}. Line numbers must be non-negative integers.`))
42+
// Force endLine to be an integer
43+
if (endLine !== undefined) {
44+
endLine = Math.floor(endLine)
3845
}
3946

4047
const effectiveStartLine = startLine === undefined ? 0 : startLine

0 commit comments

Comments
 (0)