4.3 KiB
Phase 2 — Approval Reactions
Баг 1: Сообщения дропаются при аппрувл-прерывании (подтверждён)
Дата: 2026-06-18 Статус: Подтверждён, причина установлена
Симптом
Когда LLM пишет текст (через стриминг), потом делает tool call с опасной командой — аппрув-промпт прерывает стрим. Весь текст, который LLM уже сказала ДО опасной команды, не доходит до юзера. Юзер видит только аппрув-промпт и финальный ответ (если он есть).
Почему
Причина в GatewayStreamConsumer (gateway/stream_consumer.py).
При streaming.enabled: true для webhook/Zulip:
- LLM стримит текст →
on_delta()кладёт в очередь - Стрим прерывается аппрувом (interrupt) →
got_done = False, циклrun()выходит раньше времени _send_fallback_final()не вызывается — потому что он только приgot_done(строка 580)- Накопленный
_accumulatedтекст теряется
Дополнительно: edit_supported=False для Zulip/Webhook — стример не может редактировать, fallback mode активируется, но не успевает отработать.
Логи из теста
[KIT-stream2] path=webhook streaming_enabled=True want_deltas=N/A _scfg.enabled=True transport=auto
[consumer] on_delta: 1 chars, queue=1
[send_or_edit] enter: ... edit_supported=False fallback_final=True ... (10+ раз, зациклен)
— got_done NOT FOUND в логах —
Что меняли для диагностики
gateway/stream_consumer.py:
logger.debug→logger.warningв_send_or_edit(enter, cursor-only)logger.debug→logger.warningв_send_fallback_final(enter)- Добавлен
warnings.warnна уровне импорта (для проверки загрузки модуля)
gateway/run.py:
[KIT] GatewayRunner.__init__ called— проверка что run.py подхватывается[KIT-stream] entering streaming setup— первый path (не для webhook)[KIT-stream2] path=webhook streaming_enabled=...— второй path (для webhook)
/Users/admin/.hermes/hermes-whale/config.yaml:
- Добавлено
display.platforms.webhook.streaming: true— чтобы стриминг работал для вебхука (был_TIER_MINIMALdefault)
gateway/__pycache__/stream_consumer.cpython-311.pyc:
- Был stale от June 4 — не влияет на проблему (редактируемый install работает)
Как чинить
Нужно чтобы при interrupt (аппрув-прерывание) стример отправлял накопленный текст перед выходом. Варианты:
- В
run.pyпосле прерывания стрима — вызвать_send_fallback_final(_accumulated)если есть что отправлять - В
stream_consumer.pyна interrupt path — форсироватьgot_doneили прямой вызов_send_fallback_final - Не прерывать стрим при аппруве — пусть стриминг продолжается до естественного завершения (
got_done)
История расследования
- Сначала думали что проблема в
stream_consumerс streaming enabled — но баг был ДО включения streaming - Выяснили что streaming был выключен для webhook из-за
_TIER_MINIMALвdisplay_config.py→streaming: False - После включения
display.platforms.webhook.streaming: true— стриминг пошёл - Тест с
rm -rfподтвердил: текст до аппрува не появляется у юзера - Логи подтвердили:
got_doneне вызывается →_send_fallback_finalне срабатывает