@@ -31,6 +31,7 @@ import {
3131import { countFileLines } from "../integrations/misc/line-counter"
3232import { fetchInstructionsTool } from "./tools/fetchInstructionsTool"
3333import { listFilesTool } from "./tools/listFilesTool"
34+ import { readFileTool } from "./tools/readFileTool"
3435import { ExitCodeDetails } from "../integrations/terminal/TerminalProcess"
3536import { Terminal } from "../integrations/terminal/Terminal"
3637import { TerminalRegistry } from "../integrations/terminal/TerminalRegistry"
@@ -83,9 +84,7 @@ import { insertGroups } from "./diff/insert-groups"
8384import { telemetryService } from "../services/telemetry/TelemetryService"
8485import { validateToolUse , isToolAllowedForMode , ToolName } from "./mode-validator"
8586import { parseXml } from "../utils/xml"
86- import { readLines } from "../integrations/misc/read-lines"
8787import { getWorkspacePath } from "../utils/path"
88- import { isBinaryFile } from "isbinaryfile"
8988
9089export type ToolResponse = string | Array < Anthropic . TextBlockParam | Anthropic . ImageBlockParam >
9190type UserContent = Array < Anthropic . Messages . ContentBlockParam >
@@ -2257,151 +2256,8 @@ export class Cline extends EventEmitter<ClineEvents> {
22572256 }
22582257
22592258 case "read_file" : {
2260- const relPath : string | undefined = block . params . path
2261- const startLineStr : string | undefined = block . params . start_line
2262- const endLineStr : string | undefined = block . params . end_line
2263-
2264- // Get the full path and determine if it's outside the workspace
2265- const fullPath = relPath ? path . resolve ( this . cwd , removeClosingTag ( "path" , relPath ) ) : ""
2266- const isOutsideWorkspace = isPathOutsideWorkspace ( fullPath )
2267-
2268- const sharedMessageProps : ClineSayTool = {
2269- tool : "readFile" ,
2270- path : getReadablePath ( this . cwd , removeClosingTag ( "path" , relPath ) ) ,
2271- isOutsideWorkspace,
2272- }
2273- try {
2274- if ( block . partial ) {
2275- const partialMessage = JSON . stringify ( {
2276- ...sharedMessageProps ,
2277- content : undefined ,
2278- } satisfies ClineSayTool )
2279- await this . ask ( "tool" , partialMessage , block . partial ) . catch ( ( ) => { } )
2280- break
2281- } else {
2282- if ( ! relPath ) {
2283- this . consecutiveMistakeCount ++
2284- pushToolResult ( await this . sayAndCreateMissingParamError ( "read_file" , "path" ) )
2285- break
2286- }
2287-
2288- // Check if we're doing a line range read
2289- let isRangeRead = false
2290- let startLine : number | undefined = undefined
2291- let endLine : number | undefined = undefined
2292-
2293- // Check if we have either range parameter
2294- if ( startLineStr || endLineStr ) {
2295- isRangeRead = true
2296- }
2297-
2298- // Parse start_line if provided
2299- if ( startLineStr ) {
2300- startLine = parseInt ( startLineStr )
2301- if ( isNaN ( startLine ) ) {
2302- // Invalid start_line
2303- this . consecutiveMistakeCount ++
2304- await this . say ( "error" , `Failed to parse start_line: ${ startLineStr } ` )
2305- pushToolResult ( formatResponse . toolError ( "Invalid start_line value" ) )
2306- break
2307- }
2308- startLine -= 1 // Convert to 0-based index
2309- }
2310-
2311- // Parse end_line if provided
2312- if ( endLineStr ) {
2313- endLine = parseInt ( endLineStr )
2314-
2315- if ( isNaN ( endLine ) ) {
2316- // Invalid end_line
2317- this . consecutiveMistakeCount ++
2318- await this . say ( "error" , `Failed to parse end_line: ${ endLineStr } ` )
2319- pushToolResult ( formatResponse . toolError ( "Invalid end_line value" ) )
2320- break
2321- }
2322-
2323- // Convert to 0-based index
2324- endLine -= 1
2325- }
2326-
2327- const accessAllowed = this . rooIgnoreController ?. validateAccess ( relPath )
2328- if ( ! accessAllowed ) {
2329- await this . say ( "rooignore_error" , relPath )
2330- pushToolResult ( formatResponse . toolError ( formatResponse . rooIgnoreError ( relPath ) ) )
2331-
2332- break
2333- }
2334-
2335- this . consecutiveMistakeCount = 0
2336- const absolutePath = path . resolve ( this . cwd , relPath )
2337- const completeMessage = JSON . stringify ( {
2338- ...sharedMessageProps ,
2339- content : absolutePath ,
2340- } satisfies ClineSayTool )
2341-
2342- const didApprove = await askApproval ( "tool" , completeMessage )
2343- if ( ! didApprove ) {
2344- break
2345- }
2346-
2347- // Get the maxReadFileLine setting
2348- const { maxReadFileLine = 500 } = ( await this . providerRef . deref ( ) ?. getState ( ) ) ?? { }
2349-
2350- // Count total lines in the file
2351- let totalLines = 0
2352- try {
2353- totalLines = await countFileLines ( absolutePath )
2354- } catch ( error ) {
2355- console . error ( `Error counting lines in file ${ absolutePath } :` , error )
2356- }
2357-
2358- // now execute the tool like normal
2359- let content : string
2360- let isFileTruncated = false
2361- let sourceCodeDef = ""
2362-
2363- const isBinary = await isBinaryFile ( absolutePath ) . catch ( ( ) => false )
2364-
2365- if ( isRangeRead ) {
2366- if ( startLine === undefined ) {
2367- content = addLineNumbers ( await readLines ( absolutePath , endLine , startLine ) )
2368- } else {
2369- content = addLineNumbers (
2370- await readLines ( absolutePath , endLine , startLine ) ,
2371- startLine + 1 ,
2372- )
2373- }
2374- } else if ( ! isBinary && maxReadFileLine >= 0 && totalLines > maxReadFileLine ) {
2375- // If file is too large, only read the first maxReadFileLine lines
2376- isFileTruncated = true
2377-
2378- const res = await Promise . all ( [
2379- maxReadFileLine > 0 ? readLines ( absolutePath , maxReadFileLine - 1 , 0 ) : "" ,
2380- parseSourceCodeDefinitionsForFile ( absolutePath , this . rooIgnoreController ) ,
2381- ] )
2382-
2383- content = res [ 0 ] . length > 0 ? addLineNumbers ( res [ 0 ] ) : ""
2384- const result = res [ 1 ]
2385- if ( result ) {
2386- sourceCodeDef = `\n\n${ result } `
2387- }
2388- } else {
2389- // Read entire file
2390- content = await extractTextFromFile ( absolutePath )
2391- }
2392-
2393- // Add truncation notice if applicable
2394- if ( isFileTruncated ) {
2395- content += `\n\n[Showing only ${ maxReadFileLine } of ${ totalLines } total lines. Use start_line and end_line if you need to read more]${ sourceCodeDef } `
2396- }
2397-
2398- pushToolResult ( content )
2399- break
2400- }
2401- } catch ( error ) {
2402- await handleError ( "reading file" , error )
2403- break
2404- }
2259+ readFileTool ( this , block , askApproval , handleError , pushToolResult , removeClosingTag )
2260+ break
24052261 }
24062262
24072263 case "fetch_instructions" : {
0 commit comments