hermes - ✅(Solved) Fix [Feature]: Expandable Tool Call Messages in TUI [1 pull requests, 1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#16636Fetched 2026-04-28 06:52:02
View on GitHub
Comments
1
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
labeled ×3commented ×1cross-referenced ×1

Error Message

  • See the full result or error output
  • Error message (if failed)
  • Renders a TreeTextRow header with chevron indicator (▸/▾), tool summary, optional duration, optional error marker
  • Change ActiveTool from having formatted display string to structured fields: {id, name, context, result, error, summary, startedAt, duration}

Fix Action

Fixed

PR fix notes

PR #16637: feat(tui): add expandable tool call UI with per-tool detail expansion

Description (problem / solution / changelog)

What does this PR do?

Adds per-tool expand/collapse functionality to the Hermes TUI transcript. Tool call rows are now clickable: clicking a single tool reveals its full context, result, and error details inline, with a "Show less" action to collapse. Shift/Ctrl/Meta+click expands all tools in the current turn simultaneously. This solves the usability problem of not being able to review what each tool call actually did without relying on hover tooltips or external logs.

Why this approach:

  • Keeps expansion inline so users maintain context of the turn transcript
  • Preserves existing keyboard modifier behavior (shift+click expand-all) for power users
  • Isolates expandable logic in a dedicated component for maintainability
  • Upgrades internal tool model to structured objects (no user-visible breaking change)

Related Issue

Fixes #16636

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change for collapsed views; ActiveTool object is internal)

Changes Made

New components:

  • ui-tui/src/components/ExpandableToolCall.tsx — expandable tool row with header (chevron, summary, duration, error) and collapsible detail rows (context, result, error) with "Show less" CTA
  • ui-tui/src/components/treeRow.tsx — extracted tree rendering utilities (TreeTextRow, TreeRow, nextTreeRails, treeLead) for reuse across components

Refactored pipeline:

  • ui-tui/src/components/thinking.tsx — replace inline tool group rendering with ExpandableToolCall; add tool-object lookup; maintain shift+click expand-all handler; remove ~93 lines of duplicated tree code
  • ui-tui/src/app/turnController.ts — store ActiveTool objects (not formatted strings); fix completeTool() to return ActiveTool; fix recordToolComplete to flush after append; fix recordToolProgress to lookup by toolId; fix inline-diff double-flush bug; update pushInlineDiffSegment signature to accept ActiveTool[]
  • ui-tui/src/app/createGatewayEventHandler.ts — use tool_id for tool lookup in tool.progress handler; populate result and summary fields on tool.complete
  • ui-tui/src/domain/messages.ts — ensure toTranscriptMessages attaches pending: ActiveTool[] correctly
  • ui-tui/src/gatewayTypes.ts — add tool_id?: string to tool.progress payload type
  • ui-tui/src/app/turnStore.ts, ui-tui/src/app/useMainApp.ts, ui-tui/src/components/messageLine.tsx, ui-tui/src/lib/virtualHeights.ts — minor adjustments for ActiveTool object flow and type alignment

Tests updated for ActiveTool object format:

  • ui-tui/src/__tests__/createGatewayEventHandler.test.ts
  • ui-tui/src/lib/messages.test.ts
  • ui-tui/src/lib/liveProgress.test.ts
  • ui-tui/src/__tests__/messages.test.ts
  • ui-tui/src/__tests__/virtualHeights.test.ts

