Skip to content

feat(tui): show active credential label in status bar - #66191

Closed
alvarosanchez wants to merge 9 commits into
NousResearch:mainfrom
alvarosanchez:feat/tui-credential-label
Closed

feat(tui): show active credential label in status bar#66191
alvarosanchez wants to merge 9 commits into
NousResearch:mainfrom
alvarosanchez:feat/tui-credential-label

Conversation

@alvarosanchez

@alvarosanchez alvarosanchez commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Shows the active credential-pool label beside the model in the TUI status bar, for example:

ready │ gpt 5.6 sol · personal │ 0s │ …

The label identifies the credential actually installed on the main agent. It does not rely on the pool-global current() pointer, which may temporarily reflect a subagent lease. The label follows credential rotation through normal usage snapshots, is omitted for single-entry pools, and is hidden in compact status layouts.

This changeset also hardens the affected gateway tests against real browser and voice/TTS side effects. Pytest now disables inherited interactive voice settings at both process and per-test boundaries, waits for prompt workers before restoring patches, and keeps Linux-only systemctl probes portable on platforms where systemctl is unavailable.

Related Issue

No issue — user-requested TUI visibility improvement plus test-isolation fixes discovered while validating it.

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • 🐛 Bug fix / safety hardening
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)

Changes Made

Credential identity and gateway usage

  • Resolve the active pooled credential by matching the main agent's live API key/token to its pool entry.
  • Avoid the process-global pool pointer so subagent leases cannot mislabel the main TUI.
  • Include credential_label in every usage snapshot; an explicit empty value clears stale identity after provider/model changes.
  • Suppress labels for single-entry pools and sanitize control characters/whitespace before values enter terminal chrome.

TUI status and usage synchronization

  • Render the credential label as part of the model segment: <model> · <label>.
  • Truncate labels by grapheme/display width to 20 terminal columns.
  • Hide the label in compact status layouts before essential context information is removed.
  • Prefer the model in the latest usage snapshot, falling back to session info when usage does not provide one.
  • Merge /usage responses into existing usage state instead of replacing fields, preserving model and credential identity.
  • Extend gateway/UI types and add TUI documentation, including screen-sharing guidance for account-derived OAuth labels.

Test and live-system safety

  • Forbid real browser-launch paths in the local browser-connect gateway test while still asserting the expected launch request.
  • Disable inherited HERMES_VOICE and HERMES_VOICE_TTS before test-module imports and reset both at every test boundary.
  • Make the streaming session test join its worker before monkeypatch teardown, preventing delayed fixture text from reaching production TTS.
  • Add a live-system guard self-test for the voice defaults.
  • Skip read-only systemctl pass-through probes only when systemctl is unavailable, allowing the guard suite to run cleanly on macOS.

How to Test

Manual behavior

  1. Configure at least two labeled credentials for one provider.
  2. Start hermes and verify the footer contains <model> · <credential-label>.
  3. Rotate credentials or switch provider/model and verify the label updates or clears.
  4. Use a single-credential provider and verify no extra separator or label appears.
  5. Narrow the terminal and verify compact status chrome hides the credential label cleanly.

Automated verification

Latest GitHub CI is green, including:

  • All Python test slices and e2e tests
  • Python lint and Windows-footgun checks
  • ui-tui typecheck and tests
  • Documentation checks
  • Docker builds on amd64 and arm64
  • Supply-chain and dependency scans
  • All required checks pass

Focused macOS regression verification deliberately inherited hostile interactive settings:

HERMES_VOICE=1 HERMES_VOICE_TTS=1 pytest -q \
  tests/test_live_system_guard_self_test.py \
  tests/test_tui_gateway_server.py::test_session_activate_returns_inflight_stream_before_completion

Result: 32 passed, 4 skipped. The skips are the expected Linux-only systemctl probes on macOS. No afplay, say, or ffplay process remained afterward.

Additional local verification:

  • Ruff on all changed Python test/gateway files — passed
  • git diff --check — passed
  • Changed TUI tests — 110 passed
  • npm run typecheck — passed
  • npm run build — passed
  • Live macOS PTY smoke test displayed the active credential label in the model section

Checklist

Code

  • I've read the Contributing Guide
  • Commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • The feature and accompanying test-safety changes are covered by tests
  • Relevant Python and TUI checks pass
  • Tested on macOS
  • Cross-platform behavior considered

Documentation & Housekeeping

  • Updated the TUI user guide
  • cli-config.yaml.example — N/A, no config key added
  • CONTRIBUTING.md / AGENTS.md — N/A, no architecture/workflow change
  • Tool descriptions/schemas — N/A

@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/) labels Jul 17, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to the existing status-bar work in #16644 and #27712, but this is a distinct TUI credential-pool visibility feature rather than an account-limit or CLI-only indicator.

@alvarosanchez

Copy link
Copy Markdown
Contributor Author

