Skip to content

Latest commit

 

History

History
65 lines (52 loc) · 5.86 KB

File metadata and controls

65 lines (52 loc) · 5.86 KB

Bridge судит конверт, содержимое судит Inbound pipeline

Bot API 10.1 (11.06.2026) добавил классу Message поле rich_message: до 32768 символов UTF-8 против 4096 у text, а само содержимое лежит в блоках. Версии 10.2 (14.07.2026) и 10.3 его дополнили — кнопки, раскрываемые цитаты, документы. Клиент свежей версии (проверено на iOS и Telegram Web) шлёт длинное или форматированное сообщение именно так: в апдейте есть message_id, from, chat, date, rich_message — и нет ни text, ни entities, ни caption. Changelog Bot API, RichMessage.

Ива до 0.3.33 такое сообщение теряла молча. Агент читает rich_message без потерь с 0.3.25 (agent/lib/telegram-rich-message.ts), eve upstream его пропускает, но Bridge (scripts/lib/telegram-queue.ts, hasMessagePayload) держал свой список ключей содержимого — text, caption и 11 медиа-ключей — и всё остальное отбрасывал как terminal-drop, записывая один номер апдейта. Снаружи: короткие сообщения бот отвечает, длинные и форматированные игнорирует, /restart не помогает, iva logs poll показывает drop update N — terminal ingress policy.

Класс общий для всех, кто читает Telegram. openclaw принял fix(telegram): preserve rich forwarded message text (#98735) и следом #100570: хелпер resolveTelegramRichMessageText раскладывает блоки в текст до плейсхолдера «unsupported». NousResearch/hermes-agent #63485 — входящий rich_message верхнего уровня терялся, потому что хендлер фильтровал по filters.TEXT. nanocoai/nanoclaw #3151 — 14 тихих потерь за три дня, починка тем же адаптером richMessageToText.

Что решено

Bridge судит конверт. Сообщение от пользователя из Allowlist принимается, если несёт хотя бы один ключ вне метаданных конверта Bot API (message_id, from, chat, date, reply_to_message, forward_origin, edit_date, … — поля, в которых содержимого не бывает). Новое поле Bot API поэтому доезжает до агента само.

Содержимое судит Inbound pipeline. Единственная власть над тем, что читается, — читалка agent/lib/telegram-rich-message.ts; Bridge содержимое не открывает.

Правило групп не меняется. Сообщение без text/caption в группе принимается только как reply боту.

Нечитаемое получает ответ, а не тишину. Если в личном сообщении нет ни текста, ни rich-текста, ни медиа, ни локации (poll, contact или поле, которого Ива ещё не знает), агент один раз отвечает на языке чата: Не могу прочитать это сообщение (поля: poll). Пришли текстом или файлом. Раньше poll и contact пропадали молча.

Отброс называет ключи. Строка отброса перечисляет ключи верхнего уровня — только имена, никогда содержимое: iva logs poll по-прежнему не несёт текста сообщений.

Обоснование. Доставка внутрь идёт одним швом (philosophy §2), и решение о содержимом принимается на нём один раз, в агенте, а не дважды. Баг закрывается дизайном, а не списком (philosophy §5): список знакомых ключей проигрывает каждому новому полю Bot API, конверт — нет. Молчание стоит данных (ADR-0002), поэтому непрочитанное сообщение обязано получить ответ.

Что отвергнуто

  • Добавить rich_message в список ключей Bridge — закрывает одно поле, следующее поле Bot API теряется так же молча.
  • Второй нормализатор rich_message → text в самом Bridge (предлагался ранее) — дублирует читалку агента, даёт два места, которые разойдутся, и заставляет Bridge читать содержимое, толковать которое ему нельзя.
  • Принимать всё и молчать — пользователь не отличает потерянное сообщение от медленного.

Последствия. Незнакомое поле стоит одного круга: сообщение доезжает, приходит ответ, владелец шлёт текстом или файлом. Группа остаётся с дырой — rich_message там принимается только как reply боту, потому что @mention внутри rich-текста Bridge не видит; записано в docs/tech-debt.md.