"""Model markdown → Telegram HTML, chunking, and the status line for drafts.""" from __future__ import annotations import html import re from typing import Any __all__ = ["LIMIT", "chunks", "status_label", "to_html"] LIMIT = 4000 _FENCE = re.compile(r"```[^\n]*\n(.*?)(?:```|$)", re.DOTALL) _INLINE_CODE = re.compile(r"(`[^`\n]+`)") _HEADING = re.compile(r"^#{1,6}\s+(.+)$", re.MULTILINE) _BOLD = re.compile(r"\*\*(.+?)\*\*|__(.+?)__", re.DOTALL) _ITALIC = re.compile(r"(? str: out: list[str] = [] pos = 0 for match in _FENCE.finditer(text): out.append(_inline(text[pos : match.start()])) out.append(f"
{html.escape(match.group(1).rstrip())}
") pos = match.end() out.append(_inline(text[pos:])) return "".join(out).strip() def _inline(text: str) -> str: parts = _INLINE_CODE.split(text) for i, part in enumerate(parts): if i % 2: parts[i] = f"{html.escape(part[1:-1])}" continue s = html.escape(part, quote=False) s = _HEADING.sub(r"\1", s) s = _BOLD.sub(lambda m: f"{m.group(1) or m.group(2)}", s) s = _ITALIC.sub(r"\1", s) s = _ITALIC_U.sub(r"\1", s) s = _STRIKE.sub(r"\1", s) s = _LINK.sub(r'\1', s) parts[i] = _BULLET.sub(r"\1• ", s) return "".join(parts) def chunks(text: str, limit: int = LIMIT) -> list[str]: text = text.strip() if len(text) <= limit: return [text] if text else [] out: list[str] = [] while len(text) > limit: cut = _cut_point(text, limit) out.append(text[:cut].rstrip()) text = text[cut:].lstrip() if text: out.append(text) return out def _cut_point(text: str, limit: int) -> int: for sep in ("\n\n", "\n", ". ", " "): cut = text.rfind(sep, limit // 2, limit) if cut > 0: return cut + len(sep) return limit def status_label(name: str, tool_input: dict[str, Any] | None = None) -> str: label = _LABELS.get(name) if label is not None: return label if name.startswith("mcp__"): parts = name.split("__", 2) server = parts[1] tool = parts[2] if len(parts) == 3 else "" return f"{server}: {tool}" if tool else server hint = "" if tool_input: for key in ("description", "command", "file_path", "pattern", "query"): value = tool_input.get(key) if isinstance(value, str) and value.strip(): hint = value.strip().splitlines()[0][:60] break return f"{name} {hint}" if hint else name