diff --git a/frontend/packages/agent/src/app.js b/frontend/packages/agent/src/app.js index 80c7b15a..013fe80b 100644 --- a/frontend/packages/agent/src/app.js +++ b/frontend/packages/agent/src/app.js @@ -1837,6 +1837,27 @@ window.marked = marked; api.details('note', summary, body); return; } + // compact_boundary: claude completed a compaction pass. The metadata + // carries pre/post token counts, duration, and the trigger (manual vs + // auto). Show a single summary line so the operator can gauge how much + // context was shed. + if (v.subtype === 'compact_boundary') { + const m = v.compact_metadata || {}; + const parts = ['โš™ compact']; + if (m.trigger) parts.push(m.trigger); + if (m.pre_tokens != null && m.post_tokens != null) { + const fmtTok = (n) => n >= 1_000_000 ? (n / 1_000_000).toFixed(1) + 'M' + : n >= 1_000 ? Math.round(n / 1000) + 'k' + : String(n); + parts.push(fmtTok(m.pre_tokens) + 'โ†’' + fmtTok(m.post_tokens) + ' tokens'); + } + if (m.duration_ms != null) { + const ms = m.duration_ms; + parts.push(ms < 1000 ? ms + 'ms' : (ms / 1000).toFixed(1) + 's'); + } + api.row('note', parts.join(' ยท ')); + return; + } // Other system subtypes (context_window_exceeded, etc.) โ€” render a // muted note with the subtype label; reserve the loud orange `sys` // catch-all for truly unrecognised top-level types.