@@ -97,6 +97,20 @@ import { getUri } from "./getUri"
9797 * https://github.com/KumarVariable/vscode-extension-sidebar-html/blob/master/src/customSidebarViewProvider.ts
9898 */
9999
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+
100114export class ClineProvider
101115 extends EventEmitter < TaskProviderEvents >
102116 implements vscode . WebviewViewProvider , TelemetryPropertiesProvider , TaskProviderLike
@@ -121,6 +135,8 @@ export class ClineProvider
121135 private taskEventListeners : WeakMap < Task , Array < ( ) => void > > = new WeakMap ( )
122136
123137 private recentTasksCache ?: string [ ]
138+ private pendingOperations : Map < string , PendingEditOperation > = new Map ( )
139+ private static readonly PENDING_OPERATION_TIMEOUT_MS = 30000 // 30 seconds
124140
125141 public isViewLaunched = false
126142 public settingsImportedAt ?: number
@@ -440,6 +456,71 @@ export class ClineProvider
440456 // the 'parent' calling task).
441457 await this . getCurrentTask ( ) ?. completeSubtask ( lastMessage )
442458 }
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+ }
443524
444525 /*
445526 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
465546
466547 this . log ( "Cleared all tasks" )
467548
549+ // Clear all pending edit operations to prevent memory leaks
550+ this . clearAllPendingEditOperations ( )
551+ this . log ( "Cleared pending operations" )
552+
468553 if ( this . view && "dispose" in this . view ) {
469554 this . view . dispose ( )
470555 this . log ( "Disposed webview" )
@@ -805,6 +890,49 @@ export class ClineProvider
805890 `[createTaskWithHistoryItem] ${ task . parentTask ? "child" : "parent" } task ${ task . taskId } .${ task . instanceId } instantiated` ,
806891 )
807892
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+
808936 return task
809937 }
810938
0 commit comments