Files
obsidian-vault/personal/tech/hermes-fork-vs-upstream.md
T

11 KiB
Raw Blame History

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-платформа (наша, в апстриме отсутствует):

  • b0f097a299 feat: add Zulip platform adapter (parallel to Discord)
  • ce093b0a75 zulip: switch approval prompt emojis /👍/👎
  • b1e36eb2d7 fix(zulip): lock→locked emoji name
  • f39671ba97 fix(routing): pre_gateway_dispatch before session guard
  • d4e98a8b07 / ef69e76413 / 40149225af / ddc6aa7c46 webhook: zulip in BUILTIN_DELIVER_PLATFORMS, session_chat_id из X-Chat-Id
  • 8255ea0c64 feat(zulip): session_search читает Zulip thread history
  • 049922d8cc fix(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:

  • 972004546f feat: thread-scoped memory + configurable memory instruction
  • 4ebad4f692 test: thread-scoped memory persistence, drift guard, snapshot
  • da146da5fa feat: configurable background review prompts and allowed toolsets
  • 207a1de16c feat: load stable system-prompt blocks from config prompt_overrides

Прочее:

  • 6e09a3704a fix(approval): interrupt pending approvals on user message
  • a17d02f31e fix(api_server): tool.progress → plain-text chunks
  • 81f10c306f approval: reaction emoji на webhook

Риск конфликтов при merge

Dry-run git merge-tree16 конфликтных файлов, 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 как новую базу, затем перенести наши фичи патчами заново:

  1. Сохранить наши diff'ы как patch-файлы (git format-patch)
  2. Форк от свежего апстрима
  3. Переносить по темам: Zulip-адаптер (в plugins/platforms/!), 3 фичи Whale (thread-scoped memory, bg-review, prompt_overrides), webhook-стриминг
  4. 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

Связанное