Files
oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/aggressive-truncation-strategy.ts
T
YeonGyu-Kim 5c37dc8210 feat: wire context-window-recovery callers to async SDK/HTTP variants on SQLite
- empty-content-recovery: isSqliteBackend() branch delegating to extracted
  empty-content-recovery-sdk.ts with SDK message scanning
- message-builder: sanitizeEmptyMessagesBeforeSummarize now async with SDK path
  using replaceEmptyTextPartsAsync/injectTextPartAsync
- target-token-truncation: truncateUntilTargetTokens now async with SDK path
  using findToolResultsBySizeFromSDK/truncateToolResultAsync
- aggressive-truncation-strategy: passes client to truncateUntilTargetTokens
- summarize-retry-strategy: await sanitizeEmptyMessagesBeforeSummarize
- client.ts: derive Client from PluginInput['client'] instead of manual defs
- executor.test.ts: .mockReturnValue() → .mockResolvedValue() for async fns
- storage.test.ts: add await for async truncateUntilTargetTokens
2026-02-16 16:13:40 +09:00

83 lines
2.8 KiB
TypeScript

import type { AutoCompactState } from "./types"
import { TRUNCATE_CONFIG } from "./types"
import { truncateUntilTargetTokens } from "./storage"
import type { Client } from "./client"
import { clearSessionState } from "./state"
import { formatBytes } from "./message-builder"
import { log } from "../../shared/logger"
export async function runAggressiveTruncationStrategy(params: {
sessionID: string
autoCompactState: AutoCompactState
client: Client
directory: string
truncateAttempt: number
currentTokens: number
maxTokens: number
}): Promise<{ handled: boolean; nextTruncateAttempt: number }> {
if (params.truncateAttempt >= TRUNCATE_CONFIG.maxTruncateAttempts) {
return { handled: false, nextTruncateAttempt: params.truncateAttempt }
}
log("[auto-compact] PHASE 2: aggressive truncation triggered", {
currentTokens: params.currentTokens,
maxTokens: params.maxTokens,
targetRatio: TRUNCATE_CONFIG.targetTokenRatio,
})
const aggressiveResult = await truncateUntilTargetTokens(
params.sessionID,
params.currentTokens,
params.maxTokens,
TRUNCATE_CONFIG.targetTokenRatio,
TRUNCATE_CONFIG.charsPerToken,
params.client,
)
if (aggressiveResult.truncatedCount <= 0) {
return { handled: false, nextTruncateAttempt: params.truncateAttempt }
}
const nextTruncateAttempt = params.truncateAttempt + aggressiveResult.truncatedCount
const toolNames = aggressiveResult.truncatedTools.map((t) => t.toolName).join(", ")
const statusMsg = aggressiveResult.sufficient
? `Truncated ${aggressiveResult.truncatedCount} outputs (${formatBytes(aggressiveResult.totalBytesRemoved)})`
: `Truncated ${aggressiveResult.truncatedCount} outputs (${formatBytes(aggressiveResult.totalBytesRemoved)}) - continuing to summarize...`
await params.client.tui
.showToast({
body: {
title: aggressiveResult.sufficient ? "Truncation Complete" : "Partial Truncation",
message: `${statusMsg}: ${toolNames}`,
variant: aggressiveResult.sufficient ? "success" : "warning",
duration: 4000,
},
})
.catch(() => {})
log("[auto-compact] aggressive truncation completed", aggressiveResult)
if (aggressiveResult.sufficient) {
clearSessionState(params.autoCompactState, params.sessionID)
setTimeout(async () => {
try {
await params.client.session.prompt_async({
path: { id: params.sessionID },
body: { auto: true } as never,
query: { directory: params.directory },
})
} catch {}
}, 500)
return { handled: true, nextTruncateAttempt }
}
log("[auto-compact] truncation insufficient, falling through to summarize", {
sessionID: params.sessionID,
truncatedCount: aggressiveResult.truncatedCount,
sufficient: aggressiveResult.sufficient,
})
return { handled: false, nextTruncateAttempt }
}