From 01765995ada92491ef7576d10f8d7a8da22f4223 Mon Sep 17 00:00:00 2001 From: ShayBC Date: Mon, 24 Feb 2025 23:00:11 +0200 Subject: [PATCH] added task no indicator + improved deleteTask code --- src/core/Cline.ts | 13 ++++ src/core/__tests__/Cline.test.ts | 1 + src/core/webview/ClineProvider.ts | 72 +++++++++---------- src/shared/HistoryItem.ts | 1 + webview-ui/src/components/chat/TaskHeader.tsx | 5 +- .../src/components/history/HistoryPreview.tsx | 6 ++ .../history/__tests__/HistoryView.test.tsx | 2 + 7 files changed, 62 insertions(+), 38 deletions(-) diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 35879a4291..bcec6243ff 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -75,6 +75,7 @@ type UserContent = Array< export class Cline { readonly taskId: string + private taskNumber: number // a flag that indicated if this Cline instance is a subtask (on finish return control to parent task) private isSubTask: boolean = false // a flag that indicated if this Cline instance is paused (waiting for provider to resume it after subtask completion) @@ -139,6 +140,7 @@ export class Cline { } this.taskId = crypto.randomUUID() + this.taskNumber = -1 this.api = buildApiHandler(apiConfiguration) this.terminalManager = new TerminalManager() this.urlContentFetcher = new UrlContentFetcher(provider.context) @@ -170,6 +172,16 @@ export class Cline { this.isSubTask = true } + // sets the task number (sequencial number of this task from all the subtask ran from this main task stack) + setTaskNumber(taskNumber: number) { + this.taskNumber = taskNumber + } + + // gets the task number, the sequencial number of this task from all the subtask ran from this main task stack + getTaskNumber() { + return this.taskNumber + } + // Add method to update diffStrategy async updateDiffStrategy(experimentalDiffStrategy?: boolean) { // If not provided, get from current state @@ -276,6 +288,7 @@ export class Cline { await this.providerRef.deref()?.updateTaskHistory({ id: this.taskId, + number: this.taskNumber, ts: lastRelevantMessage.ts, task: taskMessage.text ?? "", tokensIn: apiMetrics.totalTokensIn, diff --git a/src/core/__tests__/Cline.test.ts b/src/core/__tests__/Cline.test.ts index 3da0c8cdd3..0afce81bce 100644 --- a/src/core/__tests__/Cline.test.ts +++ b/src/core/__tests__/Cline.test.ts @@ -222,6 +222,7 @@ describe("Cline", () => { return [ { id: "123", + number: 0, ts: Date.now(), task: "historical task", tokensIn: 100, diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index a8f10f6fcd..6e9e202526 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -153,6 +153,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { private latestAnnouncementId = "jan-21-2025-custom-modes" // update to some unique identifier when we add a new announcement configManager: ConfigManager customModesManager: CustomModesManager + private lastTaskNumber = -1 constructor( readonly context: vscode.ExtensionContext, @@ -180,6 +181,17 @@ export class ClineProvider implements vscode.WebviewViewProvider { // The instance is pushed to the top of the stack (LIFO order). // When the task is completed, the top instance is removed, reactivating the previous task. addClineToStack(cline: Cline): void { + // if cline.getTaskNumber() is -1, it means it is a new task + if (cline.getTaskNumber() === -1) { + // increase last cline number by 1 + this.lastTaskNumber = this.lastTaskNumber + 1 + cline.setTaskNumber(this.lastTaskNumber) + } + // if cline.getTaskNumber() > lastTaskNumber, set lastTaskNumber to cline.getTaskNumber() + else if (cline.getTaskNumber() > this.lastTaskNumber) { + this.lastTaskNumber = cline.getTaskNumber() + } + // push the cline instance to the stack this.clineStack.push(cline) } @@ -192,6 +204,10 @@ export class ClineProvider implements vscode.WebviewViewProvider { // make sure no reference kept, once promises end it will be garbage collected clineToBeRemoved = undefined } + // if the stack is empty, reset the last task number + if (this.clineStack.length === 0) { + this.lastTaskNumber = -1 + } } // remove the cline object with the received clineId, and all the cline objects bove it in the stack @@ -520,6 +536,8 @@ export class ClineProvider implements vscode.WebviewViewProvider { historyItem, experiments, ) + // get this cline task number id from the history item and set it to newCline + newCline.setTaskNumber(historyItem.number) this.addClineToStack(newCline) } @@ -2384,38 +2402,25 @@ export class ClineProvider implements vscode.WebviewViewProvider { await downloadTask(historyItem.ts, apiConversationHistory) } + // this function deletes a task from task hidtory, and deletes it's checkpoints and delete the task folder async deleteTaskWithId(id: string) { + // get the task directory full path + const { taskDirPath } = await this.getTaskWithId(id) + + // remove task from stack if it's the current task if (id === this.getCurrentCline()?.taskId) { await this.removeClineWithIdFromStack(id) } - const { taskDirPath, apiConversationHistoryFilePath, uiMessagesFilePath } = await this.getTaskWithId(id) - + // delete task from the task history state await this.deleteTaskFromState(id) - // Delete the task files. - const apiConversationHistoryFileExists = await fileExistsAtPath(apiConversationHistoryFilePath) - - if (apiConversationHistoryFileExists) { - await fs.unlink(apiConversationHistoryFilePath) - } - - const uiMessagesFileExists = await fileExistsAtPath(uiMessagesFilePath) - - if (uiMessagesFileExists) { - await fs.unlink(uiMessagesFilePath) - } - - const legacyMessagesFilePath = path.join(taskDirPath, "claude_messages.json") - - if (await fileExistsAtPath(legacyMessagesFilePath)) { - await fs.unlink(legacyMessagesFilePath) - } - + // check if checkpoints are enabled const { checkpointsEnabled } = await this.getState() + // get the base directory of the project const baseDir = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) - // Delete checkpoints branch. + // delete checkpoints branch from project git repo if (checkpointsEnabled && baseDir) { const branchSummary = await simpleGit(baseDir) .branch(["-D", `roo-code-checkpoints-${id}`]) @@ -2426,22 +2431,15 @@ export class ClineProvider implements vscode.WebviewViewProvider { } } - // Delete checkpoints directory - const checkpointsDir = path.join(taskDirPath, "checkpoints") - - if (await fileExistsAtPath(checkpointsDir)) { - try { - await fs.rm(checkpointsDir, { recursive: true, force: true }) - console.log(`[deleteTaskWithId${id}] removed checkpoints repo`) - } catch (error) { - console.error( - `[deleteTaskWithId${id}] failed to remove checkpoints repo: ${error instanceof Error ? error.message : String(error)}`, - ) - } + // delete the entire task directory including checkpoints and all content + try { + await fs.rm(taskDirPath, { recursive: true, force: true }) + console.log(`[deleteTaskWithId${id}] removed task directory`) + } catch (error) { + console.error( + `[deleteTaskWithId${id}] failed to remove task directory: ${error instanceof Error ? error.message : String(error)}`, + ) } - - // Succeeds if the dir is empty. - await fs.rmdir(taskDirPath) } async deleteTaskFromState(id: string) { diff --git a/src/shared/HistoryItem.ts b/src/shared/HistoryItem.ts index ef242cb967..e6e2c09ed2 100644 --- a/src/shared/HistoryItem.ts +++ b/src/shared/HistoryItem.ts @@ -1,5 +1,6 @@ export type HistoryItem = { id: string + number: number ts: number task: string tokensIn: number diff --git a/webview-ui/src/components/chat/TaskHeader.tsx b/webview-ui/src/components/chat/TaskHeader.tsx index b35be0cd2a..90d050cf53 100644 --- a/webview-ui/src/components/chat/TaskHeader.tsx +++ b/webview-ui/src/components/chat/TaskHeader.tsx @@ -158,7 +158,10 @@ const TaskHeader: React.FC = ({ flexGrow: 1, minWidth: 0, // This allows the div to shrink below its content size }}> - Task{!isTaskExpanded && ":"} + + Task ({currentTaskItem?.number === 0 ? "Main" : currentTaskItem.number}) + {!isTaskExpanded && ":"} + {!isTaskExpanded && ( {highlightMentions(task.text, false)} )} diff --git a/webview-ui/src/components/history/HistoryPreview.tsx b/webview-ui/src/components/history/HistoryPreview.tsx index b2898fc6a8..f0484b1dcc 100644 --- a/webview-ui/src/components/history/HistoryPreview.tsx +++ b/webview-ui/src/components/history/HistoryPreview.tsx @@ -120,6 +120,12 @@ const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => { }}> {formatDate(item.ts)} + + ({item.number === 0 ? "Main" : item.number}) +