How to Test

  1. Build and run the TUI:

    cd ui-tui
    npm install
    npm run dev

    Or with your installed Hermes: hermes --tui

  2. Trigger a turn with multiple tool calls (e.g., search, read_file, terminal, web_extract).

  3. Verify single-tool expansion:

    • Tool rows appear compact (e.g., ▸ Terminal("...") (0.2s))
    • Click on a tool row → it expands inline showing:
      • Full tool context/arguments (multi-line)
      • Result payload (if successful)
      • Error message (if failed)
      • Duration already shown in header
    • At the bottom of expanded details, see "Show less" in amber; click → collapses back to compact row
  4. Verify expand-all (Shift/Ctrl/Meta+click):

    • Shift+click any tool row → all tools in the turn expand simultaneously
    • Works with Ctrl (Linux/Windows) and Cmd (macOS) as modifier keys
  5. Verify streaming behavior:

    • Start a long-running turn that streams tools
    • Expand a tool early, then keep watching: expanded tools stay expanded
    • Newly arriving tool rows start collapsed (respecting per-tool state)
  6. Run the full TUI test suite:

    cd ui-tui
    npm test

    All 366 tests should pass (including the 27 createGatewayEventHandler tests that validate inline-diff + tool grouping behavior).

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run npm test in ui-tui/ and all 366 tests pass
  • I've added tests for my changes — all existing tests updated to match new ActiveTool object format; new component coverage exercised through existing integration tests
  • I've tested on my platform: Ubuntu 24.04, Node 20, Hermes TUI

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A (deferring to maintainers; UI change self-documenting)
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact — TUI is cross-platform; no platform-specific code
  • I've updated test expectations to match new internal model

For New Skills

Not applicable — this is a core TUI component.

Screenshots / Logs

(Optional — add a screenshot of the TUI showing an expanded tool call with context/result and the "Show less" action to illustrate the feature)

Changed files

  • tui_gateway/server.py (modified, +11/-1)
  • ui-tui/src/__tests__/createGatewayEventHandler.test.ts (modified, +12/-11)
  • ui-tui/src/__tests__/messages.test.ts (modified, +1/-1)
  • ui-tui/src/__tests__/virtualHeights.test.ts (modified, +2/-2)
  • ui-tui/src/app/createGatewayEventHandler.ts (modified, +6/-3)
  • ui-tui/src/app/turnController.ts (modified, +37/-18)
  • ui-tui/src/app/turnStore.ts (modified, +3/-3)
  • ui-tui/src/app/useMainApp.ts (modified, +2/-2)
  • ui-tui/src/components/ExpandableToolCall.tsx (added, +134/-0)
  • ui-tui/src/components/messageLine.tsx (modified, +4/-2)
  • ui-tui/src/components/thinking.tsx (modified, +144/-133)
  • ui-tui/src/components/treeRow.tsx (added, +79/-0)
  • ui-tui/src/domain/messages.ts (modified, +9/-5)
  • ui-tui/src/gatewayTypes.ts (modified, +2/-1)
  • ui-tui/src/lib/liveProgress.test.ts (modified, +19/-19)
  • ui-tui/src/lib/messages.test.ts (modified, +6/-6)
  • ui-tui/src/lib/virtualHeights.ts (modified, +3/-1)
  • ui-tui/src/types.ts (modified, +5/-1)
RAW_BUFFERClick to expand / collapse

Problem or Use Case

When the Hermes TUI runs agents with multiple tool calls, the transcript shows tool call summary lines (e.g., Terminal("...") ✓) but the full context, result, and any errors are hidden. Users must rely on hover tooltips or external logs to review what each tool call actually did. This makes it difficult to:

  • Audit what data was passed to a tool (the context field)
  • See the full result or error output
  • Understand tool execution duration at a glance
  • Navigate long turns with dozens of tool calls efficiently

The attached reference image shows a common pattern: a compact summary line that expands on click to reveal details, with a "Show less" action to collapse. This pattern is missing in Hermes today.

Proposed Solution

Add per-tool expand/collapse behavior to the TUI transcript:

  1. Tool rows become interactive — each tool call line (the "tree row" showing tool name and status) is clickable
  2. Click to expand — clicking a tool row reveals:
    • Full tool context/arguments (multi-line, syntax-highlighted)
    • Tool result payload (if successful)
    • Error message (if failed)
    • Execution duration
  3. "Show less" action — a clickable link at the bottom of expanded details collapses back to the summary line
  4. Expand all — Shift/Ctrl/Meta+click on any tool row expands all tools in the current turn simultaneously (preserves existing keyboard modifier behavior from prior implementations)
  5. Persistent expansion state — expanded tools stay expanded as new streaming tool calls arrive; section visibility (/details) still controls whether the entire tools panel is shown

