diff --git a/frontend/packages/agent/src/app.js b/frontend/packages/agent/src/app.js index 053c9218..3dfa342e 100644 --- a/frontend/packages/agent/src/app.js +++ b/frontend/packages/agent/src/app.js @@ -1907,6 +1907,12 @@ window.marked = marked; // rather than one "still going" line. let statusRow = null; let statusText = null; + // Same coalescing for `plugin_install`: claude emits a `started` tick + // then a `completed` tick per plugin — without coalescing that's two + // separate rows ("loading…" then "✓ done") for what's really one event + // from the operator's point of view; update in place instead. + let pluginInstallRow = null; + let pluginInstallText = null; function renderStream(v, api) { // Drop claude's result line and rate-limit — noise. TurnEnd // communicates pass/fail; rate-limit events are noisy status chatter. @@ -1959,7 +1965,13 @@ window.marked = marked; const status = v.status === 'completed' ? '✓ done' : v.status === 'started' ? 'loading…' : (v.status || '?'); - api.row('note', '⚙ plugin install · ' + status); + const text = '⚙ plugin install · ' + status; + if (pluginInstallRow && pluginInstallRow.isConnected + && pluginInstallRow.nextElementSibling === null) { + pluginInstallText.nodeValue = text; + } else { + [pluginInstallRow, pluginInstallText] = api.mutableRow('note', text); + } return; } // commands_changed: the set of available slash commands changed (usually