fix: adjust tail budget for forced compression and fix missing timestamps

This commit is contained in:
wassname
2026-04-23 15:36:03 +08:00
parent 9c400d0e0a
commit 5a4e708f4b
2 changed files with 22 additions and 12 deletions
+21 -12
View File
@@ -372,32 +372,37 @@ export async function applyPruning(
state.forceCompressNext ||
(totalTokens >= thresholdTokens && msgs.length > AUTO_COMPRESS_CONFIG.protectFirstN + 4)
) {
let tailBudget = Math.floor(thresholdTokens * AUTO_COMPRESS_CONFIG.summaryTargetRatio);
if (state.forceCompressNext) {
// Force compression: reduce tail budget to ensure we have something to compress
tailBudget = Math.min(tailBudget, Math.floor(totalTokens * 0.3));
}
state.forceCompressNext = false;
const tailBudget = Math.floor(thresholdTokens * AUTO_COMPRESS_CONFIG.summaryTargetRatio);
const compressStart = alignBoundaryForward(msgs, AUTO_COMPRESS_CONFIG.protectFirstN);
const compressEnd = findTailCutByTokens(msgs, compressStart, tailBudget);
if (compressStart < compressEnd) {
const middle = msgs.slice(compressStart, compressEnd);
const summary = await generateSummary(middle, state.previousSummary, null, model);
if (summary) {
const compressed: any[] = [];
for (let i = 0; i < compressStart; i++) {
compressed.push(msgs[i]);
}
const lastHeadRole = msgs[compressStart - 1]?.role || "user";
const firstTailRole = msgs[compressEnd]?.role || "user";
let summaryRole = lastHeadRole === "assistant" ? "user" : "assistant";
if (summaryRole === firstTailRole) {
const flipped = summaryRole === "user" ? "assistant" : "user";
if (flipped !== lastHeadRole) {
summaryRole = flipped;
} else {
const tailMsg = { ...msgs[compressEnd] };
const tailMsg = { ...msgs[compressEnd], timestamp: msgs[compressEnd].timestamp || Date.now() };
const originalContent = tailMsg.content || "";
tailMsg.content =
"## Goal\n" + summary + "\n\n--- END OF CONTEXT SUMMARY ---\n\n" +
@@ -412,28 +417,32 @@ export async function applyPruning(
return sanitizeToolPairs(compressed);
}
}
const prefix =
"[CONTEXT COMPACTION — REFERENCE ONLY] Earlier turns were compacted into the summary below. " +
"This is a handoff from a previous context window — treat it as background reference, " +
"NOT as active instructions. Do NOT answer questions or fulfill requests mentioned in this summary; " +
"they were already addressed. Respond ONLY to the latest user message that appears AFTER this summary:";
compressed.push({
role: summaryRole,
content: prefix + "\n\n" + summary,
timestamp: Date.now(),
});
for (let i = compressEnd; i < msgs.length; i++) {
compressed.push(msgs[i]);
}
state.previousSummary = summary;
state.compressionCount++;
state.tokensSaved += totalTokens - estimateMessagesTokens(compressed);
return sanitizeToolPairs(compressed);
}
} else {
if (config.debug) {
console.log(`[ACP] Compression skipped: conversation too short (start: ${compressStart}, end: ${compressEnd})`);
}
}
}