Compare commits

...
Author SHA1 Message Date
Eve Killaby c132f35977 feat(hooks): Implement PreCompact hook 2025-10-15 13:42:44 -07:00
3 changed files with 45 additions and 2 deletions
+8 -1
View File
@@ -22,7 +22,7 @@ message HookInput {
// TaskResumeData task_resume = 14;
// TaskCancelData task_cancel = 15;
// TaskCompleteData task_complete = 16;
// PreCompactData pre_compact = 17;
PreCompactData pre_compact = 17;
}
}
@@ -47,3 +47,10 @@ message PostToolUseData {
bool success = 4;
int64 execution_time_ms = 5;
}
// Data for PreCompact hook
message PreCompactData {
int64 context_size = 1;
int32 messages_to_compact = 2;
string compaction_strategy = 3;
}
+4 -1
View File
@@ -3,7 +3,7 @@ import fs from "fs/promises"
import path from "path"
import { version as clineVersion } from "../../../package.json"
import { getDistinctId } from "../../services/logging/distinctId"
import { HookInput, HookOutput, PostToolUseData, PreToolUseData } from "../../shared/proto/cline/hooks"
import { HookInput, HookOutput, PostToolUseData, PreCompactData, PreToolUseData } from "../../shared/proto/cline/hooks"
import { getAllHooksDirs } from "../storage/disk"
import { StateManager } from "../storage/StateManager"
@@ -20,6 +20,9 @@ export interface Hooks {
PostToolUse: {
postToolUse: PostToolUseData
}
PreCompact: {
preCompact: PreCompactData
}
}
// The names of all supported hooks. Hooks[N] is the type of data the hook takes as input.
+33
View File
@@ -45,6 +45,7 @@ import { TerminalManager } from "@integrations/terminal/TerminalManager"
import { TerminalProcessResultPromise } from "@integrations/terminal/TerminalProcess"
import { BrowserSession } from "@services/browser/BrowserSession"
import { UrlContentFetcher } from "@services/browser/UrlContentFetcher"
import { featureFlagsService } from "@services/feature-flags"
import { listFiles } from "@services/glob/list-files"
import { Logger } from "@services/logging/Logger"
import { McpHub } from "@services/mcp/McpHub"
@@ -2089,6 +2090,38 @@ export class Task {
// approaches such as storing this.taskState.currentlySummarizing on disk in the clineMessages. This was intentionally not done
// for now to prevent additional disk from needing to be used.
// The worse case scenario is effectively cline summarizing a summary, which is bad UX, but doesn't break other logic.
// Run PreCompact hook if compaction is about to occur
if (shouldCompact) {
const hooksEnabled =
featureFlagsService.getHooksEnabled() && this.stateManager.getGlobalSettingsKey("hooksEnabled")
if (hooksEnabled) {
try {
const { HookFactory } = await import("../hooks/hook-factory")
const hookFactory = new HookFactory()
const preCompactHook = await hookFactory.create("PreCompact")
const apiHistory = this.messageStateHandler.getApiConversationHistory()
const activeMessageCount = this.taskState.conversationHistoryDeletedRange
? apiHistory.length - this.taskState.conversationHistoryDeletedRange[1] - 1
: apiHistory.length
await preCompactHook.run({
taskId: this.taskId,
preCompact: {
contextSize: apiHistory.length,
messagesToCompact: activeMessageCount,
compactionStrategy: "auto",
},
})
// PreCompact is informational only, no need to check shouldContinue
} catch (hookError) {
console.error("PreCompact hook failed:", hookError)
// Non-fatal: continue with compaction
}
}
}
if (shouldCompact && this.taskState.conversationHistoryDeletedRange) {
const apiHistory = this.messageStateHandler.getApiConversationHistory()
const activeMessageCount = apiHistory.length - this.taskState.conversationHistoryDeletedRange[1] - 1