diff --git a/CHANGELOG.md b/CHANGELOG.md index af4d60f..5e19e25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Roo Cline Changelog +## [2.2.14] + +- Make diff editing more robust to transient errors + ## [2.2.13] - Fixes to sound playing and applying diffs diff --git a/package-lock.json b/package-lock.json index 04f216d..17bf4b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "roo-cline", - "version": "2.2.13", + "version": "2.2.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "roo-cline", - "version": "2.2.13", + "version": "2.2.14", "dependencies": { "@anthropic-ai/bedrock-sdk": "^0.10.2", "@anthropic-ai/sdk": "^0.26.0", diff --git a/package.json b/package.json index d12cca3..6c6e7e6 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Roo Cline", "description": "A fork of Cline, an autonomous coding agent, with some added experimental configuration and automation features.", "publisher": "RooVeterinaryInc", - "version": "2.2.13", + "version": "2.2.14", "icon": "assets/icons/rocket.png", "galleryBanner": { "color": "#617A91", diff --git a/src/core/Cline.ts b/src/core/Cline.ts index e98be5e..a4569d3 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -75,6 +75,7 @@ export class Cline { private askResponseImages?: string[] private lastMessageTs?: number private consecutiveMistakeCount: number = 0 + private consecutiveMistakeCountForApplyDiff: Map = new Map() private providerRef: WeakRef private abort: boolean = false didFinishAborting = false @@ -97,7 +98,6 @@ export class Cline { apiConfiguration: ApiConfiguration, customInstructions?: string, diffEnabled?: boolean, - debugDiffEnabled?: boolean, task?: string, images?: string[], historyItem?: HistoryItem, @@ -110,7 +110,7 @@ export class Cline { this.diffViewProvider = new DiffViewProvider(cwd) this.customInstructions = customInstructions if (diffEnabled && this.api.getModel().id) { - this.diffStrategy = getDiffStrategy(this.api.getModel().id, debugDiffEnabled) + this.diffStrategy = getDiffStrategy(this.api.getModel().id) } if (historyItem) { this.taskId = historyItem.id @@ -1230,8 +1230,9 @@ export class Cline { if (!fileExists) { this.consecutiveMistakeCount++ - await this.say("error", `File does not exist at path: ${absolutePath}`) - pushToolResult(`Error: File does not exist at path: ${absolutePath}`) + const formattedError = `File does not exist at path: ${absolutePath}\n\n\nThe specified file could not be found. Please verify the file path and try again.\n` + await this.say("error", formattedError) + pushToolResult(formattedError) break } @@ -1249,15 +1250,19 @@ export class Cline { } if (!diffResult.success) { this.consecutiveMistakeCount++ - const errorDetails = diffResult.details ? `\n\nDetails:\n${JSON.stringify(diffResult.details, null, 2)}` : '' - await this.say("error", `Unable to apply diff to file: ${absolutePath}\n${diffResult.error}${errorDetails}`) - pushToolResult(`Error applying diff to file: ${absolutePath}\n${diffResult.error}${errorDetails}`) + const currentCount = (this.consecutiveMistakeCountForApplyDiff.get(relPath) || 0) + 1 + this.consecutiveMistakeCountForApplyDiff.set(relPath, currentCount) + const errorDetails = diffResult.details ? JSON.stringify(diffResult.details, null, 2) : '' + const formattedError = `Unable to apply diff to file: ${absolutePath}\n\n\n${diffResult.error}${errorDetails ? `\n\nDetails:\n${errorDetails}` : ''}\n` + if (currentCount >= 2) { + await this.say("error", formattedError) + } + pushToolResult(formattedError) break } - const newContent = diffResult.content this.consecutiveMistakeCount = 0 - + this.consecutiveMistakeCountForApplyDiff.delete(relPath) // Show diff view before asking for approval this.diffViewProvider.editType = "modify" await this.diffViewProvider.open(relPath); diff --git a/src/core/__tests__/Cline.test.ts b/src/core/__tests__/Cline.test.ts index 041298f..8365c61 100644 --- a/src/core/__tests__/Cline.test.ts +++ b/src/core/__tests__/Cline.test.ts @@ -279,8 +279,9 @@ describe('Cline', () => { mockApiConfig, 'custom instructions', false, // diffEnabled - false, // debugDiffEnabled - 'test task' + 'test task', // task + undefined, // images + undefined // historyItem ); expect(cline.customInstructions).toBe('custom instructions'); diff --git a/src/core/diff/DiffStrategy.ts b/src/core/diff/DiffStrategy.ts index c35ea83..355424e 100644 --- a/src/core/diff/DiffStrategy.ts +++ b/src/core/diff/DiffStrategy.ts @@ -6,10 +6,10 @@ import { SearchReplaceDiffStrategy } from './strategies/search-replace' * @param model The name of the model being used (e.g., 'gpt-4', 'claude-3-opus') * @returns The appropriate diff strategy for the model */ -export function getDiffStrategy(model: string, debugEnabled?: boolean): DiffStrategy { +export function getDiffStrategy(model: string): DiffStrategy { // For now, return SearchReplaceDiffStrategy for all models (with a fuzzy threshold of 0.9) // This architecture allows for future optimizations based on model capabilities - return new SearchReplaceDiffStrategy(0.9, debugEnabled) + return new SearchReplaceDiffStrategy(0.9) } export type { DiffStrategy } diff --git a/src/core/diff/strategies/__tests__/search-replace.test.ts b/src/core/diff/strategies/__tests__/search-replace.test.ts index f96aa17..f84f3c9 100644 --- a/src/core/diff/strategies/__tests__/search-replace.test.ts +++ b/src/core/diff/strategies/__tests__/search-replace.test.ts @@ -5,7 +5,7 @@ describe('SearchReplaceDiffStrategy', () => { let strategy: SearchReplaceDiffStrategy beforeEach(() => { - strategy = new SearchReplaceDiffStrategy() // Default 1.0 threshold for exact matching + strategy = new SearchReplaceDiffStrategy(1.0, 5) // Default 1.0 threshold for exact matching, 5 line buffer for tests }) it('should replace matching content', () => { @@ -562,6 +562,63 @@ this.init(); }`); } }); + + it('should find matches from middle out', () => { + const originalContent = ` +function one() { + return "target"; +} + +function two() { + return "target"; +} + +function three() { + return "target"; +} + +function four() { + return "target"; +} + +function five() { + return "target"; +}`.trim() + + const diffContent = `test.ts +<<<<<<< SEARCH + return "target"; +======= + return "updated"; +>>>>>>> REPLACE` + + // Search around the middle (function three) + // Even though all functions contain the target text, + // it should match the one closest to line 9 first + const result = strategy.applyDiff(originalContent, diffContent, 9, 9) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe(`function one() { + return "target"; +} + +function two() { + return "target"; +} + +function three() { + return "updated"; +} + +function four() { + return "target"; +} + +function five() { + return "target"; +}`) + } + }) }) describe('line number stripping', () => { @@ -915,7 +972,7 @@ function test() { } }) - it('should insert at the start of the file if no start_line is provided for insertion', () => { + it('should error if no start_line is provided for insertion', () => { const originalContent = `function test() { return true; }` @@ -926,22 +983,15 @@ console.log("test"); >>>>>>> REPLACE` const result = strategy.applyDiff(originalContent, diffContent) - expect(result.success).toBe(true) - if (result.success) { - expect(result.content).toBe(`console.log("test"); -function test() { - return true; -}`) - } + expect(result.success).toBe(false) }) }) }) describe('fuzzy matching', () => { let strategy: SearchReplaceDiffStrategy - beforeEach(() => { - strategy = new SearchReplaceDiffStrategy(0.9) // 90% similarity threshold + strategy = new SearchReplaceDiffStrategy(0.9, 5) // 90% similarity threshold, 5 line buffer for tests }) it('should match content with small differences (>90% similar)', () => { @@ -959,6 +1009,8 @@ function getData() { } >>>>>>> REPLACE` + strategy = new SearchReplaceDiffStrategy(0.9, 5) // Use 5 line buffer for tests + const result = strategy.applyDiff(originalContent, diffContent) expect(result.success).toBe(true) if (result.success) { @@ -1008,7 +1060,7 @@ function sum(a, b) { let strategy: SearchReplaceDiffStrategy beforeEach(() => { - strategy = new SearchReplaceDiffStrategy() + strategy = new SearchReplaceDiffStrategy(0.9, 5) }) it('should find and replace within specified line range', () => { @@ -1467,8 +1519,8 @@ function two() { it('should document start_line and end_line parameters', () => { const description = strategy.getToolDescription('/test') - expect(description).toContain('start_line: (required) The line number where the search block starts (inclusive).') - expect(description).toContain('end_line: (required) The line number where the search block ends (inclusive).') + expect(description).toContain('start_line: (required) The line number where the search block starts.') + expect(description).toContain('end_line: (required) The line number where the search block ends.') }) }) }) diff --git a/src/core/diff/strategies/search-replace.ts b/src/core/diff/strategies/search-replace.ts index 9153c4e..5409e1a 100644 --- a/src/core/diff/strategies/search-replace.ts +++ b/src/core/diff/strategies/search-replace.ts @@ -1,7 +1,7 @@ import { DiffStrategy, DiffResult } from "../types" import { addLineNumbers } from "../../../integrations/misc/extract-text" -const BUFFER_LINES = 5; // Number of extra context lines to show before and after matches +const BUFFER_LINES = 20; // Number of extra context lines to show before and after matches function levenshteinDistance(a: string, b: string): number { const matrix: number[][] = []; @@ -55,12 +55,12 @@ function getSimilarity(original: string, search: string): number { export class SearchReplaceDiffStrategy implements DiffStrategy { private fuzzyThreshold: number; - public debugEnabled: boolean; + private bufferLines: number; - constructor(fuzzyThreshold?: number, debugEnabled?: boolean) { + constructor(fuzzyThreshold?: number, bufferLines?: number) { // Default to exact matching (1.0) unless fuzzy threshold specified this.fuzzyThreshold = fuzzyThreshold ?? 1.0; - this.debugEnabled = debugEnabled ?? false; + this.bufferLines = bufferLines ?? BUFFER_LINES; } getToolDescription(cwd: string): string { @@ -75,8 +75,8 @@ If you're not confident in the exact content to search for, use the read_file to Parameters: - path: (required) The path of the file to modify (relative to the current working directory ${cwd}) - diff: (required) The search/replace block defining the changes. -- start_line: (required) The line number where the search block starts (inclusive). -- end_line: (required) The line number where the search block ends (inclusive). +- start_line: (required) The line number where the search block starts. +- end_line: (required) The line number where the search block ends. Diff format: \`\`\` @@ -98,90 +98,39 @@ Original file: 5 | return total \`\`\` -1. Search/replace a specific chunk of code: +Search/Replace content: \`\`\` - -File path here - <<<<<<< SEARCH +def calculate_total(items): total = 0 for item in items: total += item return total ======= +def calculate_total(items): """Calculate total with 10% markup""" return sum(item * 1.1 for item in items) >>>>>>> REPLACE - -2 -5 - \`\`\` -Result: -\`\`\` -1 | def calculate_total(items): -2 | """Calculate total with 10% markup""" -3 | return sum(item * 1.1 for item in items) -\`\`\` - -2. Insert code at a specific line (start_line and end_line must be the same, and the content gets inserted before whatever is currently at that line): -\`\`\` +Usage: File path here -<<<<<<< SEARCH -======= - """TODO: Write a test for this""" ->>>>>>> REPLACE +Your search/replace content here -2 -2 - -\`\`\` - -Result: -\`\`\` -1 | def calculate_total(items): -2 | """TODO: Write a test for this""" -3 | """Calculate total with 10% markup""" -4 | return sum(item * 1.1 for item in items) -\`\`\` - -3. Delete code at a specific line range: -\`\`\` - -File path here - -<<<<<<< SEARCH - total = 0 - for item in items: - total += item - return total -======= ->>>>>>> REPLACE - -2 +1 5 - -\`\`\` - -Result: -\`\`\` -1 | def calculate_total(items): -\`\`\` -` +` } applyDiff(originalContent: string, diffContent: string, startLine?: number, endLine?: number): DiffResult { // Extract the search and replace blocks const match = diffContent.match(/<<<<<<< SEARCH\n([\s\S]*?)\n?=======\n([\s\S]*?)\n?>>>>>>> REPLACE/); if (!match) { - const debugInfo = this.debugEnabled ? `\n\nDebug Info:\n- Expected Format: <<<<<<< SEARCH\\n[search content]\\n=======\\n[replace content]\\n>>>>>>> REPLACE\n- Tip: Make sure to include both SEARCH and REPLACE sections with correct markers` : ''; - return { success: false, - error: `Invalid diff format - missing required SEARCH/REPLACE sections${debugInfo}` + error: `Invalid diff format - missing required SEARCH/REPLACE sections\n\nDebug Info:\n- Expected Format: <<<<<<< SEARCH\\n[search content]\\n=======\\n[replace content]\\n>>>>>>> REPLACE\n- Tip: Make sure to include both SEARCH and REPLACE sections with correct markers` }; } @@ -209,70 +158,90 @@ Result: const searchLines = searchContent === '' ? [] : searchContent.split(/\r?\n/); const replaceLines = replaceContent === '' ? [] : replaceContent.split(/\r?\n/); const originalLines = originalContent.split(/\r?\n/); + + // Validate that empty search requires start line + if (searchLines.length === 0 && !startLine) { + return { + success: false, + error: `Empty search content requires start_line to be specified\n\nDebug Info:\n- Empty search content is only valid for insertions at a specific line\n- For insertions, specify the line number where content should be inserted` + }; + } + + // Validate that empty search requires same start and end line + if (searchLines.length === 0 && startLine && endLine && startLine !== endLine) { + return { + success: false, + error: `Empty search content requires start_line and end_line to be the same (got ${startLine}-${endLine})\n\nDebug Info:\n- Empty search content is only valid for insertions at a specific line\n- For insertions, use the same line number for both start_line and end_line` + }; + } - // First try exact line range if provided + // Initialize search variables let matchIndex = -1; let bestMatchScore = 0; let bestMatchContent = ""; - + const searchChunk = searchLines.join('\n'); + + // Determine search bounds + let searchStartIndex = 0; + let searchEndIndex = originalLines.length; + + // Validate and handle line range if provided if (startLine && endLine) { // Convert to 0-based index const exactStartIndex = startLine - 1; const exactEndIndex = endLine - 1; if (exactStartIndex < 0 || exactEndIndex > originalLines.length || exactStartIndex > exactEndIndex) { - const debugInfo = this.debugEnabled ? `\n\nDebug Info:\n- Requested Range: lines ${startLine}-${endLine}\n- File Bounds: lines 1-${originalLines.length}` : ''; - - // Log detailed debug information - console.log('Invalid Line Range Debug:', { - requestedRange: { start: startLine, end: endLine }, - fileBounds: { start: 1, end: originalLines.length } - }); - return { success: false, - error: `Line range ${startLine}-${endLine} is invalid (file has ${originalLines.length} lines)${debugInfo}`, + error: `Line range ${startLine}-${endLine} is invalid (file has ${originalLines.length} lines)\n\nDebug Info:\n- Requested Range: lines ${startLine}-${endLine}\n- File Bounds: lines 1-${originalLines.length}`, }; } - // Check exact range first + // Try exact match first const originalChunk = originalLines.slice(exactStartIndex, exactEndIndex + 1).join('\n'); - const searchChunk = searchLines.join('\n'); - const similarity = getSimilarity(originalChunk, searchChunk); if (similarity >= this.fuzzyThreshold) { matchIndex = exactStartIndex; bestMatchScore = similarity; bestMatchContent = originalChunk; + } else { + // Set bounds for buffered search + searchStartIndex = Math.max(0, startLine - (this.bufferLines + 1)); + searchEndIndex = Math.min(originalLines.length, endLine + this.bufferLines); } } - // If no match found in exact range, try expanded range + // If no match found yet, try middle-out search within bounds if (matchIndex === -1) { - let searchStartIndex = 0; - let searchEndIndex = originalLines.length; + const midPoint = Math.floor((searchStartIndex + searchEndIndex) / 2); + let leftIndex = midPoint; + let rightIndex = midPoint + 1; - if (startLine || endLine) { - // Convert to 0-based index and add buffer - if (startLine) { - searchStartIndex = Math.max(0, startLine - (BUFFER_LINES + 1)); + // Search outward from the middle within bounds + while (leftIndex >= searchStartIndex || rightIndex <= searchEndIndex - searchLines.length) { + // Check left side if still in range + if (leftIndex >= searchStartIndex) { + const originalChunk = originalLines.slice(leftIndex, leftIndex + searchLines.length).join('\n'); + const similarity = getSimilarity(originalChunk, searchChunk); + if (similarity > bestMatchScore) { + bestMatchScore = similarity; + matchIndex = leftIndex; + bestMatchContent = originalChunk; + } + leftIndex--; } - if (endLine) { - searchEndIndex = Math.min(originalLines.length, endLine + BUFFER_LINES); - } - } - // Find the search content in the expanded range using fuzzy matching - for (let i = searchStartIndex; i <= searchEndIndex - searchLines.length; i++) { - // Join the lines and calculate overall similarity - const originalChunk = originalLines.slice(i, i + searchLines.length).join('\n'); - const searchChunk = searchLines.join('\n'); - - const similarity = getSimilarity(originalChunk, searchChunk); - if (similarity > bestMatchScore) { - bestMatchScore = similarity; - matchIndex = i; - bestMatchContent = originalChunk; + // Check right side if still in range + if (rightIndex <= searchEndIndex - searchLines.length) { + const originalChunk = originalLines.slice(rightIndex, rightIndex + searchLines.length).join('\n'); + const similarity = getSimilarity(originalChunk, searchChunk); + if (similarity > bestMatchScore) { + bestMatchScore = similarity; + matchIndex = rightIndex; + bestMatchContent = originalChunk; + } + rightIndex++; } } } @@ -283,10 +252,10 @@ Result: const originalContentSection = startLine !== undefined && endLine !== undefined ? `\n\nOriginal Content:\n${addLineNumbers( originalLines.slice( - Math.max(0, startLine - 1 - BUFFER_LINES), - Math.min(originalLines.length, endLine + BUFFER_LINES) + Math.max(0, startLine - 1 - this.bufferLines), + Math.min(originalLines.length, endLine + this.bufferLines) ).join('\n'), - Math.max(1, startLine - BUFFER_LINES) + Math.max(1, startLine - this.bufferLines) )}` : `\n\nOriginal Content:\n${addLineNumbers(originalLines.join('\n'))}`; @@ -294,13 +263,11 @@ Result: ? `\n\nBest Match Found:\n${addLineNumbers(bestMatchContent, matchIndex + 1)}` : `\n\nBest Match Found:\n(no match)`; - const debugInfo = this.debugEnabled ? `\n\nDebug Info:\n- Similarity Score: ${Math.floor(bestMatchScore * 100)}%\n- Required Threshold: ${Math.floor(this.fuzzyThreshold * 100)}%\n- Search Range: ${startLine && endLine ? `lines ${startLine}-${endLine}` : 'start to end'}\n\nSearch Content:\n${searchChunk}${bestMatchSection}${originalContentSection}` : ''; - const lineRange = startLine || endLine ? ` at ${startLine ? `start: ${startLine}` : 'start'} to ${endLine ? `end: ${endLine}` : 'end'}` : ''; return { success: false, - error: `No sufficiently similar match found${lineRange} (${Math.floor(bestMatchScore * 100)}% similar, needs ${Math.floor(this.fuzzyThreshold * 100)}%)${debugInfo}` + error: `No sufficiently similar match found${lineRange} (${Math.floor(bestMatchScore * 100)}% similar, needs ${Math.floor(this.fuzzyThreshold * 100)}%)\n\nDebug Info:\n- Similarity Score: ${Math.floor(bestMatchScore * 100)}%\n- Required Threshold: ${Math.floor(this.fuzzyThreshold * 100)}%\n- Search Range: ${startLine && endLine ? `lines ${startLine}-${endLine}` : 'start to end'}\n\nSearch Content:\n${searchChunk}${bestMatchSection}${originalContentSection}` }; } diff --git a/src/core/diff/types.ts b/src/core/diff/types.ts index a662c47..3957a1f 100644 --- a/src/core/diff/types.ts +++ b/src/core/diff/types.ts @@ -13,11 +13,6 @@ export type DiffResult = }}; export interface DiffStrategy { - /** - * Whether to enable detailed debug logging - */ - debugEnabled?: boolean; - /** * Get the tool description for this diff strategy * @param cwd The current working directory diff --git a/src/core/prompts/system.ts b/src/core/prompts/system.ts index b497368..f9fe89e 100644 --- a/src/core/prompts/system.ts +++ b/src/core/prompts/system.ts @@ -61,7 +61,7 @@ Usage: Description: Request to write full content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Parameters: - path: (required) The path of the file to write to (relative to the current working directory ${cwd.toPosix()}) -- content: (required) The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified. +- content: (required) The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified. Do NOT include the line numbers in the content though, just the actual content of the file. Usage: File path here diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 861046e..f4d9e5b 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -68,7 +68,6 @@ type GlobalStateKey = | "soundEnabled" | "soundVolume" | "diffEnabled" - | "debugDiffEnabled" | "alwaysAllowMcp" export const GlobalFileNames = { @@ -217,8 +216,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { const { apiConfiguration, customInstructions, - diffEnabled, - debugDiffEnabled, + diffEnabled } = await this.getState() this.cline = new Cline( @@ -226,7 +224,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { apiConfiguration, customInstructions, diffEnabled, - debugDiffEnabled, task, images ) @@ -237,8 +234,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { const { apiConfiguration, customInstructions, - diffEnabled, - debugDiffEnabled, + diffEnabled } = await this.getState() this.cline = new Cline( @@ -246,10 +242,9 @@ export class ClineProvider implements vscode.WebviewViewProvider { apiConfiguration, customInstructions, diffEnabled, - debugDiffEnabled, undefined, undefined, - historyItem, + historyItem ) } @@ -614,11 +609,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.updateGlobalState("diffEnabled", diffEnabled) await this.postStateToWebview() break - case "debugDiffEnabled": - const debugDiffEnabled = message.bool ?? false - await this.updateGlobalState("debugDiffEnabled", debugDiffEnabled) - await this.postStateToWebview() - break } }, null, @@ -945,7 +935,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { alwaysAllowMcp, soundEnabled, diffEnabled, - debugDiffEnabled, taskHistory, soundVolume, } = await this.getState() @@ -970,7 +959,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { .sort((a, b) => b.ts - a.ts), soundEnabled: soundEnabled ?? false, diffEnabled: diffEnabled ?? false, - debugDiffEnabled: debugDiffEnabled ?? false, shouldShowAnnouncement: lastShownAnnouncementId !== this.latestAnnouncementId, allowedCommands, soundVolume: soundVolume ?? 0.5, @@ -1066,7 +1054,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { allowedCommands, soundEnabled, diffEnabled, - debugDiffEnabled, soundVolume, ] = await Promise.all([ this.getGlobalState("apiProvider") as Promise, @@ -1105,7 +1092,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { this.getGlobalState("allowedCommands") as Promise, this.getGlobalState("soundEnabled") as Promise, this.getGlobalState("diffEnabled") as Promise, - this.getGlobalState("debugDiffEnabled") as Promise, this.getGlobalState("soundVolume") as Promise, ]) @@ -1162,7 +1148,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { allowedCommands, soundEnabled: soundEnabled ?? false, diffEnabled: diffEnabled ?? false, - debugDiffEnabled: debugDiffEnabled ?? false, soundVolume, } } diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index e95bb80..07a3dde 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -53,7 +53,6 @@ export interface ExtensionState { soundEnabled?: boolean soundVolume?: number diffEnabled?: boolean - debugDiffEnabled?: boolean } export interface ClineMessage { diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index aca93e1..2864a94 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -34,7 +34,6 @@ export interface WebviewMessage { | "soundEnabled" | "soundVolume" | "diffEnabled" - | "debugDiffEnabled" | "openMcpSettings" | "restartMcpServer" | "toggleToolAlwaysAllow" diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index e1c9701..817c3b4 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -33,8 +33,6 @@ const SettingsView = ({ onDone }: SettingsViewProps) => { setSoundVolume, diffEnabled, setDiffEnabled, - debugDiffEnabled, - setDebugDiffEnabled, openRouterModels, setAllowedCommands, allowedCommands, @@ -64,7 +62,6 @@ const SettingsView = ({ onDone }: SettingsViewProps) => { vscode.postMessage({ type: "soundEnabled", bool: soundEnabled }) vscode.postMessage({ type: "soundVolume", value: soundVolume }) vscode.postMessage({ type: "diffEnabled", bool: diffEnabled }) - vscode.postMessage({ type: "debugDiffEnabled", bool: debugDiffEnabled }) onDone() } } @@ -358,20 +355,6 @@ const SettingsView = ({ onDone }: SettingsViewProps) => { )} - -
- setDebugDiffEnabled(e.target.checked)}> - Debug diff operations - -

- When enabled, Cline will show detailed debug information when applying diffs fails. -

-
{IS_DEV && ( diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index f4fdaa3..7b832ef 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -31,7 +31,6 @@ export interface ExtensionStateContextType extends ExtensionState { setSoundEnabled: (value: boolean) => void setSoundVolume: (value: number) => void setDiffEnabled: (value: boolean) => void - setDebugDiffEnabled: (value: boolean) => void } const ExtensionStateContext = createContext(undefined) @@ -46,7 +45,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode soundEnabled: false, soundVolume: 0.5, diffEnabled: false, - debugDiffEnabled: false, }) const [didHydrateState, setDidHydrateState] = useState(false) const [showWelcome, setShowWelcome] = useState(false) @@ -149,10 +147,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setSoundEnabled: (value) => setState((prevState) => ({ ...prevState, soundEnabled: value })), setSoundVolume: (value) => setState((prevState) => ({ ...prevState, soundVolume: value })), setDiffEnabled: (value) => setState((prevState) => ({ ...prevState, diffEnabled: value })), - setDebugDiffEnabled: (value) => setState((prevState) => ({ - ...prevState, - debugDiffEnabled: value - })), } return {children}