hermes-agent/ui-tui/src/components
brooklyn! fabca0bdd8
feat(tui): single /model command + unified Sessions overlay (#37112)
* feat(tui): single /model command + unified Sessions overlay

Collapse the redundant `/provider` alias so `/model` is the only name
everywhere (it already drove the same 2-step ModelPicker in the TUI).

Merge the separate `/resume` (cold history browser) and `/sessions` (live
switcher) surfaces into one Sessions overlay reached by `/resume`,
`/sessions`, `/session`, and `/switch`. It pins a "+ new" row at the top
(always visible), lists live sessions with status, and lists resumable
history below — dispatching session.activate for live rows vs resume for
cold ones, with close/delete in place. Fixes `/session` opening an empty
live-only switcher and the hidden new-session affordance.

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix(tui): address Copilot review on the Sessions overlay

- Track the armed history-delete by session id instead of row index so the
  1.5s live-status poll re-indexing rows can't redirect the second `d` to a
  different session.
- Re-add the busy-session guard to immediate `/resume <id>` and `/sessions new`
  actions (browsing the bare overlay stays allowed) so resuming/switching can't
  corrupt an in-flight turn's streaming/busy state.

* fix(tui): guard cold-resume (not live-switch/new) from the Sessions overlay

Copilot flagged that overlay actions bypassed the busy guard. Only cold
resume actually closes the current session, so only it is guarded — both
from the slash path and now from the overlay (appActions.resumeById).
Switching between live sessions and starting a `+ new` live session keep
the current session running in the background, so they stay unguarded:
that concurrency is the orchestrator's whole purpose. Also dropped the
over-broad guard on `/sessions new` for the same reason.

* fix(tui): address Copilot review (history dedup + desktop /provider)

- The 1.5s poll now re-derives the resumable list from the RAW session.list
  results (rawHistoryRef) against the current live set, so a session hidden
  while live reappears in history once it closes — instead of being lost
  until a full reload. Delete also prunes the raw ref.
- Drop the dead `/provider` entry from the desktop PICKER_OWNED_COMMANDS now
  that the alias is gone, so the desktop client no longer advertises it.

* fix(tui): surface session.list errors + keep selection stable across polls

- A garbled session.list response now surfaces an error and preserves the
  last good raw history, instead of silently blanking the resumable section.
- The 1.5s poll re-anchors the selection to the same row by session id
  (live or history) when the live list grows/shrinks, so the highlight no
  longer drifts to a different row mid-interaction.

* fix(tui): degrade session.list independently + cover overlay helpers

- Fetch active_list and session.list via Promise.allSettled so a failing
  session.list no longer rejects the whole load: live sessions still render
  and only the resumable history degrades (with an error).
- Add unit tests for the new helpers (sessionRowKindAt row ordering,
  resumableHistory dedupe, sessionsCountLabel, relativeSessionAge).

* test(tui-gateway): assert /provider alias is gone, /model remains

The CI test_complete_slash_includes_provider_alias asserted the removed
`/provider` alias still autocompleted. Flip it to lock in the removal:
`/pro` no longer offers `provider`, and `/mod` still completes `model`.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-01 22:28:36 -04:00
..
activeSessionSwitcher.tsx feat(tui): single /model command + unified Sessions overlay (#37112) 2026-06-01 22:28:36 -04:00
agentsOverlay.tsx fix(tui): handle timeout/error subagent statuses in /agents (#26687) 2026-05-15 20:19:02 -05:00
appChrome.tsx fix(tui): pass indicatorStyle into FaceTicker so render matches reservation 2026-06-01 21:02:32 -05:00
appLayout.tsx feat(tui): single /model command + unified Sessions overlay (#37112) 2026-06-01 22:28:36 -04:00
appOverlays.tsx feat(tui): single /model command + unified Sessions overlay (#37112) 2026-06-01 22:28:36 -04:00
branding.tsx feat(tui): responsive banner tiers 2026-05-23 17:37:51 -05:00
fpsOverlay.tsx fix(tui): restore macOS copy behavior and theme polish (#17131) 2026-04-28 18:47:14 -05:00
helpHint.tsx feat(tui): single /model command + unified Sessions overlay (#37112) 2026-06-01 22:28:36 -04:00
markdown.tsx fix(tui): preserve dunder identifiers in markdown 2026-05-19 00:06:08 -07:00
maskedPrompt.tsx fix(tui): restore macOS copy behavior and theme polish (#17131) 2026-04-28 18:47:14 -05:00
messageLine.tsx fix(tui): delineate assistant responses from details (#31087) 2026-05-25 10:23:03 -05:00
modelPicker.tsx feat: fuzzy search for the model picker (WebUI + TUI) 2026-06-01 16:58:58 -07:00
overlayControls.tsx fix(tui): restore macOS copy behavior and theme polish (#17131) 2026-04-28 18:47:14 -05:00
prompts.tsx fix(tui): allow transcript scroll + Esc during approval/clarify/confirm prompts (#26414) 2026-05-15 21:59:28 -05:00
queuedMessages.tsx fix(tui): restore macOS copy behavior and theme polish (#17131) 2026-04-28 18:47:14 -05:00
skillsHub.tsx fix(tui): restore macOS copy behavior and theme polish (#17131) 2026-04-28 18:47:14 -05:00
streamingAssistant.tsx fix(tui): inline todo in transcript, group across thinking 2026-04-26 16:09:28 -05:00
streamingMarkdown.tsx fix(tui): width-aware markdown table rendering with vertical fallback (#26195) 2026-05-15 20:25:56 -05:00
textInput.tsx fix: preserve Ctrl+J newlines in Ghostty 2026-05-28 23:30:39 -07:00
themed.tsx refactor(tui): /clean pass across ui-tui — 49 files, −217 LOC 2026-04-16 22:32:53 -05:00
thinking.tsx fix: surface /agents nudge while delegate_task is in-flight (TUI + CLI) 2026-05-30 13:22:45 +05:30
todoPanel.tsx fix(tui): restore macOS copy behavior and theme polish (#17131) 2026-04-28 18:47:14 -05:00