mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: ensure cancel button properly aborts streaming responses
- Set abort flag immediately in ClineProvider.cancelTask() before calling abortTask() - Add early abort check at the beginning of streaming loop before processing chunks - Add proper iterator cleanup when aborting stream - Keep existing abort check after chunk processing for redundancy This ensures the cancel button works even when chunks are arriving constantly, addressing the issue where the abort flag appeared to never be set. Fixes #7014
This commit is contained in:
parent
8e7a2e7bdb
commit
6aa129ec5e
2 changed files with 32 additions and 2 deletions
|
|
@ -1663,6 +1663,26 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
const iterator = stream[Symbol.asyncIterator]()
|
||||
let item = await iterator.next()
|
||||
while (!item.done) {
|
||||
// Check abort flag BEFORE processing the chunk
|
||||
if (this.abort) {
|
||||
console.log(`aborting stream (early check), 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).catch(() => {})
|
||||
}
|
||||
|
||||
break // Aborts the stream.
|
||||
}
|
||||
|
||||
const chunk = item.value
|
||||
item = await iterator.next()
|
||||
if (!chunk) {
|
||||
|
|
@ -1707,8 +1727,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
}
|
||||
}
|
||||
|
||||
// Check abort flag AFTER processing the chunk as well
|
||||
if (this.abort) {
|
||||
console.log(`aborting stream, this.abandoned = ${this.abandoned}`)
|
||||
console.log(`aborting stream (after chunk), this.abandoned = ${this.abandoned}`)
|
||||
|
||||
if (!this.abandoned) {
|
||||
// Only need to gracefully abort if this instance
|
||||
|
|
@ -1718,6 +1739,11 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
await abortStream("user_cancelled")
|
||||
}
|
||||
|
||||
// Clean up the iterator if it has a return method
|
||||
if (iterator.return) {
|
||||
await iterator.return(undefined).catch(() => {})
|
||||
}
|
||||
|
||||
break // Aborts the stream.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1228,6 +1228,10 @@ export class ClineProvider
|
|||
const rootTask = cline.rootTask
|
||||
const parentTask = cline.parentTask
|
||||
|
||||
// Set the abort flag immediately to signal cancellation
|
||||
cline.abort = true
|
||||
|
||||
// Then call abortTask to handle cleanup
|
||||
cline.abortTask()
|
||||
|
||||
await pWaitFor(
|
||||
|
|
@ -1243,7 +1247,7 @@ export class ClineProvider
|
|||
timeout: 3_000,
|
||||
},
|
||||
).catch(() => {
|
||||
console.error("Failed to abort task")
|
||||
console.error("Failed to abort task gracefully")
|
||||
})
|
||||
|
||||
if (this.getCurrentCline()) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue