import asyncio import logging import re logger = logging.getLogger("yuxi.channel.xmpp.streaming") def chunk_text( text: str, min_chars: int = 800, max_chars: int = 2000, ) -> list[str]: if len(text) <= max_chars: return [text] paragraphs = re.split(r"\n\s*\n", text) chunks = [] current = "" for para in paragraphs: candidate = f"{current}\n\n{para}".strip() if current else para if len(candidate) > max_chars and current: chunks.append(current) current = para else: current = candidate if current: chunks.append(current) merged = [] buf = "" for chunk in chunks: candidate = f"{buf}\n\n{chunk}".strip() if buf else chunk if len(candidate) <= max_chars: buf = candidate else: if buf: merged.append(buf) buf = chunk if buf: merged.append(buf) return merged if merged else [text] async def stream_xmpp_blocks( gateway, target_id: str, chunks: list[str], typing_interval_ms: int = 500, ) -> None: from yuxi.channel.extensions.xmpp.outbound import send_xmpp_text, send_xmpp_typing for i, chunk in enumerate(chunks): if i == 0: await send_xmpp_typing(gateway, target_id, composing=True) await asyncio.sleep(typing_interval_ms / 1000.0) await send_xmpp_text(gateway, target_id, chunk) if i < len(chunks) - 1: await asyncio.sleep(typing_interval_ms / 1000.0) await send_xmpp_typing(gateway, target_id, composing=True) await asyncio.sleep(typing_interval_ms / 1000.0) await send_xmpp_typing(gateway, target_id, composing=False)