fix: prevent idle cursor blink from forcing scroll to bottom in Linux terminals#2429
fix: prevent idle cursor blink from forcing scroll to bottom in Linux terminals#2429GH-ytym wants to merge 2 commits into
Conversation
| is_idle = ( | ||
| self._active_prompt_delegate() is None | ||
| and self._active_modal_delegate() is None | ||
| ) |
There was a problem hiding this comment.
🟡 Idle check doesn't account for _fast_refresh_provider, breaking MCP loading status updates
The new is_idle check only considers _active_prompt_delegate() and _active_modal_delegate(), but ignores _fast_refresh_provider. When MCP servers are loading (_mcp_status_loading() returns True at src/kimi_cli/ui/shell/__init__.py:449-453), there is no active prompt or modal delegate, so is_idle is True and app.invalidate() is never called. However, the sleep interval logic at lines 1883-1891 still correctly selects _RUNNING_REFRESH_INTERVAL when _fast_refresh_provider() is truthy, meaning the loop spins at a fast rate without actually triggering any UI redraws. The MCP loading spinner/status block (rendered via _render_agent_status → _render_status_block at line 1828, specifically designed for the no-running-delegate case) will freeze until MCP loading completes or the user interacts with the prompt.
| is_idle = ( | |
| self._active_prompt_delegate() is None | |
| and self._active_modal_delegate() is None | |
| ) | |
| is_idle = ( | |
| self._active_prompt_delegate() is None | |
| and self._active_modal_delegate() is None | |
| and not ( | |
| self._fast_refresh_provider is not None | |
| and self._fast_refresh_provider() | |
| ) | |
| ) |
Was this helpful? React with 👍 or 👎 to provide feedback.
Related Issue:
Resolve #2422
Description:
Problem
When the conversation is complete and the user scrolls up to read history,
the terminal automatically jumps back to the bottom every ~1 second.
This makes it impossible to read long outputs without quitting the shell.
Root Cause
CustomPromptSession.__enter__()starts a background_refresh()taskthat calls
app.invalidate()on a timer. When idle, this happens every1 second, causing prompt_toolkit to re-render and reposition the cursor
to the bottom input box. Some Linux terminal emulators (GNOME Terminal,
Konsole, Deepin Terminal, etc.) auto-scroll the viewport to keep the
cursor visible, which is why VS Code's xterm.js-based terminal is not
affected.
Fix
Skip
app.invalidate()when the session is truly idle:In that case, only expire stale toast entries (to avoid leaking memory),
and rely on natural refresh triggers:
on_text_changed)Verification
Tested locally on Linux with GNOME Terminal. With this patch, scrolling up
to read history no longer snaps back to the bottom.