Skip to content

Commit d2dac02

Browse files
committed
feat: Add Hard Reset button to clear Electron caches
- Implements a new hardResetElectronCache method in ClineProvider - Adds 'Hard Reset' button to the About settings section - Clears platform-specific Electron and VS Code cache directories - Handles macOS, Windows, and Linux cache locations - Includes comprehensive user confirmation and feedback - Adds JSDoc documentation for the new functionality - Includes all necessary translations Fixes #8419
1 parent 9f41ee0 commit d2dac02

File tree

9 files changed

+181
-2
lines changed

9 files changed

+181
-2
lines changed

.review/pr-8274

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit e46929b8d8add0cd3c412d69f8ac882c405a4ba9

src/core/webview/ClineProvider.ts

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2275,6 +2275,164 @@ export class ClineProvider
22752275
await this.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
22762276
}
22772277

2278+
/**
2279+
* Performs a hard reset of Electron and VS Code caches to fix corrupted runtime files.
2280+
* This method clears all Electron cache directories, IndexedDB, Local Storage, Session Storage,
2281+
* and other cached data that may become corrupted and persist even after normal resets.
2282+
*
2283+
* The operation targets platform-specific cache locations:
2284+
* - macOS: ~/Library/Caches/com.microsoft.VSCode*, ~/Library/Application Support/Code/*
2285+
* - Windows: %APPDATA%/Code/*, %LOCALAPPDATA%/Microsoft/vscode-cpptools
2286+
* - Linux: ~/.cache/Code*, ~/.config/Code/*
2287+
*
2288+
* After clearing caches, it also performs a regular state reset and offers to restart VS Code.
2289+
*
2290+
* @returns {Promise<void>} Resolves when the cache clearing operation is complete
2291+
*/
2292+
async hardResetElectronCache() {
2293+
const answer = await vscode.window.showInformationMessage(
2294+
t("common:confirmation.hard_reset_electron_cache"),
2295+
{ modal: true, detail: t("common:confirmation.hard_reset_electron_cache_detail") },
2296+
t("common:answers.yes"),
2297+
)
2298+
2299+
if (answer !== t("common:answers.yes")) {
2300+
return
2301+
}
2302+
2303+
const platform = process.platform
2304+
const homeDir = os.homedir()
2305+
const pathsToDelete: string[] = []
2306+
2307+
// Platform-specific cache paths
2308+
if (platform === "darwin") {
2309+
// macOS paths - includes all VS Code and Electron cache locations
2310+
pathsToDelete.push(
2311+
// VS Code caches
2312+
path.join(homeDir, "Library", "Caches", "com.microsoft.VSCode"),
2313+
path.join(homeDir, "Library", "Caches", "com.microsoft.VSCode.ShipIt"),
2314+
path.join(homeDir, "Library", "Caches", "com.microsoft.VSCodeInsiders"),
2315+
// Electron caches
2316+
path.join(homeDir, "Library", "Caches", "Electron"),
2317+
// Application Support (VS Code specific)
2318+
path.join(homeDir, "Library", "Application Support", "Code", "Cache"),
2319+
path.join(homeDir, "Library", "Application Support", "Code", "CachedData"),
2320+
path.join(homeDir, "Library", "Application Support", "Code", "Code Cache"),
2321+
path.join(homeDir, "Library", "Application Support", "Code", "GPUCache"),
2322+
path.join(homeDir, "Library", "Application Support", "Code", "Local Storage"),
2323+
path.join(homeDir, "Library", "Application Support", "Code", "Session Storage"),
2324+
path.join(homeDir, "Library", "Application Support", "Code", "IndexedDB"),
2325+
// VS Code Insiders
2326+
path.join(homeDir, "Library", "Application Support", "Code - Insiders", "Cache"),
2327+
path.join(homeDir, "Library", "Application Support", "Code - Insiders", "CachedData"),
2328+
path.join(homeDir, "Library", "Application Support", "Code - Insiders", "Code Cache"),
2329+
path.join(homeDir, "Library", "Application Support", "Code - Insiders", "GPUCache"),
2330+
path.join(homeDir, "Library", "Application Support", "Code - Insiders", "Local Storage"),
2331+
path.join(homeDir, "Library", "Application Support", "Code - Insiders", "Session Storage"),
2332+
path.join(homeDir, "Library", "Application Support", "Code - Insiders", "IndexedDB"),
2333+
)
2334+
} else if (platform === "win32") {
2335+
// Windows paths
2336+
const appData = process.env.APPDATA || path.join(homeDir, "AppData", "Roaming")
2337+
const localAppData = process.env.LOCALAPPDATA || path.join(homeDir, "AppData", "Local")
2338+
2339+
pathsToDelete.push(
2340+
// VS Code caches
2341+
path.join(localAppData, "Microsoft", "vscode-cpptools"),
2342+
path.join(appData, "Code", "Cache"),
2343+
path.join(appData, "Code", "CachedData"),
2344+
path.join(appData, "Code", "Code Cache"),
2345+
path.join(appData, "Code", "GPUCache"),
2346+
path.join(appData, "Code", "Local Storage"),
2347+
path.join(appData, "Code", "Session Storage"),
2348+
path.join(appData, "Code", "IndexedDB"),
2349+
// VS Code Insiders
2350+
path.join(appData, "Code - Insiders", "Cache"),
2351+
path.join(appData, "Code - Insiders", "CachedData"),
2352+
path.join(appData, "Code - Insiders", "Code Cache"),
2353+
path.join(appData, "Code - Insiders", "GPUCache"),
2354+
path.join(appData, "Code - Insiders", "Local Storage"),
2355+
path.join(appData, "Code - Insiders", "Session Storage"),
2356+
path.join(appData, "Code - Insiders", "IndexedDB"),
2357+
)
2358+
} else {
2359+
// Linux paths
2360+
const configDir = process.env.XDG_CONFIG_HOME || path.join(homeDir, ".config")
2361+
const cacheDir = process.env.XDG_CACHE_HOME || path.join(homeDir, ".cache")
2362+
2363+
pathsToDelete.push(
2364+
// VS Code caches
2365+
path.join(cacheDir, "Code"),
2366+
path.join(cacheDir, "Code - Insiders"),
2367+
path.join(configDir, "Code", "Cache"),
2368+
path.join(configDir, "Code", "CachedData"),
2369+
path.join(configDir, "Code", "Code Cache"),
2370+
path.join(configDir, "Code", "GPUCache"),
2371+
path.join(configDir, "Code", "Local Storage"),
2372+
path.join(configDir, "Code", "Session Storage"),
2373+
path.join(configDir, "Code", "IndexedDB"),
2374+
// VS Code Insiders
2375+
path.join(configDir, "Code - Insiders", "Cache"),
2376+
path.join(configDir, "Code - Insiders", "CachedData"),
2377+
path.join(configDir, "Code - Insiders", "Code Cache"),
2378+
path.join(configDir, "Code - Insiders", "GPUCache"),
2379+
path.join(configDir, "Code - Insiders", "Local Storage"),
2380+
path.join(configDir, "Code - Insiders", "Session Storage"),
2381+
path.join(configDir, "Code - Insiders", "IndexedDB"),
2382+
)
2383+
}
2384+
2385+
// Delete the cache directories
2386+
let deletedPaths: string[] = []
2387+
let failedPaths: string[] = []
2388+
2389+
for (const cachePath of pathsToDelete) {
2390+
try {
2391+
// Check if path exists before trying to delete
2392+
await fs.access(cachePath)
2393+
await fs.rm(cachePath, { recursive: true, force: true })
2394+
deletedPaths.push(cachePath)
2395+
this.log(`Deleted cache: ${cachePath}`)
2396+
} catch (error) {
2397+
// Path doesn't exist or couldn't be deleted
2398+
if (error.code !== "ENOENT") {
2399+
failedPaths.push(cachePath)
2400+
this.log(`Failed to delete cache: ${cachePath} - ${error.message}`)
2401+
}
2402+
}
2403+
}
2404+
2405+
// Also perform the regular reset
2406+
await this.contextProxy.resetAllState()
2407+
await this.providerSettingsManager.resetAllConfigs()
2408+
await this.customModesManager.resetCustomModes()
2409+
await this.removeClineFromStack()
2410+
await this.postStateToWebview()
2411+
2412+
// Show result message
2413+
if (deletedPaths.length > 0) {
2414+
const message = t("common:confirmation.hard_reset_complete", {
2415+
count: deletedPaths.length,
2416+
failed:
2417+
failedPaths.length > 0
2418+
? t("common:confirmation.hard_reset_some_failed", { count: failedPaths.length })
2419+
: "",
2420+
})
2421+
2422+
vscode.window
2423+
.showInformationMessage(message, { modal: false }, t("common:answers.restart_vscode"))
2424+
.then((selection) => {
2425+
if (selection === t("common:answers.restart_vscode")) {
2426+
vscode.commands.executeCommand("workbench.action.reloadWindow")
2427+
}
2428+
})
2429+
} else {
2430+
vscode.window.showWarningMessage(t("common:confirmation.hard_reset_no_caches_found"))
2431+
}
2432+
2433+
await this.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
2434+
}
2435+
22782436
// logging
22792437

22802438
public log(message: string) {

src/core/webview/webviewMessageHandler.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,9 @@ export const webviewMessageHandler = async (
749749
case "resetState":
750750
await provider.resetState()
751751
break
752+
case "hardResetElectronCache":
753+
await provider.hardResetElectronCache()
754+
break
752755
case "flushRouterModels":
753756
const routerNameFlush: RouterName = toRouterName(message.text)
754757
await flushModels(routerNameFlush)

src/i18n/locales/en/common.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
},
1717
"confirmation": {
1818
"reset_state": "Are you sure you want to reset all state and secret storage in the extension? This cannot be undone.",
19+
"hard_reset_electron_cache": "Are you sure you want to perform a hard reset? This will clear all Electron caches and VS Code data.",
20+
"hard_reset_electron_cache_detail": "This action will:\n• Clear all VS Code caches\n• Clear all Electron caches\n• Clear IndexedDB, Local Storage, and Session Storage\n• Reset all extension settings\n\nYou will need to restart VS Code after this operation.",
21+
"hard_reset_complete": "Hard reset completed. {{count}} cache directories were cleared.{{failed}}",
22+
"hard_reset_some_failed": " ({{count}} directories could not be deleted)",
23+
"hard_reset_no_caches_found": "No cache directories were found to clear.",
1924
"delete_config_profile": "Are you sure you want to delete this configuration profile?",
2025
"delete_custom_mode_with_rules": "Are you sure you want to delete this {scope} mode?\n\nThis will also delete the associated rules folder at:\n{rulesFolderPath}"
2126
},
@@ -148,7 +153,8 @@
148153
"yes": "Yes",
149154
"no": "No",
150155
"remove": "Remove",
151-
"keep": "Keep"
156+
"keep": "Keep",
157+
"restart_vscode": "Restart VS Code"
152158
},
153159
"buttons": {
154160
"save": "Save",

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export interface WebviewMessage {
6464
| "importSettings"
6565
| "exportSettings"
6666
| "resetState"
67+
| "hardResetElectronCache"
6768
| "flushRouterModels"
6869
| "requestRouterModels"
6970
| "requestOpenAiModels"

tmp/pr-8287-Roo-Code

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 88a473b017af37091c85ce3056e444e856f80d6e

tmp/pr-8412

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 1339c7cc8bad17f95532117f36049d84a9ee8266

webview-ui/src/components/settings/About.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ export const About = ({ telemetrySetting, setTelemetrySetting, className, ...pro
8484
<TriangleAlert className="p-0.5" />
8585
{t("settings:footer.settings.reset")}
8686
</Button>
87+
<Button
88+
variant="destructive"
89+
onClick={() => vscode.postMessage({ type: "hardResetElectronCache" })}
90+
className="w-32">
91+
<TriangleAlert className="p-0.5" />
92+
{t("settings:footer.settings.hardReset")}
93+
</Button>
8794
</div>
8895
</Section>
8996
</div>

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,8 @@
810810
"settings": {
811811
"import": "Import",
812812
"export": "Export",
813-
"reset": "Reset"
813+
"reset": "Reset",
814+
"hardReset": "Hard Reset"
814815
}
815816
},
816817
"thinkingBudget": {

0 commit comments

Comments
 (0)