mirror of
https://github.com/wassname/pi-auto-compressor.git
synced 2026-06-27 15:16:08 +08:00
fix: adjust tail budget for forced compression and fix missing timestamps
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mariozechner/pi-coding-agent": "*",
|
"@mariozechner/pi-coding-agent": "*",
|
||||||
|
"@mariozechner/pi-ai": "*",
|
||||||
"@mariozechner/pi-tui": "*",
|
"@mariozechner/pi-tui": "*",
|
||||||
"@sinclair/typebox": "*"
|
"@sinclair/typebox": "*"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -372,32 +372,37 @@ export async function applyPruning(
|
|||||||
state.forceCompressNext ||
|
state.forceCompressNext ||
|
||||||
(totalTokens >= thresholdTokens && msgs.length > AUTO_COMPRESS_CONFIG.protectFirstN + 4)
|
(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;
|
state.forceCompressNext = false;
|
||||||
const tailBudget = Math.floor(thresholdTokens * AUTO_COMPRESS_CONFIG.summaryTargetRatio);
|
|
||||||
const compressStart = alignBoundaryForward(msgs, AUTO_COMPRESS_CONFIG.protectFirstN);
|
const compressStart = alignBoundaryForward(msgs, AUTO_COMPRESS_CONFIG.protectFirstN);
|
||||||
const compressEnd = findTailCutByTokens(msgs, compressStart, tailBudget);
|
const compressEnd = findTailCutByTokens(msgs, compressStart, tailBudget);
|
||||||
|
|
||||||
if (compressStart < compressEnd) {
|
if (compressStart < compressEnd) {
|
||||||
const middle = msgs.slice(compressStart, compressEnd);
|
const middle = msgs.slice(compressStart, compressEnd);
|
||||||
const summary = await generateSummary(middle, state.previousSummary, null, model);
|
const summary = await generateSummary(middle, state.previousSummary, null, model);
|
||||||
|
|
||||||
if (summary) {
|
if (summary) {
|
||||||
const compressed: any[] = [];
|
const compressed: any[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < compressStart; i++) {
|
for (let i = 0; i < compressStart; i++) {
|
||||||
compressed.push(msgs[i]);
|
compressed.push(msgs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastHeadRole = msgs[compressStart - 1]?.role || "user";
|
const lastHeadRole = msgs[compressStart - 1]?.role || "user";
|
||||||
const firstTailRole = msgs[compressEnd]?.role || "user";
|
const firstTailRole = msgs[compressEnd]?.role || "user";
|
||||||
|
|
||||||
let summaryRole = lastHeadRole === "assistant" ? "user" : "assistant";
|
let summaryRole = lastHeadRole === "assistant" ? "user" : "assistant";
|
||||||
if (summaryRole === firstTailRole) {
|
if (summaryRole === firstTailRole) {
|
||||||
const flipped = summaryRole === "user" ? "assistant" : "user";
|
const flipped = summaryRole === "user" ? "assistant" : "user";
|
||||||
if (flipped !== lastHeadRole) {
|
if (flipped !== lastHeadRole) {
|
||||||
summaryRole = flipped;
|
summaryRole = flipped;
|
||||||
} else {
|
} else {
|
||||||
const tailMsg = { ...msgs[compressEnd] };
|
const tailMsg = { ...msgs[compressEnd], timestamp: msgs[compressEnd].timestamp || Date.now() };
|
||||||
const originalContent = tailMsg.content || "";
|
const originalContent = tailMsg.content || "";
|
||||||
tailMsg.content =
|
tailMsg.content =
|
||||||
"## Goal\n" + summary + "\n\n--- END OF CONTEXT SUMMARY ---\n\n" +
|
"## Goal\n" + summary + "\n\n--- END OF CONTEXT SUMMARY ---\n\n" +
|
||||||
@@ -412,28 +417,32 @@ export async function applyPruning(
|
|||||||
return sanitizeToolPairs(compressed);
|
return sanitizeToolPairs(compressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const prefix =
|
const prefix =
|
||||||
"[CONTEXT COMPACTION — REFERENCE ONLY] Earlier turns were compacted into the summary below. " +
|
"[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, " +
|
"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; " +
|
"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:";
|
"they were already addressed. Respond ONLY to the latest user message that appears AFTER this summary:";
|
||||||
|
|
||||||
compressed.push({
|
compressed.push({
|
||||||
role: summaryRole,
|
role: summaryRole,
|
||||||
content: prefix + "\n\n" + summary,
|
content: prefix + "\n\n" + summary,
|
||||||
|
timestamp: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = compressEnd; i < msgs.length; i++) {
|
for (let i = compressEnd; i < msgs.length; i++) {
|
||||||
compressed.push(msgs[i]);
|
compressed.push(msgs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.previousSummary = summary;
|
state.previousSummary = summary;
|
||||||
state.compressionCount++;
|
state.compressionCount++;
|
||||||
state.tokensSaved += totalTokens - estimateMessagesTokens(compressed);
|
state.tokensSaved += totalTokens - estimateMessagesTokens(compressed);
|
||||||
|
|
||||||
return sanitizeToolPairs(compressed);
|
return sanitizeToolPairs(compressed);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (config.debug) {
|
||||||
|
console.log(`[ACP] Compression skipped: conversation too short (start: ${compressStart}, end: ${compressEnd})`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user