Skip to content
Closed
Show file tree
Hide file tree
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
17 changes: 9 additions & 8 deletions src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export class Task extends EventEmitter<ClineEvents> {
providerRef: WeakRef<ClineProvider>
private readonly globalStoragePath: string
abort: boolean = false
abortReason: 'user' | 'api_failure' | null = null
didFinishAbortingStream = false
abandoned = false
isInitialized = false
Expand Down Expand Up @@ -1074,15 +1075,16 @@ export class Task extends EventEmitter<ClineEvents> {
}
}

public async abortTask(isAbandoned = false) {
console.log(`[subtasks] aborting task ${this.taskId}.${this.instanceId}`)
public async abortTask(isAbandoned = false, reason: 'user' | 'api_failure' = 'user') {
console.log(`[subtasks] aborting task ${this.taskId}.${this.instanceId} with reason: ${reason}`)

// Will stop any autonomously running promises.
if (isAbandoned) {
this.abandoned = true
}

this.abort = true
this.abortReason = reason
this.emit("taskAborted")

try {
Expand Down Expand Up @@ -1442,13 +1444,12 @@ export class Task extends EventEmitter<ClineEvents> {
// could be in (i.e. could have streamed some tools the user
// may have executed), so we just resort to replicating a
// cancel task.
this.abortTask()
this.abortTask(false, 'api_failure')

// Check if this was a user-initiated cancellation
// If this.abort is true, it means the user clicked cancel, so we should
// treat this as "user_cancelled" rather than "streaming_failed"
const cancelReason = this.abort ? "user_cancelled" : "streaming_failed"
const streamingFailedMessage = this.abort
// Check if this was a user-initiated cancellation or an API failure
// Use the abortReason to properly distinguish between user cancellations and API failures
const cancelReason = this.abortReason === 'user' ? "user_cancelled" : "streaming_failed"
const streamingFailedMessage = this.abortReason === 'user'
? undefined
: (error.message ?? JSON.stringify(serializeError(error), null, 2))

Expand Down
4 changes: 2 additions & 2 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export class ClineProvider
try {
// Abort the running task and set isAbandoned to true so
// all running promises will exit as well.
await cline.abortTask(true)
await cline.abortTask(true, 'user')
} catch (e) {
this.log(
`[subtasks] encountered error while aborting task ${cline.taskId}.${cline.instanceId}: ${e.message}`,
Expand Down Expand Up @@ -974,7 +974,7 @@ export class ClineProvider
const rootTask = cline.rootTask
const parentTask = cline.parentTask

cline.abortTask()
cline.abortTask(false, 'user')

await pWaitFor(
() =>
Expand Down