Цели
- Согласованность: один этап разбора, несколько рендереров.
- Безопасное разбиение: разделение текста перед рендерингом, чтобы встроенное форматирование никогда не разрывалось между фрагментами.
- Соответствие каналу: сопоставление одного и того же IR с Slack mrkdwn, Telegram HTML и диапазонами стилей Signal без повторного разбора Markdown.
Конвейер
- Разбор Markdown -> IR
- IR — это обычный текст плюс диапазоны стилей (жирный/курсив/зачеркнутый/код/спойлер) и диапазоны ссылок.
- Смещения указаны в кодовых единицах UTF-16, чтобы диапазоны стилей Signal совпадали с его API.
- Таблицы разбираются только тогда, когда канал включает преобразование таблиц.
- Разбиение IR (сначала форматирование)
- Разбиение выполняется по тексту IR перед рендерингом.
- Встроенное форматирование не разделяется между фрагментами; диапазоны нарезаются для каждого фрагмента.
- Рендеринг для каждого канала
- Slack: токены mrkdwn (жирный/курсив/зачеркнутый/код), ссылки как
<url|label>. - Telegram: HTML-теги (
<b>,<i>,<s>,<code>,<pre><code>,<a href>). - Signal: обычный текст + диапазоны
text-style; ссылки становятсяlabel (url), когда метка отличается.
- Slack: токены mrkdwn (жирный/курсив/зачеркнутый/код), ссылки как
Пример IR
Входной Markdown:Где это используется
- Исходящие адаптеры Slack, Telegram и Signal выполняют рендеринг из IR.
- Другие каналы (WhatsApp, iMessage, Microsoft Teams, Discord) по-прежнему используют обычный текст или собственные правила форматирования, с преобразованием таблиц Markdown перед разбиением, когда оно включено.
Обработка таблиц
Таблицы Markdown поддерживаются клиентами чатов неодинаково. Используйтеmarkdown.tables, чтобы управлять преобразованием для каждого канала (и для каждой учетной записи).
code: рендерить таблицы как блоки кода (по умолчанию для большинства каналов).bullets: преобразовывать каждую строку в пункты маркированного списка (по умолчанию для Matrix, Signal и WhatsApp).off: отключить разбор и преобразование таблиц; исходный текст таблицы передается дальше.
Правила разбиения
- Лимиты фрагментов берутся из адаптеров/конфигурации каналов и применяются к тексту IR.
- Блоки кода сохраняются как единый блок с завершающим переводом строки, чтобы каналы корректно их рендерили.
- Префиксы списков и цитат являются частью текста IR, поэтому разбиение не происходит внутри префикса.
- Встроенные стили (жирный/курсив/зачеркнутый/встроенный код/спойлер) никогда не разделяются между фрагментами; рендерер заново открывает стили внутри каждого фрагмента.
Политика ссылок
- Slack:
[label](url)-><url|label>; голые URL остаются голыми. Автоссылки отключены во время разбора, чтобы избежать двойного связывания. - Telegram:
[label](url)-><a href="url">label</a>(режим разбора HTML). - Signal:
[label](url)->label (url), если метка не совпадает с URL.
Спойлеры
Маркеры спойлеров (||spoiler||) разбираются только для Signal, где они сопоставляются с
диапазонами стиля SPOILER. Другие каналы обрабатывают их как обычный текст.
Как добавить или обновить форматтер канала
- Разобрать один раз: используйте общий помощник
markdownToIR(...)с подходящими для канала параметрами (автоссылки, стиль заголовков, префикс цитаты). - Отрендерить: реализуйте рендерер с
renderMarkdownWithMarkers(...)и картой маркеров стилей (или диапазонами стилей Signal). - Разбить: вызовите
chunkMarkdownIR(...)перед рендерингом; отрендерьте каждый фрагмент. - Подключить адаптер: обновите исходящий адаптер канала, чтобы он использовал новый разделитель и рендерер.
- Протестировать: добавьте или обновите тесты форматирования и тест исходящей доставки, если канал использует разбиение.
Частые подводные камни
- Токены Slack в угловых скобках (
<@U123>,<#C123>,<https://...>) должны сохраняться; безопасно экранируйте необработанный HTML. - Telegram HTML требует экранирования текста вне тегов, чтобы избежать поврежденной разметки.
- Диапазоны стилей Signal зависят от смещений UTF-16; не используйте смещения по кодовым точкам.
- Сохраняйте завершающие переводы строк для огражденных блоков кода, чтобы закрывающие маркеры попадали на отдельную строку.
Связанные материалы
Streaming and chunking
Поведение исходящей потоковой передачи, границы фрагментов и доставка с учетом особенностей канала.
System prompt
Что модель видит перед разговором, включая внедренные файлы рабочей области.