From 788673341c2a4158f0c01441a245638e2ee8705e Mon Sep 17 00:00:00 2001 From: damocles Date: Sun, 5 Jul 2026 12:39:26 +0200 Subject: [PATCH] refactor(term): add mutableRow to terminal api, use it for thinking_tokens --- frontend/packages/agent/src/app.js | 4 +--- frontend/packages/shared/src/terminal.js | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/frontend/packages/agent/src/app.js b/frontend/packages/agent/src/app.js index 7075344d..5769cccc 100644 --- a/frontend/packages/agent/src/app.js +++ b/frontend/packages/agent/src/app.js @@ -1933,9 +1933,7 @@ window.marked = marked; && thinkingTokensRow.nextElementSibling === null) { thinkingTokensText.nodeValue = text; } else { - thinkingTokensRow = api.row('note', '', '🧠'); - thinkingTokensText = document.createTextNode(text); - thinkingTokensRow.appendChild(thinkingTokensText); + [thinkingTokensRow, thinkingTokensText] = api.mutableRow('note', text, '🧠'); } return; } diff --git a/frontend/packages/shared/src/terminal.js b/frontend/packages/shared/src/terminal.js index ddc63c60..e00a55cd 100644 --- a/frontend/packages/shared/src/terminal.js +++ b/frontend/packages/shared/src/terminal.js @@ -215,6 +215,22 @@ export function create(opts) { afterAppend(wasNearBottom); return e; } + // Like row(), but returns [element, textNode] so the caller can update + // the text in place via textNode.nodeValue. Use for rows whose content + // changes after initial render (e.g. live-updating counters). + // Text is stored as a plain text node — no linkify, no innerHTML. + function mutableRow(cls, text, icon) { + clearPlaceholder(); + const wasNearBottom = isNearBottom(); + const e = document.createElement('div'); + e.className = 'row ' + (cls || '') + (currentNoAnim ? ' no-anim' : ''); + if (icon != null && icon !== '') e.appendChild(glyphSpan(icon)); + const tn = document.createTextNode(text == null ? '' : String(text)); + e.appendChild(tn); + log.appendChild(e); + afterAppend(wasNearBottom); + return [e, tn]; + } function details(cls, summary, body, icon) { clearPlaceholder(); const wasNearBottom = isNearBottom(); @@ -253,7 +269,7 @@ export function create(opts) { function api(extra) { return Object.assign({ - row, details, detailsDiff, placeholder, linkify, + row, mutableRow, details, detailsDiff, placeholder, linkify, fromHistory: false, }, extra || {}); } @@ -486,7 +502,7 @@ export function create(opts) { } const ready = start(); - return { row, details, detailsDiff, placeholder, ready }; + return { row, mutableRow, details, detailsDiff, placeholder, ready }; } // Build a DocumentFragment from `text`, turning bare http(s) URLs into