feat(cli,tui): show time since last final agent response on the status bar (#44265)
Adds an idle clock to the context/status bar in both the prompt_toolkit CLI and the Ink TUI: once a turn completes, a dim '✓ <elapsed>' segment shows how long the session has been idle since the last final agent response. Hidden while a turn is live (the per-prompt elapsed timer covers that) and before the first turn completes. - cli.py: track _last_turn_finished_at when the agent thread exits, surface it via _format_idle_since() in the snapshot, render in both the wide fragments path and the plain-text fallback. - ui-tui: stamp lastTurnEndedAt when busy flips false after a live turn, thread it through appStatus -> StatusRule, render via a ticking IdleSince segment sharing the duration breakpoint/width budget.
This commit is contained in:
@@ -368,6 +368,7 @@ export interface AppLayoutProgressProps {
|
||||
export interface AppLayoutStatusProps {
|
||||
cwdLabel: string
|
||||
goodVibesTick: number
|
||||
lastTurnEndedAt: null | number
|
||||
sessionStartedAt: null | number
|
||||
showStickyPrompt: boolean
|
||||
statusColor: string
|
||||
|
||||
@@ -173,6 +173,7 @@ export function useMainApp(gw: GatewayClient) {
|
||||
const [voiceRecordKey, setVoiceRecordKey] = useState<ParsedVoiceRecordKey>(DEFAULT_VOICE_RECORD_KEY)
|
||||
const [sessionStartedAt, setSessionStartedAt] = useState(() => Date.now())
|
||||
const [turnStartedAt, setTurnStartedAt] = useState<null | number>(null)
|
||||
const [lastTurnEndedAt, setLastTurnEndedAt] = useState<null | number>(null)
|
||||
const [goodVibesTick, setGoodVibesTick] = useState(0)
|
||||
const [bellOnComplete, setBellOnComplete] = useState(false)
|
||||
|
||||
@@ -500,10 +501,14 @@ export function useMainApp(gw: GatewayClient) {
|
||||
useEffect(() => {
|
||||
if (ui.busy) {
|
||||
setTurnStartedAt(prev => prev ?? Date.now())
|
||||
} else {
|
||||
} else if (turnStartedAt != null) {
|
||||
// Only stamp the idle marker when a turn was actually live — busy is
|
||||
// also false on mount and we don't want a phantom "done" timestamp
|
||||
// before the first turn has completed.
|
||||
setLastTurnEndedAt(Date.now())
|
||||
setTurnStartedAt(null)
|
||||
}
|
||||
}, [ui.busy])
|
||||
}, [ui.busy, turnStartedAt])
|
||||
|
||||
useConfigSync({ gw, setBellOnComplete, setVoiceEnabled, setVoiceRecordKey, sid: ui.sid })
|
||||
|
||||
@@ -1090,6 +1095,7 @@ export function useMainApp(gw: GatewayClient) {
|
||||
// essentials and truncates this further on narrow terminals.
|
||||
cwdLabel: fmtCwdBranch(cwd, gitBranch, 28),
|
||||
goodVibesTick,
|
||||
lastTurnEndedAt: ui.sid ? lastTurnEndedAt : null,
|
||||
sessionStartedAt: ui.sid ? sessionStartedAt : null,
|
||||
showStickyPrompt: !!stickyPrompt,
|
||||
statusColor: statusColorOf(ui.status, ui.theme.color),
|
||||
@@ -1103,6 +1109,7 @@ export function useMainApp(gw: GatewayClient) {
|
||||
cwd,
|
||||
gitBranch,
|
||||
goodVibesTick,
|
||||
lastTurnEndedAt,
|
||||
sessionStartedAt,
|
||||
stickyPrompt,
|
||||
turnStartedAt,
|
||||
|
||||
Reference in New Issue
Block a user