From e1fdf4d42e741d2ec43bc68c7526567fda82ac68 Mon Sep 17 00:00:00 2001 From: patriceckhart Date: Mon, 20 Apr 2026 16:00:10 +0200 Subject: [PATCH] tweak(tui): stable spinner phrase per turn The status-bar quip used to rotate every 2.5s through funnyWorkingLines while a turn ran. On a long response that meant five or six different phrases during one reply, which reads as activity that isn't actually happening (the model is just still streaming the same answer). Start() now picks a random index once, Message() returns that same index until the next Start(). Next turn picks a different phrase so the set still feels varied across a session. Dropped the unused lastSwap timer field that drove the rotation and its assignments in Start/StartFixed. --- internal/agent/modes/spinner.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/internal/agent/modes/spinner.go b/internal/agent/modes/spinner.go index e33fbc5..57b73aa 100644 --- a/internal/agent/modes/spinner.go +++ b/internal/agent/modes/spinner.go @@ -13,7 +13,6 @@ type spinner struct { messages []string startedAt time.Time msgIdx int - lastSwap time.Time // fixedMsg overrides the rotating funnyWorkingLines message when // set. Used for auto-compaction so the spinner clearly says what's @@ -80,12 +79,17 @@ func newSpinner() *spinner { return s } -// Start resets the spinner to the beginning of its animation and picks -// a random opening message. +// Start resets the spinner to the beginning of its animation and +// picks a random message that stays fixed for the whole run. A +// rotating rollodex of quips during a single turn felt noisy in +// practice — you'd see five different phrases for one +// long-running response, which implies progress that isn't +// actually happening. One stable phrase per turn reads calmer +// and the variety across turns (next Start picks another index) +// still keeps the set fresh over a session. func (s *spinner) Start() { s.startedAt = time.Now() s.msgIdx = rand.Intn(len(s.messages)) - s.lastSwap = s.startedAt s.fixedMsg = "" } @@ -93,7 +97,6 @@ func (s *spinner) Start() { // duration of this spinner run. Cleared by the next Start() call. func (s *spinner) StartFixed(msg string) { s.startedAt = time.Now() - s.lastSwap = s.startedAt s.fixedMsg = msg } @@ -109,18 +112,14 @@ func (s *spinner) Frame() string { return s.frames[idx] } -// Message returns the current rotating status text. The text changes -// every ~2.5 seconds so the spinner doesn't look frozen. When the -// spinner was started via StartFixed, the pinned message is returned +// Message returns the spinner's status text. One random phrase +// per Start call, pinned until the next turn. When the spinner +// was started via StartFixed, the pinned message is returned // unchanged. func (s *spinner) Message() string { if s.fixedMsg != "" { return s.fixedMsg } - if time.Since(s.lastSwap) > 2500*time.Millisecond { - s.msgIdx = (s.msgIdx + 1) % len(s.messages) - s.lastSwap = time.Now() - } return s.messages[s.msgIdx] }