Files
obsidian-vault/personal/tech/hermes-whale-mattermost-transport.md
T

13 KiB
Executable File
Raw Blame History

title, created, updated, type, namespace, status, tags, related
title created updated type namespace status tags related
hermes-whale — Mattermost как транспорт 2026-09-29 2026-09-29 tech personal in-progress — бот и канал созданы, транспорт НЕ дописан
hermes
mattermost
transport
whale
kraken
lsp
personal/projects/balda/mattermost-kraken-deploy.md
personal/tech/kraken-host-resource-limits.md
personal/tech/hermes-fork-vs-upstream.md

hermes-whale — Mattermost как транспорт

Задача Alex 2026-09-29: «Добавь mattermost на кракене транспортом в hermes-whale и добавь в MM бота себе нового (Кит/whale)». Статус: бот whale и канал созданы ✅, транспорт в .env НЕ дописан ⏳.

Расклад (решение)

Компонент Где Почему
hermes-whale gateway Mac (не Kraken) профиль живёт на Mac; это НЕ переезд
Mattermost сервер Kraken уже работает, health=healthy
Связь https://mm.qentra.top (Cloudflare Tunnel) проверено 2026-09-29: {"status":"OK"}

⚠️ На Kraken транспорт НЕ разворачивается. Там 4 ГБ RAM и история OOM (см. personal/tech/kraken-host-resource-limits.md). Mattermost-транспорт в контейнере hermes-kraken не поднимаем.

Готовое: плагин уже существует

Код писать не нужно — платформа mattermost уже в дереве:

~/.hermes/hermes-agent/plugins/platforms/mattermost/adapter.py
~/.hermes/hermes-agent/plugins/platforms/mattermost/plugin.yaml

Env-переменные (из plugin.yaml)

Переменная Обяз. Смысл
MATTERMOST_URL ✅ URL сервера, напр. https://mm.qentra.top
MATTERMOST_TOKEN ✅ токен бота или PAT
MATTERMOST_HOME_CHANNEL — канал для cron/уведомлений
MATTERMOST_REPLY_MODE — thread (вложенно) или off (плоско). Дефолт off
MATTERMOST_REQUIRE_MENTION — требовать @bot в каналах (дефолт true)
MATTERMOST_ALLOWED_USERS — белый список user id
MATTERMOST_ALLOW_ALL_USERS — любой юзер триггерит бота (dev)
MATTERMOST_FREE_RESPONSE_CHANNELS — каналы без обязательного @mention
MATTERMOST_ALLOWED_CHANNELS — если задан — бот отвечает ТОЛЬКО в них

📌 Адаптер читает config.extra.{url, reply_mode} ИЛИ env (adapter.py:77-97). В config.yaml профиля есть блок mattermost: (пока только channel_prompts).

Созданные объекты MM (2026-09-29)

Объект ID Как создано
Бот whale (Кит) k4i3uihzp3gdxj5gx3en3tbeso mmctl user create → mmctl user convert --bot
Канал whale fnm6auyc8trz5njxrfofebkbfr mmctl channel create --team qentra
Команда qentra = m1iwp7t9w7no3y8gi876iw39he существовала
Владелец бота whale (Owned by whale) ⚠️ не admin, см. ниже

✅ Бот в канале — подтверждено живой командой:

channel users list qentra:whale
→ k4i3uihzp3gdxj5gx3en3tbeso: whale (whale@localhost) channel_user

⚠️ Бот в команде — не подтверждено. mmctl team users add qentra <bot_id> вернул exit=0 (молчаливый успех), но проверить нечем: mmctl team users list не существует (только add / remove). Проверять через API GET /api/v4/teams/{team_id}/members/{user_id} — требует рабочего PAT.

