Files
mitus/cht/agent/buffer.py
2026-04-09 14:46:29 -03:00

51 lines
1.5 KiB
Python

"""Streaming text buffer — smooth reveal of bursty network chunks.
Accumulates text from the provider and reveals it at ~60fps with a
~200ms target reveal pace, so the UI sees a smooth stream regardless
of network burst patterns.
All methods must be called from the GTK main thread.
"""
from typing import Callable
from gi.repository import GLib
class StreamingTextBuffer:
TICK_MS = 16 # ~60fps
REVEAL_TARGET_MS = 200
def __init__(self, on_reveal: Callable[[str], None]):
self._pending = ""
self._on_reveal = on_reveal
self._timer_id: int | None = None
def push(self, text: str):
self._pending += text
if self._timer_id is None:
self._timer_id = GLib.timeout_add(self.TICK_MS, self._tick)
def _tick(self) -> bool:
if not self._pending:
self._timer_id = None
return False
n = max(1, len(self._pending) * self.TICK_MS // self.REVEAL_TARGET_MS)
reveal, self._pending = self._pending[:n], self._pending[n:]
self._on_reveal(reveal)
return True
def flush(self):
if self._pending:
self._on_reveal(self._pending)
self._pending = ""
if self._timer_id is not None:
GLib.source_remove(self._timer_id)
self._timer_id = None
def cancel(self):
self._pending = ""
if self._timer_id is not None:
GLib.source_remove(self._timer_id)
self._timer_id = None