@@ -184,7 +184,10 @@ export class Cline {
184184 this . checkpointStorage = checkpointStorage
185185
186186 // Initialize diffStrategy based on current state
187- this . updateDiffStrategy ( Experiments . isEnabled ( experiments ?? { } , EXPERIMENT_IDS . DIFF_STRATEGY ) )
187+ this . updateDiffStrategy (
188+ Experiments . isEnabled ( experiments ?? { } , EXPERIMENT_IDS . DIFF_STRATEGY ) ,
189+ Experiments . isEnabled ( experiments ?? { } , EXPERIMENT_IDS . MULTI_SEARCH_AND_REPLACE ) ,
190+ )
188191
189192 if ( startTask ) {
190193 if ( task || images ) {
@@ -254,13 +257,23 @@ export class Cline {
254257 }
255258
256259 // Add method to update diffStrategy
257- async updateDiffStrategy ( experimentalDiffStrategy ?: boolean ) {
260+ async updateDiffStrategy ( experimentalDiffStrategy ?: boolean , multiSearchReplaceDiffStrategy ?: boolean ) {
258261 // If not provided, get from current state
259- if ( experimentalDiffStrategy === undefined ) {
262+ if ( experimentalDiffStrategy === undefined || multiSearchReplaceDiffStrategy === undefined ) {
260263 const { experiments : stateExperimental } = ( await this . providerRef . deref ( ) ?. getState ( ) ) ?? { }
261- experimentalDiffStrategy = stateExperimental ?. [ EXPERIMENT_IDS . DIFF_STRATEGY ] ?? false
264+ if ( experimentalDiffStrategy === undefined ) {
265+ experimentalDiffStrategy = stateExperimental ?. [ EXPERIMENT_IDS . DIFF_STRATEGY ] ?? false
266+ }
267+ if ( multiSearchReplaceDiffStrategy === undefined ) {
268+ multiSearchReplaceDiffStrategy = stateExperimental ?. [ EXPERIMENT_IDS . MULTI_SEARCH_AND_REPLACE ] ?? false
269+ }
262270 }
263- this . diffStrategy = getDiffStrategy ( this . api . getModel ( ) . id , this . fuzzyMatchThreshold , experimentalDiffStrategy )
271+ this . diffStrategy = getDiffStrategy (
272+ this . api . getModel ( ) . id ,
273+ this . fuzzyMatchThreshold ,
274+ experimentalDiffStrategy ,
275+ multiSearchReplaceDiffStrategy ,
276+ )
264277 }
265278
266279 // Storing task to disk for history
@@ -1667,17 +1680,36 @@ export class Cline {
16671680 success : false ,
16681681 error : "No diff strategy available" ,
16691682 }
1683+ let partResults = ""
1684+
16701685 if ( ! diffResult . success ) {
16711686 this . consecutiveMistakeCount ++
16721687 const currentCount =
16731688 ( this . consecutiveMistakeCountForApplyDiff . get ( relPath ) || 0 ) + 1
16741689 this . consecutiveMistakeCountForApplyDiff . set ( relPath , currentCount )
1675- const errorDetails = diffResult . details
1676- ? JSON . stringify ( diffResult . details , null , 2 )
1677- : ""
1678- const formattedError = `Unable to apply diff to file: ${ absolutePath } \n\n<error_details>\n${
1679- diffResult . error
1680- } ${ errorDetails ? `\n\nDetails:\n${ errorDetails } ` : "" } \n</error_details>`
1690+ let formattedError = ""
1691+ if ( diffResult . failParts && diffResult . failParts . length > 0 ) {
1692+ for ( const failPart of diffResult . failParts ) {
1693+ if ( failPart . success ) {
1694+ continue
1695+ }
1696+ const errorDetails = failPart . details
1697+ ? JSON . stringify ( failPart . details , null , 2 )
1698+ : ""
1699+ formattedError = `<error_details>\n${
1700+ failPart . error
1701+ } ${ errorDetails ? `\n\nDetails:\n${ errorDetails } ` : "" } \n</error_details>`
1702+ partResults += formattedError
1703+ }
1704+ } else {
1705+ const errorDetails = diffResult . details
1706+ ? JSON . stringify ( diffResult . details , null , 2 )
1707+ : ""
1708+ formattedError = `Unable to apply diff to file: ${ absolutePath } \n\n<error_details>\n${
1709+ diffResult . error
1710+ } ${ errorDetails ? `\n\nDetails:\n${ errorDetails } ` : "" } \n</error_details>`
1711+ }
1712+
16811713 if ( currentCount >= 2 ) {
16821714 await this . say ( "error" , formattedError )
16831715 }
@@ -1707,6 +1739,10 @@ export class Cline {
17071739 const { newProblemsMessage, userEdits, finalContent } =
17081740 await this . diffViewProvider . saveChanges ( )
17091741 this . didEditFile = true // used to determine if we should wait for busy terminal to update before sending api request
1742+ let partFailHint = ""
1743+ if ( diffResult . failParts && diffResult . failParts . length > 0 ) {
1744+ partFailHint = `But unable to apply all diff parts to file: ${ absolutePath } , silently use <read_file> tool to check newest file version and re-apply diffs\n`
1745+ }
17101746 if ( userEdits ) {
17111747 await this . say (
17121748 "user_feedback_diff" ,
@@ -1718,6 +1754,7 @@ export class Cline {
17181754 )
17191755 pushToolResult (
17201756 `The user made the following updates to your content:\n\n${ userEdits } \n\n` +
1757+ partFailHint +
17211758 `The updated content, which includes both your original modifications and the user's edits, has been successfully saved to ${ relPath . toPosix ( ) } . Here is the full, updated content of the file, including line numbers:\n\n` +
17221759 `<final_file_content path="${ relPath . toPosix ( ) } ">\n${ addLineNumbers (
17231760 finalContent || "" ,
@@ -1730,7 +1767,8 @@ export class Cline {
17301767 )
17311768 } else {
17321769 pushToolResult (
1733- `Changes successfully applied to ${ relPath . toPosix ( ) } :\n\n${ newProblemsMessage } ` ,
1770+ `Changes successfully applied to ${ relPath . toPosix ( ) } :\n\n${ newProblemsMessage } \n` +
1771+ partFailHint ,
17341772 )
17351773 }
17361774 await this . diffViewProvider . reset ( )
0 commit comments