Commit graph

13 commits

Author SHA1 Message Date
Hermes Team
7e83c38340 perf(antigravity): из десяти аккаунтов одновременно работал один
В adapters/antigravity_adapter.py жил модульный _AGY_INVOCATION_LOCK, общий
для ВСЕХ профилей Antigravity. Он брался при каждом вызове, у которого есть
учётные данные, то есть при каждом рабочем. Ветка без мьютекса срабатывала
только у профиля без учётки — у вызова, который и так упадёт.

Измерено на живом адаптере: три параллельных вызова по одной секунде
занимали 3.01 с. При десяти подключённых аккаунтах одновременно работал ровно
один, чем обесценивалась вся мультиаккаунтность — то, ради чего хаб и делался.

Мьютекс охранял пустоту. Он был введён в 50fde5f со словами «guarded global
gemini:antigravity credential swap ... to eliminate concurrent subprocess
race», когда подмена учётных данных была ГЛОБАЛЬНОЙ. С тех пор она стала
попрофильной: agy_subprocess пишет в profile_dir/.gemini/oauth_creds.json, а
HOME, USERPROFILE, HOMEPATH и HOMEDRIVE подменяются на каталог профиля.
Общего состояния между профилями не осталось — проверено поиском глобальных
путей и обращений к keyring, их нет.

После снятия: те же три вызова занимают 1.00 с, и каждый идёт со своим HOME
(ag-w1, ag-w2, ag-w3) — изоляция не пострадала.

Ограничение одновременности остаётся за LeaseManager: он считает лизы по
профилю и настраивается через max_concurrency, в том числе значением 1 для
локальных моделей с --parallel 1.

Добавлен тест, удерживающий это свойство: он падает, если вызовы разных
профилей снова начнут сериализоваться. Существующий тест изоляции учётных
данных проходит без изменений.

Найдено при разборе анализа, который Antigravity провёл на сервере владельца
(hermes-muliacount). 459 passed, ruff чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 20:04:52 +07:00
Hermes Team
e15f12a3bd fix(router): обработчик ошибок падал сам, уровень усилия не подставлялся
Найдено проверкой всех шести ролей на живой машине владельца. До правок
работали три роли из шести.

1. antigravity_adapter.classify_error возвращал ErrorCategory.UNKNOWN —
   значения с таким именем не существует, есть AUTH_REQUIRED, FATAL,
   INVALID_REQUEST, QUOTA_EXHAUSTED, RATE_LIMITED, TRANSIENT. Обращение
   роняло сам классификатор с AttributeError, то есть отказ происходил
   ровно там, где обрабатывался другой отказ, и маршрутизация обрывалась
   вместо перехода к резервному профилю. Заменено на FATAL по образцу
   codex и opencode: неразобранная ошибка не должна давать повторов.

2. Уровень усилия не подставлялся, если у конкретного профиля не выполнен
   вход agy: карта усилий строится обнаружением ЧЕРЕЗ этот профиль, и при
   неудаче оставалась пустой. Уровни же — свойство модели, а не аккаунта.
   Добавлен запасной источник: сохранённый на диске список моделей со
   склеенными идентификаторами вида gemini-3.7-flash-high, из которых
   уровни выводятся напрямую и переживают перезапуск.

После правок работают все шесть ролей, включая живое переключение
'fast': opengo-1 -> ag-w4.

Закрыто тестами, включая защиту от возврата несуществующей категории.

Тесты: 373 passed, ruff чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 08:51:01 +07:00
Hermes Team
45fd01a15e fix(agy): подстановка уровня усилия — gemini-3.7-flash работает как есть
Владелец возразил на моё утверждение, что gemini-3.7-flash не существует.
Он прав, утверждение было неверным, и я повторил его в четырёх заданиях.

gemini-3.7-flash — настоящее семейство, уровень усилия у неё отдельный
параметр. В интерфейсе Antigravity это видно прямо: пункт «Gemini 3.7
Flash» с вложенным выбором Low/Medium/High. В коде это отражено:
_display_to_cli разбирает «Gemini 3.7 Flash (High)» в пару
("gemini-3.7-flash", "high"). Меня ввела в заблуждение первая колонка
вывода agy models со склеенными идентификаторами.

Настоящий дефект был в коде: _model_supported_efforts вызывала
discover_models() БЕЗ профиля, то есть в глобальном окружении без входа.
Карта поддерживаемых усилий оставалась пустой, подстановка уровня по
умолчанию не срабатывала, и agy отвергал вызов с «requires --effort» —
при совершенно настоящей модели.

profile_id проведён через agy_generate в _model_supported_efforts.
Проверено исполнением: gemini-3.7-flash без указания усилия отрабатывает
и возвращает ответ.

Моки в test_antigravity_concurrency приведены к терпимости по kwargs.

Добавлена поправка agents/inbox/2026-08-24-CORRECTION-gemini-model-names.md:
ложное утверждение попало в A9, A11, A18 и B8, и без опровержения кто-то
чинил бы несуществующую проблему или сломал рабочую конфигурацию.

