diff --git a/docs/web-ui/terminal-rendering.md b/docs/web-ui/terminal-rendering.md index 35798fa0..a6e100aa 100644 --- a/docs/web-ui/terminal-rendering.md +++ b/docs/web-ui/terminal-rendering.md @@ -35,6 +35,11 @@ leading the summary text rather than the icon. | `warn` | amber, left rule | stderr, an unrecognised event shape, API retries | | `error` | red, left rule | turn failed, a tool result with `is_error: true` | +The settings menu's "hide debug output" toggle (`getHideDebugPref()`, +`@hive/shared/prefs.js`) skips `debug`-level rows entirely rather than +muting them further — client-side only, same live-read-no-reload shape +as the expand-tool-output preference above. + Per-tool icon + summary formatting (what a `Read`/`Edit`/`send` call's row actually says) lives in `stream_enrich.rs`'s `fmt_tool_use()` family — read that when you need the specifics, this doc doesn't duplicate it. diff --git a/frontend/packages/agent/src/Root.tsx b/frontend/packages/agent/src/Root.tsx index 8c29be4f..23d7fed4 100644 --- a/frontend/packages/agent/src/Root.tsx +++ b/frontend/packages/agent/src/Root.tsx @@ -12,6 +12,7 @@ import { useApplyMotionOverride } from "@hive/shared/motion-apply.js"; import { Header } from "./components/Header.js"; import { MetaNav } from "./components/MetaNav.js"; import { ExpandDetailsSetting } from "./components/ExpandDetailsSetting.js"; +import { HideDebugSetting } from "./components/HideDebugSetting.js"; import { StatusChips } from "./components/StatusChips.js"; import { LiveStream, type LiveStreamHandle } from "./components/LiveStream.js"; import { HeaderPill } from "./components/HeaderPill.js"; @@ -151,6 +152,7 @@ export function Root() { ) : null} + ); diff --git a/frontend/packages/agent/src/components/HideDebugSetting.tsx b/frontend/packages/agent/src/components/HideDebugSetting.tsx new file mode 100644 index 00000000..bff063ae --- /dev/null +++ b/frontend/packages/agent/src/components/HideDebugSetting.tsx @@ -0,0 +1,25 @@ +// Agent-terminal-only settings-menu row: "hide debug output". Same shape +// as `ExpandDetailsSetting` (its own file's header comment explains why +// this lives here rather than as a `SettingsMenu` prop) — mara: "add a +// setting to not display verbose output... like the grey colored debug +// stuff." +import { useState } from "preact/hooks"; +import { getHideDebugPref, setHideDebugPref } from "@hive/shared/prefs.js"; + +export function HideDebugSetting() { + const [hideDebug, setHideDebugState] = useState(() => getHideDebugPref()); + return ( + + ); +} diff --git a/frontend/packages/agent/src/components/Row.tsx b/frontend/packages/agent/src/components/Row.tsx index 8ff6d1ca..18ade774 100644 --- a/frontend/packages/agent/src/components/Row.tsx +++ b/frontend/packages/agent/src/components/Row.tsx @@ -10,7 +10,7 @@ import { useEffect, useRef } from "preact/hooks"; import type { TermRow } from "../lib/termMsg.js"; import { linkifyToNodes } from "../lib/linkify.js"; import { renderMarkdown } from "../lib/markdown.js"; -import { getExpandDetailsPref } from "@hive/shared/prefs.js"; +import { getExpandDetailsPref, getHideDebugPref } from "@hive/shared/prefs.js"; function MarkdownBody({ text }: { text: string }) { const ref = useRef(null); @@ -51,6 +51,12 @@ function DiffBody({ text }: { text: string }) { } export function Row({ row }: { row: TermRow }) { + // "hide debug output" is a skip, not a dimmer — a hidden debug row + // still occupies no DOM node at all, same as it never streamed, rather + // than a CSS `display: none` that would keep it in the layout/DOM for + // no benefit. + if (row.level === "debug" && getHideDebugPref()) return null; + const cssClass = "level-" + row.level; const icon = row.icon != null && row.icon !== "" && ( {row.icon} diff --git a/frontend/packages/shared/src/prefs.ts b/frontend/packages/shared/src/prefs.ts index 4e927483..4ba17362 100644 --- a/frontend/packages/shared/src/prefs.ts +++ b/frontend/packages/shared/src/prefs.ts @@ -2,8 +2,9 @@ // so a future second consumer (e.g. swarm-ui's own terminal) gets the // exact same key name for free via the browser's shared per-origin // storage, rather than an independent copy that could drift. -// `ExpandDetailsSetting` (the per-agent page's own settings popover) is -// the only writer today; `Row.tsx` is the only reader. +// `ExpandDetailsSetting` / `HideDebugSetting` (the per-agent page's own +// settings popover rows) are the only writers today; `Row.tsx` is the +// only reader of either. const EXPAND_DETAILS_KEY = "hive-agent-expand-details"; @@ -29,3 +30,27 @@ export function setExpandDetailsPref(v: boolean): void { /* localStorage unavailable — preference is session-only */ } } + +const HIDE_DEBUG_KEY = "hive-agent-hide-debug"; + +// Whether a per-agent terminal's `debug`-level rows (thinking, coalesced +// ticks, ambient harness chatter — see docs/web-ui/terminal-rendering.md's +// Levels table) should be skipped entirely rather than rendered muted. +// Same shape as `getExpandDetailsPref` above: pure client-side, no +// backend field, read live (not cached) so a change applies to the next +// rendered row without a reload. +export function getHideDebugPref(): boolean { + try { + return localStorage.getItem(HIDE_DEBUG_KEY) === "1"; + } catch { + return false; + } +} +export function setHideDebugPref(v: boolean): void { + try { + if (v) localStorage.setItem(HIDE_DEBUG_KEY, "1"); + else localStorage.removeItem(HIDE_DEBUG_KEY); + } catch { + /* localStorage unavailable — preference is session-only */ + } +}