Add refresh loop for reliable TUI output updates

- Remove patch_stdout (was buffering until exit)
- Add 100ms refresh loop that periodically invalidates the app
- Ensures output buffer changes are displayed in real-time

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
dullfig 2026-01-11 14:37:02 -08:00
parent cc5257d342
commit 5a76797613

View file

@ -264,17 +264,12 @@ class TUIConsole:
self._invalidate() self._invalidate()
def _invalidate(self): def _invalidate(self):
"""Invalidate the app to trigger redraw (thread-safe).""" """Invalidate the app to trigger redraw."""
if self.app and self.app.is_running: if self.app:
# Use call_soon_threadsafe for cross-task updates
try: try:
loop = self.app.loop
if loop and loop.is_running():
loop.call_soon_threadsafe(self.app.invalidate)
else:
self.app.invalidate()
except Exception:
self.app.invalidate() self.app.invalidate()
except Exception:
pass
def _print_simple(self, text: str, style: str = "output"): def _print_simple(self, text: str, style: str = "output"):
"""Print in simple mode with ANSI colors.""" """Print in simple mode with ANSI colors."""
@ -313,12 +308,25 @@ class TUIConsole:
self.print_raw(f"Type /help for commands, @listener message to chat", "output.dim") self.print_raw(f"Type /help for commands, @listener message to chat", "output.dim")
self.print_raw("", "output") self.print_raw("", "output")
# Patch stdout so any external prints go to our output area
from prompt_toolkit.patch_stdout import patch_stdout
try: try:
with patch_stdout(raw=True): # Create a background task to poll for updates
async def refresh_loop():
while self.running:
await asyncio.sleep(0.1) # 100ms refresh rate
if self.app and self.app.is_running:
self.app.invalidate()
# Start refresh loop as background task
refresh_task = asyncio.create_task(refresh_loop())
try:
await self.app.run_async() await self.app.run_async()
finally:
refresh_task.cancel()
try:
await refresh_task
except asyncio.CancelledError:
pass
except Exception as e: except Exception as e:
print(f"Console error: {e}") print(f"Console error: {e}")
finally: finally: