Skip to content

Commit 2cc6497

Browse files
Size up the Task (RooCodeInc#2246)
* Calculate and display total tasks and checkpoints size * changeset * Remove logs and add try/catch to file deletion * call postMessage from HistoryView instead
1 parent 599c3f6 commit 2cc6497

File tree

7 files changed

+111
-48
lines changed

7 files changed

+111
-48
lines changed

.changeset/olive-apricots-help.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": minor
3+
---
4+
5+
Add size calculation to "Delete all Tasks" button

src/core/webview/ClineProvider.ts

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { telemetryService } from "../../services/telemetry/TelemetryService"
3636
import { TelemetrySetting } from "../../shared/TelemetrySetting"
3737
import { cleanupLegacyCheckpoints } from "../../integrations/checkpoints/CheckpointMigration"
3838
import CheckpointTracker from "../../integrations/checkpoints/CheckpointTracker"
39+
import { getTotalTasksSize } from "../../utils/storage"
3940

4041
/*
4142
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
@@ -816,6 +817,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
816817
}
817818
break
818819
}
820+
case "requestTotalTasksSize": {
821+
this.refreshTotalTasksSize()
822+
break
823+
}
819824
case "restartMcpServer": {
820825
try {
821826
await this.mcpHub?.restartConnection(message.text!)
@@ -917,6 +922,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
917922
case "clearAllTaskHistory": {
918923
await this.deleteAllTaskHistory()
919924
await this.postStateToWebview()
925+
this.refreshTotalTasksSize()
920926
this.postMessageToWebview({ type: "relinquishControl" })
921927
break
922928
}
@@ -1788,46 +1794,56 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
17881794
// await this.postStateToWebview()
17891795
}
17901796

1797+
async refreshTotalTasksSize() {
1798+
getTotalTasksSize(this.context.globalStorageUri.fsPath)
1799+
.then((newTotalSize) => {
1800+
this.postMessageToWebview({
1801+
type: "totalTasksSize",
1802+
totalTasksSize: newTotalSize,
1803+
})
1804+
})
1805+
.catch((error) => {
1806+
console.error("Error calculating total tasks size:", error)
1807+
})
1808+
}
1809+
17911810
async deleteTaskWithId(id: string) {
17921811
console.info("deleteTaskWithId: ", id)
17931812

1794-
if (id === this.cline?.taskId) {
1795-
await this.clearTask()
1796-
console.debug("cleared task")
1797-
}
1813+
try {
1814+
if (id === this.cline?.taskId) {
1815+
await this.clearTask()
1816+
console.debug("cleared task")
1817+
}
17981818

1799-
const { taskDirPath, apiConversationHistoryFilePath, uiMessagesFilePath } = await this.getTaskWithId(id)
1819+
const { taskDirPath, apiConversationHistoryFilePath, uiMessagesFilePath } = await this.getTaskWithId(id)
18001820

1801-
// Delete checkpoints
1802-
console.info("deleting checkpoints")
1803-
const taskHistory = ((await this.getGlobalState("taskHistory")) as HistoryItem[] | undefined) || []
1804-
const historyItem = taskHistory.find((item) => item.id === id)
1805-
//console.log("historyItem: ", historyItem)
1806-
// if (historyItem) {
1807-
// try {
1808-
// await CheckpointTracker.deleteCheckpoints(id, historyItem, this.context.globalStorageUri.fsPath)
1809-
// } catch (error) {
1810-
// console.error(`Failed to delete checkpoints for task ${id}:`, error)
1811-
// }
1812-
// }
1821+
const updatedTaskHistory = await this.deleteTaskFromState(id)
18131822

1814-
await this.deleteTaskFromState(id)
1823+
// Delete the task files
1824+
const apiConversationHistoryFileExists = await fileExistsAtPath(apiConversationHistoryFilePath)
1825+
if (apiConversationHistoryFileExists) {
1826+
await fs.unlink(apiConversationHistoryFilePath)
1827+
}
1828+
const uiMessagesFileExists = await fileExistsAtPath(uiMessagesFilePath)
1829+
if (uiMessagesFileExists) {
1830+
await fs.unlink(uiMessagesFilePath)
1831+
}
1832+
const legacyMessagesFilePath = path.join(taskDirPath, "claude_messages.json")
1833+
if (await fileExistsAtPath(legacyMessagesFilePath)) {
1834+
await fs.unlink(legacyMessagesFilePath)
1835+
}
18151836

1816-
// Delete the task files
1817-
const apiConversationHistoryFileExists = await fileExistsAtPath(apiConversationHistoryFilePath)
1818-
if (apiConversationHistoryFileExists) {
1819-
await fs.unlink(apiConversationHistoryFilePath)
1820-
}
1821-
const uiMessagesFileExists = await fileExistsAtPath(uiMessagesFilePath)
1822-
if (uiMessagesFileExists) {
1823-
await fs.unlink(uiMessagesFilePath)
1824-
}
1825-
const legacyMessagesFilePath = path.join(taskDirPath, "claude_messages.json")
1826-
if (await fileExistsAtPath(legacyMessagesFilePath)) {
1827-
await fs.unlink(legacyMessagesFilePath)
1837+
await fs.rmdir(taskDirPath) // succeeds if the dir is empty
1838+
1839+
if (updatedTaskHistory.length === 0) {
1840+
await this.deleteAllTaskHistory()
1841+
}
1842+
} catch (error) {
1843+
console.debug(`Error deleting task:`, error)
18281844
}
18291845

1830-
await fs.rmdir(taskDirPath) // succeeds if the dir is empty
1846+
this.refreshTotalTasksSize()
18311847
}
18321848

18331849
async deleteTaskFromState(id: string) {
@@ -1838,6 +1854,8 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
18381854

18391855
// Notify the webview that the task has been deleted
18401856
await this.postStateToWebview()
1857+
1858+
return updatedTaskHistory
18411859
}
18421860

18431861
async postStateToWebview() {

src/shared/ExtensionMessage.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface ExtensionMessage {
3434
| "openGraphData"
3535
| "isImageUrlResult"
3636
| "didUpdateSettings"
37+
| "totalTasksSize"
3738
text?: string
3839
action?:
3940
| "chatButtonClicked"
@@ -69,6 +70,7 @@ export interface ExtensionMessage {
6970
}
7071
url?: string
7172
isImage?: boolean
73+
totalTasksSize?: number | null
7274
}
7375

7476
export type Invoke = "sendMessage" | "primaryButtonClick" | "secondaryButtonClick"
@@ -78,27 +80,27 @@ export type Platform = "aix" | "darwin" | "freebsd" | "linux" | "openbsd" | "sun
7880
export const DEFAULT_PLATFORM = "unknown"
7981

8082
export interface ExtensionState {
81-
version: string
8283
apiConfiguration?: ApiConfiguration
83-
customInstructions?: string
84-
uriScheme?: string
85-
currentTaskItem?: HistoryItem
86-
checkpointTrackerErrorMessage?: string
87-
clineMessages: ClineMessage[]
88-
taskHistory: HistoryItem[]
89-
shouldShowAnnouncement: boolean
9084
autoApprovalSettings: AutoApprovalSettings
9185
browserSettings: BrowserSettings
9286
chatSettings: ChatSettings
87+
checkpointTrackerErrorMessage?: string
88+
clineMessages: ClineMessage[]
89+
currentTaskItem?: HistoryItem
90+
customInstructions?: string
91+
mcpMarketplaceEnabled?: boolean
92+
planActSeparateModelsSetting: boolean
9393
platform: Platform
94+
shouldShowAnnouncement: boolean
95+
taskHistory: HistoryItem[]
96+
telemetrySetting: TelemetrySetting
97+
uriScheme?: string
9498
userInfo?: {
9599
displayName: string | null
96100
email: string | null
97101
photoURL: string | null
98102
}
99-
mcpMarketplaceEnabled?: boolean
100-
telemetrySetting: TelemetrySetting
101-
planActSeparateModelsSetting: boolean
103+
version: string
102104
vscMachineId: string
103105
}
104106

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export interface WebviewMessage {
6262
| "updateSettings"
6363
| "clearAllTaskHistory"
6464
| "optionsResponse"
65+
| "requestTotalTasksSize"
6566
// | "relaunchChromeDebugMode"
6667
text?: string
6768
disabled?: boolean

src/utils/storage.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import path from "path"
2+
import getFolderSize from "get-folder-size"
3+
4+
/**
5+
* Gets the total size of tasks and checkpoints directories
6+
* @param storagePath The base storage path (typically globalStorageUri.fsPath)
7+
* @returns The total size in bytes, or null if calculation fails
8+
*/
9+
export async function getTotalTasksSize(storagePath: string): Promise<number | null> {
10+
const tasksDir = path.join(storagePath, "tasks")
11+
const checkpointsDir = path.join(storagePath, "checkpoints")
12+
13+
try {
14+
const tasksSize = await getFolderSize.loose(tasksDir)
15+
const checkpointsSize = await getFolderSize.loose(checkpointsDir)
16+
return tasksSize + checkpointsSize
17+
} catch (error) {
18+
console.error("Failed to calculate total task size:", error)
19+
return null
20+
}
21+
}

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,27 @@ type HistoryViewProps = {
1717
type SortOption = "newest" | "oldest" | "mostExpensive" | "mostTokens" | "mostRelevant"
1818

1919
const HistoryView = ({ onDone }: HistoryViewProps) => {
20-
const { taskHistory } = useExtensionState()
21-
const [searchQuery, setSearchQuery] = useState("")
22-
const [sortOption, setSortOption] = useState<SortOption>("newest")
23-
const [lastNonRelevantSort, setLastNonRelevantSort] = useState<SortOption | null>("newest")
24-
const [deleteAllDisabled, setDeleteAllDisabled] = useState(false)
20+
const { taskHistory, totalTasksSize } = useExtensionState()
21+
22+
const requestTotalTasksSize = useCallback(() => {
23+
vscode.postMessage({ type: "requestTotalTasksSize" })
24+
}, [])
2525

2626
const handleMessage = useCallback((event: MessageEvent<ExtensionMessage>) => {
2727
if (event.data.type === "relinquishControl") {
2828
setDeleteAllDisabled(false)
2929
}
3030
}, [])
3131

32+
// Request total tasks size when component mounts
33+
useEffect(() => {
34+
requestTotalTasksSize()
35+
}, [requestTotalTasksSize])
36+
const [searchQuery, setSearchQuery] = useState("")
37+
const [sortOption, setSortOption] = useState<SortOption>("newest")
38+
const [lastNonRelevantSort, setLastNonRelevantSort] = useState<SortOption | null>("newest")
39+
const [deleteAllDisabled, setDeleteAllDisabled] = useState(false)
40+
3241
useEvent("message", handleMessage)
3342

3443
useEffect(() => {
@@ -471,7 +480,7 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
471480
setDeleteAllDisabled(true)
472481
vscode.postMessage({ type: "clearAllTaskHistory" })
473482
}}>
474-
Delete All History
483+
Delete All History{totalTasksSize !== null ? ` (${formatSize(totalTasksSize)})` : ""}
475484
</DangerButton>
476485
</div>
477486
</div>

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ interface ExtensionStateContextType extends ExtensionState {
2020
mcpServers: McpServer[]
2121
mcpMarketplaceCatalog: McpMarketplaceCatalog
2222
filePaths: string[]
23+
totalTasksSize: number | null
2324
setApiConfiguration: (config: ApiConfiguration) => void
2425
setCustomInstructions: (value?: string) => void
2526
setTelemetrySetting: (value: TelemetrySetting) => void
@@ -52,6 +53,7 @@ export const ExtensionStateContextProvider: React.FC<{
5253
const [openRouterModels, setOpenRouterModels] = useState<Record<string, ModelInfo>>({
5354
[openRouterDefaultModelId]: openRouterDefaultModelInfo,
5455
})
56+
const [totalTasksSize, setTotalTasksSize] = useState<number | null>(null)
5557

5658
const [openAiModels, setOpenAiModels] = useState<string[]>([])
5759
const [mcpServers, setMcpServers] = useState<McpServer[]>([])
@@ -137,6 +139,10 @@ export const ExtensionStateContextProvider: React.FC<{
137139
}
138140
break
139141
}
142+
case "totalTasksSize": {
143+
setTotalTasksSize(message.totalTasksSize ?? null)
144+
break
145+
}
140146
}
141147
}, [])
142148

@@ -156,6 +162,7 @@ export const ExtensionStateContextProvider: React.FC<{
156162
mcpServers,
157163
mcpMarketplaceCatalog,
158164
filePaths,
165+
totalTasksSize,
159166
setApiConfiguration: (value) =>
160167
setState((prevState) => ({
161168
...prevState,

0 commit comments

Comments
 (0)