diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index 53b8ef5b87d..cf324ce8051 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -140,6 +140,7 @@ export class Task extends EventEmitter { providerRef: WeakRef private readonly globalStoragePath: string abort: boolean = false + abortReason: 'user' | 'api_failure' | null = null didFinishAbortingStream = false abandoned = false isInitialized = false @@ -1074,8 +1075,8 @@ export class Task extends EventEmitter { } } - 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) { @@ -1083,6 +1084,7 @@ export class Task extends EventEmitter { } this.abort = true + this.abortReason = reason this.emit("taskAborted") try { @@ -1442,13 +1444,12 @@ export class Task extends EventEmitter { // 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)) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 107122dcb46..17225061949 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -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}`, @@ -974,7 +974,7 @@ export class ClineProvider const rootTask = cline.rootTask const parentTask = cline.parentTask - cline.abortTask() + cline.abortTask(false, 'user') await pWaitFor( () =>