Skip to content

Commit 826a714

Browse files
committed
feat: add auto-cleanup for task history
- Add configuration settings for auto-cleanup (enabled, maxCount, maxDiskSpaceMB, maxAgeDays) - Create TaskHistoryCleanupService to handle cleanup logic - Implement cleanup by count, disk space, and age thresholds - Integrate cleanup service into ClineProvider with idle-time execution - Add comprehensive tests for cleanup service - Cleanup runs automatically when thresholds are exceeded - Protects tasks from current workspace from deletion - Default settings: disabled, 100 tasks max, 1GB disk space, 7 days age Fixes #8172
1 parent 513fce3 commit 826a714

File tree

5 files changed

+745
-0
lines changed

5 files changed

+745
-0
lines changed

packages/types/src/global-settings.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ export const globalSettingsSchema = z.object({
151151
hasOpenedModeSelector: z.boolean().optional(),
152152
lastModeExportPath: z.string().optional(),
153153
lastModeImportPath: z.string().optional(),
154+
155+
// Task history auto-cleanup settings
156+
taskHistoryAutoCleanupEnabled: z.boolean().optional(),
157+
taskHistoryMaxCount: z.number().min(0).optional(),
158+
taskHistoryMaxDiskSpaceMB: z.number().min(0).optional(),
159+
taskHistoryMaxAgeDays: z.number().min(0).optional(),
154160
})
155161

156162
export type GlobalSettings = z.infer<typeof globalSettingsSchema>

src/core/webview/ClineProvider.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ import { ShadowCheckpointService } from "../../services/checkpoints/ShadowCheckp
6868
import { CodeIndexManager } from "../../services/code-index/manager"
6969
import type { IndexProgressUpdate } from "../../services/code-index/interfaces/manager"
7070
import { MdmService } from "../../services/mdm/MdmService"
71+
import {
72+
TaskHistoryCleanupService,
73+
type TaskHistoryCleanupConfig,
74+
} from "../../services/task-cleanup/TaskHistoryCleanupService"
7175

7276
import { fileExistsAtPath } from "../../utils/fs"
7377
import { setTtsEnabled, setTtsSpeed } from "../../utils/tts"
@@ -138,6 +142,7 @@ export class ClineProvider
138142
private recentTasksCache?: string[]
139143
private pendingOperations: Map<string, PendingEditOperation> = new Map()
140144
private static readonly PENDING_OPERATION_TIMEOUT_MS = 30000 // 30 seconds
145+
private taskHistoryCleanupService?: TaskHistoryCleanupService
141146

142147
public isViewLaunched = false
143148
public settingsImportedAt?: number
@@ -253,6 +258,12 @@ export class ClineProvider
253258
} else {
254259
this.log("CloudService not ready, deferring cloud profile sync")
255260
}
261+
262+
// Initialize task history cleanup service
263+
this.taskHistoryCleanupService = new TaskHistoryCleanupService(
264+
this.context.globalStorageUri.fsPath,
265+
this.log.bind(this),
266+
)
256267
}
257268

258269
/**
@@ -1783,6 +1794,10 @@ export class ClineProvider
17831794
openRouterImageGenerationSelectedModel,
17841795
openRouterUseMiddleOutTransform,
17851796
featureRoomoteControlEnabled,
1797+
taskHistoryAutoCleanupEnabled,
1798+
taskHistoryMaxCount,
1799+
taskHistoryMaxDiskSpaceMB,
1800+
taskHistoryMaxAgeDays,
17861801
} = await this.getState()
17871802

17881803
const telemetryKey = process.env.POSTHOG_API_KEY
@@ -1920,6 +1935,10 @@ export class ClineProvider
19201935
openRouterImageGenerationSelectedModel,
19211936
openRouterUseMiddleOutTransform,
19221937
featureRoomoteControlEnabled,
1938+
taskHistoryAutoCleanupEnabled: taskHistoryAutoCleanupEnabled ?? false,
1939+
taskHistoryMaxCount: taskHistoryMaxCount ?? 100,
1940+
taskHistoryMaxDiskSpaceMB: taskHistoryMaxDiskSpaceMB ?? 1000,
1941+
taskHistoryMaxAgeDays: taskHistoryMaxAgeDays ?? 7,
19231942
}
19241943
}
19251944

@@ -2166,9 +2185,75 @@ export class ClineProvider
21662185
await this.updateGlobalState("taskHistory", history)
21672186
this.recentTasksCache = undefined
21682187

2188+
// Trigger auto-cleanup after updating task history
2189+
void this.triggerAutoCleanup()
2190+
21692191
return history
21702192
}
21712193

2194+
/**
2195+
* Triggers automatic cleanup of task history if configured
2196+
*/
2197+
private async triggerAutoCleanup(): Promise<void> {
2198+
if (!this.taskHistoryCleanupService) {
2199+
return
2200+
}
2201+
2202+
try {
2203+
const {
2204+
taskHistoryAutoCleanupEnabled,
2205+
taskHistoryMaxCount,
2206+
taskHistoryMaxDiskSpaceMB,
2207+
taskHistoryMaxAgeDays,
2208+
taskHistory,
2209+
} = await this.getState()
2210+
2211+
const config: TaskHistoryCleanupConfig = {
2212+
enabled: taskHistoryAutoCleanupEnabled ?? false,
2213+
maxCount: taskHistoryMaxCount,
2214+
maxDiskSpaceMB: taskHistoryMaxDiskSpaceMB,
2215+
maxAgeDays: taskHistoryMaxAgeDays,
2216+
}
2217+
2218+
// Check if cleanup should be triggered
2219+
if (this.taskHistoryCleanupService.shouldTriggerCleanup(taskHistory ?? [], config)) {
2220+
// Run cleanup in the background during idle time
2221+
setTimeout(async () => {
2222+
try {
2223+
const result = await this.taskHistoryCleanupService!.performCleanup(
2224+
taskHistory ?? [],
2225+
config,
2226+
async (updatedHistory) => {
2227+
await this.updateGlobalState("taskHistory", updatedHistory)
2228+
this.recentTasksCache = undefined
2229+
await this.postStateToWebview()
2230+
},
2231+
this.deleteTaskWithId.bind(this),
2232+
)
2233+
2234+
if (result.deletedCount > 0) {
2235+
this.log(
2236+
`[ClineProvider] Auto-cleanup completed: deleted ${result.deletedCount} tasks, freed ${result.freedSpaceMB.toFixed(2)}MB`,
2237+
)
2238+
}
2239+
2240+
if (result.errors.length > 0) {
2241+
this.log(`[ClineProvider] Auto-cleanup errors: ${result.errors.join(", ")}`)
2242+
}
2243+
} catch (error) {
2244+
this.log(
2245+
`[ClineProvider] Auto-cleanup failed: ${error instanceof Error ? error.message : String(error)}`,
2246+
)
2247+
}
2248+
}, 5000) // Run after 5 seconds to avoid blocking current operations
2249+
}
2250+
} catch (error) {
2251+
this.log(
2252+
`[ClineProvider] Failed to trigger auto-cleanup: ${error instanceof Error ? error.message : String(error)}`,
2253+
)
2254+
}
2255+
}
2256+
21722257
// ContextProxy
21732258

21742259
// @deprecated - Use `ContextProxy#setValue` instead.

0 commit comments

Comments
 (0)