bug(core): UI reporting for truncated read_file. (#5155)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
parent
65be9cab47
commit
ae86c7ba05
|
@ -222,7 +222,7 @@ describe('ReadFileTool', () => {
|
||||||
'Line 7',
|
'Line 7',
|
||||||
'Line 8',
|
'Line 8',
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
returnDisplay: '(truncated)',
|
returnDisplay: 'Read lines 6-8 of 20 from paginated.txt',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -420,7 +420,7 @@ describe('fileUtils', () => {
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'[File content truncated: showing lines 6-10 of 20 total lines. Use offset/limit parameters to view more.]',
|
'[File content truncated: showing lines 6-10 of 20 total lines. Use offset/limit parameters to view more.]',
|
||||||
);
|
);
|
||||||
expect(result.returnDisplay).toBe('(truncated)');
|
expect(result.returnDisplay).toBe('Read lines 6-10 of 20 from test.txt');
|
||||||
expect(result.isTruncated).toBe(true);
|
expect(result.isTruncated).toBe(true);
|
||||||
expect(result.originalLineCount).toBe(20);
|
expect(result.originalLineCount).toBe(20);
|
||||||
expect(result.linesShown).toEqual([6, 10]);
|
expect(result.linesShown).toEqual([6, 10]);
|
||||||
|
@ -465,9 +465,72 @@ describe('fileUtils', () => {
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'[File content partially truncated: some lines exceeded maximum length of 2000 characters.]',
|
'[File content partially truncated: some lines exceeded maximum length of 2000 characters.]',
|
||||||
);
|
);
|
||||||
|
expect(result.returnDisplay).toBe(
|
||||||
|
'Read all 3 lines from test.txt (some lines were shortened)',
|
||||||
|
);
|
||||||
expect(result.isTruncated).toBe(true);
|
expect(result.isTruncated).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should truncate when line count exceeds the limit', async () => {
|
||||||
|
const lines = Array.from({ length: 11 }, (_, i) => `Line ${i + 1}`);
|
||||||
|
actualNodeFs.writeFileSync(testTextFilePath, lines.join('\n'));
|
||||||
|
|
||||||
|
// Read 5 lines, but there are 11 total
|
||||||
|
const result = await processSingleFileContent(
|
||||||
|
testTextFilePath,
|
||||||
|
tempRootDir,
|
||||||
|
0,
|
||||||
|
5,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.isTruncated).toBe(true);
|
||||||
|
expect(result.returnDisplay).toBe('Read lines 1-5 of 11 from test.txt');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should truncate when a line length exceeds the character limit', async () => {
|
||||||
|
const longLine = 'b'.repeat(2500);
|
||||||
|
const lines = Array.from({ length: 10 }, (_, i) => `Line ${i + 1}`);
|
||||||
|
lines.push(longLine); // Total 11 lines
|
||||||
|
actualNodeFs.writeFileSync(testTextFilePath, lines.join('\n'));
|
||||||
|
|
||||||
|
// Read all 11 lines, including the long one
|
||||||
|
const result = await processSingleFileContent(
|
||||||
|
testTextFilePath,
|
||||||
|
tempRootDir,
|
||||||
|
0,
|
||||||
|
11,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.isTruncated).toBe(true);
|
||||||
|
expect(result.returnDisplay).toBe(
|
||||||
|
'Read all 11 lines from test.txt (some lines were shortened)',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should truncate both line count and line length when both exceed limits', async () => {
|
||||||
|
const linesWithLongInMiddle = Array.from(
|
||||||
|
{ length: 20 },
|
||||||
|
(_, i) => `Line ${i + 1}`,
|
||||||
|
);
|
||||||
|
linesWithLongInMiddle[4] = 'c'.repeat(2500);
|
||||||
|
actualNodeFs.writeFileSync(
|
||||||
|
testTextFilePath,
|
||||||
|
linesWithLongInMiddle.join('\n'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Read 10 lines out of 20, including the long line
|
||||||
|
const result = await processSingleFileContent(
|
||||||
|
testTextFilePath,
|
||||||
|
tempRootDir,
|
||||||
|
0,
|
||||||
|
10,
|
||||||
|
);
|
||||||
|
expect(result.isTruncated).toBe(true);
|
||||||
|
expect(result.returnDisplay).toBe(
|
||||||
|
'Read lines 1-10 of 20 from test.txt (some lines were shortened)',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should return an error if the file size exceeds 20MB', async () => {
|
it('should return an error if the file size exceeds 20MB', async () => {
|
||||||
// Create a file just over 20MB
|
// Create a file just over 20MB
|
||||||
const twentyOneMB = 21 * 1024 * 1024;
|
const twentyOneMB = 21 * 1024 * 1024;
|
||||||
|
|
|
@ -310,9 +310,22 @@ export async function processSingleFileContent(
|
||||||
}
|
}
|
||||||
llmTextContent += formattedLines.join('\n');
|
llmTextContent += formattedLines.join('\n');
|
||||||
|
|
||||||
|
// By default, return nothing to streamline the common case of a successful read_file.
|
||||||
|
let returnDisplay = '';
|
||||||
|
if (contentRangeTruncated) {
|
||||||
|
returnDisplay = `Read lines ${
|
||||||
|
actualStartLine + 1
|
||||||
|
}-${endLine} of ${originalLineCount} from ${relativePathForDisplay}`;
|
||||||
|
if (linesWereTruncatedInLength) {
|
||||||
|
returnDisplay += ' (some lines were shortened)';
|
||||||
|
}
|
||||||
|
} else if (linesWereTruncatedInLength) {
|
||||||
|
returnDisplay = `Read all ${originalLineCount} lines from ${relativePathForDisplay} (some lines were shortened)`;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
llmContent: llmTextContent,
|
llmContent: llmTextContent,
|
||||||
returnDisplay: isTruncated ? '(truncated)' : '',
|
returnDisplay,
|
||||||
isTruncated,
|
isTruncated,
|
||||||
originalLineCount,
|
originalLineCount,
|
||||||
linesShown: [actualStartLine + 1, endLine],
|
linesShown: [actualStartLine + 1, endLine],
|
||||||
|
|
Loading…
Reference in New Issue