Skip to content

Commit d483e4b

Browse files
committed
Extract code for read_file from Cline
1 parent 62a7bc7 commit d483e4b

File tree

4 files changed

+373
-390
lines changed

4 files changed

+373
-390
lines changed

src/core/Cline.ts

Lines changed: 3 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
} from "../integrations/misc/extract-text"
3131
import { countFileLines } from "../integrations/misc/line-counter"
3232
import { fetchInstructionsTool } from "./tools/fetchInstructionsTool"
33+
import { readFileTool } from "./tools/readFileTool"
3334
import { ExitCodeDetails } from "../integrations/terminal/TerminalProcess"
3435
import { Terminal } from "../integrations/terminal/Terminal"
3536
import { TerminalRegistry } from "../integrations/terminal/TerminalRegistry"
@@ -82,9 +83,7 @@ import { insertGroups } from "./diff/insert-groups"
8283
import { telemetryService } from "../services/telemetry/TelemetryService"
8384
import { validateToolUse, isToolAllowedForMode, ToolName } from "./mode-validator"
8485
import { parseXml } from "../utils/xml"
85-
import { readLines } from "../integrations/misc/read-lines"
8686
import { getWorkspacePath } from "../utils/path"
87-
import { isBinaryFile } from "isbinaryfile"
8887

8988
export type ToolResponse = string | Array<Anthropic.TextBlockParam | Anthropic.ImageBlockParam>
9089
type UserContent = Array<Anthropic.Messages.ContentBlockParam>
@@ -2256,151 +2255,8 @@ export class Cline extends EventEmitter<ClineEvents> {
22562255
}
22572256

22582257
case "read_file": {
2259-
const relPath: string | undefined = block.params.path
2260-
const startLineStr: string | undefined = block.params.start_line
2261-
const endLineStr: string | undefined = block.params.end_line
2262-
2263-
// Get the full path and determine if it's outside the workspace
2264-
const fullPath = relPath ? path.resolve(this.cwd, removeClosingTag("path", relPath)) : ""
2265-
const isOutsideWorkspace = isPathOutsideWorkspace(fullPath)
2266-
2267-
const sharedMessageProps: ClineSayTool = {
2268-
tool: "readFile",
2269-
path: getReadablePath(this.cwd, removeClosingTag("path", relPath)),
2270-
isOutsideWorkspace,
2271-
}
2272-
try {
2273-
if (block.partial) {
2274-
const partialMessage = JSON.stringify({
2275-
...sharedMessageProps,
2276-
content: undefined,
2277-
} satisfies ClineSayTool)
2278-
await this.ask("tool", partialMessage, block.partial).catch(() => {})
2279-
break
2280-
} else {
2281-
if (!relPath) {
2282-
this.consecutiveMistakeCount++
2283-
pushToolResult(await this.sayAndCreateMissingParamError("read_file", "path"))
2284-
break
2285-
}
2286-
2287-
// Check if we're doing a line range read
2288-
let isRangeRead = false
2289-
let startLine: number | undefined = undefined
2290-
let endLine: number | undefined = undefined
2291-
2292-
// Check if we have either range parameter
2293-
if (startLineStr || endLineStr) {
2294-
isRangeRead = true
2295-
}
2296-
2297-
// Parse start_line if provided
2298-
if (startLineStr) {
2299-
startLine = parseInt(startLineStr)
2300-
if (isNaN(startLine)) {
2301-
// Invalid start_line
2302-
this.consecutiveMistakeCount++
2303-
await this.say("error", `Failed to parse start_line: ${startLineStr}`)
2304-
pushToolResult(formatResponse.toolError("Invalid start_line value"))
2305-
break
2306-
}
2307-
startLine -= 1 // Convert to 0-based index
2308-
}
2309-
2310-
// Parse end_line if provided
2311-
if (endLineStr) {
2312-
endLine = parseInt(endLineStr)
2313-
2314-
if (isNaN(endLine)) {
2315-
// Invalid end_line
2316-
this.consecutiveMistakeCount++
2317-
await this.say("error", `Failed to parse end_line: ${endLineStr}`)
2318-
pushToolResult(formatResponse.toolError("Invalid end_line value"))
2319-
break
2320-
}
2321-
2322-
// Convert to 0-based index
2323-
endLine -= 1
2324-
}
2325-
2326-
const accessAllowed = this.rooIgnoreController?.validateAccess(relPath)
2327-
if (!accessAllowed) {
2328-
await this.say("rooignore_error", relPath)
2329-
pushToolResult(formatResponse.toolError(formatResponse.rooIgnoreError(relPath)))
2330-
2331-
break
2332-
}
2333-
2334-
this.consecutiveMistakeCount = 0
2335-
const absolutePath = path.resolve(this.cwd, relPath)
2336-
const completeMessage = JSON.stringify({
2337-
...sharedMessageProps,
2338-
content: absolutePath,
2339-
} satisfies ClineSayTool)
2340-
2341-
const didApprove = await askApproval("tool", completeMessage)
2342-
if (!didApprove) {
2343-
break
2344-
}
2345-
2346-
// Get the maxReadFileLine setting
2347-
const { maxReadFileLine = 500 } = (await this.providerRef.deref()?.getState()) ?? {}
2348-
2349-
// Count total lines in the file
2350-
let totalLines = 0
2351-
try {
2352-
totalLines = await countFileLines(absolutePath)
2353-
} catch (error) {
2354-
console.error(`Error counting lines in file ${absolutePath}:`, error)
2355-
}
2356-
2357-
// now execute the tool like normal
2358-
let content: string
2359-
let isFileTruncated = false
2360-
let sourceCodeDef = ""
2361-
2362-
const isBinary = await isBinaryFile(absolutePath).catch(() => false)
2363-
2364-
if (isRangeRead) {
2365-
if (startLine === undefined) {
2366-
content = addLineNumbers(await readLines(absolutePath, endLine, startLine))
2367-
} else {
2368-
content = addLineNumbers(
2369-
await readLines(absolutePath, endLine, startLine),
2370-
startLine + 1,
2371-
)
2372-
}
2373-
} else if (!isBinary && maxReadFileLine >= 0 && totalLines > maxReadFileLine) {
2374-
// If file is too large, only read the first maxReadFileLine lines
2375-
isFileTruncated = true
2376-
2377-
const res = await Promise.all([
2378-
maxReadFileLine > 0 ? readLines(absolutePath, maxReadFileLine - 1, 0) : "",
2379-
parseSourceCodeDefinitionsForFile(absolutePath, this.rooIgnoreController),
2380-
])
2381-
2382-
content = res[0].length > 0 ? addLineNumbers(res[0]) : ""
2383-
const result = res[1]
2384-
if (result) {
2385-
sourceCodeDef = `\n\n${result}`
2386-
}
2387-
} else {
2388-
// Read entire file
2389-
content = await extractTextFromFile(absolutePath)
2390-
}
2391-
2392-
// Add truncation notice if applicable
2393-
if (isFileTruncated) {
2394-
content += `\n\n[Showing only ${maxReadFileLine} of ${totalLines} total lines. Use start_line and end_line if you need to read more]${sourceCodeDef}`
2395-
}
2396-
2397-
pushToolResult(content)
2398-
break
2399-
}
2400-
} catch (error) {
2401-
await handleError("reading file", error)
2402-
break
2403-
}
2258+
readFileTool(this, block, askApproval, handleError, pushToolResult, removeClosingTag)
2259+
break
24042260
}
24052261

24062262
case "fetch_instructions": {

0 commit comments

Comments
 (0)