--- tags: - hermes - bug - gateway - stream_consumer - fixed --- # No-edit (webhook) segment send bug **Дата:** 20.06.2026 **Файл:** `gateway/stream_consumer.py` (lines 574, 581, 591) **Статус:** ✅ Исправлено, закоммичено ## Симптом При webhook-доставке (Zulip, Telegram через no-edit) текст, который модель генерирует между tool calls (перед tool call, после возврата результата), **не отправлялся промежуточно**. Весь текст накапливался в `_accumulated` и улетал единым куском только на `got_done`. Пользователь видел только tool calls и финальный ответ. ## Root Cause В `stream_consumer.py` в `adapter_supports_edit=False` ветке: ```python # Строка 574 — ДО (баг): _has_nl = "\\\\n" in self._accumulated # ищет буквальный \n (2 символа: \ + n) # Строка 581 — ДО (баг): _should_send = _has_nl and _can_send # segment_break не отправляет без \n # Строка 591 — ДО (баг): _nl_pos = self._accumulated.rfind("\\\\n") # ищет 2 символа вместо 1 ``` `"\\\\n"` в Python-файле — это **4 слеша**: Python видит `\\n` (строка из 2 символов: `\` + `n`). А `_accumulated` содержит реальные символы newline (ASCII 10, один символ). Проверка всегда возвращала `False`, поэтому: - `_has_nl = False` → `_should_send = False` (даже с `got_segment_break=True`) - Текст копился до `got_done` ## Фикс ```python # Строка 574 — ПОСЛЕ: _has_nl = "\\n" in self._accumulated # Python escape для newline # Строка 581 — ПОСЛЕ: _should_send = _can_send # segment break/got_done всегда отправляют # Строка 591 — ПОСЛЕ: _nl_pos = self._accumulated.rfind("\\n") # Python escape для newline ``` ## Тесты Новый файл: `tests/gateway/test_stream_consumer_no_edit.py` Три теста: 1. `test_no_edit_sends_text_across_segment_breaks` — текст с \n, 3 сегмента → 3 sends 2. `test_no_edit_sends_text_without_newline_on_segment_break` — текст без \n, segment_break → отправляет 3. `test_no_edit_multiple_segments_are_separate_messages` — 4 сегмента → 4 sends Все 92 существующих теста stream_consumer проходят зелеными. ## Верификация После фикса тест с 3x вызова терминала + промежуточные фразы — все сообщения дошли до пользователя.