🔴 Питфоллы, найденные на месте

  1. mmctl user convert --bot требует ШЕСТЬ флагов, не один. --owner не существует вовсе. Минимальный набор из --help:

    mmctl --local user convert <user> --bot \
      --email <e> --firstname <f> --lastname <l> --locale en --system-admin
    

    Без --email/--firstname/--lastname/--locale конвертация не проходит. Вывод успеха: whale converted to bot.

  2. mmctl user convert НЕ выдаёт токен. Токен выпускается отдельно: mmctl --local token generate whale <desc>. MM отдаёт значение ровно один раз.

  3. mmctl channel list --json печатает не-JSON перед JSON. Первая строка — There are 4 channels on local instance, потом [. jq падает с parse error: Invalid numeric literal at line 1, column 6. Обход: sed -n '/^\[/,$p' | jq ….

  4. mmctl team users list НЕ существует. Есть только add/remove. Проверка членства — только через REST API.

  5. REST /api/v4/... с токеном из .adminpw даёт 401 (api.context.session_expired.app_error). .adminpw — пароль, не токен. Для API нужен PAT: mmctl --local token generate admin <desc>, заголовок Authorization: Bearer <token>. ⚠️ Заголовок Token: в MM 11.x не принимается.

  6. mmctl не имеет команды чтения состава команды — приходится идти в API. Постинг тоже недоступен (post create → not supported in local mode), чтение работает.

Что осталось (следующий заход)

  1. Выпустить токен бота:

    ssh kraken "docker exec mattermost mmctl --local token generate whale whale-hermes"
    

    ⚠️ Значение показывается один раз — перехватить сразу, записать в 0600-файл.

  2. Вписать в /Users/admin/.hermes/hermes-whale/.env:

    MATTERMOST_URL=https://mm.qentra.top
    MATTERMOST_TOKEN=<токен>
    MATTERMOST_HOME_CHANNEL=fnm6auyc8trz5njxrfofebkbfr
    MATTERMOST_REPLY_MODE=thread
    MATTERMOST_REQUIRE_MENTION=true
    
  3. Перезапустить gateway на Mac: hermes gateway run --replace.

  4. Приёмка = Alex пишет @whale привет в канале whale, видит ответ в UI. Не «контейнер Up», не «curl отвечает».

Main delivery / Telegram — 🔴 ЗАБЛОКИРОВАНО

Alex: «main delivery поставь телеграм, там есть вроде бот для Кита».

Бота для Telegram НЕТ. Проверено: в hermes-whale/.env — ни одной TELEGRAM_* переменной. Полный список ключей .env:

DEEPSEEK_API_KEY  FIRECRAWL_API_URL  GLM_API_KEY
ZULIP_ALLOWED_USERS  ZULIP_API_KEY  ZULIP_BOT_EMAIL  ZULIP_DEFAULT_TOPIC
ZULIP_FREE_STREAMS  ZULIP_HOME_CHANNEL  ZULIP_POLLING_DISABLED
ZULIP_REQUIRE_MENTION  ZULIP_URL

Код адаптера есть (gateway/platforms/telegram.py), токена нет.

🔴 Создать Telegram-бота программно невозможно — только через BotFather вручную. Нужен TELEGRAM_BOT_TOKEN от Alex. Пока его нет — main delivery на Telegram поставить нечем.

Действующий home-канал профиля сейчас — Zulip (/master::hermes).

LSP-серверы — разбор (вопрос Alex)

Что это. Подсистема agent/lsp/ — language-серверы, которые write_file/patch дёргают сразу после записи файла для семантической проверки (pyright → .py, gopls → .go, yaml-language-server → .yaml). Это те самые «auto-runs syntax checks».

Обязательны? Нет. Мастер-тумблер lsp.enabled (дефолт true).

Почему их 15 и почему 2.4 ГБ. Это живые дети gateway pid 31763, не осиротевшие. Не переиспользуются: каждое открытие Go-проекта поднимает новый gopls.

ppid=31763  pid=99339  604MB  up 3д 09:38   gopls
ppid=31763  pid=67249  383MB  up 2д 10:44   gopls
ppid=31763  pid=71815  256MB  up 2д 09:14   gopls
ppid=31763  pid=95153   14MB  up 19:44     bash-language-server
… ещё 11 × 8-14 МБ (pyright / yaml-language-server / docker-langserver)

Итог: ~1.24 ГБ в трёх gopls + ~1.1 ГБ в node-серверах ≈ 2.4 ГБ.

Ручка Что делает
hermes lsp restart рвёт клиентов, при следующей правке спавнятся заново. Разово вернёт ~2 ГБ
lsp.enabled: false выключает подсистему целиком — «no servers spawn, no background event loop, no cost»
lsp.install_strategy: manual auto (дефолт) сам ставит бинари в <HERMES_HOME>/lsp/bin/
lsp.servers.<id>.disabled: true отключить конкретный сервер (напр. gopls)

📌 Gating: LSP включается только когда cwd (или файл) внутри git-worktree. Вне git-репо подсистема спит, работает только in-process синтаксическая проверка — поэтому на Kraken (контейнер, cwd не git) LSP не потребляет RAM.

📌 На Mac 64 ГБ — не проблема. Это зафиксировано, чтобы не «оптимизировать» зря.

Замер памяти Hermes (2026-09-29, вопрос Alex «сколько hermes жрёт памяти»)

Что Где RSS
hermes-whale gateway (этот профиль) Mac 165 МБ — pid 31763 = 112 МБ, pid 2934 = 53 МБ
hermes-kraken gateway Kraken (контейнер) 139 МБ (замер 2026-09-27)
LSP-серверы Mac ~2.4 ГБ (15 процессов) — это НЕ Hermes

⚠️ Не путать: «Hermes ест 165 МБ», а «2.4 ГБ едят LSP-процессы, порождённые gateway». Второй pid 2934 (up 6 дней) — второй gateway, вероятно от другого профиля/--replace-инстанс.

Бэкапы (перед правкой)

/Users/admin/.hermes/hermes-whale/backups/20260929-105131-mm-transport/

Файл md5 (совпадает с рабочим)
config.yaml 7b348fa585baede4d85e4bb7057694af
env 6f58de78b7c882bff84bf556ca8fa67b

⛔ .env и config.yaml профиля ещё НЕ изменены — транспорт не дописан.

Скрипты этой сессии (в /tmp, не переживут reboot)

whale-mm-backup.sh · whale-mm-probe.sh · whale-mm-create.sh · whale-mm-convert.sh · whale-mm-membership.sh · whale-mm-verify.sh

⚠️ /tmp/whale-mm-verify.sh остался с битым heredoc (сломан харнессом при записи) — переписать заново перед использованием, не запускать как есть.

Ответ на вопрос «можно ли создавать каналы и пинговать бота»

Вопрос Ответ
Создавать каналы ✅ да, Alex — админ. EnableOpenServer=false / EnableUserCreation=false закрывают только самостоятельную регистрацию чужих, админу не мешают
Пинговать бота ✅ да, но бот обязан быть в команде И в канале, иначе посты падают 403 api.context.permissions.app_error
Команд на MM одна — qentra

Связанные заметки