7. Идея использовать OpenRouter (`z-ai/glm-5`) как дефолт — отвергнута: используем DeepSeek как у Балды/Whale.
8. Утверждение про "актуализированную доку" 16 июня — на хост-FS дока НЕ менялась (правки шли в контейнерную FS). Реальная актуализация через `mcp_obsidian_write_note` — 2026-06-16.
## Что НЕ делаем без явного подтверждения
- Не пушить изменения в git.
-Не правим config.yaml до согласования итогового формата секции `fast-rlm`.
-Не рестартим Балду без согласования.
## Текущий статус (2026-06-19)
### ✅ Сделано
-Шаги 1–4: образ собран, контейнер `fast-rlm-mcp` Up 2 дня
-`fast-rlm-mcp` в сети `balda_default`, доступен из Валеры по DNS
- Валера (`balda-agent-valera-1`) запущен после простоя — отвечает 401 на webhook, 404 на корень
- **fast-rlm добавлен в `config.yaml` Балды** — и в `runtime.mcp_servers`, и в `balda.mcp_servers`
- Балда рестартнута
### ❓ Не проверено end-to-end
- Нужен реальный вызов `recursive_context_compress` из Валеры (через Zulip @Валера)
- В логах старта Валеры нет явного "MCP connected: fast-rlm" — возможно коннект ленивый
## История
- **2026-06-16 ~14:00**: создан после серии фабрикаций и компакций контекста. План построен с явными точками реальной проверки на каждом шаге.
- **2026-06-16 ~16:00**: пользователь поправил — провайдер LLM = DeepSeek (как у Балды/Whale), не OpenAI/OpenRouter.
- **2026-06-16 ~17:00**: актуализация через `mcp_obsidian_write_note` — добавлены секции "Провайдер LLM" и "Подтверждённый API", compose v1 вместо v2, сеть `balda_default` вместо `balda-agent_default`, файл `.env` в список, Deno в Dockerfile, галлюцинации 5–8.
- **2026-06-16 ~14:00**: создан
- **2026-06-16 ~17:00**: актуализация
- **2026-06-19 ~03:47**: Валера запущен, fast-rlm добавлен в config.yaml и рестартнут
Hermes не стримит ответ через webhook — агент отвечает одним блоком после завершения генерации. Пользователь не видит процесс печати.
**Проблема (оригинал):** WebhookAdapter не имеет `SUPPORTS_MESSAGE_EDITING` — stream_consumer не знал что редактирование не поддерживается. Consumer пытался edit, падал в fallback. Курсор `▉` оставался в финальном ответе.
**Root cause:** Webhook-транспорт не поддерживает стриминг — ответ формируется целиком и шлётся одним POST-запросом в Zulip через роутер.
1. Добавлен `adapter_supports_edit: bool = True` в `StreamConsumerConfig`
2.В`run.py` при создании consumer читается `getattr(adapter, "SUPPORTS_MESSAGE_EDITING", True)` — для WebhookAdapter возвращает `True` (нет атрибута), поэтому добавлена ручная настройка через конфиг и проверка `cfg.adapter_supports_edit`
3. Создана `else` ветка для no-edit (webhook) в stream_consumer — без курсора, отправка по `\n`
4. Добавлен rate-limit: partial на `\n` не чаще чем раз в `edit_interval` (~500ms)
5. Убран `buffer_threshold` для no-edit — partial только по `\n` + таймер, чтобы не рвать строки и не создавать дубли
6. Gateway перезапускается только через Eagle Dashboard (`localhost:8880`)
**Фикс:** ? (Пока не чинили)
**Текущее поведение:**
- Partial отправляются только при `\n` в буфере, не чаще раза в 500ms
- При `got_done` — всё накопленное отправляется
- Если LLM генерирует без `\n` — ждёт `got_done` (весь ответ одним куском)
- Всё стабильно, без дублей, без разрыва строк
### Баг 3 (Phase 2): Seed реакций не срабатывал из-за skip_bot_messages
-`data` — без него Валера видел пустой текст и слал только Session Started (никогда не отвечал моделью)
-`bot_email` — не обязателен, но для полной идентичности
-`sender_email` в message — без него `isAllowedOwner()` возвращал false
-`stream_id` в message — без него locator строился с streamID=0 (channel ID 0)
**Как это ловилось:** после исправления trigger=mention, Валера заходил в `handleAutoClaimMention`, но `payload.Data` был пустым → строка 1030 `if text == ""` → только Welcome, `handleMessage` не вызывался.
# bot_ids — sender_id ботов в Zulip (чтобы отличать сообщения человека от бота)
bot_ids:
- 9# Eagle / Орёл (Hermes)
- 10# Клавдий (claudio-bot)
- 11# Валера (balda-bot)
- 13# Кит (whale-bot)
- 14# router-bot
- 9# zulip-router-bot (legacy)
- 11# Валера (balda-bot)
- 13# Клавдий (claudio-bot)
- 14# Орёл (eagle-bot)
- 15# router-bot (current poller)
- 16# Кит (whale-bot)
default_bot:"Валера"
skip_bot_messages:true# не форвардить сообщения от ботов (включая router-bot)
skip_bot_messages:true
ownership:
ttl:24h
persist_path:"/data/ownership.json"
http:
listen::8090
```
### Поля конфига бота
| Поле | Описание |
|------|----------|
| `name` | Отображаемое имя бота |
| `bot_email` | Email бота в Zulip (для `bot_email` в forward payload) |
| `aliases` | Алиасы для @mention (все регистры) |
| `webhook` | URL POST-эндпоинта бота |
| `webhook_token` | Токен для X-Hub-Signature-256 |
| `skip_mention_forward` | Не дублировать @mention (Zulip уже доставил) |
| `forward_trigger` | Значение поля `trigger` в forward payload (fallback: owner/default) |
`forward_trigger` — добавлен 2026-06-19. Для ботов, ожидающих `trigger=mention` чтобы создать сессию. Без него роутер слал `trigger=owner`, Валера не создавал сессию и молчал.
## Что меняется в balda
После деплоя роутера Events API polling уже отключён у обоих ботов (сделано 2026-06-16):
@@ -131,62 +182,93 @@ zulip:
## Код
**Репозиторий:**`~/Developer/zulip-router/` — Go, ~260 LOC (план)
**Репозиторий:**`~/Developer/zulip-router/` — Go, ~430 LOC
**Git:**`git init` 2026-06-16. Первый коммит: `a403562` — чистый оригинал от 14:22. `.bak` файлы — слепки конфигов до правок Кита.
**Симптом:** роутер регистрирует очередь, делает `fetchEvents`с`dont_block=false`, и **зависает навсегда**. Логи отсутствуют часами. Сообщения не обрабатываются.
### 6. Валера не отвечал на сообщения от роутера (FIXED 2026-06-19)
**Фикс:**`all_public_streams=true` при регистрации очереди + обработка `BAD_EVENT_QUEUE_ID`с перерегистрацией.
**Симптом:**@mention от Zulip outgoing webhook работает, сообщения от роутера — только `Session Started`, без ответа модели. Сообщение `channel ID 0` в системных уведомлениях.
### 2. Роутер не получал события (FIXED 2026-06-17)
**Корень три проблемы в роутере:**
**Причина:** router-bot не был подписан на стримы. Очередь регистрировалась, но событий не получала.
**Фикс:**`all_public_streams=true` в `registerQueue`.
1.**Поле `data` не передавалось.** Роутер не слал `data` (текст сообщения) в payload. Валера на строке 242 читает `payload.Data` — пусто → строка 1030 `if text == ""` → только Welcome.
### 3. Сообщения до старта роутера обрабатывались (FIXED 2026-06-17)
2.**Поле `sender_email` не передавалось.**В`Message` struct не было поля `SenderEmail`. Zulip Events API не отдаёт `sender_email` — роутер не мог его заполнить. Без email `isAllowedOwner()` возвращал false.
**Фикс:** timestamp guard — сообщения с timestamp < времени старта скипаются.
3.**Поле `stream_id` не передавалось.**`Message` struct не имел `StreamID`. Валера на строке 1084 использует `payload.Message.StreamID` → default 0 → `channel ID 0`.
### 4. Сообщения от router-bot форвардились ботам (FIXED 2026-06-17)
4.**trigger=owner вместо trigger=mention.** Валера ожидает `trigger=mention` для авто-создания сессии и регистрации owner'а. Роутер слал `trigger=owner`.
**Фикс:** конфигурируемый `skip_bot_messages: true` — сообщения от ботов скипаются.
**Фиксы в коде (коммит `487f481`):**
-`config.go`: добавлены поля `SenderEmail`, `StreamID` в Message, `ForwardTrigger` в BotCfg
-`zulip.go`: добавлен метод `GetUserEmail(userID)` — дёргает Zulip API `/api/v1/users/{id}`
-`main.go`: после guards, вызов `GetUserEmail` для не-ботов; при owner-routing использует `bot.ForwardTrigger`с fallback "owner"; default-routing аналогично
-`forwarder.go`: добавлены поля `Data`, `BotEmail` в forwardPayload; заполняются при Forward()
-`config.yaml`: `forward_trigger: mention` для Валеры и Клавдия
**Итог:** роутер шлёт payload, **идентичный** Zulip outgoing webhook. Валера не видит разницы.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.