Technical approach:

  • Create new ExpandableToolCall component in ui-tui/src/components/ that:
    • Renders a TreeTextRow header with chevron indicator (▸/▾), tool summary, optional duration, optional error marker
    • Conditionally renders detail rows below when isExpanded is true
    • Displays "Show less" call-to-action as the last detail row
    • Accepts details array of {color, content, dimColor?, key} objects so parent controls what to show
  • Extract shared tree-row utilities (TreeTextRow, TreeRow, nextTreeRails, treeLead) from thinking.tsx into treeRow.tsx to avoid circular imports and enable reuse
  • Update ToolTrail in thinking.tsx to:
    • Replace inline tool group rendering with <ExpandableToolCall> for groups where group.toolId is set
    • Maintain per-tool expansion state in expandedTools: Set<string> (already present)
    • Pass tool object (looked up from tools prop by group.toolId) and computed details array to the component
    • Keep shift+click expand-all handler that sets expandedTools to all tool IDs
  • Upgrade internal tool data model:
    • Change ActiveTool from having formatted display string to structured fields: {id, name, context, result, error, summary, startedAt, duration}
    • Render formatting (buildToolTrailLine) moves from turnController to ExpandableToolCall component (format at display time, not data time)
    • Update turnController to store ActiveTool objects in pendingSegmentTools and toolStore
    • Update createGatewayEventHandler.ts tool.progress handler to use tool_id (not name) for tool lookup, and populate result/summary on tool.complete
    • Update all affected test fixtures to use tool objects instead of strings
  • Fix inline-diff segment handling bugs discovered during refactor:
    • pushInlineDiffSegment should NOT call flushStreamingSegment (caller already flushed) — removes spurious empty segment
    • recordInlineDiffToolComplete should clear pendingSegmentTools before pushing diff segment
    • recordToolProgress lookup should use toolId parameter (not search by name)
    • recordToolComplete should append ActiveTool object and then flush

Alternatives Considered

1. Inline expansion inside the existing TreeTextRow without separate component

  • Rejected: Would mix concerns and make the code harder to maintain; separate component keeps expandable logic isolated

2. Full-text modal/panel on click instead of inline expansion

  • Rejected: Users would lose context of the turn transcript; inline keeps the mental model of "this tool call belongs to this turn"

3. Always-expanded (no collapse)

  • Rejected: With many tool calls per turn, this would consume excessive screen real estate; users need control

4. Hover-based expansion

  • Rejected: Not TTY-friendly (hover doesn't exist in pure terminal); click is more reliable and accessible

Feature Type

CLI improvement

Scope

Large (new module or significant refactor)

Contribution

  • I'd like to implement this myself and submit a PR

Debug Report (optional)

extent analysis

TL;DR

Implement the proposed solution by creating a new ExpandableToolCall component and updating the internal tool data model to support per-tool expand/collapse behavior.

Guidance

  • Create a new ExpandableToolCall component in ui-tui/src/components/ that renders a TreeTextRow header with a chevron indicator and conditionally renders detail rows below when isExpanded is true.
  • Extract shared tree-row utilities from thinking.tsx into treeRow.tsx to avoid circular imports and enable reuse.
  • Update ToolTrail in thinking.tsx to replace inline tool group rendering with <ExpandableToolCall> and maintain per-tool expansion state.
  • Upgrade the internal tool data model to use structured fields instead of a formatted display string.

Example

// ExpandableToolCall component
import React from 'react';
import TreeTextRow from './TreeTextRow';

const ExpandableToolCall = ({ tool, details, isExpanded }) => {
  return (
    <div>
      <TreeTextRow>
        {tool.name}
        {isExpanded ? '▾' : '▸'}
      </TreeTextRow>
      {isExpanded && (
        <div>
          {details.map((detail) => (
            <div key={detail.key}>{detail.content}</div>
          ))}
          <div>Show less</div>
        </div>
      )}
    </div>
  );
};

Notes

The proposed solution involves significant changes to the internal tool data model and the addition of a new component. It's essential to thoroughly test the changes to ensure they don't introduce any regressions.

Recommendation

Apply the proposed solution by creating the ExpandableToolCall component and updating the internal tool data model. This will provide the desired per-tool expand/collapse behavior and improve the overall user experience.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix [Feature]: Expandable Tool Call Messages in TUI [1 pull requests, 1 comments, 1 participants]