Selaa lähdekoodia

feat: remove simpleReadFileTool completely (#10254)

- Delete simpleReadFileTool.ts file
- Delete simple-read-file.ts prompt description file
- Delete single-file-read-models.ts types file
- Remove imports and usage from presentAssistantMessage.ts
- Remove imports and usage from prompts/tools/index.ts
- Remove export from packages/types/src/index.ts

This removes all traces of the legacy single-file read tool implementation that was used for specific models. All models now use the standard read_file tool.

Co-authored-by: Roo Code <[email protected]>
roomote[bot] 4 päivää sitten
vanhempi
sitoutus
a510223a09

+ 0 - 1
packages/types/src/index.ts

@@ -17,7 +17,6 @@ export * from "./message.js"
 export * from "./mode.js"
 export * from "./model.js"
 export * from "./provider-settings.js"
-export * from "./single-file-read-models.js"
 export * from "./task.js"
 export * from "./todo.js"
 export * from "./telemetry.js"

+ 0 - 14
packages/types/src/single-file-read-models.ts

@@ -1,14 +0,0 @@
-/**
- * Configuration for models that should use simplified single-file read_file tool
- * These models will use the simpler <read_file><path>...</path></read_file> format
- * instead of the more complex multi-file args format
- */
-
-/**
- * Check if a model should use single file read format
- * @param modelId The model ID to check
- * @returns true if the model should use single file reads
- */
-export function shouldUseSingleFileRead(modelId: string): boolean {
-	return modelId.includes("grok-code-fast-1") || modelId.includes("code-supernova")
-}

+ 14 - 36
src/core/assistant-message/presentAssistantMessage.ts

@@ -19,8 +19,7 @@ import { Task } from "../task/Task"
 import { fetchInstructionsTool } from "../tools/FetchInstructionsTool"
 import { listFilesTool } from "../tools/ListFilesTool"
 import { readFileTool } from "../tools/ReadFileTool"
-import { getSimpleReadFileToolDescription, simpleReadFileTool } from "../tools/simpleReadFileTool"
-import { shouldUseSingleFileRead, TOOL_PROTOCOL } from "@roo-code/types"
+import { TOOL_PROTOCOL } from "@roo-code/types"
 import { writeToFileTool } from "../tools/WriteToFileTool"
 import { applyDiffTool } from "../tools/MultiApplyDiffTool"
 import { searchAndReplaceTool } from "../tools/SearchAndReplaceTool"
@@ -363,18 +362,12 @@ export async function presentAssistantMessage(cline: Task) {
 					case "execute_command":
 						return `[${block.name} for '${block.params.command}']`
 					case "read_file":
-						// Check if this model should use the simplified description
-						const modelId = cline.api.getModel().id
-						if (shouldUseSingleFileRead(modelId)) {
-							return getSimpleReadFileToolDescription(block.name, block.params)
-						} else {
-							// Prefer native typed args when available; fall back to legacy params
-							// Check if nativeArgs exists (native protocol)
-							if (block.nativeArgs) {
-								return readFileTool.getReadFileToolDescription(block.name, block.nativeArgs)
-							}
-							return readFileTool.getReadFileToolDescription(block.name, block.params)
+						// Prefer native typed args when available; fall back to legacy params
+						// Check if nativeArgs exists (native protocol)
+						if (block.nativeArgs) {
+							return readFileTool.getReadFileToolDescription(block.name, block.nativeArgs)
 						}
+						return readFileTool.getReadFileToolDescription(block.name, block.params)
 					case "fetch_instructions":
 						return `[${block.name} for '${block.params.task}']`
 					case "write_to_file":
@@ -909,29 +902,14 @@ export async function presentAssistantMessage(cline: Task) {
 					})
 					break
 				case "read_file":
-					// Check if this model should use the simplified single-file read tool
-					// Only use simplified tool for XML protocol - native protocol works with standard tool
-					const modelId = cline.api.getModel().id
-					if (shouldUseSingleFileRead(modelId) && toolProtocol !== TOOL_PROTOCOL.NATIVE) {
-						await simpleReadFileTool(
-							cline,
-							block,
-							askApproval,
-							handleError,
-							pushToolResult,
-							removeClosingTag,
-							toolProtocol,
-						)
-					} else {
-						// Type assertion is safe here because we're in the "read_file" case
-						await readFileTool.handle(cline, block as ToolUse<"read_file">, {
-							askApproval,
-							handleError,
-							pushToolResult,
-							removeClosingTag,
-							toolProtocol,
-						})
-					}
+					// Type assertion is safe here because we're in the "read_file" case
+					await readFileTool.handle(cline, block as ToolUse<"read_file">, {
+						askApproval,
+						handleError,
+						pushToolResult,
+						removeClosingTag,
+						toolProtocol,
+					})
 					break
 				case "fetch_instructions":
 					await fetchInstructionsTool.handle(cline, block as ToolUse<"fetch_instructions">, {

+ 1 - 11
src/core/prompts/tools/index.ts

@@ -1,5 +1,4 @@
 import type { ToolName, ModeConfig } from "@roo-code/types"
-import { shouldUseSingleFileRead } from "@roo-code/types"
 
 import { TOOL_GROUPS, ALWAYS_AVAILABLE_TOOLS, DiffStrategy } from "../../../shared/tools"
 import { Mode, getModeConfig, getGroupName } from "../../../shared/modes"
@@ -12,7 +11,6 @@ import { CodeIndexManager } from "../../../services/code-index/manager"
 import { ToolArgs } from "./types"
 import { getExecuteCommandDescription } from "./execute-command"
 import { getReadFileDescription } from "./read-file"
-import { getSimpleReadFileDescription } from "./simple-read-file"
 import { getFetchInstructionsDescription } from "./fetch-instructions"
 import { getWriteToFileDescription } from "./write-to-file"
 import { getSearchFilesDescription } from "./search-files"
@@ -32,14 +30,7 @@ import { getGenerateImageDescription } from "./generate-image"
 // Map of tool names to their description functions
 const toolDescriptionMap: Record<string, (args: ToolArgs) => string | undefined> = {
 	execute_command: (args) => getExecuteCommandDescription(args),
-	read_file: (args) => {
-		// Check if the current model should use the simplified read_file tool
-		const modelId = args.settings?.modelId
-		if (modelId && shouldUseSingleFileRead(modelId)) {
-			return getSimpleReadFileDescription(args)
-		}
-		return getReadFileDescription(args)
-	},
+	read_file: (args) => getReadFileDescription(args),
 	fetch_instructions: (args) => getFetchInstructionsDescription(args.settings?.enableMcpServerCreation),
 	write_to_file: (args) => getWriteToFileDescription(args),
 	search_files: (args) => getSearchFilesDescription(args),
@@ -162,7 +153,6 @@ export function getToolDescriptionsForMode(
 export {
 	getExecuteCommandDescription,
 	getReadFileDescription,
-	getSimpleReadFileDescription,
 	getFetchInstructionsDescription,
 	getWriteToFileDescription,
 	getSearchFilesDescription,

+ 0 - 35
src/core/prompts/tools/simple-read-file.ts

@@ -1,35 +0,0 @@
-import { ToolArgs } from "./types"
-
-/**
- * Generate a simplified read_file tool description for models that only support single file reads
- * Uses the simpler format: <read_file><path>file/path.ext</path></read_file>
- */
-export function getSimpleReadFileDescription(args: ToolArgs): string {
-	return `## read_file
-Description: Request to read the contents of a file. The tool outputs line-numbered content (e.g. "1 | const x = 1") for easy reference when discussing code.
-
-Parameters:
-- path: (required) File path (relative to workspace directory ${args.cwd})
-
-Usage:
-<read_file>
-<path>path/to/file</path>
-</read_file>
-
-Examples:
-
-1. Reading a TypeScript file:
-<read_file>
-<path>src/app.ts</path>
-</read_file>
-
-2. Reading a configuration file:
-<read_file>
-<path>config.json</path>
-</read_file>
-
-3. Reading a markdown file:
-<read_file>
-<path>README.md</path>
-</read_file>`
-}

+ 0 - 289
src/core/tools/simpleReadFileTool.ts

@@ -1,289 +0,0 @@
-import path from "path"
-import { isBinaryFile } from "isbinaryfile"
-
-import { Task } from "../task/Task"
-import { ClineSayTool } from "../../shared/ExtensionMessage"
-import { formatResponse } from "../prompts/responses"
-import { t } from "../../i18n"
-import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
-import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
-import { isPathOutsideWorkspace } from "../../utils/pathUtils"
-import { getReadablePath } from "../../utils/path"
-import { countFileLines } from "../../integrations/misc/line-counter"
-import { readLines } from "../../integrations/misc/read-lines"
-import { extractTextFromFile, addLineNumbers, getSupportedBinaryFormats } from "../../integrations/misc/extract-text"
-import { parseSourceCodeDefinitionsForFile } from "../../services/tree-sitter"
-import { ToolProtocol, isNativeProtocol } from "@roo-code/types"
-import {
-	DEFAULT_MAX_IMAGE_FILE_SIZE_MB,
-	DEFAULT_MAX_TOTAL_IMAGE_SIZE_MB,
-	isSupportedImageFormat,
-	validateImageForProcessing,
-	processImageFile,
-} from "./helpers/imageHelpers"
-
-/**
- * Simplified read file tool for models that only support single file reads
- * Uses the format: <read_file><path>file/path.ext</path></read_file>
- *
- * This is a streamlined version of readFileTool that:
- * - Only accepts a single path parameter
- * - Does not support multiple files
- * - Does not support line ranges
- * - Has simpler XML parsing
- */
-export async function simpleReadFileTool(
-	cline: Task,
-	block: ToolUse,
-	askApproval: AskApproval,
-	handleError: HandleError,
-	pushToolResult: PushToolResult,
-	_removeClosingTag: RemoveClosingTag,
-	toolProtocol?: ToolProtocol,
-) {
-	const filePath: string | undefined = block.params.path
-
-	// Check if the current model supports images
-	const modelInfo = cline.api.getModel().info
-	const supportsImages = modelInfo.supportsImages ?? false
-
-	// Handle partial message
-	if (block.partial) {
-		const fullPath = filePath ? path.resolve(cline.cwd, filePath) : ""
-		const sharedMessageProps: ClineSayTool = {
-			tool: "readFile",
-			path: getReadablePath(cline.cwd, filePath || ""),
-			isOutsideWorkspace: filePath ? isPathOutsideWorkspace(fullPath) : false,
-		}
-		const partialMessage = JSON.stringify({
-			...sharedMessageProps,
-			content: undefined,
-		} satisfies ClineSayTool)
-		await cline.ask("tool", partialMessage, block.partial).catch(() => {})
-		return
-	}
-
-	// Validate path parameter
-	if (!filePath) {
-		cline.consecutiveMistakeCount++
-		cline.recordToolError("read_file")
-		const errorMsg = await cline.sayAndCreateMissingParamError("read_file", "path")
-		pushToolResult(`<file><error>${errorMsg}</error></file>`)
-		return
-	}
-
-	const relPath = filePath
-	const fullPath = path.resolve(cline.cwd, relPath)
-
-	try {
-		// Check RooIgnore validation
-		const accessAllowed = cline.rooIgnoreController?.validateAccess(relPath)
-		if (!accessAllowed) {
-			await cline.say("rooignore_error", relPath)
-			const errorMsg = formatResponse.rooIgnoreError(relPath)
-			pushToolResult(`<file><path>${relPath}</path><error>${errorMsg}</error></file>`)
-			return
-		}
-
-		// Get max read file line setting
-		const { maxReadFileLine = -1 } = (await cline.providerRef.deref()?.getState()) ?? {}
-
-		// Create approval message
-		const isOutsideWorkspace = isPathOutsideWorkspace(fullPath)
-		let lineSnippet = ""
-		if (maxReadFileLine === 0) {
-			lineSnippet = t("tools:readFile.definitionsOnly")
-		} else if (maxReadFileLine > 0) {
-			lineSnippet = t("tools:readFile.maxLines", { max: maxReadFileLine })
-		}
-
-		const completeMessage = JSON.stringify({
-			tool: "readFile",
-			path: getReadablePath(cline.cwd, relPath),
-			isOutsideWorkspace,
-			content: fullPath,
-			reason: lineSnippet,
-		} satisfies ClineSayTool)
-
-		const { response, text, images } = await cline.ask("tool", completeMessage, false)
-
-		if (response !== "yesButtonClicked") {
-			// Handle denial
-			if (text) {
-				await cline.say("user_feedback", text, images)
-			}
-			cline.didRejectTool = true
-
-			const statusMessage = text ? formatResponse.toolDeniedWithFeedback(text) : formatResponse.toolDenied()
-
-			pushToolResult(`${statusMessage}\n<file><path>${relPath}</path><status>Denied by user</status></file>`)
-			return
-		}
-
-		// Handle approval with feedback
-		if (text) {
-			await cline.say("user_feedback", text, images)
-		}
-
-		// Process the file
-		const [totalLines, isBinary] = await Promise.all([countFileLines(fullPath), isBinaryFile(fullPath)])
-
-		// Handle binary files
-		if (isBinary) {
-			const fileExtension = path.extname(relPath).toLowerCase()
-			const supportedBinaryFormats = getSupportedBinaryFormats()
-
-			// Check if it's a supported image format
-			if (isSupportedImageFormat(fileExtension)) {
-				try {
-					const {
-						maxImageFileSize = DEFAULT_MAX_IMAGE_FILE_SIZE_MB,
-						maxTotalImageSize = DEFAULT_MAX_TOTAL_IMAGE_SIZE_MB,
-					} = (await cline.providerRef.deref()?.getState()) ?? {}
-
-					// Validate image for processing
-					const validationResult = await validateImageForProcessing(
-						fullPath,
-						supportsImages,
-						maxImageFileSize,
-						maxTotalImageSize,
-						0, // No cumulative memory for single file
-					)
-
-					if (!validationResult.isValid) {
-						await cline.fileContextTracker.trackFileContext(relPath, "read_tool" as RecordSource)
-						pushToolResult(
-							`<file><path>${relPath}</path>\n<notice>${validationResult.notice}</notice>\n</file>`,
-						)
-						return
-					}
-
-					// Process the image
-					const imageResult = await processImageFile(fullPath)
-					await cline.fileContextTracker.trackFileContext(relPath, "read_tool" as RecordSource)
-
-					// Return result with image data
-					const result = formatResponse.toolResult(
-						`<file><path>${relPath}</path>\n<notice>${imageResult.notice}</notice>\n</file>`,
-						supportsImages ? [imageResult.dataUrl] : undefined,
-					)
-
-					if (typeof result === "string") {
-						pushToolResult(result)
-					} else {
-						pushToolResult(result)
-					}
-					return
-				} catch (error) {
-					const errorMsg = error instanceof Error ? error.message : String(error)
-					pushToolResult(
-						`<file><path>${relPath}</path><error>Error reading image file: ${errorMsg}</error></file>`,
-					)
-					await handleError(
-						`reading image file ${relPath}`,
-						error instanceof Error ? error : new Error(errorMsg),
-					)
-					return
-				}
-			}
-
-			// Check if it's a supported binary format that can be processed
-			if (supportedBinaryFormats && supportedBinaryFormats.includes(fileExtension)) {
-				// For supported binary formats (.pdf, .docx, .ipynb), continue to extractTextFromFile
-				// Fall through to the normal extractTextFromFile processing below
-			} else {
-				// Handle unknown binary format
-				const fileFormat = fileExtension.slice(1) || "bin"
-				pushToolResult(
-					`<file><path>${relPath}</path>\n<binary_file format="${fileFormat}">Binary file - content not displayed</binary_file>\n</file>`,
-				)
-				return
-			}
-		}
-
-		// Handle definitions-only mode
-		if (maxReadFileLine === 0) {
-			try {
-				const defResult = await parseSourceCodeDefinitionsForFile(fullPath, cline.rooIgnoreController)
-				if (defResult) {
-					let xmlInfo = `<notice>Showing only definitions. Use standard read_file if you need to read actual content</notice>\n`
-					pushToolResult(
-						`<file><path>${relPath}</path>\n<list_code_definition_names>${defResult}</list_code_definition_names>\n${xmlInfo}</file>`,
-					)
-				}
-			} catch (error) {
-				if (error instanceof Error && error.message.startsWith("Unsupported language:")) {
-					console.warn(`[simple_read_file] Warning: ${error.message}`)
-				} else {
-					console.error(
-						`[simple_read_file] Unhandled error: ${error instanceof Error ? error.message : String(error)}`,
-					)
-				}
-			}
-			return
-		}
-
-		// Handle files exceeding line threshold
-		if (maxReadFileLine > 0 && totalLines > maxReadFileLine) {
-			const content = addLineNumbers(await readLines(fullPath, maxReadFileLine - 1, 0))
-			const lineRangeAttr = ` lines="1-${maxReadFileLine}"`
-			let xmlInfo = `<content${lineRangeAttr}>\n${content}</content>\n`
-
-			try {
-				const defResult = await parseSourceCodeDefinitionsForFile(fullPath, cline.rooIgnoreController)
-				if (defResult) {
-					xmlInfo += `<list_code_definition_names>${defResult}</list_code_definition_names>\n`
-				}
-				xmlInfo += `<notice>Showing only ${maxReadFileLine} of ${totalLines} total lines. File is too large for complete display</notice>\n`
-				pushToolResult(`<file><path>${relPath}</path>\n${xmlInfo}</file>`)
-			} catch (error) {
-				if (error instanceof Error && error.message.startsWith("Unsupported language:")) {
-					console.warn(`[simple_read_file] Warning: ${error.message}`)
-				} else {
-					console.error(
-						`[simple_read_file] Unhandled error: ${error instanceof Error ? error.message : String(error)}`,
-					)
-				}
-			}
-			return
-		}
-
-		// Handle normal file read
-		const content = await extractTextFromFile(fullPath)
-		const lineRangeAttr = ` lines="1-${totalLines}"`
-		let xmlInfo = totalLines > 0 ? `<content${lineRangeAttr}>\n${content}</content>\n` : `<content/>`
-
-		if (totalLines === 0) {
-			xmlInfo += `<notice>File is empty</notice>\n`
-		}
-
-		// Track file read
-		await cline.fileContextTracker.trackFileContext(relPath, "read_tool" as RecordSource)
-
-		// Return the result
-		if (text) {
-			const statusMessage = formatResponse.toolApprovedWithFeedback(text)
-			pushToolResult(`${statusMessage}\n<file><path>${relPath}</path>\n${xmlInfo}</file>`)
-		} else {
-			pushToolResult(`<file><path>${relPath}</path>\n${xmlInfo}</file>`)
-		}
-	} catch (error) {
-		const errorMsg = error instanceof Error ? error.message : String(error)
-		pushToolResult(`<file><path>${relPath}</path><error>Error reading file: ${errorMsg}</error></file>`)
-		await handleError(`reading file ${relPath}`, error instanceof Error ? error : new Error(errorMsg))
-	}
-}
-
-/**
- * Get description for the simple read file tool
- * @param blockName The name of the tool block
- * @param blockParams The parameters passed to the tool
- * @returns A description string for the tool use
- */
-export function getSimpleReadFileToolDescription(blockName: string, blockParams: any): string {
-	if (blockParams.path) {
-		return `[${blockName} for '${blockParams.path}']`
-	} else {
-		return `[${blockName} with missing path]`
-	}
-}