Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/core/checkpoints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,11 @@ export async function checkpointRestore(
// I'd like to revisit this in the future and try to improve the
// task flow and the communication between the webview and the
// `Task` instance.
provider?.cancelTask()
//
// Pass startTask: false to prevent the rehydrated task from auto-resuming
// and re-executing the restored message history. The task should only
// display the restored state, not continue processing.
provider?.cancelTask({ startTask: false })
} catch (err) {
provider?.log("[checkpointRestore] disabling checkpoints for this task")
task.enableCheckpoints = false
Expand Down
7 changes: 5 additions & 2 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2739,7 +2739,7 @@ export class ClineProvider
return task
}

public async cancelTask(): Promise<void> {
public async cancelTask(options?: { startTask?: boolean }): Promise<void> {
const task = this.getCurrentTask()

if (!task) {
Expand Down Expand Up @@ -2807,7 +2807,10 @@ export class ClineProvider
}

// Clears task again, so we need to abortTask manually above.
await this.createTaskWithHistoryItem({ ...historyItem, rootTask, parentTask })
// Pass startTask option to control whether the rehydrated task auto-resumes.
// When called from checkpoint restore, startTask should be false to prevent
// the task from re-executing its message history.
await this.createTaskWithHistoryItem({ ...historyItem, rootTask, parentTask }, { startTask: options?.startTask })
}

// Clear the current task without treating it as a subtask.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ describe("checkpointRestoreHandler", () => {
expect(mockProvider.getTaskWithId).toHaveBeenCalledWith("test-task-123")

// Verify createTaskWithHistoryItem was called with the correct history item
expect(mockProvider.createTaskWithHistoryItem).toHaveBeenCalledWith(expectedHistoryItem)
// startTask: false prevents the restored task from auto-resuming
expect(mockProvider.createTaskWithHistoryItem).toHaveBeenCalledWith(expectedHistoryItem, { startTask: false })
})

it("should not save messages or reinitialize for edit operation", async () => {
Expand Down
5 changes: 4 additions & 1 deletion src/core/webview/checkpointRestoreHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ export async function handleCheckpointRestoreOperation(config: CheckpointRestore
})

// Get the updated history item and reinitialize
// Pass startTask: false to prevent the restored task from auto-resuming
// and re-executing the message history. The task should only display
// the restored state, not continue processing.
const { historyItem } = await provider.getTaskWithId(currentCline.taskId)
await provider.createTaskWithHistoryItem(historyItem)
await provider.createTaskWithHistoryItem(historyItem, { startTask: false })
}
// For edit operations, the task cancellation in checkpointRestore
// will trigger reinitialization, which will process pendingEditAfterRestore
Expand Down
Loading