11 KiB
Hermes — апстрим vs наш форк
Дата: 2026-09-15
Статус: актуально — анализ расхождения сделан, стратегия подтяжки НЕ выбрана
Репо: ~/.hermes/hermes-agent (сабмодуль, форк mallexxx/hermes-agent)
Текущее решение: не принято
На 2026-09-15 Alex'у представлены 3 варианта (A merge / B перенос на свежий апстрим / C заморозка). Выбор не сделан. Работа над подтяжкой не начата. Наш форк запушен и стабилен — можно спокойно решать.
Открытый вопрос, определяющий выбор: нужны ли нам вообще 24k коммитов
апстрима? Мы используем Hermes как Zulip-бота с webhook-флоу; апстрим растёт
десктопом/TUI/платформами, которые нам не нужны. Точечный cherry-pick
(security-фиксы, фиксы agent/, новые модели) может быть достаточен.
Масштаб расхождения
| Метрика | Значение |
|---|---|
| Коммитов апстрима впереди | 24 407 |
| Наших коммитов | 32 |
| Common ancestor | 4ed63170e4 (2026-06-04) |
| Дата последнего коммита апстрима | 2026-09-15 |
| Наша версия | 0.15.1 |
| Версия апстрима | 0.21.3 |
| Файлов изменено апстримом | 12 634 |
| Строк: +2 362 152 / −763 849 |
Вывод: это не «догнать на пару недель», а ~3.5 месяца и 24k коммитов. Апстрим ушёл на мажорные версии вперёд (0.15 → 0.21).
Ремоуты
| Remote | URL | Роль |
|---|---|---|
origin |
git@github.com:mallexxx/hermes-agent.git |
наш форк |
upstream |
https://github.com/NousResearch/hermes-agent.git |
источник |
Главные изменения апстрима
1. Платформы переехали из ядра в плагины ⚠️ КРИТИЧНО
Апстрим удалил telegram.py, slack.py, matrix.py, discord.py из
gateway/platforms/ — теперь они живут в plugins/platforms/.
Состав plugins/platforms/ у апстрима (19):
a2a, buzz, dingtalk, discord, email, feishu, google_chat, homeassistant, irc, line, matrix, mattermost, ntfy, photon, raft, simplex, slack, sms, teams, telegram, wecom, whatsapp
Наш plugins/platforms/ (8): discord, google_chat, irc, line, mattermost, ntfy, simplex, teams
⚠️ Zulip НЕТ ни в ядре апстрима, ни в plugins/platforms/ апстрима.
Проверено: git ls-tree -r upstream/main | grep -i zulip → пусто.
Zulip — полностью наша разработка:
gateway/platforms/zulip.py— не существует в апстримеtools/zulip_thread_tool.py— не существует в апстриме
Это значит: наш Zulip-адаптер живёт в устаревшем месте (gateway/platforms/),
которое апстрим планомерно опустошает. При подтяжке его придётся переносить в
plugins/platforms/ — иначе он повиснет на api, которого больше нет.
2. Смежные подсистемы
Топ-скоупы по числу feat/refactor коммитов:
| Скоуп | Коммитов | Что это |
|---|---|---|
desktop |
773 | Десктоп-приложение — крупнейшая новая подсистема |
hermes_cli |
607 | CLI переработан |
gateway |
412 | Ядро гейтвея |
tools |
339 | Инструменты |
agent |
217 | Ядро агента |
cli / tui / tui_gateway |
141/100/76 | TUI (Ink/React) |
state |
106 | Персистентность сессий |
cron |
91 | Планировщик |
computer_use |
86 | Управление десктопом |
mcp |
79 | MCP-клиент |
relay |
54 | Новая подсистема релея |
Типы коммитов: fix 10 994, refactor 4 158, feat 2 113, test 1 836.
Читается так: апстрим прошёл большую волну рефакторинга (4158) + массовый
десктоп/TUI-фронт. Наши правки в gateway/run.py (13 коммитов) и
gateway/stream_consumer.py (9) — ровно в эпицентре этого рефакторинга.
Наши 32 коммита
Сгруппированы по темам:
Zulip-платформа (наша, в апстриме отсутствует):
b0f097a299feat: add Zulip platform adapter (parallel to Discord)ce093b0a75zulip: switch approval prompt emojis ✅/❌ → 👍/👎b1e36eb2d7fix(zulip): lock→locked emoji namef39671ba97fix(routing): pre_gateway_dispatch before session guardd4e98a8b07/ef69e76413/40149225af/ddc6aa7c46webhook: zulip in BUILTIN_DELIVER_PLATFORMS, session_chat_id из X-Chat-Id8255ea0c64feat(zulip): session_search читает Zulip thread history049922d8ccfix(session_search): dual Zulip+SQLite recall, FTS5 sanitization
Webhook no-edit streaming (наш флоу без редактирования сообщений):
fa271d2d19,ee41e8a847,9003d4cbbe(revert),1ac06d593a,9253fe52cc,88cbb77b95,6c95153aa8,eb8dd7b5ed,a92840dcde,a08527e85c,a88bec1762,5d3e95841b,ec9efce7e7
Фичи профиля Whale:
972004546ffeat: thread-scoped memory + configurable memory instruction4ebad4f692test: thread-scoped memory persistence, drift guard, snapshotda146da5fafeat: configurable background review prompts and allowed toolsets207a1de16cfeat: load stable system-prompt blocks from config prompt_overrides
Прочее:
6e09a3704afix(approval): interrupt pending approvals on user messagea17d02f31efix(api_server): tool.progress → plain-text chunks81f10c306fapproval: reaction emoji на webhook
Риск конфликтов при merge
Dry-run git merge-tree → 16 конфликтных файлов, 160 конфликтных маркеров.
| Файл | Наших коммитов | Коммитов апстрима | Риск |
|---|---|---|---|
gateway/run.py |
13 | 974 | 🔴 экстремальный |
cron/scheduler.py |
1 | 307 | 🟠 |
agent/agent_init.py |
3 | 226 | 🟠 |
gateway/platforms/base.py |
2 | 208 | 🟠 |
gateway/platforms/api_server.py |
1 | 177 | 🟠 |
agent/model_metadata.py |
1 | 164 | 🟡 |
tools/approval.py |
1 | 147 | 🟡 |
agent/prompt_builder.py |
0 | 131 | auto-merge ok |
gateway/stream_consumer.py |
9 | 73 | 🟠 (наш файл, апстрим переписал) |
agent/system_prompt.py |
2 | 65 | 🟡 |
gateway/platforms/webhook.py |
7 | 59 | 🟠 |
toolsets.py |
2 | 62 | 🟡 |
tools/session_search_tool.py |
2 | 41 | 🟢 |
tools/memory_tool.py |
1 | 34 | 🟢 |
| остальные | 1 | <30 | 🟢 |
Худший случай: gateway/run.py — 974 коммита апстрима против наших 13.
Это фактически переписывание файла. Конфликты там будут не «принять/отклонить
строку», а разбор чужой новой архитектуры.
Стратегии подтяжки
Вариант A: merge (сейчас) — НЕ рекомендуется
git merge upstream/main → 16 конфликтных файлов, ручной разбор 160 маркеров
в горячих файлах. Оценка: дни на run.py + stream_consumer.py, риск
потерять наши webhook/Zulip-правки.
Вариант B: перенос нашей функциональности на свежий апстрим (рекомендуется)
Взять чистый upstream/main как новую базу, затем перенести наши фичи
патчами заново:
- Сохранить наши diff'ы как patch-файлы (
git format-patch) - Форк от свежего апстрима
- Переносить по темам: Zulip-адаптер (в
plugins/platforms/!), 3 фичи Whale (thread-scoped memory, bg-review, prompt_overrides), webhook-стриминг - Webhook-стриминг — вероятно уже решён апстримом, проверить перед переносом
Плюс: результат на актуальной кодовой базе, без 24k коммитов долга. Минус: ручная работа по переносу, ~1-2 дня.
Вариант C: заморозить и жить на форке
Принять, что мы отдельный продукт. Апстрим берём точечно (git cherry-pick
отдельных фиксов безопасности). Дёшево сейчас, растёт долг потом.
Ключевой вопрос перед подтяжкой
Нужны ли нам вообще 24k коммитов апстрима? Мы используем Hermes как Zulip-бота с webhook-флоу. Ядро апстрима прирастает десктопом, TUI и платформами (telegram/slack/...), которые нам не нужны. Реальная ценность от апстрима для нас:
- фиксы безопасности (
tools/tirith_security.py, approval) - фиксы багов в
agent/(метаданные моделей, сжатие контекста) - поддержка новых моделей/провайдеров
Это можно брать точечно (cherry-pick), не таща весь долг.
Команды для проверки расхождения
cd ~/.hermes/hermes-agent
# Обновить инфу об апстриме
git fetch upstream
# Насколько отстали
git rev-list --count main..upstream/main # апстрим впереди
git rev-list --count upstream/main..main # мы впереди
# Общий предок
git merge-base main upstream/main
# Изменения по нашим файлам
git diff --name-only $(git merge-base main upstream/main)..main | sort -u
# Насколько апстрим трогал конкретный файл
git rev-list --count $(git merge-base main upstream/main)..upstream/main -- gateway/run.py
# Dry-run merge (безопасно, не трогает рабочую копию)
git merge-tree --write-tree --name-only main upstream/main
# Есть ли файл в апстриме
git cat-file -e upstream/main:gateway/platforms/zulip.py && echo yes || echo NO
Связанное
- hermes-git-repo — структура репо, .gitignore, что коммитить
- hermes-whale-system-prompt — prompt_overrides (наша фича)
- hermes-memory-architecture — thread-scoped память (наша фича)