feat(core): migrate read_file to 1-based start_line/end_line parameters (#19526)

This commit is contained in:
Adam Weidman
2026-02-20 17:59:18 -05:00
committed by GitHub
parent 58d637f919
commit 547f5d45f5
10 changed files with 140 additions and 106 deletions
+33 -21
View File
@@ -53,7 +53,7 @@ export async function loadWasmBinary(
}
// Constants for text file processing
const DEFAULT_MAX_LINES_TEXT_FILE = 2000;
export const DEFAULT_MAX_LINES_TEXT_FILE = 2000;
const MAX_LINE_LENGTH_TEXT_FILE = 2000;
// Default values for encoding and separator format
@@ -399,16 +399,17 @@ export interface ProcessedFileReadResult {
* Reads and processes a single file, handling text, images, and PDFs.
* @param filePath Absolute path to the file.
* @param rootDirectory Absolute path to the project root for relative path display.
* @param offset Optional offset for text files (0-based line number).
* @param limit Optional limit for text files (number of lines to read).
* @param _fileSystemService Currently unused in this function; kept for signature stability.
* @param startLine Optional 1-based line number to start reading from.
* @param endLine Optional 1-based line number to end reading at (inclusive).
* @returns ProcessedFileReadResult object.
*/
export async function processSingleFileContent(
filePath: string,
rootDirectory: string,
fileSystemService: FileSystemService,
offset?: number,
limit?: number,
_fileSystemService: FileSystemService,
startLine?: number,
endLine?: number,
): Promise<ProcessedFileReadResult> {
try {
if (!fs.existsSync(filePath)) {
@@ -474,14 +475,24 @@ export async function processSingleFileContent(
const lines = content.split('\n');
const originalLineCount = lines.length;
const startLine = offset || 0;
const effectiveLimit =
limit === undefined ? DEFAULT_MAX_LINES_TEXT_FILE : limit;
// Ensure endLine does not exceed originalLineCount
const endLine = Math.min(startLine + effectiveLimit, originalLineCount);
// Ensure selectedLines doesn't try to slice beyond array bounds if startLine is too high
const actualStartLine = Math.min(startLine, originalLineCount);
const selectedLines = lines.slice(actualStartLine, endLine);
let sliceStart = 0;
let sliceEnd = originalLineCount;
if (startLine !== undefined || endLine !== undefined) {
sliceStart = startLine ? startLine - 1 : 0;
sliceEnd = endLine
? Math.min(endLine, originalLineCount)
: Math.min(
sliceStart + DEFAULT_MAX_LINES_TEXT_FILE,
originalLineCount,
);
} else {
sliceEnd = Math.min(DEFAULT_MAX_LINES_TEXT_FILE, originalLineCount);
}
// Ensure selectedLines doesn't try to slice beyond array bounds
const actualStart = Math.min(sliceStart, originalLineCount);
const selectedLines = lines.slice(actualStart, sliceEnd);
let linesWereTruncatedInLength = false;
const formattedLines = selectedLines.map((line) => {
@@ -494,17 +505,18 @@ export async function processSingleFileContent(
return line;
});
const contentRangeTruncated =
startLine > 0 || endLine < originalLineCount;
const isTruncated = contentRangeTruncated || linesWereTruncatedInLength;
const isTruncated =
actualStart > 0 ||
sliceEnd < originalLineCount ||
linesWereTruncatedInLength;
const llmContent = formattedLines.join('\n');
// By default, return nothing to streamline the common case of a successful read_file.
let returnDisplay = '';
if (contentRangeTruncated) {
if (actualStart > 0 || sliceEnd < originalLineCount) {
returnDisplay = `Read lines ${
actualStartLine + 1
}-${endLine} of ${originalLineCount} from ${relativePathForDisplay}`;
actualStart + 1
}-${sliceEnd} of ${originalLineCount} from ${relativePathForDisplay}`;
if (linesWereTruncatedInLength) {
returnDisplay += ' (some lines were shortened)';
}
@@ -517,7 +529,7 @@ export async function processSingleFileContent(
returnDisplay,
isTruncated,
originalLineCount,
linesShown: [actualStartLine + 1, endLine],
linesShown: [actualStart + 1, sliceEnd],
};
}
case 'image':