Independent review follow-up applied in 3a65c4ba7:

  • keep model + credential identity atomic through the same usage snapshot during cross-provider fallback
  • bound labels to 20 display columns with grapheme-safe truncation and hide them below the 72-column breakpoint
  • preserve runtime identity across /usage refreshes
  • document possible OAuth-derived email labels for screen-sharing privacy

Added fallback-snapshot, /usage, narrow-width, ASCII/email/CJK/emoji coverage. Targeted TUI verification: 106 passed; typecheck, ESLint, production build, 352 gateway tests, Ruff, and diff checks pass.

@alvarosanchez
alvarosanchez marked this pull request as ready for review July 17, 2026 09:26
Copilot AI review requested due to automatic review settings July 17, 2026 09:26
@alvarosanchez

Copy link
Copy Markdown
Contributor Author

UI polish: changed the model/account qualifier from | to a middle dot: gpt 5.6 sol · personal. This keeps reserved for top-level footer sections while making the account visibly part of the model section.

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 active credential-pool label visibility to the Hermes TUI status bar by plumbing the selected credential label through backend usage snapshots and rendering it next to the model (with truncation and compact-layout hiding).

Changes:

  • Expose the active pooled credential label (sanitized) via tui_gateway usage snapshots and ensure stale labels can be cleared.
  • Render the credential label beside the model in the TUI status rule (with width bounds and compact-mode suppression).
  • Add targeted backend + TUI unit tests and update TUI documentation.

Reviewed changes

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

Show a summary per file
File Description
website/docs/user-guide/tui.md Documents the new “model + active pooled account” status-bar behavior and privacy guidance.
ui-tui/src/types.ts Extends Usage to carry credential_label (and model) through the UI state.
ui-tui/src/gatewayTypes.ts Extends SessionUsageResponse to include credential_label.
ui-tui/src/components/appLayout.tsx Wires credentialLabel and prefers usage-provided model when rendering the status rule.
ui-tui/src/components/appChrome.tsx Implements bounded/truncated credential label rendering in the status bar.
ui-tui/src/app/slash/commands/session.ts Merges /usage RPC snapshots into existing UI usage state instead of overwriting.
ui-tui/src/tests/sessionUsageCommand.test.ts Tests that /usage refresh merges model + credential identity into UI state.
ui-tui/src/tests/createGatewayEventHandler.test.ts Tests that completion snapshots merge credential/model identity into UI state.
ui-tui/src/tests/appChromeStatusRule.test.tsx Adds rendering + truncation tests for the credential label in the status rule.
tui_gateway/server.py Adds active credential label extraction (agent-installed key match) and includes it in usage snapshots.
tests/test_tui_gateway_server.py Adds unit tests for label selection, single-entry suppression, and sanitization.

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

Comment thread ui-tui/src/components/appChrome.tsx
Comment thread ui-tui/src/components/appLayout.tsx Outdated
@alvarosanchez

Copy link
Copy Markdown
Contributor Author

Safety follow-up in c9e395f6d:

  • update the browser-connect test to mock the current launch_chrome_debug API and assert exact port/system
  • fail closed on subprocess.Popen, builtins.open, and webbrowser.open
  • disable runtime voice TTS in the in-flight fixture test so partial answer complete cannot be spoken

Focused verification ran under macOS sandbox-exec denying browser, open, say, and osascript execution: 21 passed. Independent safety review found no medium-or-higher issues.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused TUI visibility improvement. Current main still emits no credential label from tui_gateway/server.py:_get_usage() (tui_gateway/server.py:3468) and renders only ui.info?.model in the status pane (ui-tui/src/components/appLayout.tsx:475-495), so the requested capability remains distinct and needed.

The implementation follows the live-agent credential-rotation mechanism: _swap_credential() assigns the selected entry's runtime key to agent.api_key (run_agent.py:4597-4625), which supports matching the displayed label by live key rather than pool-global current().

GitHub currently reports the branch as conflicting with main; salvage will require resolving the moved TUI/backend context rather than a clean cherry-pick.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 18, 2026
@alt-glitch alt-glitch removed the sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades label Jul 18, 2026
@alvarosanchez

Copy link
Copy Markdown
Contributor Author

Resolved the reported conflicts by rebasing onto current main (98cadadd84) and force-pushing the preserved change set. The browser-test conflict keeps both upstream local_port_in_use behavior and this PR's fail-closed launch guards/exact mock assertion.

Post-rebase verification:

  • gateway tests: 382 passed under browser/TTS process guards
  • changed TUI tests: 110 passed
  • typecheck, ESLint, Prettier, Ruff, production build, and diff checks: passed
  • range-diff reviewed for semantic preservation

The 19 failures in the canonical TUI suite reproduce unchanged on the exact origin/main commit (18 subscription overlay tests plus the existing backpressure timing test); this PR changes neither file.

@alvarosanchez
alvarosanchez deleted the feat/tui-credential-label branch August 3, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants