fix(#1286): pretty-print system events in the agent terminal

The catch-all renderer was dumping raw JSON (in loud orange) for
claude's system events like api_retry — producing noise like:
  ! {"attempt":1,"error":"unknown","subtype":"api_retry",...}

Replace the single 'init' filter with a full system-event block:
- api_retry → muted note: '⚠ api retry 1/10 · unknown · 502ms'
- api_error → amber note:  '✗ api error · <message>'
- other subtypes (context_window_exceeded, etc.) → '⚙ <subtype>'

The loud orange sys catch-all is now reserved for truly unrecognised
top-level event types, not routine operational noise.
This commit is contained in:
iris 2026-06-04 18:40:47 +02:00 committed by mara
commit bddeb5478e

View file

@ -1431,11 +1431,38 @@ window.marked = marked;
return false;
}
function renderStream(v, api) {
// Drop session init, claude's result line, rate-limit — noise.
// TurnEnd communicates pass/fail; session init isn't actionable.
if (v.type === 'system' && v.subtype === 'init') return;
// Drop claude's result line and rate-limit — noise. TurnEnd
// communicates pass/fail; rate-limit events are noisy status chatter.
if (v.type === 'rate_limit_event') return;
if (v.type === 'result') return;
// `system` events: `init` is silent startup noise; `api_retry`
// and `api_error` get human-readable notes; unknown subtypes get a
// muted line rather than a raw-JSON dump in the loud `sys` colour.
if (v.type === 'system') {
if (v.subtype === 'init') return;
if (v.subtype === 'api_retry') {
const parts = ['⚠ api retry'];
if (v.attempt != null && v.max_retries != null)
parts.push(v.attempt + '/' + v.max_retries);
if (v.error) parts.push(String(v.error));
else if (v.error_status) parts.push('HTTP ' + v.error_status);
if (v.retry_delay_ms != null)
parts.push(Math.round(v.retry_delay_ms) + 'ms');
api.row('note', parts.join(' · '));
return;
}
if (v.subtype === 'api_error') {
const msg = v.error || v.message
|| (v.error_status ? 'HTTP ' + v.error_status : 'unknown');
api.row('note stderr', '✗ api error · ' + msg);
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.
api.row('note', '⚙ ' + (v.subtype || 'system'));
return;
}
// Background-task subagent events (claude's `Task` tool spawns
// a separate session whose progress lands here as `task_*`
// subtypes). Match by subtype so we don't have to track which