formatCompactionReport function
Auto/manual compaction run methods (moved from agent_cli.dart under the
repo's 2800-line size gate). Same library, so private state is in scope.
Formats the in-chat compaction report block (issue #276): tokens
before → after, freed count/percent, WHICH ENGINE did the summarizing
(the smol/main role — review major 3: a report that doesn't name
the engine can't be judged), how many records were hidden vs
summarized, and — when the pass actually wrote summary text — the
summary in a fenced block so the user can eyeball — and copy — what
the transcript was condensed to. A pass with no summary text (all
evictions went to hide, or the model returned blank — issue #578)
omits the block: an empty ```-fence says nothing and reads as a bug.
Pure; _AgentCliCompactionReportPrinter.print renders it.
Implementation
/// Formats the in-chat compaction report block (issue #276): tokens
/// before → after, freed count/percent, WHICH ENGINE did the summarizing
/// (the `smol`/`main` role — review major 3: a report that doesn't name
/// the engine can't be judged), how many records were hidden vs
/// summarized, and — when the pass actually wrote summary text — the
/// summary in a fenced block so the user can eyeball — and copy — what
/// the transcript was condensed to. A pass with no summary text (all
/// evictions went to hide, or the model returned blank — issue #578)
/// omits the block: an empty ```-fence says nothing and reads as a bug.
/// Pure; [_AgentCliCompactionReportPrinter.print] renders it.
List<String> formatCompactionReport(
AutoCompactorPass pass, {
required bool auto,
}) {
final freedRaw = pass.tokensBefore - pass.tokensAfter;
// A restamped estimator can report a slightly larger after-count (same
// clamp as onDone's HEP end frame): "-30 freed" reads as a bug.
final freed = freedRaw < 0 ? 0 : freedRaw;
final pct = pass.tokensBefore == 0
? 0
: (freed * 100 / pass.tokensBefore).round();
final engine = pass.fallback == null ? '' : ' · ${pass.fallback}';
final passSuffix = pass.pass == 1 ? '' : ' · pass ${pass.pass}';
final summary = pass.summary?.trim();
return [
'${auto ? 'auto-compacted' : 'compacted'}$engine$passSuffix',
'tokens: ${pass.tokensBefore} → ${pass.tokensAfter} '
'($freed freed · $pct%)',
// Issue #673 AC3: the local-trim valve frees tokens WITHOUT hiding
// session records or folding a summary — a bare "0 hidden · 0
// summarized" next to a big freed count cannot describe a real
// compaction. Name the in-memory drop so the line is truthful for
// BOTH engines.
if (pass.droppedMessages > 0)
'records: ${pass.droppedMessages} dropped (in-memory) · '
'${pass.hiddenRecords} hidden · '
'${pass.summarizedMessages} summarized'
else
'records: ${pass.hiddenRecords} hidden · '
'${pass.summarizedMessages} summarized',
if (summary != null && summary.isNotEmpty) ...[
'summary:',
'```',
summary,
'```',
],
];
}