diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 4ab60899df8..9919d6c202e 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -16,7 +16,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" diff --git a/packages/types/src/single-file-read-models.ts b/packages/types/src/single-file-read-models.ts deleted file mode 100644 index 302b8d42023..00000000000 --- a/packages/types/src/single-file-read-models.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Configuration for models that should use simplified single-file read_file tool - * These models will use the simpler ... 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") -} diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index 004e76af563..0620b514f9a 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -18,8 +18,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" @@ -362,18 +361,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": @@ -908,29 +901,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">, { diff --git a/src/core/prompts/tools/index.ts b/src/core/prompts/tools/index.ts index c9a69efae83..b75725a99b3 100644 --- a/src/core/prompts/tools/index.ts +++ b/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 | 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, diff --git a/src/core/prompts/tools/simple-read-file.ts b/src/core/prompts/tools/simple-read-file.ts deleted file mode 100644 index 28f4f1129e7..00000000000 --- a/src/core/prompts/tools/simple-read-file.ts +++ /dev/null @@ -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: file/path.ext - */ -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: - -path/to/file - - -Examples: - -1. Reading a TypeScript file: - -src/app.ts - - -2. Reading a configuration file: - -config.json - - -3. Reading a markdown file: - -README.md -` -} diff --git a/src/core/tools/simpleReadFileTool.ts b/src/core/tools/simpleReadFileTool.ts deleted file mode 100644 index 1b41e9e9d68..00000000000 --- a/src/core/tools/simpleReadFileTool.ts +++ /dev/null @@ -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: file/path.ext - * - * 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(`${errorMsg}`) - 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(`${relPath}${errorMsg}`) - 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${relPath}Denied by user`) - 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( - `${relPath}\n${validationResult.notice}\n`, - ) - 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( - `${relPath}\n${imageResult.notice}\n`, - 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( - `${relPath}Error reading image file: ${errorMsg}`, - ) - 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( - `${relPath}\nBinary file - content not displayed\n`, - ) - return - } - } - - // Handle definitions-only mode - if (maxReadFileLine === 0) { - try { - const defResult = await parseSourceCodeDefinitionsForFile(fullPath, cline.rooIgnoreController) - if (defResult) { - let xmlInfo = `Showing only definitions. Use standard read_file if you need to read actual content\n` - pushToolResult( - `${relPath}\n${defResult}\n${xmlInfo}`, - ) - } - } 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 = `\n${content}\n` - - try { - const defResult = await parseSourceCodeDefinitionsForFile(fullPath, cline.rooIgnoreController) - if (defResult) { - xmlInfo += `${defResult}\n` - } - xmlInfo += `Showing only ${maxReadFileLine} of ${totalLines} total lines. File is too large for complete display\n` - pushToolResult(`${relPath}\n${xmlInfo}`) - } 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 ? `\n${content}\n` : `` - - if (totalLines === 0) { - xmlInfo += `File is empty\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${relPath}\n${xmlInfo}`) - } else { - pushToolResult(`${relPath}\n${xmlInfo}`) - } - } catch (error) { - const errorMsg = error instanceof Error ? error.message : String(error) - pushToolResult(`${relPath}Error reading file: ${errorMsg}`) - 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]` - } -}