[2026-06-18] taiga-vault: family/how-to/hermes-eagle-mac.md family/how-to/kraken-access.md family/how-to/switch-emulation-rom-infra.md personal/projects/balda/balda-valera.md personal/projects/balda/claudio-klaudiy.md personal/projects/balda/fast-rlm-integration.md personal/projects/balda/setup.md personal/projects/hermes-configs/eagle-config.example.yaml personal/projects/hermes-configs/whale-config.example.yaml personal/projects/personal-os/eagle-dashboard.md
This commit is contained in:
@@ -1,54 +1,88 @@
|
||||
# Балда / Валера — эксплуатация
|
||||
|
||||
## Расположение
|
||||
- Repo: `~/Developer/balda/`
|
||||
- Repo: `~/Developer/balda/` (ветка `main`)
|
||||
- Code: upstream `normahq/balda` + `feat/zulip-transport` влит, `normahq/norma` v0.0.10
|
||||
- **Рабочий compose**: `~/Docker/balda-agent/docker-compose.yaml` → контейнер `balda-agent-valera-1`
|
||||
- Config (persistent): `~/Docker/balda-agent/.config/balda/config.yaml`
|
||||
- Env: `~/Docker/balda-agent/.env`
|
||||
- Дублирующий compose `~/Developer/balda/compose.valera.yaml` — НЕ использовать (сеть `balda_default` без DNS)
|
||||
- Owner: `allowed_owners` в config.yaml (статически, `/start owner=` не нужен)
|
||||
|
||||
## Запуск / рестарт
|
||||
|
||||
```bash
|
||||
cd ~/Docker/balda-agent
|
||||
docker-compose restart
|
||||
docker-compose restart # без пересборки, только конфиг/env не менялись
|
||||
docker-compose up -d # пересоздать контейнер, перечитать .env
|
||||
|
||||
# Rebuild после изменений в коде:
|
||||
docker-compose build && docker-compose up -d
|
||||
cd ~/Docker/claudio-agent && docker-compose build
|
||||
docker tag claudio-agent-claudio:latest balda-agent-valera:latest
|
||||
cd ~/Docker/claudio-agent && docker-compose up -d
|
||||
cd ~/Docker/balda-agent && docker-compose up -d
|
||||
```
|
||||
|
||||
> Валера и Клавдий — **один образ** (`balda-agent-valera`), собирается из одного Dockerfile (`Dockerfile.claudio`). Разница только в конфиге (`config.yaml`) и `.env`, которые монтируются volumes. Сборка идёт из `~/Docker/claudio-agent/` — там есть build секция.
|
||||
|
||||
## Архитектура получения сообщений
|
||||
Валера — **outgoing webhook bot** (bot_type=3). Zulip отправляет webhook только для @mention и DM.
|
||||
|
||||
Для получения всех сообщений в теме — Events API polling (горутина в коде):
|
||||
- `events_polling.enabled: true` в config.yaml
|
||||
- Очередь регистрируется с `all_public_streams=true`
|
||||
- Бот подписывается на все публичные стримы при старте (`SubscribeToPublicStreams`)
|
||||
- `events_polling.enabled: false` в config.yaml
|
||||
- Сообщения приходят только через **outgoing webhook** (webhook_token в .env)
|
||||
- После @mention создаётся сессия; последующие сообщения без @mention обрабатываются
|
||||
|
||||
**После перезапуска**: нужно один раз написать `@Валера <текст>` чтобы создать сессию в теме.
|
||||
**После перезапуска**: написать `@Валера <текст>` чтобы создать сессию.
|
||||
|
||||
## MCP Obsidian — конфиг
|
||||
Balda через SSE подключается к obsidian-mcp. **URL обязательно с `/sse`**:
|
||||
|
||||
```yaml
|
||||
runtime:
|
||||
mcp_servers:
|
||||
obsidian:
|
||||
type: sse
|
||||
url: http://obsidian-mcp:3101/sse # <-- без /sse → 404 Not Found
|
||||
name: obsidian
|
||||
```
|
||||
|
||||
## Контекст (история сообщений)
|
||||
**Работает** (на upstream `normahq/balda` с поддержкой hosted LLM agent sessions). ADK inject'ит историю корректно для OpenAI-совместимых провайдеров.
|
||||
|
||||
Раньше не работало — исправлено в upstream `32e33a8 fix: support hosted MCP toolsets` / `d774c78 fix: use hosted llmagent sessions`.
|
||||
|
||||
## Диагностика молчания
|
||||
1. Проверить логи: `docker logs balda-agent-valera-1 --tail 50`
|
||||
2. Проверить что Events API polling запустился: `zulip events queue registered` в логах
|
||||
3. Стухший NATS-таск (симптом: логов нет после @mention)
|
||||
Фикс: `docker-compose restart` (NATS embedded, состояние в памяти)
|
||||
4. Бот не подписан на стримы (симптом: `processing zulip message trigger=stream` не появляется):
|
||||
```bash
|
||||
curl -u "<bot_email>:<api_key>" https://zulip.qentra.top/api/v1/users/me/subscriptions
|
||||
```
|
||||
Если пустой — должен подписаться при следующем старте. Или вручную через API.
|
||||
|
||||
## Патчи в коде (общие с Клавдием)
|
||||
### 1. MCP ошибка: `failed to list MCP tools: failed to connect: Not Found`
|
||||
**Причина**: в config.yaml url без `/sse` на конце.
|
||||
**Фикс**: `url: http://obsidian-mcp:3101/sse` → `docker-compose restart`.
|
||||
|
||||
В `zulip_handler.go` добавлены:
|
||||
1. `botName` — извлекается из bot_email (часть до @). Используется чтобы отличить свой @mention от чужого.
|
||||
2. `extractOtherMention()` — проверяет текст на @**Name**, где Name не равен botName и не @**all**/@**everyone**. Если найден чужой @mention — сообщение игнорируется.
|
||||
3. Детальное логирование в `handleAutoClaimMention` — видны все шаги от входа до ошибки.
|
||||
### 2. В логах `command running → command handled` за секунду, без `received provider event`
|
||||
**Причина**: стухший embedded NATS. Swarm внутри процесса не доставляет команду до session/task actor'ов.
|
||||
**Фикс**: `docker-compose restart` (если не помогло → `up -d`).
|
||||
|
||||
### 3. Удалён / пустой state.db
|
||||
После удаления balda не может зарегистрировать swarm акторы.
|
||||
**Фикс**: `rm state.db` и `up -d` (balda создаст заново).
|
||||
|
||||
### 4. Нет owner
|
||||
`handleMessage` выходит при `getOwnerID() == 0`.
|
||||
**Фикс**: прописать `allowed_owners` в config.yaml (не нужен `/start owner=`).
|
||||
|
||||
### 5. stream_only_with_session
|
||||
Сообщение в теме без сессии молча дропается.
|
||||
**Фикс**: написать `@Валера <текст>` чтобы создать сессию.
|
||||
|
||||
### 6. Проверить webhook со стороны
|
||||
```bash
|
||||
curl -X POST http://localhost:8091/zulip/webhook \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"type":"test"}'
|
||||
```
|
||||
|
||||
## Ключевые грабли
|
||||
|
||||
### 1. OPENAI_BASE_URL — обязательная env var
|
||||
Norma не читает `base_url` из config.yaml для `provider: deepseek`. Она читает env `OPENAI_BASE_URL`.
|
||||
### OPENAI_BASE_URL — обязательная env var
|
||||
Norma не читает `base_url` из config.yaml для `provider: deepseek`. Читает env `OPENAI_BASE_URL`.
|
||||
Без неё запросы уходят на `api.openai.com` (401).
|
||||
|
||||
**В `.env` обязательно:**
|
||||
@@ -56,37 +90,12 @@ Norma не читает `base_url` из config.yaml для `provider: deepseek`.
|
||||
OPENAI_BASE_URL=https://api.deepseek.com/v1
|
||||
```
|
||||
|
||||
**ВАЖНО:** `docker-compose restart` не перечитывает `.env`. Нужно `docker-compose up -d` (пересоздание контейнера).
|
||||
|
||||
### 2. DOCKER_OPTS — пустая строка убивает старт
|
||||
Если `DOCKER_OPTS=""` (или пустая строка в `.env`), norma падает на парсинге float:
|
||||
```
|
||||
strconv.ParseFloat: parsing ""
|
||||
```
|
||||
|
||||
**Должен быть валидный JSON:**
|
||||
### DOCKER_OPTS — пустая строка убивает старт
|
||||
Должен быть валидный JSON:
|
||||
```
|
||||
DOCKER_OPTS={"max_tokens": 2048, "temperature": 0.7}
|
||||
```
|
||||
|
||||
### 3. composerestart vs compose up -d
|
||||
- `docker-compose restart` — не перечитывает `.env`, не пересоздаёт контейнер
|
||||
- `docker-compose up -d` — пересоздаёт контейнер с обновлённым `.env`
|
||||
|
||||
При изменении `.env` всегда использовать `up -d`.
|
||||
|
||||
## Конфигурация провайдера
|
||||
В `config.yaml` обязательно:
|
||||
```yaml
|
||||
balda:
|
||||
provider: deepseek
|
||||
zulip:
|
||||
events_polling:
|
||||
enabled: true
|
||||
stream_only_with_session: true
|
||||
runtime:
|
||||
providers:
|
||||
deepseek:
|
||||
openai:
|
||||
base_url: https://api.deepseek.com/v1
|
||||
```
|
||||
### composerestart vs compose up -d
|
||||
- `restart` — не перечитывает `.env`
|
||||
- `up -d` — пересоздаёт контейнер с обновлённым `.env`
|
||||
|
||||
Reference in New Issue
Block a user