zot/internal
patriceckhart 6019404644 fix(tui): blinking cursor in /btw, proper idle redraws, tighter status bar
Three related tweaks to how the interactive mode drives its redraw
loop, the terminal cursor, and the status-bar layout.

1) Redraw-on-tick narrowed to things that actually animate.

   The render loop used to force a redraw every 120ms for every
   open dialog (model picker, jump, sessions, btw, etc). Most
   of those are static pickers \u2014 the repaint was wasted and had
   a visible side effect: the re-emitted hide-cursor / show-cursor
   pair at the start of each frame cancels the terminal's blink
   cycle for any dialog that hosts its own input field. Concretely
   the blinking cursor in /btw never blinked, it just sat as a
   steady reverse-video block.

   Tick-driven redraw is now only triggered when i.busy (main
   spinner animates) or btw.Loading() (side-chat spinner animates).
   Static dialogs rely on the dirty-channel invalidations that
   fire on key events, which is sufficient because nothing else
   on screen is moving.

2) btw side-chat redraws on completion.

   Consequence of (1): the btw goroutine that streams a model
   response used to depend on the 120ms tick to make the final
   answer visible. With the tick gone for idle dialogs, the
   answer landed in d.turns but the screen stayed blank until
   the user pressed a key.

   btwDialog.Open and submit now take an invalidate callback
   that the goroutine fires after completeTurn, including the
   early-error branch. While the request is in flight,
   btw.Loading() returns true so the tick keeps the spinner
   animating; once the answer lands, a single invalidate()
   redraws and the tick stops.

3) Cursor routed into btw while it's open.

   btwDialog already had a CursorPos(width) method that returns
   where the side-chat editor's caret sits within the dialog's
   rendered rows. The host never used it \u2014 the real terminal
   cursor stayed on the main editor below. Now when btw is
   active the host picks up CursorPos and points the terminal
   cursor there, so the blink shows in the correct input and
   the main editor has no cursor.

4) Status bar idle-path spacing.

   Idle row used to render as "<pad><pad>(provider) model" =
   4 spaces before the model, so the line started at column 4
   while busy and idle didn't match. Dropped one pad in the
   idle branch; both paths now start at column 2, aligned with
   the conversation column ('  you' / '  zot' message markers).

No semantic change to transcripts or provider calls. All tests
pass.
2026-04-21 18:09:10 +02:00
..
agent fix(tui): blinking cursor in /btw, proper idle redraws, tighter status bar 2026-04-21 18:09:10 +02:00
assets assets: refresh zot logo to cleaner pixel-art Z 2026-04-20 12:01:43 +02:00
auth feat(auth,tui): dark login pages + /logout picker 2026-04-19 20:14:22 +02:00
core feat(session): /session fork + /session tree 2026-04-20 11:10:56 +02:00
extproto feat(ext): phase 4 - full-event interception, arg rewrites, /reload-ext 2026-04-19 17:02:04 +02:00
provider perf(anthropic): fix cost double-count, tighten caching, correct catalog 2026-04-19 18:57:18 +02:00
skills perf(prompt): cut system prompt to the bone (410 -> 54 tokens) 2026-04-19 17:39:38 +02:00
tui fix(tui): blinking cursor in /btw, proper idle redraws, tighter status bar 2026-04-21 18:09:10 +02:00