feat(tui): add adaptive session tabs - #39396
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds opt-in persistent session tabs to the TUI while preserving pinned sessions as the default navigation mode.
How
context/session-tabs.tsxowns the real root-session working set, unread state, family activity, navigation, deletion reconciliation, and serialized persistence writes. Failed writes do not advance the persisted snapshot, so a later save can retry them.context/session-tabs-model.tscontains the pure open, close, cycle, sticky-window, and adaptive-width rules.component/session-tabs.tsxcoordinates adaptive geometry, cached family status, state transitions, terminal-width title fading, and overlaid hover actions for real sessions.ui/animation.tsgives numeric objects and arrays one lazy shared scheduler with spring and tween retargeting, disabled-animation snapping, and per-animation timing. The existing prompt metadata fade uses the same scheduler.component/tab-pulse.tsxuses OpenTUI's shared render frame. Inactive pulse renderables are not live; running, fade-out, and completion channels share one compositing pass.Persistence
Real tabs and unread state are stored in the TUI global state directory as
session-tabs.json.Each TUI reads the global snapshot at startup and then owns process-local state. Running terminals do not live-sync, so concurrent writers are currently last-writer-wins. This PR does not claim project-scoped or synchronized tab workspaces; if cross-terminal sharing is desired, that state should become service-owned rather than adding more client-side file coordination.
Scope
Ctrl+Tab; leader-arrow bindings remain available.Testing
bun run testfrompackages/tui: 562 passed, 5 skipped, 0 failed.bun typecheckfrompackages/tui: passed.Demo
Real-session route with one-space rail-less tab spacing:
Flow
flowchart LR Settings{Session tabs enabled?} Pins[Pinned session picker] Sessions[Persisted real tabs] Home[New session screen] Created[First prompt creates session] Settings -- No --> Pins Settings -- Yes --> Sessions Sessions -- New session action --> Home Home -- Submit first prompt --> Created Created -- Add real tab --> Sessions