Skip to content

feat(tui): per-section visibility for the details accordion - #14968

Merged
OutThisLife merged 6 commits into
mainfrom
bb/tui-section-visibility
Apr 24, 2026
Merged

feat(tui): per-section visibility for the details accordion#14968
OutThisLife merged 6 commits into
mainfrom
bb/tui-section-visibility

Conversation

@OutThisLife

@OutThisLife OutThisLife commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Two changes that together let users shape exactly what the TUI shows:

  1. Opinionated per-section defaults. Out of the box the TUI now streams the turn as a live transcript — reasoning and tool calls render inline, the activity noise feed is silenced, spawn trees stay quiet until a delegation actually happens. Driven by the request: "all that I want to see is thinking, content/midstream content, and tools, always — no errors/warnings".
  2. Per-section visibility overrides. New optional display.sections map lets users override visibility for any subset of sections without affecting the rest. Pairs with the existing global details_mode.

Default matrix

Section Default Rationale
thinking expanded Reasoning streams inline as the model emits it.
tools expanded Tool calls + results render open.
subagents falls through to details_mode (collapsed) Stays quiet until a delegation actually happens.
activity hidden Ambient meta (gateway hints, terminal-parity nudges, background notifications) is noise for typical use. Tool failures still render inline on the failing tool row; ambient errors/warnings surface via a floating-alert backstop when every panel is hidden.

Streaming/midstream assistant content is unaffected — it always renders inline, it's not part of the section accordion.

Opting out

Everything explicit in display.sections wins over the built-in defaults, so existing configs keep working unchanged. To reshape the layout:

display:
  details_mode: collapsed       # global fallback (existing — unchanged)
  sections:
    thinking: collapsed         # put thinking back under a chevron
    tools: collapsed            # put tool calls back under a chevron
    activity: collapsed         # opt the activity panel back in
    subagents: expanded         # always open spawn tree

Or at runtime: /details <section> [hidden|collapsed|expanded|reset].

Slash command

Extended /details:

  • /details — show current global + active overrides
  • /details [hidden|collapsed|expanded|cycle] — set global mode (existing)
  • /details <section> [hidden|collapsed|expanded|reset] — per-section override (new)

Sections: thinking, tools, subagents, activity. Per-section overrides take precedence over both the section default and the global mode — so details_mode: hidden + sections.tools: expanded renders the tools panel even when the global mode is hidden.

