feat: Show spinner while waiting for first stream content

This commit is contained in:
Paul Gauthier (aider) 2025-05-08 12:30:06 -07:00
parent 82f33c1220
commit 6e1327f66d

View file

@ -2,6 +2,8 @@
import io import io
import time import time
import threading
from aider.utils import Spinner
from rich import box from rich import box
from rich.console import Console from rich.console import Console
@ -115,9 +117,20 @@ class MarkdownStream:
else: else:
self.mdargs = dict() self.mdargs = dict()
# Initialize rich Live display with empty text # Defer Live creation until the first update so the Spinner can be shown.
self.live = Live(Text(""), refresh_per_second=1.0 / self.min_delay) self.live = None
self.live.start() self.spinner = Spinner("Streaming markdown...")
self._spinner_stop_event = threading.Event()
self._spinner_thread = threading.Thread(target=self._spin, daemon=True)
self._spinner_thread.start()
self._live_started = False
def _spin(self):
"""Background thread that keeps the spinner moving until stopped."""
while not self._spinner_stop_event.is_set():
time.sleep(0.1)
self.spinner.step()
self.spinner.end()
def _render_markdown_to_lines(self, text): def _render_markdown_to_lines(self, text):
"""Render markdown text to a list of lines. """Render markdown text to a list of lines.
@ -146,6 +159,15 @@ class MarkdownStream:
except Exception: except Exception:
pass # Ignore any errors during cleanup pass # Ignore any errors during cleanup
# Ensure the spinner thread is properly shut down
if hasattr(self, "_spinner_stop_event"):
self._spinner_stop_event.set()
if hasattr(self, "_spinner_thread") and self._spinner_thread.is_alive():
try:
self._spinner_thread.join(timeout=0.1)
except Exception:
pass
def update(self, text, final=False): def update(self, text, final=False):
"""Update the displayed markdown content. """Update the displayed markdown content.
@ -163,6 +185,16 @@ class MarkdownStream:
Markdown going to the console works better in terminal scrollback buffers. Markdown going to the console works better in terminal scrollback buffers.
The live window doesn't play nice with terminal scrollback. The live window doesn't play nice with terminal scrollback.
""" """
# On the first call, stop the spinner and start the Live renderer
if not getattr(self, "_live_started", False):
if hasattr(self, "_spinner_stop_event"):
self._spinner_stop_event.set()
if hasattr(self, "_spinner_thread"):
self._spinner_thread.join()
self.live = Live(Text(""), refresh_per_second=1.0 / self.min_delay)
self.live.start()
self._live_started = True
now = time.time() now = time.time()
# Throttle updates to maintain smooth rendering # Throttle updates to maintain smooth rendering
if not final and now - self.when < self.min_delay: if not final and now - self.when < self.min_delay: