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
50 changes: 35 additions & 15 deletions src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1663,11 +1663,32 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
const iterator = stream[Symbol.asyncIterator]()
let item = await iterator.next()
while (!item.done) {
// Check for abort BEFORE processing the chunk and waiting for the next one
if (this.abort) {
console.log(`aborting stream, this.abandoned = ${this.abandoned}`)

if (!this.abandoned) {
// Only need to gracefully abort if this instance
// isn't abandoned (sometimes OpenRouter stream
// hangs, in which case this would affect future
// instances of Cline).
await abortStream("user_cancelled")
}

// Clean up the iterator if it has a return method
if (iterator.return) {
await iterator.return(undefined)
}

break // Aborts the stream.
}

const chunk = item.value
item = await iterator.next()

if (!chunk) {
// Sometimes chunk is undefined, no idea that can cause
// it, but this workaround seems to fix it.
item = await iterator.next()
continue
}

Expand Down Expand Up @@ -1707,20 +1728,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
}
}

if (this.abort) {
console.log(`aborting stream, this.abandoned = ${this.abandoned}`)

if (!this.abandoned) {
// Only need to gracefully abort if this instance
// isn't abandoned (sometimes OpenRouter stream
// hangs, in which case this would affect future
// instances of Cline).
await abortStream("user_cancelled")
}

break // Aborts the stream.
}

if (this.didRejectTool) {
// `userContent` has a tool rejection, so interrupt the
// assistant's response to present the user's feedback.
Expand All @@ -1737,6 +1744,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
"\n\n[Response interrupted by a tool use result. Only one tool may be used at a time and should be placed at the end of the message.]"
break
}

// Get next item at the end, after all checks
item = await iterator.next()
}

// Create a copy of current token values to avoid race conditions
Expand Down Expand Up @@ -1815,6 +1825,16 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {

// Use the same iterator that the main loop was using
while (!item.done) {
// Check for abort first
if (this.abort) {
console.log(`[Background Usage Collection] Aborting due to task cancellation`)
// Clean up the iterator before breaking
if (iterator.return) {
await iterator.return(undefined)
}
break
}

// Check for timeout
if (Date.now() - startTime > timeoutMs) {
console.warn(
Expand Down
Loading