From da3fc9bf95cc1ceec27ddcb67eb63c47ad60654b Mon Sep 17 00:00:00 2001 From: iris Date: Sun, 2 Aug 2026 18:34:40 +0200 Subject: [PATCH] move terminal-verbosity toggle from agent overflow menu to /settings.html MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per mara: 'i wanted you to put this in .../settings.html' — the toggle belongs with the other operator-local browser preferences, not buried in each agent's own overflow menu. Extracted the get/set + localStorage key into @hive/shared/prefs.js so settings.html (writer) and every per-agent app.js (reader, via HiveTerminal.create's expandDetails option) agree on the exact same key without two independently-typed copies that could drift. Removed the now-unused overflow-menu toggle + its agent.css rules from the agent page. Docs moved from docs/web-ui/agent.md's overflow-button section to docs/web-ui/dashboard.md's S3TT1NGS section, next to the existing browser-notifications preference. --- docs/web-ui/agent.md | 10 ---- docs/web-ui/dashboard.md | 20 ++++++-- frontend/packages/agent/src/agent.css | 13 ----- frontend/packages/agent/src/app.js | 51 +------------------ frontend/packages/dashboard/src/settings.html | 6 +++ frontend/packages/dashboard/src/settings.js | 34 ++++++++++--- frontend/packages/shared/package.json | 1 + frontend/packages/shared/src/prefs.js | 27 ++++++++++ 8 files changed, 79 insertions(+), 83 deletions(-) create mode 100644 frontend/packages/shared/src/prefs.js diff --git a/docs/web-ui/agent.md b/docs/web-ui/agent.md index ffd82a32..ff51a5d9 100644 --- a/docs/web-ui/agent.md +++ b/docs/web-ui/agent.md @@ -101,16 +101,6 @@ through. Three flex columns: the `/effort ` slash command). The active level's button is highlighted; `renderEffortChip` keeps the picker in sync with `StateSnapshot.effort` from the cold-load snapshot. - A third separator + **settings** section holds a single - `role="menuitemcheckbox"` toggle, `☐/☑ expand tool output` — flips - whether otherwise-collapsed `
` rows in the terminal (long - tool-results, Write/Edit diffs, …) default open. Pure client-side: - persisted to this browser's `localStorage` only (no backend field, - no `/api/*` call), read live by the shared terminal factory's - `expandDetails` option (see docs/web-ui/shape.md::Shared terminal - pane) so toggling mid-session applies to the next rendered row - without a reload. Rows that already default open regardless (send / - ask / answer / recv) are unaffected either way. The popover's display rules are scoped to `:not([hidden])` so the `[hidden]` HTML attribute's UA `display: none` isn't overridden by the author CSS's `display: flex` — the popover stays hidden until diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index a8cfaff2..ae22d0b3 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -622,10 +622,9 @@ frontend reads. Operator-local preferences. State lives in the browser's `localStorage` — preferences do NOT sync between devices and -do NOT survive a profile wipe. Today the tab holds one section -(browser notifications); future preferences (theme, density, -etc.) land here as sibling `

` blocks -under the same `
`. +do NOT survive a profile wipe. Two sections today (browser +notifications, agent terminal); future preferences (theme, density, +etc.) land here as sibling `

` blocks in `settings.html`. **◇ browser notifications** — `🔔 enable notifications` button when permission ungranted; `🔕 mute / 🔔 unmute` toggle once granted @@ -636,6 +635,19 @@ single status line explains why. See `### Browser notifications` below for the dispatch model + the three signals the dashboard emits OS notifications on. +**◇ agent terminal** — a single `☐/☑ expand tool output panels` +toggle button (`role="switch"`, live `aria-checked`). Controls whether +every per-agent page's terminal defaults otherwise-collapsed +`
` rows (long tool-results, Write/Edit diffs, …) open; rows +that already default open regardless (send/ask/answer/recv) are +unaffected either way. Pure client-side — the key + get/set live in +`@hive/shared/prefs.js` (`getExpandDetailsPref`/`setExpandDetailsPref`) +so this page and every agent page's `app.js` read/write the exact same +`localStorage` key without a backend field; the shared terminal +factory reads it live via its `expandDetails` option (see +docs/web-ui/shape.md::Shared terminal pane), so a change here applies +to any already-open agent tab's next rendered row without a reload. + The FL0W page does NOT host this pane — settings live only on the dashboard's S3TT1NGS tab (reach it via the FL0W page's `← home` back-link → Dashboard). Notifications still fire on the FL0W page when diff --git a/frontend/packages/agent/src/agent.css b/frontend/packages/agent/src/agent.css index 4818b3a4..79f32625 100644 --- a/frontend/packages/agent/src/agent.css +++ b/frontend/packages/agent/src/agent.css @@ -299,19 +299,6 @@ h2, h3 { border-color: var(--purple-dim); background: color-mix(in srgb, var(--purple) 6%, transparent); } -.overflow-item-verbosity { - color: var(--muted); -} -.overflow-item-verbosity:hover { - color: var(--fg); - background: color-mix(in srgb, var(--purple) 8%, transparent); - border-color: var(--purple-dim); -} -.overflow-item-verbosity.active { - color: var(--purple); - border-color: var(--purple-dim); - background: color-mix(in srgb, var(--purple) 6%, transparent); -} /* Header pill — inbox / loose-ends triggers. Compact, count-prominent. */ .header-pill { diff --git a/frontend/packages/agent/src/app.js b/frontend/packages/agent/src/app.js index f8be2e10..94661e0e 100644 --- a/frontend/packages/agent/src/app.js +++ b/frontend/packages/agent/src/app.js @@ -6,6 +6,7 @@ import { create as termCreate, linkify as termLinkify } from '@hive/shared/termi import { asyncBtn, bindAsyncForms } from '@hive/shared/forms.js'; import { themedConfirm } from '@hive/shared/modal.js'; import { el } from '@hive/shared/dom.js'; +import { getExpandDetailsPref } from '@hive/shared/prefs.js'; import '@hive/shared/side-panel.js'; // registers — side-effect import import { marked } from 'marked'; import DOMPurify from 'dompurify'; @@ -26,22 +27,6 @@ window.marked = marked; ({ '&':'&', '<':'<', '>':'>', '"':'"' }[c]) ); - // "Expand tool output by default" terminal-verbosity preference — - // pure client-side, browser-local (localStorage only, no backend - // field). See the overflow-menu settings toggle below + the - // `expandDetails` option passed to HiveTerminal.create(). - const EXPAND_DETAILS_KEY = 'hive-agent-expand-details'; - function getExpandDetailsPref() { - try { return localStorage.getItem(EXPAND_DETAILS_KEY) === '1'; } - catch { return false; } - } - function setExpandDetailsPref(v) { - try { - if (v) localStorage.setItem(EXPAND_DETAILS_KEY, '1'); - else localStorage.removeItem(EXPAND_DETAILS_KEY); - } catch { /* localStorage unavailable — preference is session-only */ } - } - // Base URL of the host dashboard (core backend). Set once the first // /api/state lands. Operator-authority actions (answering a question // as the operator) POST here rather than to this agent's own socket — @@ -310,40 +295,6 @@ window.marked = marked; } } - // ─── settings: expand tool output by default ─────────────────── - // Pure client-side, browser-local preference (no backend involved) — - // see docs/web-ui/agent.md::Overflow button. Controls the *default* - // open state of otherwise-collapsed `
` rows in the live - // terminal (long tool-results, Write/Edit diffs, …); rows that - // already default open (send/ask/answer/recv) are unaffected. - // Read live by the shared terminal factory (HiveTerminal.create's - // `expandDetails` option below), so toggling mid-session applies to - // the next rendered row without a reload. - const settingsSep = el('div', { class: 'overflow-sep', 'aria-hidden': 'true' }); - const settingsLabel = el('div', { class: 'overflow-section-label' }, 'settings'); - menu.append(settingsSep, settingsLabel); - const expandIcon = el('span', { class: 'overflow-item-icon', 'aria-hidden': 'true' }, - getExpandDetailsPref() ? '☑' : '☐'); - const expandBtn = el('button', { - type: 'button', - class: 'overflow-item overflow-item-verbosity' + (getExpandDetailsPref() ? ' active' : ''), - role: 'menuitemcheckbox', - 'aria-checked': String(getExpandDetailsPref()), - title: 'expand tool output panels by default in this terminal (persisted to this browser only)', - id: 'expand-details-btn', - }, - expandIcon, - 'expand tool output', - ); - expandBtn.addEventListener('click', () => { - const next = !getExpandDetailsPref(); - setExpandDetailsPref(next); - expandBtn.classList.toggle('active', next); - expandBtn.setAttribute('aria-checked', String(next)); - expandIcon.textContent = next ? '☑' : '☐'; - }); - menu.append(expandBtn); - overflowMenuPopulated = true; } diff --git a/frontend/packages/dashboard/src/settings.html b/frontend/packages/dashboard/src/settings.html index 1f98dfec..7fd6ed28 100644 --- a/frontend/packages/dashboard/src/settings.html +++ b/frontend/packages/dashboard/src/settings.html @@ -31,6 +31,12 @@ + +

◇ agent terminal

+

applies to every agent's terminal viewed in this browser — whether otherwise-collapsed tool-output panels (long results, Write/Edit diffs, …) default open. rows that already default open (send/ask/answer/recv) are unaffected either way.

+
+ +
diff --git a/frontend/packages/dashboard/src/settings.js b/frontend/packages/dashboard/src/settings.js index c6d5fc29..3a4f4a6e 100644 --- a/frontend/packages/dashboard/src/settings.js +++ b/frontend/packages/dashboard/src/settings.js @@ -1,15 +1,37 @@ // /settings.html — operator-local preferences page. // -// Extracted from the dashboard S3TT1NGS tab. Today the only setting is -// the browser-notification toggle: NOTIF.bind() wires the enable / mute / -// unmute buttons and persists state to localStorage. The dashboard's -// NOTIF.show() calls (approvals / questions) read that same localStorage -// state + the browser-level permission, so firing still works from the -// dashboard even though the toggle UI now lives on its own page. +// Extracted from the dashboard S3TT1NGS tab. The browser-notification +// toggle: NOTIF.bind() wires the enable / mute / unmute buttons and +// persists state to localStorage. The dashboard's NOTIF.show() calls +// (approvals / questions) read that same localStorage state + the +// browser-level permission, so firing still works from the dashboard +// even though the toggle UI now lives on its own page. +// +// The agent-terminal-verbosity toggle below is a second, unrelated +// browser-local preference — @hive/shared/prefs.js owns the key name + +// get/set so this page and every per-agent page's app.js agree on it +// without a backend field. Both preferences are per-origin localStorage, +// so they only apply within this browser (per the page's own copy). // // initServerWarnings() renders the shared top-of-page warnings banner, // matching the other stand-alone pages (FL0W / L0GS / H0M3). import { NOTIF, initServerWarnings } from './common.js'; +import { getExpandDetailsPref, setExpandDetailsPref } from '@hive/shared/prefs.js'; initServerWarnings(); NOTIF.bind(); + +(function bindExpandDetailsToggle() { + const btn = document.getElementById('expand-details-toggle'); + if (!btn) return; + function render() { + const on = getExpandDetailsPref(); + btn.textContent = on ? '☑ expand tool output panels' : '☐ expand tool output panels'; + btn.setAttribute('aria-checked', String(on)); + } + btn.addEventListener('click', () => { + setExpandDetailsPref(!getExpandDetailsPref()); + render(); + }); + render(); +})(); diff --git a/frontend/packages/shared/package.json b/frontend/packages/shared/package.json index b0dde490..5134f006 100644 --- a/frontend/packages/shared/package.json +++ b/frontend/packages/shared/package.json @@ -17,6 +17,7 @@ "./terminal.css": "./src/terminal/terminal.css", "./chrome.css": "./src/chrome.css", "./forms.js": "./src/forms.js", + "./prefs.js": "./src/prefs.js", "./dom.js": "./src/dom.js", "./modal.js": "./src/modal.js", "./shadow-css.js": "./src/shadow-css.js", diff --git a/frontend/packages/shared/src/prefs.js b/frontend/packages/shared/src/prefs.js new file mode 100644 index 00000000..f73fb005 --- /dev/null +++ b/frontend/packages/shared/src/prefs.js @@ -0,0 +1,27 @@ +// Tiny browser-local (localStorage) preference helpers shared by the +// dashboard's /settings.html and the per-agent page — both need the +// exact same key name to actually talk to each other via the browser's +// shared per-origin storage (settings.html is where the operator sets +// the preference; every per-agent page's terminal reads it), so the +// get/set pair — and the key itself — live here once rather than as +// independent copies in each package that could drift out of sync. + +const EXPAND_DETAILS_KEY = 'hive-agent-expand-details'; + +// Whether a per-agent terminal's otherwise-collapsed `
` panels +// (long tool-results, Write/Edit diffs, …) should default open. Pure +// client-side — no backend field, nothing round-trips through +// `/api/*`. Read live (not cached) by the shared terminal factory's +// `expandDetails` option — see docs/web-ui/shape.md::Shared terminal +// pane — so a preference change on /settings.html applies to the next +// rendered row in any already-open agent tab without a reload. +export function getExpandDetailsPref() { + try { return localStorage.getItem(EXPAND_DETAILS_KEY) === '1'; } + catch { return false; } +} +export function setExpandDetailsPref(v) { + try { + if (v) localStorage.setItem(EXPAND_DETAILS_KEY, '1'); + else localStorage.removeItem(EXPAND_DETAILS_KEY); + } catch { /* localStorage unavailable — preference is session-only */ } +}