Skip to content

Commit 0176599

Browse files
author
ShayBC
committed
added task no indicator + improved deleteTask code
1 parent 655930c commit 0176599

File tree

7 files changed

+62
-38
lines changed

7 files changed

+62
-38
lines changed

src/core/Cline.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type UserContent = Array<
7575

7676
export class Cline {
7777
readonly taskId: string
78+
private taskNumber: number
7879
// a flag that indicated if this Cline instance is a subtask (on finish return control to parent task)
7980
private isSubTask: boolean = false
8081
// 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 {
139140
}
140141

141142
this.taskId = crypto.randomUUID()
143+
this.taskNumber = -1
142144
this.api = buildApiHandler(apiConfiguration)
143145
this.terminalManager = new TerminalManager()
144146
this.urlContentFetcher = new UrlContentFetcher(provider.context)
@@ -170,6 +172,16 @@ export class Cline {
170172
this.isSubTask = true
171173
}
172174

175+
// sets the task number (sequencial number of this task from all the subtask ran from this main task stack)
176+
setTaskNumber(taskNumber: number) {
177+
this.taskNumber = taskNumber
178+
}
179+
180+
// gets the task number, the sequencial number of this task from all the subtask ran from this main task stack
181+
getTaskNumber() {
182+
return this.taskNumber
183+
}
184+
173185
// Add method to update diffStrategy
174186
async updateDiffStrategy(experimentalDiffStrategy?: boolean) {
175187
// If not provided, get from current state
@@ -276,6 +288,7 @@ export class Cline {
276288

277289
await this.providerRef.deref()?.updateTaskHistory({
278290
id: this.taskId,
291+
number: this.taskNumber,
279292
ts: lastRelevantMessage.ts,
280293
task: taskMessage.text ?? "",
281294
tokensIn: apiMetrics.totalTokensIn,

src/core/__tests__/Cline.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ describe("Cline", () => {
222222
return [
223223
{
224224
id: "123",
225+
number: 0,
225226
ts: Date.now(),
226227
task: "historical task",
227228
tokensIn: 100,

src/core/webview/ClineProvider.ts

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
153153
private latestAnnouncementId = "jan-21-2025-custom-modes" // update to some unique identifier when we add a new announcement
154154
configManager: ConfigManager
155155
customModesManager: CustomModesManager
156+
private lastTaskNumber = -1
156157

157158
constructor(
158159
readonly context: vscode.ExtensionContext,
@@ -180,6 +181,17 @@ export class ClineProvider implements vscode.WebviewViewProvider {
180181
// The instance is pushed to the top of the stack (LIFO order).
181182
// When the task is completed, the top instance is removed, reactivating the previous task.
182183
addClineToStack(cline: Cline): void {
184+
// if cline.getTaskNumber() is -1, it means it is a new task
185+
if (cline.getTaskNumber() === -1) {
186+
// increase last cline number by 1
187+
this.lastTaskNumber = this.lastTaskNumber + 1
188+
cline.setTaskNumber(this.lastTaskNumber)
189+
}
190+
// if cline.getTaskNumber() > lastTaskNumber, set lastTaskNumber to cline.getTaskNumber()
191+
else if (cline.getTaskNumber() > this.lastTaskNumber) {
192+
this.lastTaskNumber = cline.getTaskNumber()
193+
}
194+
// push the cline instance to the stack
183195
this.clineStack.push(cline)
184196
}
185197

@@ -192,6 +204,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
192204
// make sure no reference kept, once promises end it will be garbage collected
193205
clineToBeRemoved = undefined
194206
}
207+
// if the stack is empty, reset the last task number
208+
if (this.clineStack.length === 0) {
209+
this.lastTaskNumber = -1
210+
}
195211
}
196212

197213
// 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 {
520536
historyItem,
521537
experiments,
522538
)
539+
// get this cline task number id from the history item and set it to newCline
540+
newCline.setTaskNumber(historyItem.number)
523541
this.addClineToStack(newCline)
524542
}
525543

@@ -2384,38 +2402,25 @@ export class ClineProvider implements vscode.WebviewViewProvider {
23842402
await downloadTask(historyItem.ts, apiConversationHistory)
23852403
}
23862404

2405+
// this function deletes a task from task hidtory, and deletes it's checkpoints and delete the task folder
23872406
async deleteTaskWithId(id: string) {
2407+
// get the task directory full path
2408+
const { taskDirPath } = await this.getTaskWithId(id)
2409+
2410+
// remove task from stack if it's the current task
23882411
if (id === this.getCurrentCline()?.taskId) {
23892412
await this.removeClineWithIdFromStack(id)
23902413
}
23912414

2392-
const { taskDirPath, apiConversationHistoryFilePath, uiMessagesFilePath } = await this.getTaskWithId(id)
2393-
2415+
// delete task from the task history state
23942416
await this.deleteTaskFromState(id)
23952417

2396-
// Delete the task files.
2397-
const apiConversationHistoryFileExists = await fileExistsAtPath(apiConversationHistoryFilePath)
2398-
2399-
if (apiConversationHistoryFileExists) {
2400-
await fs.unlink(apiConversationHistoryFilePath)
2401-
}
2402-
2403-
const uiMessagesFileExists = await fileExistsAtPath(uiMessagesFilePath)
2404-
2405-
if (uiMessagesFileExists) {
2406-
await fs.unlink(uiMessagesFilePath)
2407-
}
2408-
2409-
const legacyMessagesFilePath = path.join(taskDirPath, "claude_messages.json")
2410-
2411-
if (await fileExistsAtPath(legacyMessagesFilePath)) {
2412-
await fs.unlink(legacyMessagesFilePath)
2413-
}
2414-
2418+
// check if checkpoints are enabled
24152419
const { checkpointsEnabled } = await this.getState()
2420+
// get the base directory of the project
24162421
const baseDir = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
24172422

2418-
// Delete checkpoints branch.
2423+
// delete checkpoints branch from project git repo
24192424
if (checkpointsEnabled && baseDir) {
24202425
const branchSummary = await simpleGit(baseDir)
24212426
.branch(["-D", `roo-code-checkpoints-${id}`])
@@ -2426,22 +2431,15 @@ export class ClineProvider implements vscode.WebviewViewProvider {
24262431
}
24272432
}
24282433

2429-
// Delete checkpoints directory
2430-
const checkpointsDir = path.join(taskDirPath, "checkpoints")
2431-
2432-
if (await fileExistsAtPath(checkpointsDir)) {
2433-
try {
2434-
await fs.rm(checkpointsDir, { recursive: true, force: true })
2435-
console.log(`[deleteTaskWithId${id}] removed checkpoints repo`)
2436-
} catch (error) {
2437-
console.error(
2438-
`[deleteTaskWithId${id}] failed to remove checkpoints repo: ${error instanceof Error ? error.message : String(error)}`,
2439-
)
2440-
}
2434+
// delete the entire task directory including checkpoints and all content
2435+
try {
2436+
await fs.rm(taskDirPath, { recursive: true, force: true })
2437+
console.log(`[deleteTaskWithId${id}] removed task directory`)
2438+
} catch (error) {
2439+
console.error(
2440+
`[deleteTaskWithId${id}] failed to remove task directory: ${error instanceof Error ? error.message : String(error)}`,
2441+
)
24412442
}
2442-
2443-
// Succeeds if the dir is empty.
2444-
await fs.rmdir(taskDirPath)
24452443
}
24462444

24472445
async deleteTaskFromState(id: string) {

src/shared/HistoryItem.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export type HistoryItem = {
22
id: string
3+
number: number
34
ts: number
45
task: string
56
tokensIn: number

webview-ui/src/components/chat/TaskHeader.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
158158
flexGrow: 1,
159159
minWidth: 0, // This allows the div to shrink below its content size
160160
}}>
161-
<span style={{ fontWeight: "bold" }}>Task{!isTaskExpanded && ":"}</span>
161+
<span style={{ fontWeight: "bold" }}>
162+
Task ({currentTaskItem?.number === 0 ? "Main" : currentTaskItem.number})
163+
{!isTaskExpanded && ":"}
164+
</span>
162165
{!isTaskExpanded && (
163166
<span style={{ marginLeft: 4 }}>{highlightMentions(task.text, false)}</span>
164167
)}

webview-ui/src/components/history/HistoryPreview.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
120120
}}>
121121
{formatDate(item.ts)}
122122
</span>
123+
<span
124+
style={{
125+
marginLeft: "auto",
126+
}}>
127+
({item.number === 0 ? "Main" : item.number})
128+
</span>
123129
<button
124130
title="Copy Prompt"
125131
aria-label="Copy Prompt"

webview-ui/src/components/history/__tests__/HistoryView.test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jest.mock("react-virtuoso", () => ({
2323
const mockTaskHistory = [
2424
{
2525
id: "1",
26+
number: 0,
2627
task: "Test task 1",
2728
ts: new Date("2022-02-16T00:00:00").getTime(),
2829
tokensIn: 100,
@@ -31,6 +32,7 @@ const mockTaskHistory = [
3132
},
3233
{
3334
id: "2",
35+
number: 0,
3436
task: "Test task 2",
3537
ts: new Date("2022-02-17T00:00:00").getTime(),
3638
tokensIn: 200,

0 commit comments

Comments
 (0)