diff --git a/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts b/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts
index d23eab923..0642a5fb9 100644
--- a/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts
+++ b/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts
@@ -1,10 +1,9 @@
///
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test"
+import { executeCompact } from "./executor"
import type { AutoCompactState } from "./types"
-
-type ExecuteCompact = typeof import("./executor").executeCompact
-type StorageModule = typeof import("./storage")
-type MessagesReaderModule = typeof import("../session-recovery/storage/messages-reader")
+import * as recoveryStrategy from "./recovery-strategy"
+import * as messagesReader from "../session-recovery/storage/messages-reader"
type TimerCallback = (...args: any[]) => void
@@ -78,9 +77,6 @@ function createFakeTimeouts(): FakeTimeouts {
}
describe("executeCompact lock management", () => {
- let executeCompact: ExecuteCompact
- let storageModule: StorageModule
- let messagesReaderModule: MessagesReaderModule
let autoCompactState: AutoCompactState
let mockClient: any
let fakeTimeouts: FakeTimeouts
@@ -88,13 +84,7 @@ describe("executeCompact lock management", () => {
const directory = "/test/dir"
const msg = { providerID: "anthropic", modelID: "claude-opus-4-6" }
- beforeEach(async () => {
- mock.restore()
- const executorModule = await import("./executor")
- executeCompact = executorModule.executeCompact
- storageModule = await import("./storage")
- messagesReaderModule = await import("../session-recovery/storage/messages-reader")
-
+ beforeEach(() => {
// given: Fresh state for each test
autoCompactState = {
pendingCompact: new Set(),
@@ -121,7 +111,6 @@ describe("executeCompact lock management", () => {
})
afterEach(() => {
- mock.restore()
fakeTimeouts.restore()
})
@@ -182,7 +171,7 @@ describe("executeCompact lock management", () => {
test("clears lock when fixEmptyMessages path executes", async () => {
//#given - Empty content error scenario with no messages in storage
- const readMessagesSpy = spyOn(messagesReaderModule, "readMessages").mockReturnValue([])
+ const readMessagesSpy = spyOn(messagesReader, "readMessages").mockReturnValue([])
autoCompactState.errorDataBySession.set(sessionID, {
errorType: "non-empty content required",
messageIndex: 0,
@@ -200,7 +189,7 @@ describe("executeCompact lock management", () => {
test("clears lock when truncation is sufficient", async () => {
//#given - Aggressive truncation scenario with no messages in storage
- const readMessagesSpy = spyOn(messagesReaderModule, "readMessages").mockReturnValue([])
+ const readMessagesSpy = spyOn(messagesReader, "readMessages").mockReturnValue([])
autoCompactState.errorDataBySession.set(sessionID, {
errorType: "token_limit",
currentTokens: 250000,
@@ -325,18 +314,13 @@ describe("executeCompact lock management", () => {
maxTokens: 200000,
})
- const truncateSpy = spyOn(storageModule, "truncateUntilTargetTokens").mockResolvedValue({
- success: true,
- sufficient: false,
- truncatedCount: 3,
- totalBytesRemoved: 10000,
- targetBytesToRemove: 50000,
- truncatedTools: [
- { toolName: "Grep", originalSize: 5000 },
- { toolName: "Read", originalSize: 3000 },
- { toolName: "Bash", originalSize: 2000 },
- ],
- })
+ const truncateSpy = spyOn(
+ recoveryStrategy,
+ "runAggressiveTruncationStrategy",
+ ).mockImplementation(async (params) => ({
+ handled: false,
+ nextTruncateAttempt: params.truncateAttempt + 1,
+ }))
// when: Execute compaction
await executeCompact(sessionID, msg, autoCompactState, mockClient, directory)
@@ -366,16 +350,24 @@ describe("executeCompact lock management", () => {
maxTokens: 200000,
})
- const truncateSpy = spyOn(storageModule, "truncateUntilTargetTokens").mockResolvedValue({
- success: true,
- sufficient: true,
- truncatedCount: 5,
- totalBytesRemoved: 60000,
- targetBytesToRemove: 50000,
- truncatedTools: [
- { toolName: "Grep", originalSize: 30000 },
- { toolName: "Read", originalSize: 30000 },
- ],
+ const truncateSpy = spyOn(
+ recoveryStrategy,
+ "runAggressiveTruncationStrategy",
+ ).mockImplementation(async (params) => {
+ setTimeout(() => {
+ void params.client.session
+ .promptAsync({
+ path: { id: params.sessionID },
+ body: { auto: true } as never,
+ query: { directory: params.directory },
+ })
+ .catch(() => {})
+ }, 500)
+
+ return {
+ handled: true,
+ nextTruncateAttempt: params.truncateAttempt + 1,
+ }
})
// when: Execute compaction