@@ -977,6 +977,59 @@ export class Task extends EventEmitter<ClineEvents> {
977977 await this . initiateTaskLoop ( newUserContent )
978978 }
979979
980+ public dispose ( ) : void {
981+ // Stop waiting for child task completion.
982+ if ( this . pauseInterval ) {
983+ clearInterval ( this . pauseInterval )
984+ this . pauseInterval = undefined
985+ }
986+
987+ // Release any terminals associated with this task.
988+ try {
989+ // Release any terminals associated with this task.
990+ TerminalRegistry . releaseTerminalsForTask ( this . taskId )
991+ } catch ( error ) {
992+ console . error ( "Error releasing terminals:" , error )
993+ }
994+
995+ try {
996+ this . urlContentFetcher . closeBrowser ( )
997+ } catch ( error ) {
998+ console . error ( "Error closing URL content fetcher browser:" , error )
999+ }
1000+
1001+ try {
1002+ this . browserSession . closeBrowser ( )
1003+ } catch ( error ) {
1004+ console . error ( "Error closing browser session:" , error )
1005+ }
1006+
1007+ try {
1008+ if ( this . rooIgnoreController ) {
1009+ this . rooIgnoreController . dispose ( )
1010+ this . rooIgnoreController = undefined
1011+ }
1012+ } catch ( error ) {
1013+ console . error ( "Error disposing RooIgnoreController:" , error )
1014+ // This is the critical one for the leak fix
1015+ }
1016+
1017+ try {
1018+ this . fileContextTracker . dispose ( )
1019+ } catch ( error ) {
1020+ console . error ( "Error disposing file context tracker:" , error )
1021+ }
1022+
1023+ try {
1024+ // If we're not streaming then `abortStream` won't be called
1025+ if ( this . isStreaming && this . diffViewProvider . isEditing ) {
1026+ this . diffViewProvider . revertChanges ( ) . catch ( console . error )
1027+ }
1028+ } catch ( error ) {
1029+ console . error ( "Error reverting diff changes:" , error )
1030+ }
1031+ }
1032+
9801033 public async abortTask ( isAbandoned = false ) {
9811034 console . log ( `[subtasks] aborting task ${ this . taskId } .${ this . instanceId } ` )
9821035
@@ -988,28 +1041,19 @@ export class Task extends EventEmitter<ClineEvents> {
9881041 this . abort = true
9891042 this . emit ( "taskAborted" )
9901043
991- // Stop waiting for child task completion.
992- if ( this . pauseInterval ) {
993- clearInterval ( this . pauseInterval )
994- this . pauseInterval = undefined
995- }
996-
997- // Release any terminals associated with this task.
998- TerminalRegistry . releaseTerminalsForTask ( this . taskId )
999-
1000- this . urlContentFetcher . closeBrowser ( )
1001- this . browserSession . closeBrowser ( )
1002- this . rooIgnoreController ?. dispose ( )
1003- this . fileContextTracker . dispose ( )
1004-
1005- // If we're not streaming then `abortStream` (which reverts the diff
1006- // view changes) won't be called, so we need to revert the changes here.
1007- if ( this . isStreaming && this . diffViewProvider . isEditing ) {
1008- await this . diffViewProvider . revertChanges ( )
1044+ try {
1045+ this . dispose ( ) // Call the centralized dispose method
1046+ } catch ( error ) {
1047+ console . error ( `Error during task ${ this . taskId } .${ this . instanceId } disposal:` , error )
1048+ // Don't rethrow - we want abort to always succeed
10091049 }
1010-
10111050 // Save the countdown message in the automatic retry or other content.
1012- await this . saveClineMessages ( )
1051+ try {
1052+ // Save the countdown message in the automatic retry or other content.
1053+ await this . saveClineMessages ( )
1054+ } catch ( error ) {
1055+ console . error ( `Error saving messages during abort for task ${ this . taskId } .${ this . instanceId } :` , error )
1056+ }
10131057 }
10141058
10151059 // Used when a sub-task is launched and the parent task is waiting for it to
0 commit comments