@@ -980,6 +980,8 @@ export class Cline {
980980 const previousRequest = this . clineMessages [ previousApiReqIndex ] ?. text
981981 if ( ! previousRequest ) return
982982
983+ this . deduplicateReadFileHistory ( )
984+
983985 const {
984986 tokensIn = 0 ,
985987 tokensOut = 0 ,
@@ -1091,7 +1093,40 @@ export class Cline {
10911093 // this delegates to another generator or iterable object. In this case, it's saying "yield all remaining values from this iterator". This effectively passes along all subsequent chunks from the original stream.
10921094 yield * iterator
10931095 }
1096+ deduplicateReadFileHistory ( ) {
1097+ for ( let i = this . apiConversationHistory . length - 1 ; i >= 0 ; i -- ) {
1098+ const conversation = this . apiConversationHistory [ i ]
1099+
1100+ if ( conversation . role !== "user" ) continue
1101+
1102+ const content = conversation . content
1103+ if ( typeof content === "string" ) continue
1104+
1105+ const firstItem = content [ 0 ]
1106+ if ( typeof firstItem === "string" || ! ( "type" in firstItem ) || firstItem . type !== "text" ) continue
1107+
1108+ const toolUseText = firstItem . text
1109+ if ( ! toolUseText || ! toolUseText . startsWith ( "[read_file for " ) ) continue
1110+
1111+ for ( let j = i - 1 ; j >= 0 ; j -- ) {
1112+ const prevConversation = this . apiConversationHistory [ j ]
1113+
1114+ if ( prevConversation . role === "assistant" ) continue
10941115
1116+ const prevContent = prevConversation . content
1117+ if ( typeof prevContent === "string" ) continue
1118+
1119+ const prevFirstItem = prevContent [ 0 ]
1120+ if ( typeof prevFirstItem === "string" || ! ( "type" in prevFirstItem ) || prevFirstItem . type !== "text" )
1121+ continue
1122+
1123+ if ( prevFirstItem . text === toolUseText && prevContent . length === 3 ) {
1124+ prevContent . splice ( 1 , 1 )
1125+ break
1126+ }
1127+ }
1128+ }
1129+ }
10951130 async presentAssistantMessage ( ) {
10961131 if ( this . abort ) {
10971132 throw new Error ( "Roo Code instance aborted" )
0 commit comments