Skip to content

Commit d9a73b5

Browse files
author
Eric Wheeler
committed
refactor: make condenseContext history updates atomic
Moves the conversation summarization logic into the critical section of `modifyApiConversationHistory`. This refactoring ensures that the process of reading the existing history, summarizing it, and writing the condensed version back to disk is a single, atomic transaction. Previously, the summary was generated outside the critical section, creating a potential race condition where the history could have changed between summarization and writing. Additionally, any side effects, such as `say()` notifications, are now performed only after the atomic write operation has successfully completed, preventing deadlocks and ensuring a cleaner separation of concerns. Signed-off-by: Eric Wheeler <[email protected]>
1 parent 293a439 commit d9a73b5

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

src/core/task/Task.ts

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -674,26 +674,40 @@ export class Task extends EventEmitter<ClineEvents> {
674674
}
675675

676676
const { contextTokens: prevContextTokens } = this.getTokenUsage()
677-
const {
678-
messages,
679-
summary,
680-
cost,
681-
newContextTokens = 0,
682-
error,
683-
} = await summarizeConversation(
684-
this.apiConversationHistory,
685-
this.api, // Main API handler (fallback)
686-
systemPrompt, // Default summarization prompt (fallback)
687-
this.taskId,
688-
prevContextTokens,
689-
false, // manual trigger
690-
customCondensingPrompt, // User's custom prompt
691-
condensingApiHandler, // Specific handler for condensing
692-
)
693-
if (error) {
677+
678+
let contextCondense: ContextCondense | undefined
679+
let errorResult: string | undefined = undefined
680+
681+
await this.modifyApiConversationHistory(async (history) => {
682+
const {
683+
messages,
684+
summary,
685+
cost,
686+
newContextTokens = 0,
687+
error,
688+
} = await summarizeConversation(
689+
history,
690+
this.api, // Main API handler (fallback)
691+
systemPrompt, // Default summarization prompt (fallback)
692+
this.taskId,
693+
prevContextTokens,
694+
false, // manual trigger
695+
customCondensingPrompt, // User's custom prompt
696+
condensingApiHandler, // Specific handler for condensing
697+
)
698+
if (error) {
699+
errorResult = error
700+
return undefined // abort transaction
701+
}
702+
703+
contextCondense = { summary, cost, newContextTokens, prevContextTokens }
704+
return messages
705+
})
706+
707+
if (errorResult) {
694708
this.say(
695709
"condense_context_error",
696-
error,
710+
errorResult,
697711
undefined /* images */,
698712
false /* partial */,
699713
undefined /* checkpoint */,
@@ -703,11 +717,6 @@ export class Task extends EventEmitter<ClineEvents> {
703717
return
704718
}
705719

706-
await this.modifyApiConversationHistory(async () => {
707-
return messages
708-
})
709-
710-
const contextCondense: ContextCondense = { summary, cost, newContextTokens, prevContextTokens }
711720
await this.say(
712721
"condense_context",
713722
undefined /* text */,

0 commit comments

Comments
 (0)