fix: wire deduplication into compaction recovery for prompt-too-long errors (#96)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-02-07 19:18:12 +09:00
parent 42843013e2
commit c9af4f33e8
4 changed files with 320 additions and 0 deletions
@@ -0,0 +1,71 @@
import type { ParsedTokenLimitError } from "./types"
import type { ExperimentalConfig } from "../../config"
import type { DeduplicationConfig } from "./pruning-deduplication"
import type { PruningState } from "./pruning-types"
import { executeDeduplication } from "./pruning-deduplication"
import { truncateToolOutputsByCallId } from "./pruning-tool-output-truncation"
import { log } from "../../shared/logger"
function createPruningState(): PruningState {
return {
toolIdsToPrune: new Set<string>(),
currentTurn: 0,
fileOperations: new Map(),
toolSignatures: new Map(),
erroredTools: new Map(),
}
}
function isPromptTooLongError(parsed: ParsedTokenLimitError): boolean {
return !parsed.errorType.toLowerCase().includes("non-empty content")
}
function getDeduplicationPlan(
experimental?: ExperimentalConfig,
): { config: DeduplicationConfig; protectedTools: Set<string> } | null {
const pruningConfig = experimental?.dynamic_context_pruning
if (!pruningConfig?.enabled) return null
const deduplicationEnabled = pruningConfig.strategies?.deduplication?.enabled
if (deduplicationEnabled === false) return null
const protectedTools = new Set(pruningConfig.protected_tools ?? [])
return {
config: {
enabled: true,
protectedTools: pruningConfig.protected_tools ?? [],
},
protectedTools,
}
}
export async function attemptDeduplicationRecovery(
sessionID: string,
parsed: ParsedTokenLimitError,
experimental: ExperimentalConfig | undefined,
): Promise<void> {
if (!isPromptTooLongError(parsed)) return
const plan = getDeduplicationPlan(experimental)
if (!plan) return
const pruningState = createPruningState()
const prunedCount = executeDeduplication(
sessionID,
pruningState,
plan.config,
plan.protectedTools,
)
const { truncatedCount } = truncateToolOutputsByCallId(
sessionID,
pruningState.toolIdsToPrune,
)
if (prunedCount > 0 || truncatedCount > 0) {
log("[auto-compact] deduplication recovery applied", {
sessionID,
prunedCount,
truncatedCount,
})
}
}