refactor: improve markdown streaming with stable/unstable line handling

This commit is contained in:
Paul Gauthier 2025-01-07 06:11:52 -08:00 committed by Paul Gauthier (aider)
parent d616c3fed7
commit 8e64f171b8

View file

@ -82,8 +82,18 @@ class MarkdownStream:
"""Update the displayed markdown content. """Update the displayed markdown content.
Args: Args:
text (str): New markdown text to append text (str): The markdown text received so far
final (bool): If True, this is the final update and we should clean up final (bool): If True, this is the final update and we should clean up
Splits the output into "stable" older lines and the "last few" lines
which aren't considered stable. They may shift around as new chunks
are appended to the markdown text.
The stable lines emit to the console above the Live window.
The unstable lines emit into the Live window so they can be repainted.
Markdown going to the console works better in terminal scrollback buffers.
The live window doesn't play nice with terminal scrollback.
""" """
now = time.time() now = time.time()
# Throttle updates to maintain smooth rendering # Throttle updates to maintain smooth rendering
@ -91,6 +101,7 @@ class MarkdownStream:
return return
self.when = now self.when = now
# ai: refactor this into a helper function...
# Render the markdown to a string buffer # Render the markdown to a string buffer
string_io = io.StringIO() string_io = io.StringIO()
console = Console(file=string_io, force_terminal=True) console = Console(file=string_io, force_terminal=True)
@ -100,18 +111,23 @@ class MarkdownStream:
# Split rendered output into lines # Split rendered output into lines
lines = output.splitlines(keepends=True) lines = output.splitlines(keepends=True)
# ... ai!
num_lines = len(lines) num_lines = len(lines)
# During streaming, keep a window of lines at the bottom visible # How many lines have "left" the live window and are now considered stable?
# Or if final, consider all lines to be stable.
if not final: if not final:
num_lines -= self.live_window num_lines -= self.live_window
# If we have new content to display... # If we have stable content to display...
if final or num_lines > 0: if final or num_lines > 0:
# How many stable lines do we need to newly show above the live window?
num_printed = len(self.printed) num_printed = len(self.printed)
show = num_lines - num_printed show = num_lines - num_printed
# Skip if no new lines to show # Skip if no new lines to show above live window
if show <= 0: if show <= 0:
return return
@ -119,7 +135,7 @@ class MarkdownStream:
show = lines[num_printed:num_lines] show = lines[num_printed:num_lines]
show = "".join(show) show = "".join(show)
show = Text.from_ansi(show) show = Text.from_ansi(show)
self.live.console.print(show) self.live.console.print(show) # to the console above the live area
# Update our record of printed lines # Update our record of printed lines
self.printed = lines[:num_lines] self.printed = lines[:num_lines]