* Interactive cache-clear flow. Presents one combined picker showing * cleanable caches across every installed harness with their current * sizes; the user selects which to clear.
()
| 93 | * sizes; the user selects which to clear. |
| 94 | */ |
| 95 | async function runClear(): Promise<number> { |
| 96 | intro("Magic Context — Clear caches"); |
| 97 | |
| 98 | const installed = getInstalledAdapters(); |
| 99 | if (installed.length === 0) { |
| 100 | log.warn("No installed harnesses detected. Nothing to clear."); |
| 101 | outro("Done."); |
| 102 | return 0; |
| 103 | } |
| 104 | |
| 105 | const items: { adapter: HarnessAdapter; path: string; sizeBytes: number }[] = []; |
| 106 | for (const adapter of installed) { |
| 107 | const cache = adapter.getPluginCacheInfo(); |
| 108 | if (cache.path && cache.exists) { |
| 109 | items.push({ adapter, path: cache.path, sizeBytes: cache.sizeBytes }); |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | if (items.length === 0) { |
| 114 | log.info("No clearable plugin caches found across installed harnesses."); |
| 115 | outro("Done."); |
| 116 | return 0; |
| 117 | } |
| 118 | |
| 119 | const picks = await selectMany( |
| 120 | "Select caches to clear:", |
| 121 | items.map((item, idx) => ({ |
| 122 | label: `${item.adapter.displayName}: ${formatSize(item.sizeBytes)} — ${item.path}`, |
| 123 | value: String(idx), |
| 124 | })), |
| 125 | ); |
| 126 | |
| 127 | if (picks.length === 0) { |
| 128 | log.info("Nothing selected. Done."); |
| 129 | outro("Done."); |
| 130 | return 0; |
| 131 | } |
| 132 | |
| 133 | const confirmed = await confirm( |
| 134 | `Delete ${picks.length} cache director${picks.length === 1 ? "y" : "ies"}? This is irreversible.`, |
| 135 | false, |
| 136 | ); |
| 137 | if (!confirmed) { |
| 138 | log.info("Cancelled."); |
| 139 | outro("Done."); |
| 140 | return 0; |
| 141 | } |
| 142 | |
| 143 | let failed = 0; |
| 144 | for (const idxStr of picks) { |
| 145 | const idx = Number.parseInt(idxStr, 10); |
| 146 | const item = items[idx]; |
| 147 | if (!item) continue; |
| 148 | const s = spinner(); |
| 149 | s.start(`Clearing ${item.path}`); |
| 150 | try { |
| 151 | if (existsSync(item.path)) { |
| 152 | rmSync(item.path, { recursive: true, force: true }); |
no test coverage detected