Implementation

  • ui-tui/src/types.tsSectionName + SectionVisibility types.
  • ui-tui/src/domain/details.tsresolveSections, isSectionName, SECTION_NAMES, plus SECTION_DEFAULTS (thinking/tools expanded, activity hidden) and sectionMode which resolves explicit override → SECTION_DEFAULTS → global. Single source of truth for "what mode does this section render in".
  • ui-tui/src/app/{interfaces,uiStore,useConfigSync}.tssections (the explicit-overrides map) threaded into UiState, parsed from display.sections on initial config sync.
  • ui-tui/src/components/thinking.tsxToolTrail consumes per-section modes via sectionMode. Hidden sections are skipped entirely; expanded ones seed open state to true. Renamed the local sections array to panels to avoid shadowing the new prop. Early-return now keys off allHidden (every section resolved to hidden) so per-section overrides still render when the global mode is hidden; floating-alert backstop surfaces under that all-hidden case.
  • ui-tui/src/components/{messageLine,appLayout}.tsx — pass sections through; skip the trail wrapper only when every section resolves to hidden.
  • ui-tui/src/app/useMainApp.tsshowProgressArea rebuilt around anyPanelVisible (mirrors ToolTrail's short-circuit, kills the empty-wrapper-Box cosmetic gap).
  • ui-tui/src/app/slash/commands/core.ts/details <section> <mode> parsing + dispatch via config.set with details_mode.<section> key. reset clears the override.
  • tui_gateway/server.pyconfig.set details_mode.<section> handler writes to display.sections.<section>. Empty value clears the override. Validation rejects unknown sections / unknown modes with 4002.
  • website/docs/user-guide/tui.md — documented defaults, overrides, and the opt-out story.

Behavioural changes for existing users

  • Most users: thinking + tools panels now stream expanded by default; activity panel disappears; spawn trees unchanged. Tool failures still surface inline; ambient hints (e.g. "tmux detected", "Apple Terminal detected") no longer clutter the transcript chrome.
  • Users on details_mode: expanded: no visible change — thinking/tools were already open; activity is now hidden but gets a floating backstop for errors.
  • Users on details_mode: hidden (legacy quiet mode): thinking + tools now render open regardless (section defaults win over the global). To restore silence: pin each section explicitly (display.sections.thinking: hidden, etc.).
  • Users who already set display.sections entries: their overrides win. No migration needed.

One config line reverts each default in every case.

Test plan

  • vitest run (ui-tui) — 272/272 passing (17 new: 6 domain, 4 config sync, 3 slash, 3 gateway, 1 override-escapes-hidden regression)
  • tsc --noEmit (ui-tui) — clean (the pre-existing dom.ts warning on main is untouched)
  • pytest tests/test_tui_gateway_server.py -k config_set_section — 3/3
  • Copilot review threads (3) — addressed + resolved
  • Manual: fresh ~/.hermes/ directory → run hermes --tui → thinking + tools stream open, activity never surfaces, spawn tree stays collapsed until a delegation fires
  • Manual: /details thinking collapsed → thinking back under a chevron + persists to config; /details thinking reset → restores the new default (expanded)
  • Manual: details_mode: hidden + sections.tools: expanded → tools panel still renders (regression coverage for Copilot's catch)

Adds optional per-section overrides on top of the existing global
details_mode (hidden | collapsed | expanded).  Lets users keep the
accordion collapsed by default while auto-expanding tools, or hide the
activity panel entirely without touching thinking/tools/subagents.

Config (~/.hermes/config.yaml):

    display:
      details_mode: collapsed
      sections:
        thinking: expanded
        tools:    expanded
        activity: hidden

Slash command:

  /details                              show current global + overrides
  /details [hidden|collapsed|expanded]  set global mode (existing)
  /details <section> <mode|reset>       per-section override (new)
  /details <section> reset              clear override

Sections: thinking, tools, subagents, activity.

Implementation:

- ui-tui/src/types.ts             SectionName + SectionVisibility
- ui-tui/src/domain/details.ts    parseSectionMode / resolveSections /
                                  sectionMode + SECTION_NAMES
- ui-tui/src/app/uiStore.ts +
  app/interfaces.ts +
  app/useConfigSync.ts            sections threaded into UiState
- ui-tui/src/components/
  thinking.tsx                    ToolTrail consults per-section mode for
                                  hidden/expanded behaviour; expandAll
                                  skips hidden sections; floating-alert
                                  fallback respects activity:hidden
- ui-tui/src/components/
  messageLine.tsx + appLayout.tsx pass sections through render tree
- ui-tui/src/app/slash/
  commands/core.ts                /details <section> <mode|reset> syntax
- tui_gateway/server.py           config.set details_mode.<section>
                                  writes to display.sections.<section>
                                  (empty value clears the override)
- website/docs/user-guide/tui.md  documented

Tests: 14 new (4 domain, 4 useConfigSync, 3 slash, 3 gateway).
Total: 269/269 vitest, all gateway tests pass.
The activity panel (gateway hints, terminal-parity nudges, background
notifications) is noise for the typical day-to-day user, who only cares
about thinking + tools + streamed content.  Make `hidden` the built-in
default for that section so users land on the quiet mode out of the box.

Tool failures still render inline on the failing tool row, so this
default suppresses the noise feed without losing the signal.

Opt back in with `display.sections.activity: collapsed` (chevron) or
`expanded` (always open) in `~/.hermes/config.yaml`, or live with
`/details activity collapsed`.

Implementation: SECTION_DEFAULTS in domain/details.ts, applied as the
fallback in `sectionMode()` between the explicit override and the
global details_mode.  Existing `display.sections.activity` overrides
take precedence — no migration needed for users who already set it.
- domain/details: extract `norm()`, fold parseDetailsMode + resolveSections
  into terser functional form, reject array values for resolveSections
- slash /details: destructure tokens, factor reset/mode into one dispatch,
  drop DETAIL_MODES set + DetailsMode/SectionName imports (parseDetailsMode
  + isSectionName narrow + return), centralize usage strings
- ToolTrail: collapse 4 separate xxxSection vars into one memoized
  `visible` map; effect deps stabilize on the memo identity instead of
  4 primitives

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds per-section visibility overrides for the TUI “details” accordion (thinking/tools/subagents/activity), with the activity panel now hidden by default, plus config + slash-command plumbing end-to-end (TUI ↔ gateway ↔ docs/tests).

Changes:

  • Introduces display.sections per-section overrides resolved via a shared sectionMode() helper (activity defaults to hidden).
  • Threads sections through UI state/config sync and down into transcript rendering (ToolTrail).
  • Extends /details to support per-section overrides and persists them via config.set details_mode.<section> (gateway writes to display.sections.<section>).

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
website/docs/user-guide/tui.md Documents new defaults, per-section overrides, and /details syntax.
ui-tui/src/types.ts Adds SectionName and SectionVisibility types for per-section overrides.
ui-tui/src/gatewayTypes.ts Extends display config shape to include sections.
ui-tui/src/domain/details.ts Adds section parsing, validation, defaults, and sectionMode() resolver.
ui-tui/src/components/thinking.tsx Applies per-section modes to ToolTrail panels; hides activity by default; adjusts expand-all behavior.
ui-tui/src/components/messageLine.tsx Passes sections through to ToolTrail for per-message rendering.
ui-tui/src/components/appLayout.tsx Threads sections into streaming/progress and transcript rendering.
ui-tui/src/app/useConfigSync.ts Parses display.sections from gateway config into UI state.
ui-tui/src/app/uiStore.ts Initializes sections in the default UI store state.
ui-tui/src/app/slash/commands/core.ts Extends /details parsing and persists per-section overrides via config.set.
ui-tui/src/app/interfaces.ts Adds sections to UiState.
ui-tui/src/tests/useConfigSync.test.ts Adds tests for parsing/dropping invalid display.sections.
ui-tui/src/tests/details.test.ts Adds unit tests for section parsing/validation and default resolution.
ui-tui/src/tests/createSlashHandler.test.ts Adds tests for /details <section> … set/reset/usage behavior.
tui_gateway/server.py Implements config.set details_mode.<section>display.sections.<section> with validation.
tests/test_tui_gateway_server.py Adds pytest coverage for per-section config set/clear/validation.
Comments suppressed due to low confidence (1)

ui-tui/src/components/appLayout.tsx:67

  • progress.showProgressArea can be true in modes where <ToolTrail …/> intentionally returns null (e.g., global detailsMode: hidden with activity resolved to hidden). In that case this wrapper <Box> will still render and may introduce a blank gap in the streaming area. Consider suppressing the wrapper when the effective activity section is hidden (or otherwise ensuring showProgressArea is false in that case).
      {progress.showProgressArea && (
        <Box flexDirection="column" marginBottom={progress.showStreamingArea ? 1 : 0}>
          <ToolTrail
            activity={progress.activity}
            busy={busy}
            detailsMode={detailsMode}
            outcome={progress.outcome}
            reasoning={progress.reasoning}
            reasoningActive={progress.reasoningActive}
            reasoningStreaming={progress.reasoningStreaming}
            reasoningTokens={progress.reasoningTokens}
            sections={sections}
            subagents={progress.subagents}
            t={t}
            tools={progress.tools}
            toolTokens={progress.toolTokens}
            trail={progress.turnTrail}
          />
        </Box>

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ui-tui/src/components/thinking.tsx Outdated
Comment thread ui-tui/src/components/thinking.tsx Outdated
Comment thread ui-tui/src/components/messageLine.tsx Outdated
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/tui Terminal UI (ui-tui/ + tui_gateway/) area/config Config system, migrations, profiles labels Apr 24, 2026
Copilot review on #14968 caught that the early returns gated on the
global `detailsMode === 'hidden'` short-circuited every render path
before sectionMode() got a chance to apply per-section overrides — so
`details_mode: hidden` + `sections.tools: expanded` was silently a no-op.

Three call sites had the same bug shape; all now key off the resolved
section modes:

- ToolTrail: replace the `detailsMode === 'hidden'` early return with
  an `allHidden = every section resolved to hidden` check.  When that's
  true, fall back to the floating-alert backstop (errors/warnings) so
  quiet-mode users aren't blind to ambient failures, and update the
  comment block to match the actual condition.

- messageLine.tsx: drop the same `detailsMode === 'hidden'` pre-check
  on `msg.kind === 'trail'`; only skip rendering the wrapper when every
  section resolves to hidden (`SECTION_NAMES.some(...) !== 'hidden'`).

- useMainApp.ts: rebuild `showProgressArea` around `anyPanelVisible`
  instead of branching on the global mode.  This also fixes the
  suppressed Copilot concern about an empty wrapper Box rendering above
  the streaming area when ToolTrail returns null.

Regression test in details.test.ts pins the override-escapes-hidden
behaviour for tools/thinking/activity.  271/271 vitest, lints clean.
Extends SECTION_DEFAULTS so the out-of-the-box TUI shows the turn as
a live transcript (reasoning + tool calls streaming inline) instead of
a wall of `▸` chevrons the user has to click every turn.

Final default matrix:

  - thinking: expanded
  - tools:    expanded
  - activity: hidden    (unchanged from the previous commit)
  - subagents: falls through to details_mode (collapsed by default)

Everything explicit in `display.sections` still wins, so anyone who
already pinned an override keeps their layout.  One-line revert is
`display.sections.<name>: collapsed`.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

ui-tui/src/components/messageLine.tsx:113

  • showDetails (computed above this block) currently short-circuits on detailsMode !== 'hidden', so when the global mode is hidden this ToolTrail never mounts for normal assistant messages—even if per-section overrides (or built-in section defaults) would resolve thinking/tools to expanded.

To make per-section visibility truly override global hidden (as /details <section> … and sectionMode() imply), compute showDetails using sectionMode() for the sections that actually have content (e.g., show when (thinking && thinkingMode!==hidden) or (msg.tools?.length && toolsMode!==hidden)), rather than checking only the global mode.

      {showDetails && (
        <Box flexDirection="column" marginBottom={1}>
          <ToolTrail
            detailsMode={detailsMode}
            reasoning={thinking}
            reasoningTokens={msg.thinkingTokens}
            sections={sections}
            t={t}
            toolTokens={msg.toolTokens}
            trail={msg.tools}
          />
        </Box>

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ui-tui/src/components/messageLine.tsx Outdated
Comment thread ui-tui/src/types.ts Outdated
Round-2 Copilot review on #14968 caught two leftover spots that didn't
fully respect per-section overrides:

- messageLine.tsx (trail branch): the previous fix gated on
  `SECTION_NAMES.some(...)`, which stayed true whenever any section was
  visible.  With `thinking: 'expanded'` as the new built-in default,
  that meant `display.sections.tools: hidden` left an empty wrapper Box
  alive for trail messages.  Now gates on the actual content-bearing
  sections for a trail message — `tools` OR `activity` — so a
  tools-hidden config drops the wrapper cleanly.

- messageLine.tsx (showDetails): still keyed off the global
  `detailsMode !== 'hidden'`, so per-section overrides like
  `sections.thinking: expanded` couldn't escape global hidden for
  assistant messages with reasoning + tool metadata.  Recomputed via
  resolved per-section modes (`thinkingMode`/`toolsMode`).

- types.ts: rewrote the SectionVisibility doc comment to reflect the
  actual resolution order (explicit override → SECTION_DEFAULTS →
  global), so the docstring stops claiming "missing keys fall back to
  the global mode" when SECTION_DEFAULTS now layers in between.

All three lookups (thinking/tools/activity) are computed once at the
top of MessageLine and shared by every branch.
@OutThisLife
OutThisLife merged commit 5dda4ca into main Apr 24, 2026
11 of 13 checks passed
@OutThisLife
OutThisLife deleted the bb/tui-section-visibility branch April 24, 2026 08:02
pull Bot pushed a commit to YIING99/hermes-agent that referenced this pull request Apr 24, 2026
Recovers the manual click on the details accordion: with NousResearch#14968's new
SECTION_DEFAULTS (thinking/tools start `expanded`), every panel render
was OR-ing the local open toggle against `visible.X === 'expanded'`.
That pinned `open=true` for the default-expanded sections, so clicking
the chevron flipped the local state but the panel never collapsed.

Local toggle is now the sole source of truth at render time; the
useState init still seeds from the resolved visibility (so first paint
is correct) and the existing useEffect still re-syncs when the user
mutates visibility at runtime via `/details`.

Same OR-lock cleared inside SubagentAccordion (`showChildren ||
openX`) — pre-existing but the same shape, so expand-all on the
spawn tree no longer makes inner sections un-collapsible either.
nekorytaylor666 pushed a commit to nekorytaylor666/hermes-agent that referenced this pull request Apr 24, 2026
Copilot review on NousResearch#14968 caught that the early returns gated on the
global `detailsMode === 'hidden'` short-circuited every render path
before sectionMode() got a chance to apply per-section overrides — so
`details_mode: hidden` + `sections.tools: expanded` was silently a no-op.

Three call sites had the same bug shape; all now key off the resolved
section modes:

- ToolTrail: replace the `detailsMode === 'hidden'` early return with
  an `allHidden = every section resolved to hidden` check.  When that's
  true, fall back to the floating-alert backstop (errors/warnings) so
  quiet-mode users aren't blind to ambient failures, and update the
  comment block to match the actual condition.

- messageLine.tsx: drop the same `detailsMode === 'hidden'` pre-check
  on `msg.kind === 'trail'`; only skip rendering the wrapper when every
  section resolves to hidden (`SECTION_NAMES.some(...) !== 'hidden'`).

- useMainApp.ts: rebuild `showProgressArea` around `anyPanelVisible`
  instead of branching on the global mode.  This also fixes the
  suppressed Copilot concern about an empty wrapper Box rendering above
  the streaming area when ToolTrail returns null.

Regression test in details.test.ts pins the override-escapes-hidden
behaviour for tools/thinking/activity.  271/271 vitest, lints clean.
nekorytaylor666 pushed a commit to nekorytaylor666/hermes-agent that referenced this pull request Apr 24, 2026
Round-2 Copilot review on NousResearch#14968 caught two leftover spots that didn't
fully respect per-section overrides:

- messageLine.tsx (trail branch): the previous fix gated on
  `SECTION_NAMES.some(...)`, which stayed true whenever any section was
  visible.  With `thinking: 'expanded'` as the new built-in default,
  that meant `display.sections.tools: hidden` left an empty wrapper Box
  alive for trail messages.  Now gates on the actual content-bearing
  sections for a trail message — `tools` OR `activity` — so a
  tools-hidden config drops the wrapper cleanly.

- messageLine.tsx (showDetails): still keyed off the global
  `detailsMode !== 'hidden'`, so per-section overrides like
  `sections.thinking: expanded` couldn't escape global hidden for
  assistant messages with reasoning + tool metadata.  Recomputed via
  resolved per-section modes (`thinkingMode`/`toolsMode`).

- types.ts: rewrote the SectionVisibility doc comment to reflect the
  actual resolution order (explicit override → SECTION_DEFAULTS →
  global), so the docstring stops claiming "missing keys fall back to
  the global mode" when SECTION_DEFAULTS now layers in between.

All three lookups (thinking/tools/activity) are computed once at the
top of MessageLine and shared by every branch.
justrhoto pushed a commit to justrhoto/hermes-agent that referenced this pull request Apr 24, 2026
Copilot review on NousResearch#14968 caught that the early returns gated on the
global `detailsMode === 'hidden'` short-circuited every render path
before sectionMode() got a chance to apply per-section overrides — so
`details_mode: hidden` + `sections.tools: expanded` was silently a no-op.

Three call sites had the same bug shape; all now key off the resolved
section modes:

- ToolTrail: replace the `detailsMode === 'hidden'` early return with
  an `allHidden = every section resolved to hidden` check.  When that's
  true, fall back to the floating-alert backstop (errors/warnings) so
  quiet-mode users aren't blind to ambient failures, and update the
  comment block to match the actual condition.

- messageLine.tsx: drop the same `detailsMode === 'hidden'` pre-check
  on `msg.kind === 'trail'`; only skip rendering the wrapper when every
  section resolves to hidden (`SECTION_NAMES.some(...) !== 'hidden'`).

- useMainApp.ts: rebuild `showProgressArea` around `anyPanelVisible`
  instead of branching on the global mode.  This also fixes the
  suppressed Copilot concern about an empty wrapper Box rendering above
  the streaming area when ToolTrail returns null.

Regression test in details.test.ts pins the override-escapes-hidden
behaviour for tools/thinking/activity.  271/271 vitest, lints clean.
justrhoto pushed a commit to justrhoto/hermes-agent that referenced this pull request Apr 24, 2026
Round-2 Copilot review on NousResearch#14968 caught two leftover spots that didn't
fully respect per-section overrides:

- messageLine.tsx (trail branch): the previous fix gated on
  `SECTION_NAMES.some(...)`, which stayed true whenever any section was
  visible.  With `thinking: 'expanded'` as the new built-in default,
  that meant `display.sections.tools: hidden` left an empty wrapper Box
  alive for trail messages.  Now gates on the actual content-bearing
  sections for a trail message — `tools` OR `activity` — so a
  tools-hidden config drops the wrapper cleanly.

- messageLine.tsx (showDetails): still keyed off the global
  `detailsMode !== 'hidden'`, so per-section overrides like
  `sections.thinking: expanded` couldn't escape global hidden for
  assistant messages with reasoning + tool metadata.  Recomputed via
  resolved per-section modes (`thinkingMode`/`toolsMode`).

- types.ts: rewrote the SectionVisibility doc comment to reflect the
  actual resolution order (explicit override → SECTION_DEFAULTS →
  global), so the docstring stops claiming "missing keys fall back to
  the global mode" when SECTION_DEFAULTS now layers in between.

All three lookups (thinking/tools/activity) are computed once at the
top of MessageLine and shared by every branch.
justrhoto pushed a commit to justrhoto/hermes-agent that referenced this pull request Apr 24, 2026
Recovers the manual click on the details accordion: with NousResearch#14968's new
SECTION_DEFAULTS (thinking/tools start `expanded`), every panel render
was OR-ing the local open toggle against `visible.X === 'expanded'`.
That pinned `open=true` for the default-expanded sections, so clicking
the chevron flipped the local state but the panel never collapsed.

Local toggle is now the sole source of truth at render time; the
useState init still seeds from the resolved visibility (so first paint
is correct) and the existing useEffect still re-syncs when the user
mutates visibility at runtime via `/details`.

Same OR-lock cleared inside SubagentAccordion (`showChildren ||
openX`) — pre-existing but the same shape, so expand-all on the
spawn tree no longer makes inner sections un-collapsible either.
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
Copilot review on NousResearch#14968 caught that the early returns gated on the
global `detailsMode === 'hidden'` short-circuited every render path
before sectionMode() got a chance to apply per-section overrides — so
`details_mode: hidden` + `sections.tools: expanded` was silently a no-op.

Three call sites had the same bug shape; all now key off the resolved
section modes:

- ToolTrail: replace the `detailsMode === 'hidden'` early return with
  an `allHidden = every section resolved to hidden` check.  When that's
  true, fall back to the floating-alert backstop (errors/warnings) so
  quiet-mode users aren't blind to ambient failures, and update the
  comment block to match the actual condition.

- messageLine.tsx: drop the same `detailsMode === 'hidden'` pre-check
  on `msg.kind === 'trail'`; only skip rendering the wrapper when every
  section resolves to hidden (`SECTION_NAMES.some(...) !== 'hidden'`).

- useMainApp.ts: rebuild `showProgressArea` around `anyPanelVisible`
  instead of branching on the global mode.  This also fixes the
  suppressed Copilot concern about an empty wrapper Box rendering above
  the streaming area when ToolTrail returns null.

Regression test in details.test.ts pins the override-escapes-hidden
behaviour for tools/thinking/activity.  271/271 vitest, lints clean.
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
Round-2 Copilot review on NousResearch#14968 caught two leftover spots that didn't
fully respect per-section overrides:

- messageLine.tsx (trail branch): the previous fix gated on
  `SECTION_NAMES.some(...)`, which stayed true whenever any section was
  visible.  With `thinking: 'expanded'` as the new built-in default,
  that meant `display.sections.tools: hidden` left an empty wrapper Box
  alive for trail messages.  Now gates on the actual content-bearing
  sections for a trail message — `tools` OR `activity` — so a
  tools-hidden config drops the wrapper cleanly.

- messageLine.tsx (showDetails): still keyed off the global
  `detailsMode !== 'hidden'`, so per-section overrides like
  `sections.thinking: expanded` couldn't escape global hidden for
  assistant messages with reasoning + tool metadata.  Recomputed via
  resolved per-section modes (`thinkingMode`/`toolsMode`).

- types.ts: rewrote the SectionVisibility doc comment to reflect the
  actual resolution order (explicit override → SECTION_DEFAULTS →
  global), so the docstring stops claiming "missing keys fall back to
  the global mode" when SECTION_DEFAULTS now layers in between.

All three lookups (thinking/tools/activity) are computed once at the
top of MessageLine and shared by every branch.
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…n-visibility

feat(tui): per-section visibility for the details accordion
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
Recovers the manual click on the details accordion: with NousResearch#14968's new
SECTION_DEFAULTS (thinking/tools start `expanded`), every panel render
was OR-ing the local open toggle against `visible.X === 'expanded'`.
That pinned `open=true` for the default-expanded sections, so clicking
the chevron flipped the local state but the panel never collapsed.

Local toggle is now the sole source of truth at render time; the
useState init still seeds from the resolved visibility (so first paint
is correct) and the existing useEffect still re-syncs when the user
mutates visibility at runtime via `/details`.

Same OR-lock cleared inside SubagentAccordion (`showChildren ||
openX`) — pre-existing but the same shape, so expand-all on the
spawn tree no longer makes inner sections un-collapsible either.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
Copilot review on NousResearch#14968 caught that the early returns gated on the
global `detailsMode === 'hidden'` short-circuited every render path
before sectionMode() got a chance to apply per-section overrides — so
`details_mode: hidden` + `sections.tools: expanded` was silently a no-op.

Three call sites had the same bug shape; all now key off the resolved
section modes:

- ToolTrail: replace the `detailsMode === 'hidden'` early return with
  an `allHidden = every section resolved to hidden` check.  When that's
  true, fall back to the floating-alert backstop (errors/warnings) so
  quiet-mode users aren't blind to ambient failures, and update the
  comment block to match the actual condition.

- messageLine.tsx: drop the same `detailsMode === 'hidden'` pre-check
  on `msg.kind === 'trail'`; only skip rendering the wrapper when every
  section resolves to hidden (`SECTION_NAMES.some(...) !== 'hidden'`).

- useMainApp.ts: rebuild `showProgressArea` around `anyPanelVisible`
  instead of branching on the global mode.  This also fixes the
  suppressed Copilot concern about an empty wrapper Box rendering above
  the streaming area when ToolTrail returns null.

Regression test in details.test.ts pins the override-escapes-hidden
behaviour for tools/thinking/activity.  271/271 vitest, lints clean.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
Round-2 Copilot review on NousResearch#14968 caught two leftover spots that didn't
fully respect per-section overrides:

- messageLine.tsx (trail branch): the previous fix gated on
  `SECTION_NAMES.some(...)`, which stayed true whenever any section was
  visible.  With `thinking: 'expanded'` as the new built-in default,
  that meant `display.sections.tools: hidden` left an empty wrapper Box
  alive for trail messages.  Now gates on the actual content-bearing
  sections for a trail message — `tools` OR `activity` — so a
  tools-hidden config drops the wrapper cleanly.

- messageLine.tsx (showDetails): still keyed off the global
  `detailsMode !== 'hidden'`, so per-section overrides like
  `sections.thinking: expanded` couldn't escape global hidden for
  assistant messages with reasoning + tool metadata.  Recomputed via
  resolved per-section modes (`thinkingMode`/`toolsMode`).

- types.ts: rewrote the SectionVisibility doc comment to reflect the
  actual resolution order (explicit override → SECTION_DEFAULTS →
  global), so the docstring stops claiming "missing keys fall back to
  the global mode" when SECTION_DEFAULTS now layers in between.

All three lookups (thinking/tools/activity) are computed once at the
top of MessageLine and shared by every branch.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…n-visibility

feat(tui): per-section visibility for the details accordion
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
Recovers the manual click on the details accordion: with NousResearch#14968's new
SECTION_DEFAULTS (thinking/tools start `expanded`), every panel render
was OR-ing the local open toggle against `visible.X === 'expanded'`.
That pinned `open=true` for the default-expanded sections, so clicking
the chevron flipped the local state but the panel never collapsed.

Local toggle is now the sole source of truth at render time; the
useState init still seeds from the resolved visibility (so first paint
is correct) and the existing useEffect still re-syncs when the user
mutates visibility at runtime via `/details`.

Same OR-lock cleared inside SubagentAccordion (`showChildren ||
openX`) — pre-existing but the same shape, so expand-all on the
spawn tree no longer makes inner sections un-collapsible either.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
Copilot review on NousResearch#14968 caught that the early returns gated on the
global `detailsMode === 'hidden'` short-circuited every render path
before sectionMode() got a chance to apply per-section overrides — so
`details_mode: hidden` + `sections.tools: expanded` was silently a no-op.

Three call sites had the same bug shape; all now key off the resolved
section modes:

- ToolTrail: replace the `detailsMode === 'hidden'` early return with
  an `allHidden = every section resolved to hidden` check.  When that's
  true, fall back to the floating-alert backstop (errors/warnings) so
  quiet-mode users aren't blind to ambient failures, and update the
  comment block to match the actual condition.

- messageLine.tsx: drop the same `detailsMode === 'hidden'` pre-check
  on `msg.kind === 'trail'`; only skip rendering the wrapper when every
  section resolves to hidden (`SECTION_NAMES.some(...) !== 'hidden'`).

- useMainApp.ts: rebuild `showProgressArea` around `anyPanelVisible`
  instead of branching on the global mode.  This also fixes the
  suppressed Copilot concern about an empty wrapper Box rendering above
  the streaming area when ToolTrail returns null.

Regression test in details.test.ts pins the override-escapes-hidden
behaviour for tools/thinking/activity.  271/271 vitest, lints clean.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
Round-2 Copilot review on NousResearch#14968 caught two leftover spots that didn't
fully respect per-section overrides:

- messageLine.tsx (trail branch): the previous fix gated on
  `SECTION_NAMES.some(...)`, which stayed true whenever any section was
  visible.  With `thinking: 'expanded'` as the new built-in default,
  that meant `display.sections.tools: hidden` left an empty wrapper Box
  alive for trail messages.  Now gates on the actual content-bearing
  sections for a trail message — `tools` OR `activity` — so a
  tools-hidden config drops the wrapper cleanly.

- messageLine.tsx (showDetails): still keyed off the global
  `detailsMode !== 'hidden'`, so per-section overrides like
  `sections.thinking: expanded` couldn't escape global hidden for
  assistant messages with reasoning + tool metadata.  Recomputed via
  resolved per-section modes (`thinkingMode`/`toolsMode`).

- types.ts: rewrote the SectionVisibility doc comment to reflect the
  actual resolution order (explicit override → SECTION_DEFAULTS →
  global), so the docstring stops claiming "missing keys fall back to
  the global mode" when SECTION_DEFAULTS now layers in between.

All three lookups (thinking/tools/activity) are computed once at the
top of MessageLine and shared by every branch.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…n-visibility

feat(tui): per-section visibility for the details accordion
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
Recovers the manual click on the details accordion: with NousResearch#14968's new
SECTION_DEFAULTS (thinking/tools start `expanded`), every panel render
was OR-ing the local open toggle against `visible.X === 'expanded'`.
That pinned `open=true` for the default-expanded sections, so clicking
the chevron flipped the local state but the panel never collapsed.

Local toggle is now the sole source of truth at render time; the
useState init still seeds from the resolved visibility (so first paint
is correct) and the existing useEffect still re-syncs when the user
mutates visibility at runtime via `/details`.

Same OR-lock cleared inside SubagentAccordion (`showChildren ||
openX`) — pre-existing but the same shape, so expand-all on the
spawn tree no longer makes inner sections un-collapsible either.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants