@@ -163,7 +163,10 @@ export class Cline {
163163 this . enableCheckpoints = enableCheckpoints ?? false
164164
165165 // Initialize diffStrategy based on current state
166- this . updateDiffStrategy ( Experiments . isEnabled ( experiments ?? { } , EXPERIMENT_IDS . DIFF_STRATEGY ) )
166+ this . updateDiffStrategy (
167+ Experiments . isEnabled ( experiments ?? { } , EXPERIMENT_IDS . DIFF_STRATEGY ) ,
168+ Experiments . isEnabled ( experiments ?? { } , EXPERIMENT_IDS . MULTI_SEARCH_AND_REPLACE ) ,
169+ )
167170
168171 if ( startTask ) {
169172 if ( task || images ) {
@@ -193,13 +196,23 @@ export class Cline {
193196 }
194197
195198 // Add method to update diffStrategy
196- async updateDiffStrategy ( experimentalDiffStrategy ?: boolean ) {
199+ async updateDiffStrategy ( experimentalDiffStrategy ?: boolean , multiSearchReplaceDiffStrategy ?: boolean ) {
197200 // If not provided, get from current state
198- if ( experimentalDiffStrategy === undefined ) {
201+ if ( experimentalDiffStrategy === undefined || multiSearchReplaceDiffStrategy === undefined ) {
199202 const { experiments : stateExperimental } = ( await this . providerRef . deref ( ) ?. getState ( ) ) ?? { }
200- experimentalDiffStrategy = stateExperimental ?. [ EXPERIMENT_IDS . DIFF_STRATEGY ] ?? false
203+ if ( experimentalDiffStrategy === undefined ) {
204+ experimentalDiffStrategy = stateExperimental ?. [ EXPERIMENT_IDS . DIFF_STRATEGY ] ?? false
205+ }
206+ if ( multiSearchReplaceDiffStrategy === undefined ) {
207+ multiSearchReplaceDiffStrategy = stateExperimental ?. [ EXPERIMENT_IDS . MULTI_SEARCH_AND_REPLACE ] ?? false
208+ }
201209 }
202- this . diffStrategy = getDiffStrategy ( this . api . getModel ( ) . id , this . fuzzyMatchThreshold , experimentalDiffStrategy )
210+ this . diffStrategy = getDiffStrategy (
211+ this . api . getModel ( ) . id ,
212+ this . fuzzyMatchThreshold ,
213+ experimentalDiffStrategy ,
214+ multiSearchReplaceDiffStrategy ,
215+ )
203216 }
204217
205218 // Storing task to disk for history
@@ -1578,17 +1591,36 @@ export class Cline {
15781591 success : false ,
15791592 error : "No diff strategy available" ,
15801593 }
1594+ let partResults = ""
1595+
15811596 if ( ! diffResult . success ) {
15821597 this . consecutiveMistakeCount ++
15831598 const currentCount =
15841599 ( this . consecutiveMistakeCountForApplyDiff . get ( relPath ) || 0 ) + 1
15851600 this . consecutiveMistakeCountForApplyDiff . set ( relPath , currentCount )
1586- const errorDetails = diffResult . details
1587- ? JSON . stringify ( diffResult . details , null , 2 )
1588- : ""
1589- const formattedError = `Unable to apply diff to file: ${ absolutePath } \n\n<error_details>\n${
1590- diffResult . error
1591- } ${ errorDetails ? `\n\nDetails:\n${ errorDetails } ` : "" } \n</error_details>`
1601+ let formattedError = ""
1602+ if ( diffResult . failParts && diffResult . failParts . length > 0 ) {
1603+ for ( const failPart of diffResult . failParts ) {
1604+ if ( failPart . success ) {
1605+ continue
1606+ }
1607+ const errorDetails = failPart . details
1608+ ? JSON . stringify ( failPart . details , null , 2 )
1609+ : ""
1610+ formattedError = `<error_details>\n${
1611+ failPart . error
1612+ } ${ errorDetails ? `\n\nDetails:\n${ errorDetails } ` : "" } \n</error_details>`
1613+ partResults += formattedError
1614+ }
1615+ } else {
1616+ const errorDetails = diffResult . details
1617+ ? JSON . stringify ( diffResult . details , null , 2 )
1618+ : ""
1619+ formattedError = `Unable to apply diff to file: ${ absolutePath } \n\n<error_details>\n${
1620+ diffResult . error
1621+ } ${ errorDetails ? `\n\nDetails:\n${ errorDetails } ` : "" } \n</error_details>`
1622+ }
1623+
15921624 if ( currentCount >= 2 ) {
15931625 await this . say ( "error" , formattedError )
15941626 }
@@ -1618,6 +1650,10 @@ export class Cline {
16181650 const { newProblemsMessage, userEdits, finalContent } =
16191651 await this . diffViewProvider . saveChanges ( )
16201652 this . didEditFile = true // used to determine if we should wait for busy terminal to update before sending api request
1653+ let partFailHint = ""
1654+ if ( diffResult . failParts && diffResult . failParts . length > 0 ) {
1655+ 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`
1656+ }
16211657 if ( userEdits ) {
16221658 await this . say (
16231659 "user_feedback_diff" ,
@@ -1629,6 +1665,7 @@ export class Cline {
16291665 )
16301666 pushToolResult (
16311667 `The user made the following updates to your content:\n\n${ userEdits } \n\n` +
1668+ partFailHint +
16321669 `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` +
16331670 `<final_file_content path="${ relPath . toPosix ( ) } ">\n${ addLineNumbers (
16341671 finalContent || "" ,
@@ -1641,7 +1678,8 @@ export class Cline {
16411678 )
16421679 } else {
16431680 pushToolResult (
1644- `Changes successfully applied to ${ relPath . toPosix ( ) } :\n\n${ newProblemsMessage } ` ,
1681+ `Changes successfully applied to ${ relPath . toPosix ( ) } :\n\n${ newProblemsMessage } \n` +
1682+ partFailHint ,
16451683 )
16461684 }
16471685 await this . diffViewProvider . reset ( )
0 commit comments