diff --git a/src/integrations/misc/__tests__/read-file-content.spec.ts b/src/integrations/misc/__tests__/read-file-content.spec.ts index bfa6fa6456..2526908ff6 100644 --- a/src/integrations/misc/__tests__/read-file-content.spec.ts +++ b/src/integrations/misc/__tests__/read-file-content.spec.ts @@ -122,14 +122,14 @@ describe("read-file-content", () => { describe("readIndentationBlock", () => { const pythonCode = `def outer(): - x = 1 - def inner(): - y = 2 - return y - return inner() - -def another(): - pass` + x = 1 + def inner(): + y = 2 + return y + return inner() + + def another(): + pass` it("should extract a function block with its contents", async () => { await withTempFile("indent-function-test.py", pythonCode, async (filepath) => { @@ -180,6 +180,16 @@ def another(): }) }) + it("should return empty content when offset exceeds file length (no explicit anchorLine)", async () => { + await withTempFile("indent-offset-past-end-test.py", pythonCode, async (filepath) => { + const result = await readIndentationBlock(filepath, 100, 10) + expect(result.content).toBe("") + expect(result.lineCount).toBe(0) + expect(result.totalLines).toBeGreaterThan(0) + expect(result.metadata.totalLinesInFile).toBe(result.totalLines) + }) + }) + it("should handle single line result", async () => { const content = "single line" await withTempFile("indent-single-test.txt", content, async (filepath) => { diff --git a/src/integrations/misc/read-file-content.ts b/src/integrations/misc/read-file-content.ts index 48bfae29e1..38301a83b5 100644 --- a/src/integrations/misc/read-file-content.ts +++ b/src/integrations/misc/read-file-content.ts @@ -356,13 +356,9 @@ export async function readIndentationBlock( limit: number = FALLBACK_LIMIT, config: IndentationConfig = {}, ): Promise { - const { - anchorLine = offset, - maxLevels = 0, - includeSiblings = false, - includeHeader = true, - maxLines = limit, - } = config + const hasExplicitAnchorLine = typeof config.anchorLine === "number" + const anchorLine = config.anchorLine ?? offset + const { maxLevels = 0, includeSiblings = false, includeHeader = true, maxLines = limit } = config if (anchorLine === 0) { throw new RangeError("anchorLine must be a 1-indexed line number") @@ -374,8 +370,53 @@ export async function readIndentationBlock( // Load all lines const records = await collectFileLines(filePath) - if (records.length === 0 || anchorLine > records.length) { - throw new RangeError("anchorLine exceeds file length") + // If the file is empty, match slice mode and return an empty page. + if (records.length === 0) { + return { + content: "", + lineCount: 0, + totalLines: 0, + metadata: { + filePath, + totalLinesInFile: 0, + linesReturned: 0, + startLine: anchorLine, + endLine: anchorLine, + hasMoreBefore: anchorLine > 1, + hasMoreAfter: false, + linesBeforeStart: 0, + linesAfterEnd: 0, + truncatedByLimit: false, + lineLengthTruncations: [], + }, + } + } + + // If offset is out-of-range and no explicit anchorLine was provided, match slice mode and return an empty page. + if (anchorLine > records.length) { + if (hasExplicitAnchorLine) { + throw new RangeError("anchorLine exceeds file length") + } + + const totalLines = records.length + return { + content: "", + lineCount: 0, + totalLines, + metadata: { + filePath, + totalLinesInFile: totalLines, + linesReturned: 0, + startLine: anchorLine, + endLine: anchorLine, + hasMoreBefore: anchorLine > 1, + hasMoreAfter: false, + linesBeforeStart: Math.min(anchorLine - 1, totalLines), + linesAfterEnd: 0, + truncatedByLimit: false, + lineLengthTruncations: [], + }, + } } const anchorIndex = anchorLine - 1