Тесты: 359 passed, ruff чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 01:18:00 +07:00
Hermes Team
ae813a991b feat(antigravity): implement native agy login, profile isolation, and protect global ~/.gemini (A22) 2026-08-23 23:57:57 +07:00
Hermes Team
bb4f6df67a fix(oauth): preserve complete credentials and sync oauth_creds.json for Antigravity profiles (A20)
- Add openid to OAuth scopes for id_token issuance
- Preserve id_token, scope, and token_type on token exchange and refresh
- Atomically write and sync .gemini/oauth_creds.json in profile directories
- Auto-resolve active profile environment in discover_models
- Cache discovered models in models_cache.json with graceful timeout handling
- Add unit test coverage for full OAuth lifecycle and model discovery caching
2026-08-23 23:09:58 +07:00
Hermes Team
b0a939cecd feat(A11): интеграция с Hermes, токены Codex, честное обнаружение моделей
Работа A11 была выполнена, но осталась незакоммиченной в рабочем каталоге
на машине владельца: в origin ушла пустая ветка. Восстановлена ревьюером
из рабочего дерева и зафиксирована здесь.

Содержание:
- agy_subprocess: зонд обнаружения моделей переведён с разбора ошибки
  заведомо неверной модели на штатную команду `agy models`;
- antigravity_adapter: убран выдуманный запасной список gemini-2.5-*,
  моделей с такими именами у провайдера не существует;
- codex_oauth: добавлен refresh_codex_token — обновление по refresh_token,
  которого не было вовсе;
- quota_collector: source больше не заявляет provider_api там, где ни
  одна корзина не измерена; применено к antigravity и opencode-go;
- hermes_plugin: правка обработки роли, поверх сохранённой 2d62d39.

Исправлено при фиксации: тест test_opencode_shows_published_limits
закреплял прежнюю семантику source и падал. Приведён к честной:
source описывает происхождение чисел, а не факт ответа провайдера;
информация об ответе сохраняется в unavailable_reason.

Проверено исполнением: `agy models` сейчас нестабилен и висит даже при
прямом вызове (rc=124 по таймауту 100 с) — зонд честно возвращает пусто
и сохраняет кэш, а не выдумывает список.

Тесты: 303 passed, ruff чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 15:27:28 +07:00
Hermes Team
ee5108eb3e fix(deployment): implement self-healing bootstrap, Claude & Grok profiles, non-interactive test mode, mirror installer, and comprehensive doctor CLI 2026-08-22 21:22:21 +07:00
Hermes Team
9d93a1739b feat(security): isolate subprocess credentials, implement selection explanation matrix, and resolve installer registry isolation 2026-08-21 10:17:19 +07:00
Hermes Team
50fde5f16e refactor(plan-a): close residual blockers, concurrency race, and feed verification
- Implemented 3-tier release feed status (MANIFEST_LIVE, PACKAGE_LIVE, PACKAGE_HASH_VERIFIED)
- Added reproducible package and checksum builder in scripts/build_dist.py
- Preserved user header comments across YAML saves in router_config.py
- Connected model_timeout_seconds, monitoring_interval_seconds, and auto_monitoring to runtime
- Guarded global gemini:antigravity credential swap with _AGY_INVOCATION_LOCK to eliminate concurrent subprocess race
- Added concurrency regression test in tests/test_antigravity_concurrency.py
- Added interprocess file locking (_FileLock) for router_state.json in health_tracker.py
- Sandboxed APPDATA and USERPROFILE in tests/test_installer.py
- Exported roadmap modules in router/__init__.py
- Verified 151 passing tests (100%) and 7/7 release gate checks
2026-08-20 22:55:43 +07:00
Hermes Team
0c511cd3b6 feat(hub): Plan A stabilization, refresh architecture, delta UI, and capability routing
- Implemented HubSnapshot and central HubStateStore for normalized in-memory state caching (<0.05ms)
- Refactored AccountsView and RoutingView with reusable AccountCardWidget and RoutingRoleWidget to eliminate widget recreation
- Implemented central HermesRefreshScheduler with 5s tick, concurrency throttling, dedup, and spread initial delays
- Added typed EventBus with thread-safe UI main loop dispatching via root.after
- Implemented dynamic ModelRegistry with capability-based role requirements and multi-dimensional scoring
- Integrated Antigravity separate quota buckets (Claude vs Gemini) and same-account model fallback
- Enhanced SessionAffinityTracker with TTL expiration and LRU capacity bounds
- Eliminated long subprocess holding of _CM_LOCK and ensured Windows credential restoration in finally block
- Added FastAPI REST contracts in gui_server.py as foundation for future Tauri frontend
- Verified 100% pass across all 91 pytest tests and 7/7 release gate criteria
2026-08-20 21:20:51 +07:00
Hermes Team
65482e8eee fix(router): address review findings B1-B4 and S1-S9 with full regression suite 2026-08-20 17:04:49 +07:00
Hermes Team
2a97e80a3e fix: close P0 release blockers 2026-08-20 16:25:11 +07:00
Hermes Team
fdf9eccbdb feat: initialize standalone Hermes Hub 2026-08-20 00:17:11 +07:00