feat(tui): include session name in the terminal titlebar (#43188)
The terminal/console titlebar was composed from status marker + model + cwd only; the session's (auto-)title never appeared, even though the TUI already knows it. Change the format to `<marker> <session name> · <model> · <cwd>`, with the session name and cwd each omitted when absent so single-segment titles stay clean. The current session's live title is pulled from the existing session.active_list poll (which already carries each session's current flag and title), so there's no extra round-trip; UiState gains a sessionTitle field updated only when it actually changes, preserving the existing idle-flicker guard. Extract the join logic into a pure composeTabTitle() helper in domain/paths and cover its edge cases (name omitted, cwd omitted, whitespace-only name, marker-only fallback, truncation, boundary length) in paths.test.ts.
This commit is contained in:
@@ -128,6 +128,7 @@ export interface UiState {
|
||||
pasteCollapseChars: number
|
||||
|
||||
sections: SectionVisibility
|
||||
sessionTitle: string
|
||||
showCost: boolean
|
||||
showReasoning: boolean
|
||||
indicatorStyle: IndicatorStyle
|
||||
|
||||
@@ -22,6 +22,7 @@ const buildUiState = (): UiState => ({
|
||||
pasteCollapseLines: 5,
|
||||
pasteCollapseChars: 2000,
|
||||
sections: {},
|
||||
sessionTitle: '',
|
||||
showCost: false,
|
||||
showReasoning: false,
|
||||
sid: null,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { MAX_HISTORY, WHEEL_SCROLL_STEP } from '../config/limits.js'
|
||||
import { hasLeadGap, prevRenderedMsg } from '../domain/blockLayout.js'
|
||||
import { SECTION_NAMES, sectionMode } from '../domain/details.js'
|
||||
import { attachedImageNotice, imageTokenMeta } from '../domain/messages.js'
|
||||
import { fmtCwdBranch, shortCwd } from '../domain/paths.js'
|
||||
import { composeTabTitle, fmtCwdBranch, shortCwd } from '../domain/paths.js'
|
||||
import { type GatewayClient } from '../gatewayClient.js'
|
||||
import type {
|
||||
ClarifyRespondResponse,
|
||||
@@ -524,12 +524,22 @@ export function useMainApp(gw: GatewayClient) {
|
||||
if (!stopped && result?.sessions) {
|
||||
const liveSessionCount = result.sessions.length
|
||||
|
||||
// Only patch when the count actually changed. patchUiState always
|
||||
// Surface the current session's (auto-)title for the terminal
|
||||
// titlebar. The active_list poll already carries it, so no extra
|
||||
// round-trip is needed.
|
||||
const currentSid = getUiState().sid
|
||||
|
||||
const sessionTitle =
|
||||
result.sessions.find(s => s.current || s.id === currentSid)?.title?.trim() ?? ''
|
||||
|
||||
// Only patch when something actually changed. patchUiState always
|
||||
// produces a new state object, which notifies every $uiState
|
||||
// subscriber; patching unconditionally on each 1.5s poll re-renders
|
||||
// the whole TUI and causes idle flicker.
|
||||
if (getUiState().liveSessionCount !== liveSessionCount) {
|
||||
patchUiState({ liveSessionCount })
|
||||
const prev = getUiState()
|
||||
|
||||
if (prev.liveSessionCount !== liveSessionCount || prev.sessionTitle !== sessionTitle) {
|
||||
patchUiState({ liveSessionCount, sessionTitle })
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -546,13 +556,16 @@ export function useMainApp(gw: GatewayClient) {
|
||||
}, [gw, ui.sid])
|
||||
|
||||
// Tab title: `⚠` waiting on approval/sudo/secret/clarify, `⏳` busy, `✓` idle.
|
||||
// Format: `<marker> <session name> · <model> · <cwd>` — name/cwd omitted when absent.
|
||||
const model = ui.info?.model?.replace(/^.*\//, '') ?? ''
|
||||
|
||||
const marker = overlay.approval || overlay.sudo || overlay.secret || overlay.clarify ? '⚠' : ui.busy ? '⏳' : '✓'
|
||||
|
||||
const tabCwd = ui.info?.cwd
|
||||
|
||||
useTerminalTitle(model ? `${marker} ${model}${tabCwd ? ` · ${shortCwd(tabCwd, 24)}` : ''}` : 'Hermes')
|
||||
useTerminalTitle(
|
||||
model ? composeTabTitle(marker, ui.sessionTitle, model, tabCwd ? shortCwd(tabCwd, 24) : '') : 'Hermes'
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!ui.sid || !stdout) {
|
||||
|
||||
Reference in New Issue
Block a user