Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/kimi_cli/ui/shell/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,26 @@ async def _refresh() -> None:
while True:
app = get_app_or_none()
if app is not None:
app.invalidate()
# Only redraw when not idle. Idle redraws cause the
# terminal to scroll to the bottom on every tick in
# some terminal emulators (GNOME Terminal, Konsole).
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()
)
)
Comment on lines +1862 to +1869

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Suggested change
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()
)
)
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

if not is_idle:
app.invalidate()
else:
# Still clean up expired toasts to avoid leaks.
now = time.monotonic()
for pos in ("left", "right"):
queue = _toast_queues[pos]
while queue and queue[0].expires_at <= now:
queue.popleft()

try:
asyncio.get_running_loop()
Expand Down