@@ -102,18 +102,18 @@ export const webviewMessageHandler = async (
102
102
* Handles message deletion operations with user confirmation
103
103
*/
104
104
const handleDeleteOperation = async ( messageTs : number ) : Promise < void > => {
105
- // Check if the message has a checkpoint
105
+ // Check if there's a checkpoint before this message
106
106
const currentCline = provider . getCurrentCline ( )
107
107
let hasCheckpoint = false
108
108
if ( currentCline ) {
109
109
const { messageIndex } = findMessageIndices ( messageTs , currentCline )
110
110
if ( messageIndex !== - 1 ) {
111
- const targetMessage = currentCline . clineMessages [ messageIndex ]
112
- hasCheckpoint = ! ! (
113
- targetMessage ?. checkpoint &&
114
- typeof targetMessage . checkpoint === "object" &&
115
- "hash" in targetMessage . checkpoint
116
- )
111
+ // Find the last checkpoint before this message
112
+ const checkpoints = currentCline . clineMessages
113
+ . filter ( ( msg ) => msg . say === "checkpoint_saved" && msg . ts < messageTs )
114
+ . sort ( ( a , b ) => b . ts - a . ts )
115
+
116
+ hasCheckpoint = checkpoints . length > 0
117
117
} else {
118
118
console . log ( "[webviewMessageHandler] Message not found! Looking for ts:" , messageTs )
119
119
}
@@ -149,16 +149,29 @@ export const webviewMessageHandler = async (
149
149
try {
150
150
const targetMessage = currentCline . clineMessages [ messageIndex ]
151
151
152
- // If checkpoint restoration is requested, restore to the checkpoint first
153
- if ( restoreCheckpoint && hasValidCheckpoint ( targetMessage ) ) {
154
- await handleCheckpointRestoreOperation ( {
155
- provider,
156
- currentCline,
157
- messageTs : targetMessage . ts ! ,
158
- messageIndex,
159
- checkpoint : targetMessage . checkpoint as ValidCheckpoint ,
160
- operation : "delete" ,
161
- } )
152
+ // If checkpoint restoration is requested, find and restore to the last checkpoint before this message
153
+ if ( restoreCheckpoint ) {
154
+ // Find the last checkpoint before this message
155
+ const checkpoints = currentCline . clineMessages
156
+ . filter ( ( msg ) => msg . say === "checkpoint_saved" && msg . ts < messageTs )
157
+ . sort ( ( a , b ) => b . ts - a . ts )
158
+
159
+ const lastCheckpoint = checkpoints [ 0 ]
160
+
161
+ if ( lastCheckpoint && lastCheckpoint . text ) {
162
+ await handleCheckpointRestoreOperation ( {
163
+ provider,
164
+ currentCline,
165
+ messageTs : targetMessage . ts ! ,
166
+ messageIndex,
167
+ checkpoint : { hash : lastCheckpoint . text } ,
168
+ operation : "delete" ,
169
+ } )
170
+ } else {
171
+ // No checkpoint found before this message
172
+ console . log ( "[handleDeleteMessageConfirm] No checkpoint found before message" )
173
+ vscode . window . showWarningMessage ( "No checkpoint found before this message" )
174
+ }
162
175
} else {
163
176
// For non-checkpoint deletes, preserve checkpoint associations for remaining messages
164
177
// Store checkpoints from messages that will be preserved
@@ -200,43 +213,33 @@ export const webviewMessageHandler = async (
200
213
* Handles message editing operations with user confirmation
201
214
*/
202
215
const handleEditOperation = async ( messageTs : number , editedContent : string , images ?: string [ ] ) : Promise < void > => {
203
- // Always check if the message has a checkpoint first
216
+ // Check if there's a checkpoint before this message
204
217
const currentCline = provider . getCurrentCline ( )
205
218
let hasCheckpoint = false
206
219
if ( currentCline ) {
207
220
const { messageIndex } = findMessageIndices ( messageTs , currentCline )
208
221
if ( messageIndex !== - 1 ) {
209
- const targetMessage = currentCline . clineMessages [ messageIndex ]
210
- hasCheckpoint = ! ! (
211
- targetMessage ?. checkpoint &&
212
- typeof targetMessage . checkpoint === "object" &&
213
- "hash" in targetMessage . checkpoint
214
- )
222
+ // Find the last checkpoint before this message
223
+ const checkpoints = currentCline . clineMessages
224
+ . filter ( ( msg ) => msg . say === "checkpoint_saved" && msg . ts < messageTs )
225
+ . sort ( ( a , b ) => b . ts - a . ts )
226
+
227
+ hasCheckpoint = checkpoints . length > 0
215
228
} else {
216
229
console . log ( "[webviewMessageHandler] Edit - Message not found in clineMessages!" )
217
230
}
218
231
} else {
219
232
console . log ( "[webviewMessageHandler] Edit - No currentCline available!" )
220
233
}
221
- // If there's a checkpoint, show the checkpoint dialog even when skipping confirmation
222
- if ( hasCheckpoint ) {
223
- await provider . postMessageToWebview ( {
224
- type : "showEditMessageDialog" ,
225
- messageTs,
226
- text : editedContent ,
227
- hasCheckpoint,
228
- images,
229
- } )
230
- } else {
231
- // Send message to webview to show edit confirmation dialog
232
- await provider . postMessageToWebview ( {
233
- type : "showEditMessageDialog" ,
234
- messageTs,
235
- text : editedContent ,
236
- hasCheckpoint,
237
- images,
238
- } )
239
- }
234
+
235
+ // Send message to webview to show edit confirmation dialog
236
+ await provider . postMessageToWebview ( {
237
+ type : "showEditMessageDialog" ,
238
+ messageTs,
239
+ text : editedContent ,
240
+ hasCheckpoint,
241
+ images,
242
+ } )
240
243
}
241
244
242
245
/**
@@ -267,27 +270,38 @@ export const webviewMessageHandler = async (
267
270
try {
268
271
const targetMessage = currentCline . clineMessages [ messageIndex ]
269
272
270
- // Preserve the original checkpoint data for the edited message
271
- const originalCheckpoint = targetMessage ?. checkpoint
272
-
273
- // If checkpoint restoration is requested, restore to the checkpoint first
274
- if ( restoreCheckpoint && hasValidCheckpoint ( targetMessage ) ) {
275
- await handleCheckpointRestoreOperation ( {
276
- provider,
277
- currentCline,
278
- messageTs : targetMessage . ts ! ,
279
- messageIndex,
280
- checkpoint : targetMessage . checkpoint as ValidCheckpoint ,
281
- operation : "edit" ,
282
- editData : {
283
- editedContent,
284
- images,
285
- apiConversationHistoryIndex,
286
- } ,
287
- } )
288
- // The task will be cancelled and reinitialized by checkpointRestore
289
- // The pending edit will be processed in the reinitialized task
290
- return
273
+ // If checkpoint restoration is requested, find and restore to the last checkpoint before this message
274
+ if ( restoreCheckpoint ) {
275
+ // Find the last checkpoint before this message
276
+ const checkpoints = currentCline . clineMessages
277
+ . filter ( ( msg ) => msg . say === "checkpoint_saved" && msg . ts < messageTs )
278
+ . sort ( ( a , b ) => b . ts - a . ts )
279
+
280
+ const lastCheckpoint = checkpoints [ 0 ]
281
+
282
+ if ( lastCheckpoint && lastCheckpoint . text ) {
283
+ await handleCheckpointRestoreOperation ( {
284
+ provider,
285
+ currentCline,
286
+ messageTs : targetMessage . ts ! ,
287
+ messageIndex,
288
+ checkpoint : { hash : lastCheckpoint . text } ,
289
+ operation : "edit" ,
290
+ editData : {
291
+ editedContent,
292
+ images,
293
+ apiConversationHistoryIndex,
294
+ } ,
295
+ } )
296
+ // The task will be cancelled and reinitialized by checkpointRestore
297
+ // The pending edit will be processed in the reinitialized task
298
+ return
299
+ } else {
300
+ // No checkpoint found before this message
301
+ console . log ( "[handleEditMessageConfirm] No checkpoint found before message" )
302
+ vscode . window . showWarningMessage ( "No checkpoint found before this message" )
303
+ // Continue with non-checkpoint edit
304
+ }
291
305
}
292
306
293
307
// For non-checkpoint edits, preserve checkpoint associations for remaining messages
@@ -319,12 +333,6 @@ export const webviewMessageHandler = async (
319
333
} )
320
334
321
335
// Process the edited message as a regular user message
322
- // Preserve the original checkpoint for the new message
323
- if ( originalCheckpoint ) {
324
- // Store the checkpoint to be attached to the new message
325
- currentCline . pendingUserMessageCheckpoint = originalCheckpoint
326
- }
327
-
328
336
webviewMessageHandler ( provider , {
329
337
type : "askResponse" ,
330
338
askResponse : "messageResponse" ,
@@ -495,25 +503,7 @@ export const webviewMessageHandler = async (
495
503
await provider . postStateToWebview ( )
496
504
break
497
505
case "askResponse" :
498
- // Save checkpoint BEFORE processing the user message if checkpoints are enabled
499
- const currentCline = provider . getCurrentCline ( )
500
- if ( currentCline && currentCline . enableCheckpoints && message . askResponse === "messageResponse" ) {
501
- try {
502
- const checkpointResult = await currentCline . checkpointSave ( true ) // Force checkpoint save
503
- if ( checkpointResult ?. commit ) {
504
- // Store checkpoint data temporarily to be used when creating the user_feedback message
505
- currentCline . pendingUserMessageCheckpoint = {
506
- hash : checkpointResult . commit ,
507
- timestamp : Date . now ( ) ,
508
- type : "user_message" ,
509
- }
510
- }
511
- } catch ( error ) {
512
- console . error ( "[webviewMessageHandler] Failed to save checkpoint before user message:" , error )
513
- }
514
- }
515
-
516
- currentCline ?. handleWebviewAskResponse ( message . askResponse ! , message . text , message . images )
506
+ provider . getCurrentCline ( ) ?. handleWebviewAskResponse ( message . askResponse ! , message . text , message . images )
517
507
break
518
508
case "autoCondenseContext" :
519
509
await updateGlobalState ( "autoCondenseContext" , message . bool )
0 commit comments