Skip to content

Commit 9782fd7

Browse files
committed
feat: add fork task from message functionality
- Add fork button to ChatRow component for user messages - Implement forkTaskFromMessage handler in webviewMessageHandler - Add forkTaskFromMessage method in ClineProvider to create forked tasks - Include tests for the new fork functionality Implements #7904
1 parent 8fee312 commit 9782fd7

File tree

5 files changed

+803
-0
lines changed

5 files changed

+803
-0
lines changed

src/core/webview/ClineProvider.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,6 +1557,59 @@ export class ClineProvider
15571557
}
15581558
}
15591559

1560+
async forkTaskFromMessage(messageTs: number) {
1561+
const currentTask = this.getCurrentTask()
1562+
if (!currentTask) {
1563+
throw new Error("No active task to fork from")
1564+
}
1565+
1566+
// Find the message index
1567+
const messageIndex = currentTask.clineMessages.findIndex((msg) => msg.ts === messageTs)
1568+
if (messageIndex === -1) {
1569+
throw new Error("Message not found")
1570+
}
1571+
1572+
// Get messages up to and including the selected message
1573+
const messagesToCopy = currentTask.clineMessages.slice(0, messageIndex + 1)
1574+
1575+
// Create a new task with the copied conversation
1576+
const newTaskId = `${Date.now()}`
1577+
const historyItem: HistoryItem = {
1578+
id: newTaskId,
1579+
ts: Date.now(),
1580+
task: messagesToCopy[0]?.text || "Forked conversation",
1581+
mode: currentTask.taskMode || defaultModeSlug,
1582+
workspace: this.cwd,
1583+
number: (this.getGlobalState("taskHistory") ?? []).length + 1,
1584+
tokensIn: 0,
1585+
tokensOut: 0,
1586+
totalCost: 0,
1587+
}
1588+
1589+
// Save the new task to history
1590+
await this.updateTaskHistory(historyItem)
1591+
1592+
// Create the task directory and save messages
1593+
const { getTaskDirectoryPath } = await import("../../utils/storage")
1594+
const globalStoragePath = this.contextProxy.globalStorageUri.fsPath
1595+
const taskDirPath = await getTaskDirectoryPath(globalStoragePath, newTaskId)
1596+
1597+
// Ensure directory exists
1598+
await fs.mkdir(taskDirPath, { recursive: true })
1599+
1600+
// Save the messages to the new task
1601+
const uiMessagesFilePath = path.join(taskDirPath, GlobalFileNames.uiMessages)
1602+
await fs.writeFile(uiMessagesFilePath, JSON.stringify(messagesToCopy, null, 2))
1603+
1604+
// Create and show the new forked task
1605+
await this.createTaskWithHistoryItem(historyItem)
1606+
1607+
// Show success message
1608+
vscode.window.showInformationMessage(
1609+
"Task forked successfully. You can now continue the conversation from this point.",
1610+
)
1611+
}
1612+
15601613
async deleteTaskFromState(id: string) {
15611614
const taskHistory = this.getGlobalState("taskHistory") ?? []
15621615
const updatedTaskHistory = taskHistory.filter((task) => task.id !== id)

0 commit comments

Comments
 (0)