@@ -97,6 +97,20 @@ import { getUri } from "./getUri"
97
97
* https://github.com/KumarVariable/vscode-extension-sidebar-html/blob/master/src/customSidebarViewProvider.ts
98
98
*/
99
99
100
+ export type ClineProviderEvents = {
101
+ clineCreated : [ cline : Task ]
102
+ }
103
+
104
+ interface PendingEditOperation {
105
+ messageTs : number
106
+ editedContent : string
107
+ images ?: string [ ]
108
+ messageIndex : number
109
+ apiConversationHistoryIndex : number
110
+ timeoutId : NodeJS . Timeout
111
+ createdAt : number
112
+ }
113
+
100
114
export class ClineProvider
101
115
extends EventEmitter < TaskProviderEvents >
102
116
implements vscode . WebviewViewProvider , TelemetryPropertiesProvider , TaskProviderLike
@@ -121,6 +135,8 @@ export class ClineProvider
121
135
private taskEventListeners : WeakMap < Task , Array < ( ) => void > > = new WeakMap ( )
122
136
123
137
private recentTasksCache ?: string [ ]
138
+ private pendingOperations : Map < string , PendingEditOperation > = new Map ( )
139
+ private static readonly PENDING_OPERATION_TIMEOUT_MS = 30000 // 30 seconds
124
140
125
141
public isViewLaunched = false
126
142
public settingsImportedAt ?: number
@@ -440,6 +456,71 @@ export class ClineProvider
440
456
// the 'parent' calling task).
441
457
await this . getCurrentTask ( ) ?. completeSubtask ( lastMessage )
442
458
}
459
+ // Pending Edit Operations Management
460
+
461
+ /**
462
+ * Sets a pending edit operation with automatic timeout cleanup
463
+ */
464
+ public setPendingEditOperation (
465
+ operationId : string ,
466
+ editData : {
467
+ messageTs : number
468
+ editedContent : string
469
+ images ?: string [ ]
470
+ messageIndex : number
471
+ apiConversationHistoryIndex : number
472
+ } ,
473
+ ) : void {
474
+ // Clear any existing operation with the same ID
475
+ this . clearPendingEditOperation ( operationId )
476
+
477
+ // Create timeout for automatic cleanup
478
+ const timeoutId = setTimeout ( ( ) => {
479
+ this . clearPendingEditOperation ( operationId )
480
+ this . log ( `[setPendingEditOperation] Automatically cleared stale pending operation: ${ operationId } ` )
481
+ } , ClineProvider . PENDING_OPERATION_TIMEOUT_MS )
482
+
483
+ // Store the operation
484
+ this . pendingOperations . set ( operationId , {
485
+ ...editData ,
486
+ timeoutId,
487
+ createdAt : Date . now ( ) ,
488
+ } )
489
+
490
+ this . log ( `[setPendingEditOperation] Set pending operation: ${ operationId } ` )
491
+ }
492
+
493
+ /**
494
+ * Gets a pending edit operation by ID
495
+ */
496
+ private getPendingEditOperation ( operationId : string ) : PendingEditOperation | undefined {
497
+ return this . pendingOperations . get ( operationId )
498
+ }
499
+
500
+ /**
501
+ * Clears a specific pending edit operation
502
+ */
503
+ private clearPendingEditOperation ( operationId : string ) : boolean {
504
+ const operation = this . pendingOperations . get ( operationId )
505
+ if ( operation ) {
506
+ clearTimeout ( operation . timeoutId )
507
+ this . pendingOperations . delete ( operationId )
508
+ this . log ( `[clearPendingEditOperation] Cleared pending operation: ${ operationId } ` )
509
+ return true
510
+ }
511
+ return false
512
+ }
513
+
514
+ /**
515
+ * Clears all pending edit operations
516
+ */
517
+ private clearAllPendingEditOperations ( ) : void {
518
+ for ( const [ operationId , operation ] of this . pendingOperations ) {
519
+ clearTimeout ( operation . timeoutId )
520
+ }
521
+ this . pendingOperations . clear ( )
522
+ this . log ( `[clearAllPendingEditOperations] Cleared all pending operations` )
523
+ }
443
524
444
525
/*
445
526
VSCode extensions use the disposable pattern to clean up resources when the sidebar/editor tab is closed by the user or system. This applies to event listening, commands, interacting with the UI, etc.
@@ -465,6 +546,10 @@ export class ClineProvider
465
546
466
547
this . log ( "Cleared all tasks" )
467
548
549
+ // Clear all pending edit operations to prevent memory leaks
550
+ this . clearAllPendingEditOperations ( )
551
+ this . log ( "Cleared pending operations" )
552
+
468
553
if ( this . view && "dispose" in this . view ) {
469
554
this . view . dispose ( )
470
555
this . log ( "Disposed webview" )
@@ -805,6 +890,49 @@ export class ClineProvider
805
890
`[createTaskWithHistoryItem] ${ task . parentTask ? "child" : "parent" } task ${ task . taskId } .${ task . instanceId } instantiated` ,
806
891
)
807
892
893
+ // Check if there's a pending edit after checkpoint restoration
894
+ const operationId = `task-${ task . taskId } `
895
+ const pendingEdit = this . getPendingEditOperation ( operationId )
896
+ if ( pendingEdit ) {
897
+ this . clearPendingEditOperation ( operationId ) // Clear the pending edit
898
+
899
+ this . log ( `[createTaskWithHistoryItem] Processing pending edit after checkpoint restoration` )
900
+
901
+ // Process the pending edit after a short delay to ensure the task is fully initialized
902
+ setTimeout ( async ( ) => {
903
+ try {
904
+ // Find the message index in the restored state
905
+ const { messageIndex, apiConversationHistoryIndex } = ( ( ) => {
906
+ const messageIndex = task . clineMessages . findIndex ( ( msg ) => msg . ts === pendingEdit . messageTs )
907
+ const apiConversationHistoryIndex = task . apiConversationHistory . findIndex (
908
+ ( msg ) => msg . ts === pendingEdit . messageTs ,
909
+ )
910
+ return { messageIndex, apiConversationHistoryIndex }
911
+ } ) ( )
912
+
913
+ if ( messageIndex !== - 1 ) {
914
+ // Remove the target message and all subsequent messages
915
+ await task . overwriteClineMessages ( task . clineMessages . slice ( 0 , messageIndex ) )
916
+
917
+ if ( apiConversationHistoryIndex !== - 1 ) {
918
+ await task . overwriteApiConversationHistory (
919
+ task . apiConversationHistory . slice ( 0 , apiConversationHistoryIndex ) ,
920
+ )
921
+ }
922
+
923
+ // Process the edited message
924
+ await task . handleWebviewAskResponse (
925
+ "messageResponse" ,
926
+ pendingEdit . editedContent ,
927
+ pendingEdit . images ,
928
+ )
929
+ }
930
+ } catch ( error ) {
931
+ this . log ( `[createTaskWithHistoryItem] Error processing pending edit: ${ error } ` )
932
+ }
933
+ } , 100 ) // Small delay to ensure task is fully ready
934
+ }
935
+
808
936
return task
809
937
}
810
938
0 commit comments