from __future__ import annotations from typing import Any from yuxi.channels.models import ChannelResponse _PARAGRAPH_SEP = "\n\n" _DEFAULT_CHUNK_LIMIT = 16383 def build_post_options(response: ChannelResponse) -> dict[str, Any]: return { "channel_id": response.identity.channel_chat_id, "message": response.content, "root_id": response.reply_to_message_id or "", "props": response.metadata.get("props", {}), "file_ids": response.metadata.get("file_ids", []), } def build_patch_options(chunk_text: str) -> dict[str, Any]: return {"message": chunk_text} def chunk_text_for_outbound(text: str, limit: int = _DEFAULT_CHUNK_LIMIT) -> list[str]: """按段落边界将文本拆分为不超过 limit 的分块。 优先在双换行符(段落)边界拆分;如果单段仍超限, 则在单换行符(行)边界拆分;如果单行仍超限,则硬截断。 """ if len(text) <= limit: return [text] chunks: list[str] = [] paragraphs = text.split(_PARAGRAPH_SEP) current = "" for para in paragraphs: if len(para) > limit: if current: chunks.append(current.rstrip()) current = "" chunks.extend(_split_by_lines(para, limit)) continue candidate = f"{current}{_PARAGRAPH_SEP}{para}" if current else para if len(candidate) > limit: chunks.append(current.rstrip()) current = para else: current = candidate if current: chunks.append(current.rstrip()) if not chunks: chunks.append(text[:limit]) return chunks def _split_by_lines(text: str, limit: int) -> list[str]: """在换行符边界拆分超限段落。""" chunks: list[str] = [] lines = text.split("\n") current = "" for line in lines: if len(line) > limit: if current: chunks.append(current.rstrip()) current = "" chunks.extend(_split_hard(line, limit)) continue candidate = f"{current}\n{line}" if current else line if len(candidate) > limit: chunks.append(current.rstrip()) current = line else: current = candidate if current: chunks.append(current.rstrip()) return chunks def _split_hard(text: str, limit: int) -> list[str]: """硬截断超长行。""" return [text[i : i + limit] for i in range(0, len(text), limit)]