@@ -1489,8 +1489,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
14891489 }
14901490 }
14911491
1492- public async abortTask ( isAbandoned = false ) {
1493- // Aborting task
1492+ public async abortTask ( isAbandoned = false , skipSave = false ) {
1493+ console . log ( `[subtasks] aborting task ${ this . taskId } . ${ this . instanceId } ` )
14941494
14951495 // Will stop any autonomously running promises.
14961496 if ( isAbandoned ) {
@@ -1506,15 +1506,74 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
15061506 console . error ( `Error during task ${ this . taskId } .${ this . instanceId } disposal:` , error )
15071507 // Don't rethrow - we want abort to always succeed
15081508 }
1509- // Save the countdown message in the automatic retry or other content.
1510- try {
1511- // Save the countdown message in the automatic retry or other content.
1512- await this . saveClineMessages ( )
1513- } catch ( error ) {
1514- console . error ( `Error saving messages during abort for task ${ this . taskId } .${ this . instanceId } :` , error )
1509+
1510+ // Only save messages if not skipping (e.g., during user cancellation where messages are already saved)
1511+ if ( ! skipSave ) {
1512+ try {
1513+ // Save the countdown message in the automatic retry or other content.
1514+ await this . saveClineMessages ( )
1515+ } catch ( error ) {
1516+ console . error ( `Error saving messages during abort for task ${ this . taskId } .${ this . instanceId } :` , error )
1517+ }
15151518 }
15161519 }
15171520
1521+ /**
1522+ * Reset the task to a resumable state without recreating the instance.
1523+ * This is used when canceling a task to avoid unnecessary rerenders.
1524+ */
1525+ public async resetToResumableState ( ) {
1526+ console . log ( `[subtasks] resetting task ${ this . taskId } .${ this . instanceId } to resumable state` )
1527+
1528+ // Reset abort flags
1529+ this . abort = false
1530+ this . abandoned = false
1531+
1532+ // Reset streaming state
1533+ this . isStreaming = false
1534+ this . isWaitingForFirstChunk = false
1535+ this . didFinishAbortingStream = true
1536+ this . didCompleteReadingStream = false
1537+
1538+ // Clear streaming content
1539+ this . currentStreamingContentIndex = 0
1540+ this . currentStreamingDidCheckpoint = false
1541+ this . assistantMessageContent = [ ]
1542+ this . userMessageContent = [ ]
1543+ this . userMessageContentReady = false
1544+ this . didRejectTool = false
1545+ this . didAlreadyUseTool = false
1546+ this . presentAssistantMessageLocked = false
1547+ this . presentAssistantMessageHasPendingUpdates = false
1548+
1549+ // Reset API state
1550+ this . consecutiveMistakeCount = 0
1551+
1552+ // Reset ask response state to allow new messages
1553+ this . askResponse = undefined
1554+ this . askResponseText = undefined
1555+ this . askResponseImages = undefined
1556+ this . blockingAsk = undefined
1557+
1558+ // Reset parser if exists
1559+ if ( this . assistantMessageParser ) {
1560+ this . assistantMessageParser . reset ( )
1561+ }
1562+
1563+ // Only reset diff view if it's actively editing
1564+ // This avoids unnecessary operations when diff view is not in use
1565+ if ( this . diffViewProvider && this . diffViewProvider . isEditing ) {
1566+ await this . diffViewProvider . reset ( )
1567+ }
1568+
1569+ // The task is now ready to be resumed
1570+ // The API request status has already been updated by abortStream
1571+ // We don't add the resume_task message here because ask() will add it
1572+
1573+ // Keep messages and history intact for resumption
1574+ // The task is now ready to be resumed without recreation
1575+ }
1576+
15181577 // Used when a sub-task is launched and the parent task is waiting for it to
15191578 // finish.
15201579 // TBD: The 1s should be added to the settings, also should add a timeout to
@@ -1584,7 +1643,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
15841643 const currentUserContent = currentItem . userContent
15851644 const currentIncludeFileDetails = currentItem . includeFileDetails
15861645
1587- if ( this . abort ) {
1646+ if ( this . abort ) {
15881647 throw new Error ( `[RooCode#recursivelyMakeRooRequests] task ${ this . taskId } .${ this . instanceId } aborted` )
15891648 }
15901649
0 commit comments