Skip to content

Commit c5112cd

Browse files
fix(core): truncate excessively long lines in grep search output (#21147)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent c72cfad commit c5112cd

3 files changed

Lines changed: 51 additions & 1 deletion

File tree

packages/core/src/tools/grep-utils.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import fsPromises from 'node:fs/promises';
88
import { debugLogger } from '../utils/debugLogger.js';
9+
import { MAX_LINE_LENGTH_TEXT_FILE } from '../utils/constants.js';
910

1011
/**
1112
* Result object for a single grep match
@@ -198,7 +199,14 @@ export async function formatGrepResults(
198199
// If isContext is undefined, assume it's a match (false)
199200
const separator = match.isContext ? '-' : ':';
200201
// trimEnd to avoid double newlines if line has them, but we want to preserve indentation
201-
llmContent += `L${match.lineNumber}${separator} ${match.line.trimEnd()}\n`;
202+
let lineContent = match.line.trimEnd();
203+
const graphemes = Array.from(lineContent);
204+
if (graphemes.length > MAX_LINE_LENGTH_TEXT_FILE) {
205+
lineContent =
206+
graphemes.slice(0, MAX_LINE_LENGTH_TEXT_FILE).join('') +
207+
'... [truncated]';
208+
}
209+
llmContent += `L${match.lineNumber}${separator} ${lineContent}\n`;
202210
});
203211
llmContent += '---\n';
204212
}

packages/core/src/tools/grep.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,22 @@ describe('GrepTool', () => {
562562
// Verify context after
563563
expect(result.llmContent).toContain('L60- Line 60');
564564
});
565+
566+
it('should truncate excessively long lines', async () => {
567+
const longString = 'a'.repeat(3000);
568+
await fs.writeFile(
569+
path.join(tempRootDir, 'longline.txt'),
570+
`Target match ${longString}`,
571+
);
572+
573+
const params: GrepToolParams = { pattern: 'Target match' };
574+
const invocation = grepTool.build(params);
575+
const result = await invocation.execute(abortSignal);
576+
577+
// MAX_LINE_LENGTH_TEXT_FILE is 2000. It should be truncated.
578+
expect(result.llmContent).toContain('... [truncated]');
579+
expect(result.llmContent).not.toContain(longString);
580+
});
565581
});
566582

567583
describe('getDescription', () => {

packages/core/src/tools/ripGrep.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,6 +2028,32 @@ describe('RipGrepTool', () => {
20282028
expect(result.llmContent).not.toContain('fileB.txt');
20292029
expect(result.llmContent).toContain('Copyright 2025 Google LLC');
20302030
});
2031+
2032+
it('should truncate excessively long lines', async () => {
2033+
const longString = 'a'.repeat(3000);
2034+
mockSpawn.mockImplementation(
2035+
createMockSpawn({
2036+
outputData:
2037+
JSON.stringify({
2038+
type: 'match',
2039+
data: {
2040+
path: { text: 'longline.txt' },
2041+
line_number: 1,
2042+
lines: { text: `Target match ${longString}\n` },
2043+
},
2044+
}) + '\n',
2045+
exitCode: 0,
2046+
}),
2047+
);
2048+
2049+
const params: RipGrepToolParams = { pattern: 'Target match', context: 0 };
2050+
const invocation = grepTool.build(params);
2051+
const result = await invocation.execute(abortSignal);
2052+
2053+
// MAX_LINE_LENGTH_TEXT_FILE is 2000. It should be truncated.
2054+
expect(result.llmContent).toContain('... [truncated]');
2055+
expect(result.llmContent).not.toContain(longString);
2056+
});
20312057
});
20322058
});
20332059

0 commit comments

Comments
 (0)