agent web UI: add terminal verbosity setting (expand tool output by default)

Adds a browser-local (localStorage only, no backend field) toggle in
the per-agent overflow menu's new settings section: whether otherwise-
collapsed <details> rows in the live terminal (long tool-results,
Write/Edit diffs, ...) default open. Message-bearing rows that already
default open (send/ask/answer/recv) are unaffected either way.

The shared terminal factory (frontend/packages/shared/src/terminal/terminal.js)
gains an optional expandDetails option (boolean or zero-arg function),
read live on every details()/detailsDiff() call rather than captured
once, so flipping the toggle mid-session applies to the next rendered
row without a reload. Unused by the dashboard's own terminal pane, so
its default-closed behaviour is unchanged.

Closes #2961.
This commit is contained in:
iris 2026-08-02 18:25:45 +02:00
commit 198db326b3
5 changed files with 94 additions and 1 deletions

View file

@ -231,11 +231,23 @@ export function create(opts) {
afterAppend(wasNearBottom);
return [e, tn];
}
// `opts.expandDetails` (boolean or zero-arg function returning one) lets
// the caller default every otherwise-collapsed `<details>` row open —
// e.g. an "expand panels by default" browser-local preference. Read
// live (not captured once) so a mid-session preference flip takes
// effect on the next row without recreating the terminal. Renderers
// that need a row open regardless (message-bearing tool_use/tool_result)
// already set `d.open = true` themselves after calling this — this only
// changes the *default* for panels that would otherwise start closed.
function wantsExpandedDefault() {
return typeof opts.expandDetails === 'function' ? !!opts.expandDetails() : !!opts.expandDetails;
}
function details(cls, summary, body, icon) {
clearPlaceholder();
const wasNearBottom = isNearBottom();
const d = document.createElement('details');
d.className = 'row ' + (cls || '') + (currentNoAnim ? ' no-anim' : '');
if (wantsExpandedDefault()) d.open = true;
d.appendChild(buildSummary(summary, icon));
const pre = document.createElement('pre');
pre.className = 'tool-body';
@ -250,6 +262,7 @@ export function create(opts) {
const wasNearBottom = isNearBottom();
const d = document.createElement('details');
d.className = 'row ' + (cls || '') + (currentNoAnim ? ' no-anim' : '');
if (wantsExpandedDefault()) d.open = true;
d.appendChild(buildSummary(summary, icon));
const pre = document.createElement('pre');
pre.className = 'tool-body diff-body';