Skip to content

fix: onboarding redesign, session restore, interrupt handling, and exit coordinates#62

Merged
wangtsiao merged 11 commits intomainfrom
dev/tui0501
May 5, 2026
Merged

fix: onboarding redesign, session restore, interrupt handling, and exit coordinates#62
wangtsiao merged 11 commits intomainfrom
dev/tui0501

Conversation

@wangtsiao
Copy link
Copy Markdown
Contributor

  • Onboarding redesign: replace text-input wizard with modern picker-based UI; dedicated OnboardingHandle separated from view_stack so Esc interrupts always work
  • Session restore: restore pending messages to bottom pane, fix InputQueueUpdated infinite loop, reset busy on switch, preserve server-side pending queue
  • Interrupt: fix deadlock in handle_turn_interrupt (tokio Mutex reentrancy), fix core_session lock blocking interrupt response
  • Exit coordinates: clear full viewport (history_area + bottom_pane) on exit, add 4 tests covering delta_y correction, scrollback preservation, onboarding view cleanup
  • Steer/BTW: show /btw messages in TUI history during live sessions
  • Duplicate cells: guard against duplicate history cells after turn interrupt

wangtsiao added 11 commits May 1, 2026 22:28
… queue persistence

- Add rusqlite dependency for embedded SQLite database
- Create db module with Database, SessionStats, QueueType types
- Rename queue variables for clarity:
  - steering_queue → pending_turn_queue
  - steer_input_queue → btw_input_queue
  - Remove idle_pending_input, merge into pending_turn_queue
- Persist token statistics to SQLite after each turn
- Persist pending messages to SQLite for crash recovery
- Restore token stats and pending queues from SQLite on startup
- Update all tests to include new db parameter
- Fix clippy warnings (collapsible_if, useless_conversion, too_many_arguments)
…messages on resume

- Add ServerRuntime.shutdown() to complete deferred assistant/reasoning
  items and persist Interrupted turn records on Ctrl+C
- Call shutdown() from bootstrap before returning
- Add pending_texts to SessionSwitched event in TUI
- Pass pending_texts through worker to chatwidget
- Restore queued_count in TUI when resuming a session with pending messages
The hardcoded desired_height of 20 caused the ExitLayoutSnapshot's
bottom_pane_area to be too large, placing the cursor too far below
actual content on exit.
…a loss

- Fix infinite loop in unqueue_oldest_pending: always decrement queued_count,
  even when bottom_pane has no pending cells
- Restore pending_texts into bottom_pane.pending_cell_texts on SessionSwitched
- Reset self.busy to false on session switch
- Remove clear_pending on new turn start to preserve restored queue items
- Add /btw steer messages to TUI history during live session
Replace the fragile view_stack-based onboarding with a dedicated
OnboardingHandle that owns the full lifecycle:

- OnboardingHandle wraps OnboardingView, preserves result before cleanup
- BottomPane.onboarding field replaces view_stack.push for onboarding
- handle_key_event routes to onboarding first, Esc interrupt always reachable
- Single poll_onboarding_result() replaces scattered take_result() calls
- BottomPaneView trait cleaned of 3 onboarding-specific methods
- ChatWidget simplified: no is_onboarding_active checks, no force-Esc hacks
handle_turn_interrupt tried to acquire core_session.lock() to read
session/turn context for the rollout record. When execute_turn held
this lock during the provider query() call (which can take 30+ seconds),
the interrupt RPC would block until timeout (10s), producing the error:
'timed out waiting for server response to request N'.

Fix: use try_lock() in the interrupt path. If the lock is held by the
running turn task, skip the context snapshot in the rollout record
instead of blocking the interrupt response.
…plete_item

handle_turn_interrupt locked session_arc, then called complete_item which
calls persist_item which tries to lock session_arc again. tokio::sync::Mutex
is not reentrant, causing a deadlock when deferred_assistant or
deferred_reasoning items were present. The interrupt RPC would block
indefinitely, producing the timeout error on the TUI side.

Fix: take deferred items out of the session before dropping the lock,
then call complete_item without holding the session lock.
After commit_active_streams clears the text buffers on TurnFinished,
AssistanceMessageCompleted/ReasoningCompleted events from the server's
deferred item completion could still arrive and re-populate
active_assistant_text/active_reasoning_text. When the next turn (from
spawn_next_turn_from_queue) finished, commit_active_streams would see
the leftover text and create a duplicate history cell.

Guard: only accept completed item text when self.busy is true (i.e.,
the turn is still active and commit_active_streams hasn't run yet).
Previously apply_exit_layout_snapshot only cleared bottom_pane_area,
leaving history_area content (session header, live text) on screen after
exit. This caused the shell prompt to appear at the wrong position
because uncleaned content occupied rows between scrollback and the
cursor.

Fix: extend the clear area from history_area.top() to
bottom_pane_area.bottom() (both offset by delta_y), covering the
entire inline viewport area.

Added 4 new tests covering:
- Full shutdown flow with scrollback preservation and delta_y correction
- History area content clearance
- Correct cursor positioning with no pending history lines
- Onboarding view area clearance
@wangtsiao wangtsiao merged commit a8e0462 into main May 5, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant