From 0cccb2228d4772569e62f24d135ea6ca5fb299f3 Mon Sep 17 00:00:00 2001 From: cannuri <91494156+cannuri@users.noreply.github.com> Date: Wed, 14 May 2025 20:21:07 +0200 Subject: [PATCH 1/4] enhance readFileTool with auto-truncate handling --- src/core/tools/readFileTool.ts | 730 ++++++--------------- src/i18n/locales/en/tools.json | 3 +- src/shared/ExtensionMessage.ts | 1 + webview-ui/src/components/chat/ChatRow.tsx | 10 +- 4 files changed, 206 insertions(+), 538 deletions(-) diff --git a/src/core/tools/readFileTool.ts b/src/core/tools/readFileTool.ts index e49ac43d7b..a1c337e025 100644 --- a/src/core/tools/readFileTool.ts +++ b/src/core/tools/readFileTool.ts @@ -11,64 +11,8 @@ 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 { extractTextFromFile, addLineNumbers } from "../../integrations/misc/extract-text" import { parseSourceCodeDefinitionsForFile } from "../../services/tree-sitter" -import { parseXml } from "../../utils/xml" - -export function getReadFileToolDescription(blockName: string, blockParams: any): string { - // Handle both single path and multiple files via args - if (blockParams.args) { - try { - const parsed = parseXml(blockParams.args) as any - const files = Array.isArray(parsed.file) ? parsed.file : [parsed.file].filter(Boolean) - const paths = files.map((f: any) => f?.path).filter(Boolean) as string[] - - if (paths.length === 0) { - return `[${blockName} with no valid paths]` - } else if (paths.length === 1) { - // Modified part for single file - return `[${blockName} for '${paths[0]}'. Reading multiple files at once is more efficient for the LLM. If other files are relevant to your current task, please read them simultaneously.]` - } else if (paths.length <= 3) { - const pathList = paths.map((p) => `'${p}'`).join(", ") - return `[${blockName} for ${pathList}]` - } else { - return `[${blockName} for ${paths.length} files]` - } - } catch (error) { - console.error("Failed to parse read_file args XML for description:", error) - return `[${blockName} with unparseable args]` - } - } else if (blockParams.path) { - // Fallback for legacy single-path usage - // Modified part for single file (legacy) - return `[${blockName} for '${blockParams.path}'. Reading multiple files at once is more efficient for the LLM. If other files are relevant to your current task, please read them simultaneously.]` - } else { - return `[${blockName} with missing path/args]` - } -} -// Types -interface LineRange { - start: number - end: number -} - -interface FileEntry { - path?: string - lineRanges?: LineRange[] -} - -// New interface to track file processing state -interface FileResult { - path: string - status: "approved" | "denied" | "blocked" | "error" | "pending" - content?: string - error?: string - notice?: string - lineRanges?: LineRange[] - xmlContent?: string // Final XML content for this file - feedbackText?: string // User feedback text from approval/denial - feedbackImages?: any[] // User feedback images from approval/denial -} export async function readFileTool( cline: Task, @@ -76,538 +20,252 @@ export async function readFileTool( askApproval: AskApproval, handleError: HandleError, pushToolResult: PushToolResult, - _removeClosingTag: RemoveClosingTag, + removeClosingTag: RemoveClosingTag, ) { - const argsXmlTag: string | undefined = block.params.args - const legacyPath: string | undefined = block.params.path - const legacyStartLineStr: string | undefined = block.params.start_line - const legacyEndLineStr: string | undefined = block.params.end_line - - // Handle partial message first - if (block.partial) { - let filePath = "" - // Prioritize args for partial, then legacy path - if (argsXmlTag) { - const match = argsXmlTag.match(/.*?([^<]+)<\/path>/s) - if (match) filePath = match[1] - } - if (!filePath && legacyPath) { - // If args didn't yield a path, try legacy - filePath = legacyPath - } - - 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 + const relPath: string | undefined = block.params.path + const startLineStr: string | undefined = block.params.start_line + const endLineStr: string | undefined = block.params.end_line + + // Get the full path and determine if it's outside the workspace + const fullPath = relPath ? path.resolve(cline.cwd, removeClosingTag("path", relPath)) : "" + const isOutsideWorkspace = isPathOutsideWorkspace(fullPath) + + const sharedMessageProps: ClineSayTool = { + tool: "readFile", + path: getReadablePath(cline.cwd, removeClosingTag("path", relPath)), + isOutsideWorkspace, } - const fileEntries: FileEntry[] = [] - - if (argsXmlTag) { - // Parse file entries from XML (new multi-file format) - try { - const parsed = parseXml(argsXmlTag) as any - const files = Array.isArray(parsed.file) ? parsed.file : [parsed.file].filter(Boolean) - - for (const file of files) { - if (!file.path) continue // Skip if no path in a file entry - - const fileEntry: FileEntry = { - path: file.path, - lineRanges: [], - } - - if (file.line_range) { - const ranges = Array.isArray(file.line_range) ? file.line_range : [file.line_range] - for (const range of ranges) { - const match = String(range).match(/(\d+)-(\d+)/) // Ensure range is treated as string - if (match) { - const [, start, end] = match.map(Number) - if (!isNaN(start) && !isNaN(end)) { - fileEntry.lineRanges?.push({ start, end }) - } - } - } - } - fileEntries.push(fileEntry) - } - } catch (error) { - const errorMessage = `Failed to parse read_file XML args: ${error instanceof Error ? error.message : String(error)}` - await handleError("parsing read_file args", new Error(errorMessage)) - pushToolResult(`${errorMessage}`) + // wasAutoTruncated is now set directly in the completeMessage + try { + if (block.partial) { + const partialMessage = JSON.stringify({ ...sharedMessageProps, content: undefined } satisfies ClineSayTool) + await cline.ask("tool", partialMessage, block.partial).catch(() => {}) return - } - } else if (legacyPath) { - // Handle legacy single file path as a fallback - console.warn("[readFileTool] Received legacy 'path' parameter. Consider updating to use 'args' structure.") - - const fileEntry: FileEntry = { - path: legacyPath, - lineRanges: [], - } - - if (legacyStartLineStr && legacyEndLineStr) { - const start = parseInt(legacyStartLineStr, 10) - const end = parseInt(legacyEndLineStr, 10) - if (!isNaN(start) && !isNaN(end) && start > 0 && end > 0) { - fileEntry.lineRanges?.push({ start, end }) - } else { - console.warn( - `[readFileTool] Invalid legacy line range for ${legacyPath}: start='${legacyStartLineStr}', end='${legacyEndLineStr}'`, - ) + } else { + if (!relPath) { + cline.consecutiveMistakeCount++ + cline.recordToolError("read_file") + const errorMsg = await cline.sayAndCreateMissingParamError("read_file", "path") + pushToolResult(`${errorMsg}`) + return } - } - fileEntries.push(fileEntry) - } - // If, after trying both new and legacy, no valid file entries are found. - if (fileEntries.length === 0) { - cline.consecutiveMistakeCount++ - cline.recordToolError("read_file") - const errorMsg = await cline.sayAndCreateMissingParamError("read_file", "args (containing valid file paths)") - pushToolResult(`${errorMsg}`) - return - } + const { maxReadFileLine = 500 } = (await cline.providerRef.deref()?.getState()) ?? {} + const isFullRead = maxReadFileLine === -1 - // Create an array to track the state of each file - const fileResults: FileResult[] = fileEntries.map((entry) => ({ - path: entry.path || "", - status: "pending", - lineRanges: entry.lineRanges, - })) - - // Function to update file result status - const updateFileResult = (path: string, updates: Partial) => { - const index = fileResults.findIndex((result) => result.path === path) - if (index !== -1) { - fileResults[index] = { ...fileResults[index], ...updates } - } - } + // Check if we're doing a line range read + let isRangeRead = false + let startLine: number | undefined = undefined + let endLine: number | undefined = undefined - try { - // First validate all files and prepare for batch approval - const filesToApprove: FileResult[] = [] - - for (let i = 0; i < fileResults.length; i++) { - const fileResult = fileResults[i] - const relPath = fileResult.path - const fullPath = path.resolve(cline.cwd, relPath) - - // Validate line ranges first - if (fileResult.lineRanges) { - let hasRangeError = false - for (const range of fileResult.lineRanges) { - if (range.start > range.end) { - const errorMsg = "Invalid line range: end line cannot be less than start line" - updateFileResult(relPath, { - status: "blocked", - error: errorMsg, - xmlContent: `${relPath}Error reading file: ${errorMsg}`, - }) - await handleError(`reading file ${relPath}`, new Error(errorMsg)) - hasRangeError = true - break - } - if (isNaN(range.start) || isNaN(range.end)) { - const errorMsg = "Invalid line range values" - updateFileResult(relPath, { - status: "blocked", - error: errorMsg, - xmlContent: `${relPath}Error reading file: ${errorMsg}`, - }) - await handleError(`reading file ${relPath}`, new Error(errorMsg)) - hasRangeError = true - break - } - } - if (hasRangeError) continue + // Check if we have either range parameter and we're not doing a full read + if (!isFullRead && (startLineStr || endLineStr)) { + isRangeRead = true } - // Then check RooIgnore validation - if (fileResult.status === "pending") { - const accessAllowed = cline.rooIgnoreController?.validateAccess(relPath) - if (!accessAllowed) { - await cline.say("rooignore_error", relPath) - const errorMsg = formatResponse.rooIgnoreError(relPath) - updateFileResult(relPath, { - status: "blocked", - error: errorMsg, - xmlContent: `${relPath}${errorMsg}`, - }) - continue + // Parse start_line if provided + if (startLineStr) { + startLine = parseInt(startLineStr) + + if (isNaN(startLine)) { + // Invalid start_line + cline.consecutiveMistakeCount++ + cline.recordToolError("read_file") + await cline.say("error", `Failed to parse start_line: ${startLineStr}`) + pushToolResult(`${relPath}Invalid start_line value`) + return } - // Add to files that need approval - filesToApprove.push(fileResult) + startLine -= 1 // Convert to 0-based index } - } - - // Handle batch approval if there are multiple files to approve - if (filesToApprove.length > 1) { - const { maxReadFileLine = -1 } = (await cline.providerRef.deref()?.getState()) ?? {} - - // Prepare batch file data - const batchFiles = filesToApprove.map((fileResult) => { - const relPath = fileResult.path - const fullPath = path.resolve(cline.cwd, relPath) - const isOutsideWorkspace = isPathOutsideWorkspace(fullPath) - - // Create line snippet for this file - let lineSnippet = "" - if (fileResult.lineRanges && fileResult.lineRanges.length > 0) { - const ranges = fileResult.lineRanges.map((range) => - t("tools:readFile.linesRange", { start: range.start, end: range.end }), - ) - lineSnippet = ranges.join(", ") - } else if (maxReadFileLine === 0) { - lineSnippet = t("tools:readFile.definitionsOnly") - } else if (maxReadFileLine > 0) { - lineSnippet = t("tools:readFile.maxLines", { max: maxReadFileLine }) - } - - const readablePath = getReadablePath(cline.cwd, relPath) - const key = `${readablePath}${lineSnippet ? ` (${lineSnippet})` : ""}` - return { - path: readablePath, - lineSnippet, - isOutsideWorkspace, - key, - content: fullPath, // Include full path for content + // Parse end_line if provided + if (endLineStr) { + endLine = parseInt(endLineStr) + + if (isNaN(endLine)) { + // Invalid end_line + cline.consecutiveMistakeCount++ + cline.recordToolError("read_file") + await cline.say("error", `Failed to parse end_line: ${endLineStr}`) + pushToolResult(`${relPath}Invalid end_line value`) + return } - }) - const completeMessage = JSON.stringify({ - tool: "readFile", - batchFiles, - } satisfies ClineSayTool) + // Convert to 0-based index + endLine -= 1 + } - const { response, text, images } = await cline.ask("tool", completeMessage, false) + const accessAllowed = cline.rooIgnoreController?.validateAccess(relPath) - // Process batch response - if (response === "yesButtonClicked") { - // Approve all files - if (text) { - await cline.say("user_feedback", text, images) - } - filesToApprove.forEach((fileResult) => { - updateFileResult(fileResult.path, { - status: "approved", - feedbackText: text, - feedbackImages: images, - }) - }) - } else if (response === "noButtonClicked") { - // Deny all files - if (text) { - await cline.say("user_feedback", text, images) - } - cline.didRejectTool = true - filesToApprove.forEach((fileResult) => { - updateFileResult(fileResult.path, { - status: "denied", - xmlContent: `${fileResult.path}Denied by user`, - feedbackText: text, - feedbackImages: images, - }) - }) - } else { - // Handle individual permissions from objectResponse - // if (text) { - // await cline.say("user_feedback", text, images) - // } - - try { - const individualPermissions = JSON.parse(text || "{}") - let hasAnyDenial = false - - batchFiles.forEach((batchFile, index) => { - const fileResult = filesToApprove[index] - const approved = individualPermissions[batchFile.key] === true - - if (approved) { - updateFileResult(fileResult.path, { - status: "approved", - }) - } else { - hasAnyDenial = true - updateFileResult(fileResult.path, { - status: "denied", - xmlContent: `${fileResult.path}Denied by user`, - }) - } - }) - - if (hasAnyDenial) { - cline.didRejectTool = true - } - } catch (error) { - // Fallback: if JSON parsing fails, deny all files - console.error("Failed to parse individual permissions:", error) - cline.didRejectTool = true - filesToApprove.forEach((fileResult) => { - updateFileResult(fileResult.path, { - status: "denied", - xmlContent: `${fileResult.path}Denied by user`, - }) - }) - } + if (!accessAllowed) { + await cline.say("rooignore_error", relPath) + const errorMsg = formatResponse.rooIgnoreError(relPath) + pushToolResult(`${relPath}${errorMsg}`) + return } - } else if (filesToApprove.length === 1) { - // Handle single file approval (existing logic) - const fileResult = filesToApprove[0] - const relPath = fileResult.path - const fullPath = path.resolve(cline.cwd, relPath) - const isOutsideWorkspace = isPathOutsideWorkspace(fullPath) - const { maxReadFileLine = -1 } = (await cline.providerRef.deref()?.getState()) ?? {} - - // Create line snippet for approval message + + // Create line snippet description for approval message let lineSnippet = "" - if (fileResult.lineRanges && fileResult.lineRanges.length > 0) { - const ranges = fileResult.lineRanges.map((range) => - t("tools:readFile.linesRange", { start: range.start, end: range.end }), - ) - lineSnippet = ranges.join(", ") + + if (isFullRead) { + // No snippet for full read + } else if (startLine !== undefined && endLine !== undefined) { + lineSnippet = t("tools:readFile.linesRange", { start: startLine + 1, end: endLine + 1 }) + } else if (startLine !== undefined) { + lineSnippet = t("tools:readFile.linesFromToEnd", { start: startLine + 1 }) + } else if (endLine !== undefined) { + lineSnippet = t("tools:readFile.linesFromStartTo", { end: endLine + 1 }) } else if (maxReadFileLine === 0) { lineSnippet = t("tools:readFile.definitionsOnly") } else if (maxReadFileLine > 0) { lineSnippet = t("tools:readFile.maxLines", { max: maxReadFileLine }) } + cline.consecutiveMistakeCount = 0 + const absolutePath = path.resolve(cline.cwd, relPath) + + // Count total lines in the file + let totalLines = 0 + + try { + totalLines = await countFileLines(absolutePath) + } catch (error) { + console.error(`Error counting lines in file ${absolutePath}:`, error) + } + const completeMessage = JSON.stringify({ - tool: "readFile", - path: getReadablePath(cline.cwd, relPath), - isOutsideWorkspace, - content: fullPath, - reason: lineSnippet, + ...sharedMessageProps, + content: absolutePath, + // Only include reason (truncation message) if the file will actually be truncated + // or if it's a specific range read (not the default max lines message) + ...(!isFullRead && maxReadFileLine > 0 && totalLines > maxReadFileLine + ? { reason: lineSnippet, wasAutoTruncated: true } + : lineSnippet && lineSnippet !== t("tools:readFile.maxLines", { max: maxReadFileLine }) + ? { reason: lineSnippet } + : {}), } satisfies ClineSayTool) - const { response, text, images } = await cline.ask("tool", completeMessage, false) - - if (response !== "yesButtonClicked") { - // Handle both messageResponse and noButtonClicked with text - if (text) { - await cline.say("user_feedback", text, images) - } - cline.didRejectTool = true - - updateFileResult(relPath, { - status: "denied", - xmlContent: `${relPath}Denied by user`, - feedbackText: text, - feedbackImages: images, - }) - } else { - // Handle yesButtonClicked with text - if (text) { - await cline.say("user_feedback", text, images) - } + const didApprove = await askApproval("tool", completeMessage) - updateFileResult(relPath, { - status: "approved", - feedbackText: text, - feedbackImages: images, - }) + if (!didApprove) { + return } - } - // Then process only approved files - for (const fileResult of fileResults) { - // Skip files that weren't approved - if (fileResult.status !== "approved") { - continue - } + // totalLines is already counted above - const relPath = fileResult.path - const fullPath = path.resolve(cline.cwd, relPath) - const { maxReadFileLine = 500 } = (await cline.providerRef.deref()?.getState()) ?? {} + // now execute the tool like normal + let content: string + let isFileTruncated = false + let sourceCodeDef = "" - // Process approved files - try { - const [totalLines, isBinary] = await Promise.all([countFileLines(fullPath), isBinaryFile(fullPath)]) - - // Handle binary files (but allow specific file types that extractTextFromFile can handle) - if (isBinary) { - const fileExtension = path.extname(relPath).toLowerCase() - const supportedBinaryFormats = getSupportedBinaryFormats() - - if (!supportedBinaryFormats.includes(fileExtension)) { - updateFileResult(relPath, { - notice: "Binary file", - xmlContent: `${relPath}\nBinary file\n`, - }) - continue - } - // For supported binary formats (.pdf, .docx, .ipynb), continue to extractTextFromFile - } + const isBinary = await isBinaryFile(absolutePath).catch(() => false) - // Handle range reads (bypass maxReadFileLine) - if (fileResult.lineRanges && fileResult.lineRanges.length > 0) { - const rangeResults: string[] = [] - for (const range of fileResult.lineRanges) { - const content = addLineNumbers( - await readLines(fullPath, range.end - 1, range.start - 1), - range.start, - ) - const lineRangeAttr = ` lines="${range.start}-${range.end}"` - rangeResults.push(`\n${content}`) - } - updateFileResult(relPath, { - xmlContent: `${relPath}\n${rangeResults.join("\n")}\n`, - }) - continue + if (isRangeRead) { + if (startLine === undefined) { + content = addLineNumbers(await readLines(absolutePath, endLine, startLine)) + } else { + content = addLineNumbers(await readLines(absolutePath, endLine, startLine), startLine + 1) } - - // Handle definitions-only mode - if (maxReadFileLine === 0) { - try { - const defResult = await parseSourceCodeDefinitionsForFile(fullPath, cline.rooIgnoreController) - if (defResult) { - let xmlInfo = `Showing only ${maxReadFileLine} of ${totalLines} total lines. Use line_range if you need to read more lines\n` - updateFileResult(relPath, { - xmlContent: `${relPath}\n${defResult}\n${xmlInfo}`, - }) - } - } catch (error) { - if (error instanceof Error && error.message.startsWith("Unsupported language:")) { - console.warn(`[read_file] Warning: ${error.message}`) - } else { - console.error( - `[read_file] Unhandled error: ${error instanceof Error ? error.message : String(error)}`, - ) + } else if (!isBinary && maxReadFileLine >= 0 && totalLines > maxReadFileLine) { + // If file is too large, only read the first maxReadFileLine lines + isFileTruncated = true + // wasAutoTruncated is now set in the completeMessage + + const res = await Promise.all([ + maxReadFileLine > 0 ? readLines(absolutePath, maxReadFileLine - 1, 0) : "", + (async () => { + try { + return await parseSourceCodeDefinitionsForFile(absolutePath, cline.rooIgnoreController) + } catch (error) { + if (error instanceof Error && error.message.startsWith("Unsupported language:")) { + console.warn(`[read_file] Warning: ${error.message}`) + return undefined + } else { + console.error( + `[read_file] Unhandled error: ${error instanceof Error ? error.message : String(error)}`, + ) + return undefined + } } - } - continue - } + })(), + ]) - // 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` + content = res[0].length > 0 ? addLineNumbers(res[0]) : "" + const result = res[1] - try { - const defResult = await parseSourceCodeDefinitionsForFile(fullPath, cline.rooIgnoreController) - if (defResult) { - xmlInfo += `${defResult}\n` - } - xmlInfo += `Showing only ${maxReadFileLine} of ${totalLines} total lines. Use line_range if you need to read more lines\n` - updateFileResult(relPath, { - xmlContent: `${relPath}\n${xmlInfo}`, - }) - } catch (error) { - if (error instanceof Error && error.message.startsWith("Unsupported language:")) { - console.warn(`[read_file] Warning: ${error.message}`) - } else { - console.error( - `[read_file] Unhandled error: ${error instanceof Error ? error.message : String(error)}`, - ) - } - } - continue + if (result) { + sourceCodeDef = `${result}` } + } else { + // Read entire file + content = await extractTextFromFile(absolutePath) + } - // 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` - } + // Create variables to store XML components + let xmlInfo = "" + let contentTag = "" - // Track file read - await cline.fileContextTracker.trackFileContext(relPath, "read_tool" as RecordSource) + // Add truncation notice if applicable + if (isFileTruncated) { + xmlInfo += `Showing only ${maxReadFileLine} of ${totalLines} total lines. Use start_line and end_line if you need to read more\n` - updateFileResult(relPath, { - xmlContent: `${relPath}\n${xmlInfo}`, - }) - } catch (error) { - const errorMsg = error instanceof Error ? error.message : String(error) - updateFileResult(relPath, { - status: "error", - error: `Error reading file: ${errorMsg}`, - xmlContent: `${relPath}Error reading file: ${errorMsg}`, - }) - await handleError(`reading file ${relPath}`, error instanceof Error ? error : new Error(errorMsg)) + // Add source code definitions if available + if (sourceCodeDef) { + xmlInfo += `${sourceCodeDef}\n` + } } - } - // Generate final XML result from all file results - const xmlResults = fileResults.filter((result) => result.xmlContent).map((result) => result.xmlContent) - const filesXml = `\n${xmlResults.join("\n")}\n` + // Empty files (zero lines) + if (content === "" && totalLines === 0) { + // Always add self-closing content tag and notice for empty files + contentTag = `` + xmlInfo += `File is empty\n` + } + // Range reads should always show content regardless of maxReadFileLine + else if (isRangeRead) { + // Create content tag with line range information + let lineRangeAttr = "" + const displayStartLine = startLine !== undefined ? startLine + 1 : 1 + const displayEndLine = endLine !== undefined ? endLine + 1 : totalLines + lineRangeAttr = ` lines="${displayStartLine}-${displayEndLine}"` + + // Maintain exact format expected by tests + contentTag = `\n${content}\n` + } + // maxReadFileLine=0 for non-range reads + else if (maxReadFileLine === 0) { + // Skip content tag for maxReadFileLine=0 (definitions only mode) + contentTag = "" + } + // Normal case: non-empty files with content (non-range reads) + else { + // For non-range reads, always show line range + let lines = totalLines - // Process all feedback in a unified way without branching - let statusMessage = "" - let feedbackImages: any[] = [] + if (maxReadFileLine >= 0 && totalLines > maxReadFileLine) { + lines = maxReadFileLine + } - // Handle denial with feedback (highest priority) - const deniedWithFeedback = fileResults.find((result) => result.status === "denied" && result.feedbackText) + const lineRangeAttr = ` lines="1-${lines}"` - if (deniedWithFeedback && deniedWithFeedback.feedbackText) { - statusMessage = formatResponse.toolDeniedWithFeedback(deniedWithFeedback.feedbackText) - feedbackImages = deniedWithFeedback.feedbackImages || [] - } - // Handle generic denial - else if (cline.didRejectTool) { - statusMessage = formatResponse.toolDenied() - } - // Handle approval with feedback - else { - const approvedWithFeedback = fileResults.find( - (result) => result.status === "approved" && result.feedbackText, - ) - - if (approvedWithFeedback && approvedWithFeedback.feedbackText) { - statusMessage = formatResponse.toolApprovedWithFeedback(approvedWithFeedback.feedbackText) - feedbackImages = approvedWithFeedback.feedbackImages || [] + // Maintain exact format expected by tests + contentTag = `\n${content}\n` } - } - - // Push the result with appropriate formatting - if (statusMessage) { - const result = formatResponse.toolResult(statusMessage, feedbackImages) - // Handle different return types from toolResult - if (typeof result === "string") { - pushToolResult(`${result}\n${filesXml}`) - } else { - // For block-based results, we need to convert the filesXml to a text block and append it - const textBlock = { type: "text" as const, text: filesXml } - pushToolResult([...result, textBlock]) + // Track file read operation + if (relPath) { + await cline.fileContextTracker.trackFileContext(relPath, "read_tool" as RecordSource) } - } else { - // No status message, just push the files XML - pushToolResult(filesXml) + + // Format the result into the required XML structure + const xmlResult = `${relPath}\n${contentTag}${xmlInfo}` + pushToolResult(xmlResult) } } catch (error) { - // Handle all errors using per-file format for consistency - const relPath = fileEntries[0]?.path || "unknown" const errorMsg = error instanceof Error ? error.message : String(error) - - // If we have file results, update the first one with the error - if (fileResults.length > 0) { - updateFileResult(relPath, { - status: "error", - error: `Error reading file: ${errorMsg}`, - xmlContent: `${relPath}Error reading file: ${errorMsg}`, - }) - } - - await handleError(`reading file ${relPath}`, error instanceof Error ? error : new Error(errorMsg)) - - // Generate final XML result from all file results - const xmlResults = fileResults.filter((result) => result.xmlContent).map((result) => result.xmlContent) - - pushToolResult(`\n${xmlResults.join("\n")}\n`) + pushToolResult(`${relPath || ""}Error reading file: ${errorMsg}`) + await handleError("reading file", error) } } diff --git a/src/i18n/locales/en/tools.json b/src/i18n/locales/en/tools.json index 9932fc4d06..2079e468b8 100644 --- a/src/i18n/locales/en/tools.json +++ b/src/i18n/locales/en/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (lines {{start}}-{{end}})", "definitionsOnly": " (definitions only)", - "maxLines": " (max {{max}} lines)" + "maxLines": " (max {{max}} lines)", + "autoTruncateTooltip": "To adjust this limit, click the \"Settings\" icon (⚙️) in the Roo-Code panel, then click on \"Context\" and find the 'File read auto-truncate threshold' option." }, "toolRepetitionLimitReached": "Roo appears to be stuck in a loop, attempting the same action ({{toolName}}) repeatedly. This might indicate a problem with its current strategy. Consider rephrasing the task, providing more specific instructions, or guiding it towards a different approach.", "codebaseSearch": { diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 3044d1d301..f63c838e7c 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -289,6 +289,7 @@ export interface ClineSayTool { }> }> question?: string + wasAutoTruncated?: boolean } // Must keep in sync with system prompt. diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index a40a50ef53..b5ee69bc11 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -465,8 +465,16 @@ export const ChatRowContent = ({ {tool.path?.startsWith(".") && .} {removeLeadingNonAlphanumeric(tool.path ?? "") + "\u200E"} - {tool.reason} + {tool.wasAutoTruncated && tool.reason && ( + + {tool.reason} + + + )} + {!tool.wasAutoTruncated && tool.reason && {tool.reason}}
Date: Wed, 14 May 2025 20:44:20 +0200 Subject: [PATCH 2/4] hide maxReadFileLine truncation message for explicit line range reads --- src/core/tools/readFileTool.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/tools/readFileTool.ts b/src/core/tools/readFileTool.ts index a1c337e025..76be26bb09 100644 --- a/src/core/tools/readFileTool.ts +++ b/src/core/tools/readFileTool.ts @@ -140,9 +140,16 @@ export async function readFileTool( content: absolutePath, // Only include reason (truncation message) if the file will actually be truncated // or if it's a specific range read (not the default max lines message) - ...(!isFullRead && maxReadFileLine > 0 && totalLines > maxReadFileLine + ...// Only set wasAutoTruncated to true when: + // 1. It's not a full read + // 2. It's not a range read (no explicit start_line/end_line) + // 3. maxReadFileLine is greater than 0 + // 4. The total lines in the file exceed maxReadFileLine + (!isFullRead && !isRangeRead && maxReadFileLine > 0 && totalLines > maxReadFileLine ? { reason: lineSnippet, wasAutoTruncated: true } - : lineSnippet && lineSnippet !== t("tools:readFile.maxLines", { max: maxReadFileLine }) + : lineSnippet && + // For range reads or other cases, include the reason without wasAutoTruncated + (isRangeRead || lineSnippet !== t("tools:readFile.maxLines", { max: maxReadFileLine })) ? { reason: lineSnippet } : {}), } satisfies ClineSayTool) From 71cfa744d44bc894a8badb9a76a784fe561decf0 Mon Sep 17 00:00:00 2001 From: cannuri <91494156+cannuri@users.noreply.github.com> Date: Wed, 14 May 2025 21:03:19 +0200 Subject: [PATCH 3/4] fix: Always display line range notification in readFileTool regardless of maxReadFileLine setting --- src/core/tools/readFileTool.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/core/tools/readFileTool.ts b/src/core/tools/readFileTool.ts index 76be26bb09..5406316e6e 100644 --- a/src/core/tools/readFileTool.ts +++ b/src/core/tools/readFileTool.ts @@ -59,8 +59,13 @@ export async function readFileTool( let startLine: number | undefined = undefined let endLine: number | undefined = undefined - // Check if we have either range parameter and we're not doing a full read - if (!isFullRead && (startLineStr || endLineStr)) { + // Track if range parameters are provided, regardless of maxReadFileLine setting + // This is used for displaying the line range notification + let hasRangeParams = startLineStr || endLineStr + + // For actual range reading behavior, only consider it a range read + // if we're not doing a full read (maxReadFileLine != -1) + if (!isFullRead && hasRangeParams) { isRangeRead = true } @@ -109,14 +114,15 @@ export async function readFileTool( // Create line snippet description for approval message let lineSnippet = "" - if (isFullRead) { - // No snippet for full read - } else if (startLine !== undefined && endLine !== undefined) { + // Always set line snippet for range parameters, regardless of maxReadFileLine setting + if (startLine !== undefined && endLine !== undefined) { lineSnippet = t("tools:readFile.linesRange", { start: startLine + 1, end: endLine + 1 }) } else if (startLine !== undefined) { lineSnippet = t("tools:readFile.linesFromToEnd", { start: startLine + 1 }) } else if (endLine !== undefined) { lineSnippet = t("tools:readFile.linesFromStartTo", { end: endLine + 1 }) + } else if (isFullRead) { + // No snippet for full read without range parameters } else if (maxReadFileLine === 0) { lineSnippet = t("tools:readFile.definitionsOnly") } else if (maxReadFileLine > 0) { @@ -148,8 +154,11 @@ export async function readFileTool( (!isFullRead && !isRangeRead && maxReadFileLine > 0 && totalLines > maxReadFileLine ? { reason: lineSnippet, wasAutoTruncated: true } : lineSnippet && - // For range reads or other cases, include the reason without wasAutoTruncated - (isRangeRead || lineSnippet !== t("tools:readFile.maxLines", { max: maxReadFileLine })) + // For range parameters, always include the reason without wasAutoTruncated + // regardless of maxReadFileLine setting + (hasRangeParams || + // For other cases, include the reason if it's not the default max lines message + lineSnippet !== t("tools:readFile.maxLines", { max: maxReadFileLine })) ? { reason: lineSnippet } : {}), } satisfies ClineSayTool) From 83e4e7e1c14e1ce5109a26c26fea392c6fbadd23 Mon Sep 17 00:00:00 2001 From: cannuri <91494156+cannuri@users.noreply.github.com> Date: Thu, 15 May 2025 18:58:14 +0200 Subject: [PATCH 4/4] Add localization support for readFile tool across multiple languages --- src/i18n/locales/ca/tools.json | 3 ++- src/i18n/locales/de/tools.json | 3 ++- src/i18n/locales/en/tools.json | 2 +- src/i18n/locales/es/tools.json | 3 ++- src/i18n/locales/fr/tools.json | 3 ++- src/i18n/locales/hi/tools.json | 3 ++- src/i18n/locales/it/tools.json | 3 ++- src/i18n/locales/ja/tools.json | 3 ++- src/i18n/locales/ko/tools.json | 3 ++- src/i18n/locales/nl/tools.json | 3 ++- src/i18n/locales/pl/tools.json | 3 ++- src/i18n/locales/pt-BR/tools.json | 3 ++- src/i18n/locales/ru/tools.json | 3 ++- src/i18n/locales/tr/tools.json | 3 ++- src/i18n/locales/vi/tools.json | 3 ++- src/i18n/locales/zh-CN/tools.json | 3 ++- src/i18n/locales/zh-TW/tools.json | 3 ++- webview-ui/src/components/chat/ChatRow.tsx | 13 +++++++++---- webview-ui/src/i18n/locales/ca/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/de/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/en/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/es/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/fr/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/hi/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/it/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/ja/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/ko/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/nl/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/pl/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/pt-BR/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/ru/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/tr/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/vi/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/zh-CN/tools.json | 11 +++++++++++ webview-ui/src/i18n/locales/zh-TW/tools.json | 11 +++++++++++ 35 files changed, 229 insertions(+), 21 deletions(-) create mode 100644 webview-ui/src/i18n/locales/ca/tools.json create mode 100644 webview-ui/src/i18n/locales/de/tools.json create mode 100644 webview-ui/src/i18n/locales/en/tools.json create mode 100644 webview-ui/src/i18n/locales/es/tools.json create mode 100644 webview-ui/src/i18n/locales/fr/tools.json create mode 100644 webview-ui/src/i18n/locales/hi/tools.json create mode 100644 webview-ui/src/i18n/locales/it/tools.json create mode 100644 webview-ui/src/i18n/locales/ja/tools.json create mode 100644 webview-ui/src/i18n/locales/ko/tools.json create mode 100644 webview-ui/src/i18n/locales/nl/tools.json create mode 100644 webview-ui/src/i18n/locales/pl/tools.json create mode 100644 webview-ui/src/i18n/locales/pt-BR/tools.json create mode 100644 webview-ui/src/i18n/locales/ru/tools.json create mode 100644 webview-ui/src/i18n/locales/tr/tools.json create mode 100644 webview-ui/src/i18n/locales/vi/tools.json create mode 100644 webview-ui/src/i18n/locales/zh-CN/tools.json create mode 100644 webview-ui/src/i18n/locales/zh-TW/tools.json diff --git a/src/i18n/locales/ca/tools.json b/src/i18n/locales/ca/tools.json index 0fe673310f..21215828c9 100644 --- a/src/i18n/locales/ca/tools.json +++ b/src/i18n/locales/ca/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (línies {{start}}-{{end}})", "definitionsOnly": " (només definicions)", - "maxLines": " (màxim {{max}} línies)" + "maxLines": " (màxim {{max}} línies)", + "autoTruncateTooltip": "Per ajustar aquest límit, feu clic a la icona '{{settings}}' (⚙️) al panell de Roo-Code, després feu clic a '{{context}}' i trobeu l'opció '{{threshold}}'." }, "toolRepetitionLimitReached": "Roo sembla estar atrapat en un bucle, intentant la mateixa acció ({{toolName}}) repetidament. Això podria indicar un problema amb la seva estratègia actual. Considera reformular la tasca, proporcionar instruccions més específiques o guiar-lo cap a un enfocament diferent.", "codebaseSearch": { diff --git a/src/i18n/locales/de/tools.json b/src/i18n/locales/de/tools.json index 03c491c115..54968f2b4b 100644 --- a/src/i18n/locales/de/tools.json +++ b/src/i18n/locales/de/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (Zeilen {{start}}-{{end}})", "definitionsOnly": " (nur Definitionen)", - "maxLines": " (maximal {{max}} Zeilen)" + "maxLines": " (maximal {{max}} Zeilen)", + "autoTruncateTooltip": "Um dieses Limit anzupassen, klicke auf das '{{settings}}'-Symbol (⚙️) im Roo-Code-Panel, dann auf '{{context}}' und finde die Option '{{threshold}}'." }, "toolRepetitionLimitReached": "Roo scheint in einer Schleife festzustecken und versucht wiederholt dieselbe Aktion ({{toolName}}). Dies könnte auf ein Problem mit der aktuellen Strategie hindeuten. Überlege dir, die Aufgabe umzuformulieren, genauere Anweisungen zu geben oder Roo zu einem anderen Ansatz zu führen.", "codebaseSearch": { diff --git a/src/i18n/locales/en/tools.json b/src/i18n/locales/en/tools.json index 2079e468b8..7c72b2bbfa 100644 --- a/src/i18n/locales/en/tools.json +++ b/src/i18n/locales/en/tools.json @@ -3,7 +3,7 @@ "linesRange": " (lines {{start}}-{{end}})", "definitionsOnly": " (definitions only)", "maxLines": " (max {{max}} lines)", - "autoTruncateTooltip": "To adjust this limit, click the \"Settings\" icon (⚙️) in the Roo-Code panel, then click on \"Context\" and find the 'File read auto-truncate threshold' option." + "autoTruncateTooltip": "To adjust this limit, click the '{{settings}}' icon (⚙️) in the Roo-Code panel, then click on '{{context}}' and find the '{{threshold}}' option." }, "toolRepetitionLimitReached": "Roo appears to be stuck in a loop, attempting the same action ({{toolName}}) repeatedly. This might indicate a problem with its current strategy. Consider rephrasing the task, providing more specific instructions, or guiding it towards a different approach.", "codebaseSearch": { diff --git a/src/i18n/locales/es/tools.json b/src/i18n/locales/es/tools.json index 0dbba751b7..7eb196d906 100644 --- a/src/i18n/locales/es/tools.json +++ b/src/i18n/locales/es/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (líneas {{start}}-{{end}})", "definitionsOnly": " (solo definiciones)", - "maxLines": " (máximo {{max}} líneas)" + "maxLines": " (máximo {{max}} líneas)", + "autoTruncateTooltip": "Para ajustar este límite, haz clic en el icono '{{settings}}' (⚙️) en el panel de Roo-Code, luego en '{{context}}' y busca la opción '{{threshold}}'." }, "toolRepetitionLimitReached": "Roo parece estar atrapado en un bucle, intentando la misma acción ({{toolName}}) repetidamente. Esto podría indicar un problema con su estrategia actual. Considera reformular la tarea, proporcionar instrucciones más específicas o guiarlo hacia un enfoque diferente.", "codebaseSearch": { diff --git a/src/i18n/locales/fr/tools.json b/src/i18n/locales/fr/tools.json index bdf26fb3cb..e3be1e0e7f 100644 --- a/src/i18n/locales/fr/tools.json +++ b/src/i18n/locales/fr/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (lignes {{start}}-{{end}})", "definitionsOnly": " (définitions uniquement)", - "maxLines": " (max {{max}} lignes)" + "maxLines": " (max {{max}} lignes)", + "autoTruncateTooltip": "Pour ajuster cette limite, clique sur l'icône '{{settings}}' (⚙️) dans le panneau Roo-Code, puis sur '{{context}}' et trouve l'option '{{threshold}}'." }, "toolRepetitionLimitReached": "Roo semble être bloqué dans une boucle, tentant la même action ({{toolName}}) de façon répétée. Cela pourrait indiquer un problème avec sa stratégie actuelle. Envisage de reformuler la tâche, de fournir des instructions plus spécifiques ou de le guider vers une approche différente.", "codebaseSearch": { diff --git a/src/i18n/locales/hi/tools.json b/src/i18n/locales/hi/tools.json index 257fc8a531..40fcc1e81e 100644 --- a/src/i18n/locales/hi/tools.json +++ b/src/i18n/locales/hi/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (पंक्तियाँ {{start}}-{{end}})", "definitionsOnly": " (केवल परिभाषाएँ)", - "maxLines": " (अधिकतम {{max}} पंक्तियाँ)" + "maxLines": " (अधिकतम {{max}} पंक्तियाँ)", + "autoTruncateTooltip": "इस सीमा को समायोजित करने के लिए, Roo-Code पैनल में '{{settings}}' आइकन (⚙️) पर क्लिक करें, फिर '{{context}}' पर क्लिक करें और '{{threshold}}' विकल्प खोजें।" }, "toolRepetitionLimitReached": "Roo एक लूप में फंसा हुआ लगता है, बार-बार एक ही क्रिया ({{toolName}}) को दोहरा रहा है। यह उसकी वर्तमान रणनीति में किसी समस्या का संकेत हो सकता है। कार्य को पुनः परिभाषित करने, अधिक विशिष्ट निर्देश देने, या उसे एक अलग दृष्टिकोण की ओर मार्गदर्शित करने पर विचार करें।", "codebaseSearch": { diff --git a/src/i18n/locales/it/tools.json b/src/i18n/locales/it/tools.json index 0dc14f94a5..18922b051c 100644 --- a/src/i18n/locales/it/tools.json +++ b/src/i18n/locales/it/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (righe {{start}}-{{end}})", "definitionsOnly": " (solo definizioni)", - "maxLines": " (max {{max}} righe)" + "maxLines": " (max {{max}} righe)", + "autoTruncateTooltip": "Per regolare questo limite, fai clic sull'icona '{{settings}}' (⚙️) nel pannello Roo-Code, poi su '{{context}}' e trova l'opzione '{{threshold}}'." }, "toolRepetitionLimitReached": "Roo sembra essere bloccato in un ciclo, tentando ripetutamente la stessa azione ({{toolName}}). Questo potrebbe indicare un problema con la sua strategia attuale. Considera di riformulare l'attività, fornire istruzioni più specifiche o guidarlo verso un approccio diverso.", "codebaseSearch": { diff --git a/src/i18n/locales/ja/tools.json b/src/i18n/locales/ja/tools.json index ad6b7019c8..b4a075dcae 100644 --- a/src/i18n/locales/ja/tools.json +++ b/src/i18n/locales/ja/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " ({{start}}-{{end}}行目)", "definitionsOnly": " (定義のみ)", - "maxLines": " (最大{{max}}行)" + "maxLines": " (最大{{max}}行)", + "autoTruncateTooltip": "この制限を調整するには、Roo-Codeパネルの「{{settings}}」アイコン(⚙️)をクリックし、「{{context}}」をクリックして「{{threshold}}」オプションを探してください。" }, "toolRepetitionLimitReached": "Rooが同じ操作({{toolName}})を繰り返し試みるループに陥っているようです。これは現在の方法に問題がある可能性を示しています。タスクの言い換え、より具体的な指示の提供、または別のアプローチへの誘導を検討してください。", "codebaseSearch": { diff --git a/src/i18n/locales/ko/tools.json b/src/i18n/locales/ko/tools.json index c8c8deebec..a1caf4aa65 100644 --- a/src/i18n/locales/ko/tools.json +++ b/src/i18n/locales/ko/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " ({{start}}-{{end}}행)", "definitionsOnly": " (정의만)", - "maxLines": " (최대 {{max}}행)" + "maxLines": " (최대 {{max}}행)", + "autoTruncateTooltip": "이 제한을 조정하려면 Roo-Code 패널에서 '{{settings}}' 아이콘(⚙️)을 클릭한 다음 '{{context}}'를 클릭하고 '{{threshold}}' 옵션을 찾으세요." }, "toolRepetitionLimitReached": "Roo가 같은 동작({{toolName}})을 반복적으로 시도하면서 루프에 갇힌 것 같습니다. 이는 현재 전략에 문제가 있을 수 있음을 나타냅니다. 작업을 다시 표현하거나, 더 구체적인 지침을 제공하거나, 다른 접근 방식으로 안내해 보세요.", "codebaseSearch": { diff --git a/src/i18n/locales/nl/tools.json b/src/i18n/locales/nl/tools.json index 8779caaf38..f3ed15f1e6 100644 --- a/src/i18n/locales/nl/tools.json +++ b/src/i18n/locales/nl/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (regels {{start}}-{{end}})", "definitionsOnly": " (alleen definities)", - "maxLines": " (max {{max}} regels)" + "maxLines": " (max {{max}} regels)", + "autoTruncateTooltip": "Om deze limiet aan te passen, klik op het '{{settings}}' icoon (⚙️) in het Roo-Code paneel, klik vervolgens op '{{context}}' en zoek de optie '{{threshold}}'." }, "toolRepetitionLimitReached": "Roo lijkt vast te zitten in een lus, waarbij hij herhaaldelijk dezelfde actie ({{toolName}}) probeert. Dit kan duiden op een probleem met de huidige strategie. Overweeg de taak te herformuleren, specifiekere instructies te geven of Roo naar een andere aanpak te leiden.", "codebaseSearch": { diff --git a/src/i18n/locales/pl/tools.json b/src/i18n/locales/pl/tools.json index 1cfb8d59de..c984cebcad 100644 --- a/src/i18n/locales/pl/tools.json +++ b/src/i18n/locales/pl/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (linie {{start}}-{{end}})", "definitionsOnly": " (tylko definicje)", - "maxLines": " (maks. {{max}} linii)" + "maxLines": " (maks. {{max}} linii)", + "autoTruncateTooltip": "Aby dostosować ten limit, kliknij ikonę '{{settings}}' (⚙️) w panelu Roo-Code, następnie kliknij '{{context}}' i znajdź opcję '{{threshold}}'." }, "toolRepetitionLimitReached": "Wygląda na to, że Roo utknął w pętli, wielokrotnie próbując wykonać tę samą akcję ({{toolName}}). Może to wskazywać na problem z jego obecną strategią. Rozważ przeformułowanie zadania, podanie bardziej szczegółowych instrukcji lub nakierowanie go na inne podejście.", "codebaseSearch": { diff --git a/src/i18n/locales/pt-BR/tools.json b/src/i18n/locales/pt-BR/tools.json index 9c03e6082f..a8c3add645 100644 --- a/src/i18n/locales/pt-BR/tools.json +++ b/src/i18n/locales/pt-BR/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (linhas {{start}}-{{end}})", "definitionsOnly": " (apenas definições)", - "maxLines": " (máx. {{max}} linhas)" + "maxLines": " (máx. {{max}} linhas)", + "autoTruncateTooltip": "Para ajustar este limite, clique no ícone '{{settings}}' (⚙️) no painel Roo-Code, depois clique em '{{context}}' e encontre a opção '{{threshold}}'." }, "toolRepetitionLimitReached": "Roo parece estar preso em um loop, tentando a mesma ação ({{toolName}}) repetidamente. Isso pode indicar um problema com sua estratégia atual. Considere reformular a tarefa, fornecer instruções mais específicas ou guiá-lo para uma abordagem diferente.", "codebaseSearch": { diff --git a/src/i18n/locales/ru/tools.json b/src/i18n/locales/ru/tools.json index 42705f5ec3..a56941478c 100644 --- a/src/i18n/locales/ru/tools.json +++ b/src/i18n/locales/ru/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (строки {{start}}-{{end}})", "definitionsOnly": " (только определения)", - "maxLines": " (макс. {{max}} строк)" + "maxLines": " (макс. {{max}} строк)", + "autoTruncateTooltip": "Чтобы изменить этот лимит, нажмите на значок '{{settings}}' (⚙️) в панели Roo-Code, затем нажмите на '{{context}}' и найдите опцию '{{threshold}}'." }, "toolRepetitionLimitReached": "Похоже, что Roo застрял в цикле, многократно пытаясь выполнить одно и то же действие ({{toolName}}). Это может указывать на проблему с его текущей стратегией. Попробуйте переформулировать задачу, предоставить более конкретные инструкции или направить его к другому подходу.", "codebaseSearch": { diff --git a/src/i18n/locales/tr/tools.json b/src/i18n/locales/tr/tools.json index 4dff83eac4..3149481bbc 100644 --- a/src/i18n/locales/tr/tools.json +++ b/src/i18n/locales/tr/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (satır {{start}}-{{end}})", "definitionsOnly": " (sadece tanımlar)", - "maxLines": " (maks. {{max}} satır)" + "maxLines": " (maks. {{max}} satır)", + "autoTruncateTooltip": "Bu limiti ayarlamak için, Roo-Code panelindeki '{{settings}}' simgesine (⚙️) tıklayın, ardından '{{context}}' seçeneğine tıklayın ve '{{threshold}}' seçeneğini bulun." }, "toolRepetitionLimitReached": "Roo bir döngüye takılmış gibi görünüyor, aynı eylemi ({{toolName}}) tekrar tekrar deniyor. Bu, mevcut stratejisinde bir sorun olduğunu gösterebilir. Görevi yeniden ifade etmeyi, daha spesifik talimatlar vermeyi veya onu farklı bir yaklaşıma yönlendirmeyi düşünün.", "codebaseSearch": { diff --git a/src/i18n/locales/vi/tools.json b/src/i18n/locales/vi/tools.json index 67d83f90fc..5c03f2cc51 100644 --- a/src/i18n/locales/vi/tools.json +++ b/src/i18n/locales/vi/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (dòng {{start}}-{{end}})", "definitionsOnly": " (chỉ định nghĩa)", - "maxLines": " (tối đa {{max}} dòng)" + "maxLines": " (tối đa {{max}} dòng)", + "autoTruncateTooltip": "Để điều chỉnh giới hạn này, nhấp vào biểu tượng '{{settings}}' (⚙️) trong bảng điều khiển Roo-Code, sau đó nhấp vào '{{context}}' và tìm tùy chọn '{{threshold}}'." }, "toolRepetitionLimitReached": "Roo dường như đang bị mắc kẹt trong một vòng lặp, liên tục cố gắng thực hiện cùng một hành động ({{toolName}}). Điều này có thể cho thấy vấn đề với chiến lược hiện tại. Hãy cân nhắc việc diễn đạt lại nhiệm vụ, cung cấp hướng dẫn cụ thể hơn, hoặc hướng Roo theo một cách tiếp cận khác.", "codebaseSearch": { diff --git a/src/i18n/locales/zh-CN/tools.json b/src/i18n/locales/zh-CN/tools.json index 9328251d05..432a55d41b 100644 --- a/src/i18n/locales/zh-CN/tools.json +++ b/src/i18n/locales/zh-CN/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (第 {{start}}-{{end}} 行)", "definitionsOnly": " (仅定义)", - "maxLines": " (最多 {{max}} 行)" + "maxLines": " (最多 {{max}} 行)", + "autoTruncateTooltip": "要调整此限制,请点击 Roo-Code 面板中的\"{{settings}}\"图标 (⚙️),然后点击\"{{context}}\"并找到\"{{threshold}}\"选项。" }, "toolRepetitionLimitReached": "Roo 似乎陷入循环,反复尝试同一操作 ({{toolName}})。这可能表明当前策略存在问题。请考虑重新描述任务、提供更具体的指示或引导其尝试不同的方法。", "codebaseSearch": { diff --git a/src/i18n/locales/zh-TW/tools.json b/src/i18n/locales/zh-TW/tools.json index 04b16c2bc7..43c4d18c38 100644 --- a/src/i18n/locales/zh-TW/tools.json +++ b/src/i18n/locales/zh-TW/tools.json @@ -2,7 +2,8 @@ "readFile": { "linesRange": " (第 {{start}}-{{end}} 行)", "definitionsOnly": " (僅定義)", - "maxLines": " (最多 {{max}} 行)" + "maxLines": " (最多 {{max}} 行)", + "autoTruncateTooltip": "要調整此限制,請點擊 Roo-Code 面板中的\"{{settings}}\"圖示 (⚙️),然後點擊\"{{context}}\"並找到\"{{threshold}}\"選項。" }, "toolRepetitionLimitReached": "Roo 似乎陷入循環,反覆嘗試同一操作 ({{toolName}})。這可能表明目前策略存在問題。請考慮重新描述工作、提供更具體的指示或引導其嘗試不同的方法。", "codebaseSearch": { diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index b5ee69bc11..32935011c5 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -467,11 +467,16 @@ export const ChatRowContent = ({ {removeLeadingNonAlphanumeric(tool.path ?? "") + "\u200E"} {tool.wasAutoTruncated && tool.reason && ( - + {tool.reason} - + )} {!tool.wasAutoTruncated && tool.reason && {tool.reason}} diff --git a/webview-ui/src/i18n/locales/ca/tools.json b/webview-ui/src/i18n/locales/ca/tools.json new file mode 100644 index 0000000000..c59d908e17 --- /dev/null +++ b/webview-ui/src/i18n/locales/ca/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (línies {{start}}-{{end}})", + "linesFromToEnd": " (línies {{start}}-final)", + "linesFromStartTo": " (línies 1-{{end}})", + "definitionsOnly": " (només definicions)", + "maxLines": " (màxim {{max}} línies)", + "autoTruncateTooltip": "Per ajustar aquest límit, feu clic a la icona '{{settings}}' (⚙️) al panell de Roo-Code, després feu clic a '{{context}}' i trobeu l'opció '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Sembla que Roo està atrapat en un bucle, intentant la mateixa acció ({{toolName}}) repetidament. Això podria indicar un problema amb la seva estratègia actual. Considereu reformular la tasca, proporcionar instruccions més específiques o guiar-lo cap a un enfocament diferent." +} diff --git a/webview-ui/src/i18n/locales/de/tools.json b/webview-ui/src/i18n/locales/de/tools.json new file mode 100644 index 0000000000..4f3509c1f0 --- /dev/null +++ b/webview-ui/src/i18n/locales/de/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (Zeilen {{start}}-{{end}})", + "linesFromToEnd": " (Zeilen {{start}}-Ende)", + "linesFromStartTo": " (Zeilen 1-{{end}})", + "definitionsOnly": " (nur Definitionen)", + "maxLines": " (maximal {{max}} Zeilen)", + "autoTruncateTooltip": "Um dieses Limit anzupassen, klicke auf das '{{settings}}'-Symbol (⚙️) im Roo-Code-Panel, dann auf '{{context}}' und finde die Option '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Roo scheint in einer Schleife festzustecken und versucht wiederholt dieselbe Aktion ({{toolName}}). Dies könnte auf ein Problem mit der aktuellen Strategie hindeuten. Überlege dir, die Aufgabe umzuformulieren, genauere Anweisungen zu geben oder Roo zu einem anderen Ansatz zu führen." +} diff --git a/webview-ui/src/i18n/locales/en/tools.json b/webview-ui/src/i18n/locales/en/tools.json new file mode 100644 index 0000000000..1d3c9d6dbb --- /dev/null +++ b/webview-ui/src/i18n/locales/en/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (lines {{start}}-{{end}})", + "linesFromToEnd": " (lines {{start}}-end)", + "linesFromStartTo": " (lines 1-{{end}})", + "definitionsOnly": " (definitions only)", + "maxLines": " (max {{max}} lines)", + "autoTruncateTooltip": "To adjust this limit, click the '{{settings}}' icon (⚙️) in the Roo-Code panel, then click on '{{context}}' and find the '{{threshold}}' option." + }, + "toolRepetitionLimitReached": "Roo appears to be stuck in a loop, attempting the same action ({{toolName}}) repeatedly. This might indicate a problem with its current strategy. Consider rephrasing the task, providing more specific instructions, or guiding it towards a different approach." +} diff --git a/webview-ui/src/i18n/locales/es/tools.json b/webview-ui/src/i18n/locales/es/tools.json new file mode 100644 index 0000000000..56baadd495 --- /dev/null +++ b/webview-ui/src/i18n/locales/es/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (líneas {{start}}-{{end}})", + "linesFromToEnd": " (líneas {{start}}-final)", + "linesFromStartTo": " (líneas 1-{{end}})", + "definitionsOnly": " (solo definiciones)", + "maxLines": " (máximo {{max}} líneas)", + "autoTruncateTooltip": "Para ajustar este límite, haz clic en el icono '{{settings}}' (⚙️) en el panel de Roo-Code, luego en '{{context}}' y busca la opción '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Roo parece estar atrapado en un bucle, intentando la misma acción ({{toolName}}) repetidamente. Esto podría indicar un problema con su estrategia actual. Considera reformular la tarea, proporcionar instrucciones más específicas o guiarlo hacia un enfoque diferente." +} diff --git a/webview-ui/src/i18n/locales/fr/tools.json b/webview-ui/src/i18n/locales/fr/tools.json new file mode 100644 index 0000000000..88caf61fa1 --- /dev/null +++ b/webview-ui/src/i18n/locales/fr/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (lignes {{start}}-{{end}})", + "linesFromToEnd": " (lignes {{start}}-fin)", + "linesFromStartTo": " (lignes 1-{{end}})", + "definitionsOnly": " (définitions uniquement)", + "maxLines": " (max {{max}} lignes)", + "autoTruncateTooltip": "Pour ajuster cette limite, clique sur l'icône '{{settings}}' (⚙️) dans le panneau Roo-Code, puis sur '{{context}}' et trouve l'option '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Roo semble être bloqué dans une boucle, tentant la même action ({{toolName}}) de façon répétée. Cela pourrait indiquer un problème avec sa stratégie actuelle. Envisage de reformuler la tâche, de fournir des instructions plus spécifiques ou de le guider vers une approche différente." +} diff --git a/webview-ui/src/i18n/locales/hi/tools.json b/webview-ui/src/i18n/locales/hi/tools.json new file mode 100644 index 0000000000..77b206f1bd --- /dev/null +++ b/webview-ui/src/i18n/locales/hi/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (लाइन {{start}}-{{end}})", + "linesFromToEnd": " (लाइन {{start}}-अंत)", + "linesFromStartTo": " (लाइन 1-{{end}})", + "definitionsOnly": " (केवल परिभाषाएँ)", + "maxLines": " (अधिकतम {{max}} लाइनें)", + "autoTruncateTooltip": "इस सीमा को समायोजित करने के लिए, Roo-Code पैनल में '{{settings}}' आइकन (⚙️) पर क्लिक करें, फिर '{{context}}' पर क्लिक करें और '{{threshold}}' विकल्प खोजें।" + }, + "toolRepetitionLimitReached": "ऐसा लगता है कि Roo एक लूप में फंस गया है, बार-बार एक ही क्रिया ({{toolName}}) का प्रयास कर रहा है। यह उसकी वर्तमान रणनीति में किसी समस्या का संकेत हो सकता है। कार्य को पुनः प्रस्तुत करने, अधिक विशिष्ट निर्देश देने, या इसे एक अलग दृष्टिकोण की ओर निर्देशित करने पर विचार करें।" +} diff --git a/webview-ui/src/i18n/locales/it/tools.json b/webview-ui/src/i18n/locales/it/tools.json new file mode 100644 index 0000000000..2534e5f36e --- /dev/null +++ b/webview-ui/src/i18n/locales/it/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (righe {{start}}-{{end}})", + "linesFromToEnd": " (righe {{start}}-fine)", + "linesFromStartTo": " (righe 1-{{end}})", + "definitionsOnly": " (solo definizioni)", + "maxLines": " (max {{max}} righe)", + "autoTruncateTooltip": "Per regolare questo limite, fai clic sull'icona '{{settings}}' (⚙️) nel pannello Roo-Code, poi su '{{context}}' e trova l'opzione '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Roo sembra essere bloccato in un ciclo, tentando ripetutamente la stessa azione ({{toolName}}). Questo potrebbe indicare un problema con la sua strategia attuale. Considera di riformulare l'attività, fornire istruzioni più specifiche o guidarlo verso un approccio diverso." +} diff --git a/webview-ui/src/i18n/locales/ja/tools.json b/webview-ui/src/i18n/locales/ja/tools.json new file mode 100644 index 0000000000..02d2f44936 --- /dev/null +++ b/webview-ui/src/i18n/locales/ja/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " ({{start}}-{{end}}行目)", + "linesFromToEnd": " ({{start}}行目-最後まで)", + "linesFromStartTo": " (1-{{end}}行目)", + "definitionsOnly": " (定義のみ)", + "maxLines": " (最大{{max}}行)", + "autoTruncateTooltip": "この制限を調整するには、Roo-Codeパネルの「{{settings}}」アイコン(⚙️)をクリックし、「{{context}}」をクリックして「{{threshold}}」オプションを探してください。" + }, + "toolRepetitionLimitReached": "Rooが同じ操作({{toolName}})を繰り返し試みるループに陥っているようです。これは現在の方法に問題がある可能性を示しています。タスクの言い換え、より具体的な指示の提供、または別のアプローチへの誘導を検討してください。" +} diff --git a/webview-ui/src/i18n/locales/ko/tools.json b/webview-ui/src/i18n/locales/ko/tools.json new file mode 100644 index 0000000000..823b155518 --- /dev/null +++ b/webview-ui/src/i18n/locales/ko/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " ({{start}}-{{end}}행)", + "linesFromToEnd": " ({{start}}행-끝)", + "linesFromStartTo": " (1-{{end}}행)", + "definitionsOnly": " (정의만)", + "maxLines": " (최대 {{max}}행)", + "autoTruncateTooltip": "이 제한을 조정하려면 Roo-Code 패널에서 '{{settings}}' 아이콘(⚙️)을 클릭한 다음 '{{context}}'를 클릭하고 '{{threshold}}' 옵션을 찾으세요." + }, + "toolRepetitionLimitReached": "Roo가 같은 동작({{toolName}})을 반복적으로 시도하면서 루프에 갇힌 것 같습니다. 이는 현재 전략에 문제가 있을 수 있음을 나타냅니다. 작업을 다시 표현하거나, 더 구체적인 지침을 제공하거나, 다른 접근 방식으로 안내해 보세요." +} diff --git a/webview-ui/src/i18n/locales/nl/tools.json b/webview-ui/src/i18n/locales/nl/tools.json new file mode 100644 index 0000000000..19d7446d11 --- /dev/null +++ b/webview-ui/src/i18n/locales/nl/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (regels {{start}}-{{end}})", + "linesFromToEnd": " (regels {{start}}-einde)", + "linesFromStartTo": " (regels 1-{{end}})", + "definitionsOnly": " (alleen definities)", + "maxLines": " (max {{max}} regels)", + "autoTruncateTooltip": "Om deze limiet aan te passen, klik op het '{{settings}}' icoon (⚙️) in het Roo-Code paneel, klik vervolgens op '{{context}}' en zoek de optie '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Roo lijkt vast te zitten in een lus, waarbij dezelfde actie ({{toolName}}) herhaaldelijk wordt geprobeerd. Dit kan wijzen op een probleem met de huidige strategie. Overweeg de taak te herformuleren, specifiekere instructies te geven of Roo naar een andere aanpak te leiden." +} diff --git a/webview-ui/src/i18n/locales/pl/tools.json b/webview-ui/src/i18n/locales/pl/tools.json new file mode 100644 index 0000000000..e8dc7660e4 --- /dev/null +++ b/webview-ui/src/i18n/locales/pl/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (linie {{start}}-{{end}})", + "linesFromToEnd": " (linie {{start}}-koniec)", + "linesFromStartTo": " (linie 1-{{end}})", + "definitionsOnly": " (tylko definicje)", + "maxLines": " (maks. {{max}} linii)", + "autoTruncateTooltip": "Aby dostosować ten limit, kliknij ikonę '{{settings}}' (⚙️) w panelu Roo-Code, następnie kliknij '{{context}}' i znajdź opcję '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Wygląda na to, że Roo utknął w pętli, wielokrotnie próbując wykonać tę samą akcję ({{toolName}}). Może to wskazywać na problem z obecną strategią. Rozważ przeformułowanie zadania, dostarczenie bardziej szczegółowych instrukcji lub skierowanie go w stronę innego podejścia." +} diff --git a/webview-ui/src/i18n/locales/pt-BR/tools.json b/webview-ui/src/i18n/locales/pt-BR/tools.json new file mode 100644 index 0000000000..45e663eebe --- /dev/null +++ b/webview-ui/src/i18n/locales/pt-BR/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (linhas {{start}}-{{end}})", + "linesFromToEnd": " (linhas {{start}}-fim)", + "linesFromStartTo": " (linhas 1-{{end}})", + "definitionsOnly": " (apenas definições)", + "maxLines": " (máx {{max}} linhas)", + "autoTruncateTooltip": "Para ajustar este limite, clique no ícone '{{settings}}' (⚙️) no painel Roo-Code, depois clique em '{{context}}' e encontre a opção '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Roo parece estar preso em um loop, tentando a mesma ação ({{toolName}}) repetidamente. Isso pode indicar um problema com sua estratégia atual. Considere reformular a tarefa, fornecer instruções mais específicas ou guiá-lo para uma abordagem diferente." +} diff --git a/webview-ui/src/i18n/locales/ru/tools.json b/webview-ui/src/i18n/locales/ru/tools.json new file mode 100644 index 0000000000..0a5a591dbe --- /dev/null +++ b/webview-ui/src/i18n/locales/ru/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (строки {{start}}-{{end}})", + "linesFromToEnd": " (строки {{start}}-конец)", + "linesFromStartTo": " (строки 1-{{end}})", + "definitionsOnly": " (только определения)", + "maxLines": " (макс. {{max}} строк)", + "autoTruncateTooltip": "Чтобы изменить этот лимит, нажмите на значок '{{settings}}' (⚙️) в панели Roo-Code, затем нажмите на '{{context}}' и найдите опцию '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Похоже, Roo застрял в цикле, многократно пытаясь выполнить одно и то же действие ({{toolName}}). Это может указывать на проблему с текущей стратегией. Рассмотрите возможность переформулировать задачу, предоставить более конкретные инструкции или направить его к другому подходу." +} diff --git a/webview-ui/src/i18n/locales/tr/tools.json b/webview-ui/src/i18n/locales/tr/tools.json new file mode 100644 index 0000000000..5403159d55 --- /dev/null +++ b/webview-ui/src/i18n/locales/tr/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (satır {{start}}-{{end}})", + "linesFromToEnd": " (satır {{start}}-son)", + "linesFromStartTo": " (satır 1-{{end}})", + "definitionsOnly": " (sadece tanımlar)", + "maxLines": " (maks {{max}} satır)", + "autoTruncateTooltip": "Bu limiti ayarlamak için, Roo-Code panelindeki '{{settings}}' simgesine (⚙️) tıklayın, ardından '{{context}}' seçeneğine tıklayın ve '{{threshold}}' seçeneğini bulun." + }, + "toolRepetitionLimitReached": "Roo bir döngüye takılmış gibi görünüyor, aynı eylemi ({{toolName}}) tekrar tekrar deniyor. Bu, mevcut stratejisinde bir sorun olduğunu gösterebilir. Görevi yeniden ifade etmeyi, daha spesifik talimatlar vermeyi veya onu farklı bir yaklaşıma yönlendirmeyi düşünün." +} diff --git a/webview-ui/src/i18n/locales/vi/tools.json b/webview-ui/src/i18n/locales/vi/tools.json new file mode 100644 index 0000000000..85cae45564 --- /dev/null +++ b/webview-ui/src/i18n/locales/vi/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (dòng {{start}}-{{end}})", + "linesFromToEnd": " (dòng {{start}}-cuối)", + "linesFromStartTo": " (dòng 1-{{end}})", + "definitionsOnly": " (chỉ định nghĩa)", + "maxLines": " (tối đa {{max}} dòng)", + "autoTruncateTooltip": "Để điều chỉnh giới hạn này, nhấp vào biểu tượng '{{settings}}' (⚙️) trong bảng điều khiển Roo-Code, sau đó nhấp vào '{{context}}' và tìm tùy chọn '{{threshold}}'." + }, + "toolRepetitionLimitReached": "Roo dường như đang bị mắc kẹt trong một vòng lặp, liên tục cố gắng thực hiện cùng một hành động ({{toolName}}). Điều này có thể chỉ ra vấn đề với chiến lược hiện tại. Hãy cân nhắc diễn đạt lại nhiệm vụ, cung cấp hướng dẫn cụ thể hơn hoặc hướng dẫn nó theo một cách tiếp cận khác." +} diff --git a/webview-ui/src/i18n/locales/zh-CN/tools.json b/webview-ui/src/i18n/locales/zh-CN/tools.json new file mode 100644 index 0000000000..30f631713a --- /dev/null +++ b/webview-ui/src/i18n/locales/zh-CN/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (第 {{start}}-{{end}} 行)", + "linesFromToEnd": " (第 {{start}} 行至末尾)", + "linesFromStartTo": " (第 1-{{end}} 行)", + "definitionsOnly": " (仅定义)", + "maxLines": " (最多 {{max}} 行)", + "autoTruncateTooltip": "要调整此限制,请点击 Roo-Code 面板中的\"{{settings}}\"图标 (⚙️),然后点击\"{{context}}\"并找到\"{{threshold}}\"选项。" + }, + "toolRepetitionLimitReached": "Roo 似乎陷入循环,反复尝试同一操作 ({{toolName}})。这可能表明当前策略存在问题。请考虑重新描述任务、提供更具体的指示或引导其尝试不同的方法。" +} diff --git a/webview-ui/src/i18n/locales/zh-TW/tools.json b/webview-ui/src/i18n/locales/zh-TW/tools.json new file mode 100644 index 0000000000..311bc918d2 --- /dev/null +++ b/webview-ui/src/i18n/locales/zh-TW/tools.json @@ -0,0 +1,11 @@ +{ + "readFile": { + "linesRange": " (第 {{start}}-{{end}} 行)", + "linesFromToEnd": " (第 {{start}} 行至結尾)", + "linesFromStartTo": " (第 1-{{end}} 行)", + "definitionsOnly": " (僅定義)", + "maxLines": " (最多 {{max}} 行)", + "autoTruncateTooltip": "要調整此限制,請點擊 Roo-Code 面板中的\"{{settings}}\"圖示 (⚙️),然後點擊\"{{context}}\"並找到\"{{threshold}}\"選項。" + }, + "toolRepetitionLimitReached": "Roo 似乎陷入循環,反覆嘗試同一操作 ({{toolName}})。這可能表明目前策略存在問題。請考慮重新描述工作、提供更具體的指示或引導其嘗試不同的方法。" +}