Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/core/Cline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,8 @@ export class Cline {
const previousRequest = this.clineMessages[previousApiReqIndex]?.text
if (!previousRequest) return

this.deduplicateReadFileHistory()

const {
tokensIn = 0,
tokensOut = 0,
Expand Down Expand Up @@ -1091,7 +1093,40 @@ export class Cline {
// 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.
yield* iterator
}
deduplicateReadFileHistory() {
for (let i = this.apiConversationHistory.length - 1; i >= 0; i--) {
const conversation = this.apiConversationHistory[i]

if (conversation.role !== "user") continue

const content = conversation.content
if (typeof content === "string") continue

const firstItem = content[0]
if (typeof firstItem === "string" || !("type" in firstItem) || firstItem.type !== "text") continue

const toolUseText = firstItem.text
if (!toolUseText || !toolUseText.startsWith("[read_file for ")) continue

for (let j = i - 1; j >= 0; j--) {
const prevConversation = this.apiConversationHistory[j]

if (prevConversation.role === "assistant") continue

const prevContent = prevConversation.content
if (typeof prevContent === "string") continue

const prevFirstItem = prevContent[0]
if (typeof prevFirstItem === "string" || !("type" in prevFirstItem) || prevFirstItem.type !== "text")
continue

if (prevFirstItem.text === toolUseText && prevContent.length === 3) {
prevContent.splice(1, 1)
break
}
}
}
}
async presentAssistantMessage() {
if (this.abort) {
throw new Error("Roo Code instance aborted")
Expand Down