mirror of
https://github.com/wassname/pi-auto-compressor.git
synced 2026-06-27 15:16:08 +08:00
fix: ensure forced compression works on next turn and improve stats UI
This commit is contained in:
@@ -89,7 +89,7 @@ export default function (pi: ExtensionAPI) {
|
||||
const argsStr = args.trim().toLowerCase();
|
||||
if (argsStr === "compress") {
|
||||
state.forceCompressNext = true;
|
||||
ctx.ui.notify("Manual compression triggered. It will run in the background on the next agent turn.", "info");
|
||||
ctx.ui.notify("Manual compression scheduled. It will run when you send your next message.", "info");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,16 +110,17 @@ export default function (pi: ExtensionAPI) {
|
||||
}
|
||||
|
||||
const lines = [
|
||||
"Auto-Compressor (Hermes) Stats:",
|
||||
` Total Compressions: ${state.compressionCount}`,
|
||||
` Tokens Saved (Compaction): ~${state.tokensSaved.toLocaleString()}`,
|
||||
` Tokens Saved (Tool Pruning): ~${prunedToolTokens.toLocaleString()}`,
|
||||
` Total Tool Calls Tracked: ${state.toolCalls.size}`,
|
||||
` Pruned Tool Outputs (Deduplication/Errors): ${state.prunedToolIds.size}`,
|
||||
` Total Tool Tokens Generated: ~${totalToolTokens.toLocaleString()}`,
|
||||
` Current User Turn: ${state.currentTurn}`,
|
||||
` Summary Exists (Has Compressed): ${state.previousSummary !== null ? "Yes" : "No"}`,
|
||||
` Current Context Tokens: ${tokenStr}`,
|
||||
`Auto-Compressor (Hermes) Stats:`,
|
||||
` Total Compressions: ${state.compressionCount}`,
|
||||
` Pending Compression: ${state.forceCompressNext ? "YES (Scheduled for next turn)" : "No"}`,
|
||||
` Tokens Saved (Compaction): ~${state.tokensSaved.toLocaleString()}`,
|
||||
` Tokens Saved (Tool Pruning): ~${prunedToolTokens.toLocaleString()}`,
|
||||
` Total Tool Calls Tracked: ${state.toolCalls.size}`,
|
||||
` Pruned Tool Outputs (Deduplication/Errors): ${state.prunedToolIds.size}`,
|
||||
` Total Tool Tokens Generated: ~${totalToolTokens.toLocaleString()}`,
|
||||
` Current User Turn: ${state.currentTurn}`,
|
||||
` Summary Exists (Has Compressed): ${state.previousSummary !== null ? "Yes" : "No"}`,
|
||||
` Current Context Tokens: ${tokenStr}`,
|
||||
"",
|
||||
"Type '/acp compress' to force a compression on the next turn."
|
||||
];
|
||||
|
||||
@@ -372,18 +372,26 @@ export async function applyPruning(
|
||||
state.forceCompressNext ||
|
||||
(totalTokens >= thresholdTokens && msgs.length > AUTO_COMPRESS_CONFIG.protectFirstN + 4)
|
||||
) {
|
||||
const wasForced = state.forceCompressNext;
|
||||
state.forceCompressNext = false;
|
||||
|
||||
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));
|
||||
if (wasForced) {
|
||||
// Force compression: use a tiny tail budget to ensure we summarize almost everything
|
||||
tailBudget = Math.max(100, Math.floor(totalTokens * 0.05));
|
||||
}
|
||||
|
||||
state.forceCompressNext = false;
|
||||
const compressStart = alignBoundaryForward(msgs, AUTO_COMPRESS_CONFIG.protectFirstN);
|
||||
const compressEnd = findTailCutByTokens(msgs, compressStart, tailBudget);
|
||||
|
||||
if (compressStart < compressEnd) {
|
||||
const middle = msgs.slice(compressStart, compressEnd);
|
||||
// If forced, we MUST compress something if we have any messages after protectFirstN
|
||||
let finalCompressEnd = compressEnd;
|
||||
if (wasForced && finalCompressEnd <= compressStart && msgs.length > compressStart + 1) {
|
||||
finalCompressEnd = msgs.length - 1;
|
||||
}
|
||||
|
||||
if (compressStart < finalCompressEnd) {
|
||||
const middle = msgs.slice(compressStart, finalCompressEnd);
|
||||
const summary = await generateSummary(middle, state.previousSummary, null, model);
|
||||
|
||||
if (summary) {
|
||||
@@ -394,7 +402,7 @@ export async function applyPruning(
|
||||
}
|
||||
|
||||
const lastHeadRole = msgs[compressStart - 1]?.role || "user";
|
||||
const firstTailRole = msgs[compressEnd]?.role || "user";
|
||||
const firstTailRole = msgs[finalCompressEnd]?.role || "user";
|
||||
|
||||
let summaryRole = lastHeadRole === "assistant" ? "user" : "assistant";
|
||||
if (summaryRole === firstTailRole) {
|
||||
@@ -402,13 +410,13 @@ export async function applyPruning(
|
||||
if (flipped !== lastHeadRole) {
|
||||
summaryRole = flipped;
|
||||
} else {
|
||||
const tailMsg = { ...msgs[compressEnd], timestamp: msgs[compressEnd].timestamp || Date.now() };
|
||||
const tailMsg = { ...msgs[finalCompressEnd], timestamp: msgs[finalCompressEnd].timestamp || Date.now() };
|
||||
const originalContent = tailMsg.content || "";
|
||||
tailMsg.content =
|
||||
"## Goal\n" + summary + "\n\n--- END OF CONTEXT SUMMARY ---\n\n" +
|
||||
(typeof originalContent === "string" ? originalContent : "");
|
||||
compressed.push(tailMsg);
|
||||
for (let i = compressEnd + 1; i < msgs.length; i++) {
|
||||
for (let i = finalCompressEnd + 1; i < msgs.length; i++) {
|
||||
compressed.push(msgs[i]);
|
||||
}
|
||||
state.previousSummary = summary;
|
||||
@@ -430,7 +438,7 @@ export async function applyPruning(
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
for (let i = compressEnd; i < msgs.length; i++) {
|
||||
for (let i = finalCompressEnd; i < msgs.length; i++) {
|
||||
compressed.push(msgs[i]);
|
||||
}
|
||||
|
||||
@@ -440,11 +448,10 @@ export async function applyPruning(
|
||||
return sanitizeToolPairs(compressed);
|
||||
}
|
||||
} else {
|
||||
if (config.debug) {
|
||||
console.log(`[ACP] Compression skipped: conversation too short (start: ${compressStart}, end: ${compressEnd})`);
|
||||
if (config.debug || wasForced) {
|
||||
console.log(`[ACP] Compression skipped: conversation too short (start: ${compressStart}, end: ${finalCompressEnd})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return sanitizeToolPairs(msgs);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user