Files
obsidian-vault/personal/agent/Phase 2 — Approval Reactions.md
T

61 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 2 — Approval Reactions
## Баг 1: Сообщения дропаются при аппрувл-прерывании (подтверждён)
**Дата:** 2026-06-18
**Статус:** Подтверждён, причина установлена
### Симптом
Когда LLM пишет текст (через стриминг), потом делает tool call с опасной командой — аппрув-промпт прерывает стрим. Весь текст, который LLM уже сказала ДО опасной команды, **не доходит до юзера**. Юзер видит только аппрув-промпт и финальный ответ (если он есть).
### Почему
Причина в **GatewayStreamConsumer** (`gateway/stream_consumer.py`).
При `streaming.enabled: true` для webhook/Zulip:
1. LLM стримит текст → `on_delta()` кладёт в очередь
2. Стрим прерывается аппрувом (interrupt) → `got_done = False`, цикл `run()` выходит раньше времени
3. `_send_fallback_final()` не вызывается — потому что он только при `got_done` (строка 580)
4. Накопленный `_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_MINIMAL` default)
**`gateway/__pycache__/stream_consumer.cpython-311.pyc`:**
- Был stale от June 4 — не влияет на проблему (редактируемый install работает)
### Как чинить
Нужно чтобы при interrupt (аппрув-прерывание) стример **отправлял накопленный текст** перед выходом. Варианты:
1. **В `run.py` после прерывания стрима** — вызвать `_send_fallback_final(_accumulated)` если есть что отправлять
2. **В `stream_consumer.py` на interrupt path** — форсировать `got_done` или прямой вызов `_send_fallback_final`
3. **Не прерывать стрим при аппруве** — пусть стриминг продолжается до естественного завершения (`got_done`)
### История расследования
1. Сначала думали что проблема в `stream_consumer` с streaming enabled — но баг был ДО включения streaming
2. Выяснили что streaming был выключен для webhook из-за `_TIER_MINIMAL` в `display_config.py``streaming: False`
3. После включения `display.platforms.webhook.streaming: true` — стриминг пошёл
4. Тест с `rm -rf` подтвердил: текст до аппрува **не появляется** у юзера
5. Логи подтвердили: `got_done` не вызывается → `_send_fallback_final` не срабатывает