hermes-hub/docs/reports/A50.md

66 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# A50 — аккаунты, обнаружение моделей и проверка подключения
Дата: 2026-08-31. Исполнитель: Codex.
**Статус: реализация и проверки исполнителя готовы; независимый проход Pro не выполнен.** Flash и Pro недоступны среди моделей этой сессии. Замена независимого аудитора на Codex запрошена у владельца, ответа пока нет. Не считать этот отчёт независимым аудитом или разрешением на релиз.
## База и область изменений
- START_HEAD / origin/main: `17b368a155fde354ece0b0fa65aaefa6eb5db1fe`.
- Ветка: `antigravity/a50-accounts-discovery`, отдельный worktree.
- Логотипы: отдельный коммит `1fbbeacd1345bb028b735e58d5468ac52a750193`, [источники и лицензии](model-provider-logos.md).
- FINAL_HEAD и состояние origin фиксируются после финального коммита в отчёте передачи и worklog AI-Memory. Собственный SHA файла отчёта не записывается внутрь этого же коммита.
- A49, граф и алгоритм исполнения субагентов не изменялись. Версия осталась 0.1.1. Службы моделей и пользовательские учётные данные не изменялись.
## Что изменено
1. **Слот аккаунта.** Центральная проверка отвергает чужие зарезервированные префиксы, конфликт с провайдером существующего профиля и небезопасные идентификаторы до записи. Применяется к регистрации профиля, прямому добавлению и началу OAuth. При исчерпании слотов нет отката к занятому `provider-1`.
2. **Мастер.** Состояние очищается при возврате к списку и смене провайдера; пустой выбор явно сохраняется. Запоздалый ответ начала OAuth другого провайдера игнорируется. По умолчанию предлагается новый свободный слот; занятые можно выбрать явно. Повторное сохранение блокируется в UI; повтор того же подключения во время проверки блокируется сервером.
3. **Группы.** Восстановлены заголовок с логотипом, счётчик и сетка карточек. Убрана фиксированная высота карточки: иначе новая диагностика и длинные ошибки обрезали квоты. Это необходимая локальная поправка, не переделка A48.
4. **Фоновая проверка.** При запуске веб-сервера, завершении подключения и периодически проверяются подключённые включённые профили. До четырёх независимых аккаунтов одновременно, один опрос на профиль. Состояния: ещё не проверялся → проверяется → работает либо ошибка с причиной. Снимок обновляется при начале, получении моделей и завершении. Есть ручные кнопки одного аккаунта и всех аккаунтов.
5. **Период.** `account_check_interval_seconds`, 300 секунд по умолчанию, минимум 60. Значение читается в настройках из `/api/settings`, а не изображается полученным из снапшота. Пять минут ограничивают частоту платных тестовых запросов и повторных OAuth/CLI вызовов, сохраняя достаточно свежую диагностику. Проверка отправляет короткий запрос с `max_tokens=1`; предупреждение о расходе квоты есть в настройках.
6. **Модели.** Дисковый кэш дополнен ключом провайдер + профиль. Discovery выбирает именно этот аккаунт, включая Antigravity. Показаны время получения и ошибка сервера; при ошибке старый список и время сохраняются. Успешный пустой список отделён от неудачи. Ручная кнопка блокируется на время опроса и показывает ход.
7. **Медленные операции.** Проверка модели допускает до 60 секунд; обнаружение — отдельный этап до 20 секунд. UI предупреждает о минуте на этап и показывает профиль. Синхронные обработчики действий вынесены из event loop HTTP-сервера; медленное добавление не блокирует `/api/health` и чтение состояния.
8. **Название движка.** `local` отображается как `llama.cpp`; идентификаторы `local-1`/`local-2` не меняются. Ollama и vLLM не переименованы.
## Ollama: подтверждённая документация
[Официальная документация Cloud](https://docs.ollama.com/cloud) прямо документирует `GET https://ollama.com/api/tags` для облачного каталога. Это отличается от `/api/tags` локального хоста. Прямой вызов облачных моделей требует API-ключа Ollama; локальный клиент использует `ollama signin`.
Каталог получен реальным публичным запросом без ключей: **19 моделей**, ошибка отсутствует, 2026-08-31. В приложении он кэшируется отдельно от моделей сервера профиля. Каталог не доказывает индивидуальное право аккаунта на инференс: UI сообщает **Н/Д до успешного вызова**. Неподтверждённый endpoint личных разрешений не добавлен. При недоступности сети — Нс причиной.
## Проверки исполнителя
- Python: **535 passed / 1 skipped / 0 failed**, ещё 4 deselected штатным фильтром `not live and not network and not installer`.
- Skip: `test_windows_csharp_launchers_and_setup_compile` — на Linux нет Windows `csc.exe`.
- `ruff check .`: чисто; `git diff --check`: чисто.
- `verify_multi_provider_router.py`: **10/10**, 0 errors, 0 warnings.
- `release_gate.py`: **PASSED**, включая полную suite, P0, updater/rollback, версии и проверки секретов.
- JS: `test_web_handlers_dom_contract.js`, `test_workspace_a48.js`, `test_brand_icons.js` — пройдены.
- 18 регрессий A50: чужие/небезопасные слоты; реальный loopback HTTP 401 для NVIDIA и OpenRouter; дедупликация; состояние проверки; периодический запуск; раздельные кэши; сохранение времени и текста ошибки; документированный cloud URL без передачи авторизации; переименование без изменения ID; отзывчивость HTTP при медленном действии.
## Браузерные свидетельства
Стенд `tests/manual/a50_preview.py` использует отдельный временный каталог данных, синтетические аккаунты `A50-TEST-*` и настоящий loopback HTTP-провайдер. Это **не замеры аккаунтов владельца**. OAuth, квоты и обновления в fixture отключены. Воспроизводится командой `PYTHONPATH=src python tests/manual/a50_preview.py` (порты 5803 и 5813).
- Без ручного запуска увидены `Проверяется…`, затем два работающих и два отказавших аккаунта с HTTP 401; появились модели с временем получения.
- Мастер: выбор Antigravity → назад → NVIDIA → неверный тестовый ключ → правильный NVIDIA-профиль и явный 401. Дополнительный JS-тест намеренно сохраняет `ag-w1` до переключения и проверяет очистку для обоих провайдеров.
- Мастер OpenRouter: автоматический новый `openrouter-2`, затем фоновый 401.
- Период в настройках прочитан с сервера: 300, поле доступно для изменения.
- Логотипы визуально проверены в Dark / Medium / Light; 16 локальных изображений без битых ссылок.
Снимки: [в процессе](../screenshots/a50/accounts-checking.png), [результат](../screenshots/a50/accounts-checked.png), [NVIDIA Dark](../screenshots/a50/accounts-nvidia-dark.png), [Medium](../screenshots/a50/accounts-nvidia-medium.png), [Light](../screenshots/a50/accounts-nvidia-light.png), [OpenRouter после мастера](../screenshots/a50/openrouter-wizard-result.png), [набор логотипов](../screenshots/a50/brand-catalog.png).
Первые два снимка сделаны до поправки фиксированной высоты карточек; окончательная вёрстка показана на трёх снимках NVIDIA.
## Оставшиеся ограничения / пункты P0-8
- **Независимый второй проход Pro пропущен:** модель недоступна. Реализация сделана Codex, а не Flash; все проверки выше — проверки самого исполнителя.
- Состояние `не проверялся` проверено тестом до запуска worker. Отдельный браузерный снимок одновременно `не проверялся` и `проверен: не работает` не снят: стартовый автоматический опрос сразу забирает подключённые профили.
- Периодический повтор подтверждён детерминированным тестом часов; пять минут в браузере отдельно не выжидались.
- Производственные OAuth аккаунты владельца, Windows installer и установленная сборка не проверялись/не обновлялись. Превью 5801 не заменялось.
- Таймаут ожидания не отменяет уже отправленный провайдеру запрос: адаптер завершит собственный сетевой timeout. Повтор самого фонового задания не допускается, пока оно имеет статус `checking`; после сообщения о timeout повтор разрешён.
- Фоновая служба запускается жизненным циклом веб-сервера. Отдельный вызов ActionExecutor вне запущенного сервера сохраняет аккаунт, но честно сообщает, что служба проверки не запущена.
- API-ответы не превращаются в подтверждение работоспособности при одном только сохранении: сообщение говорит «сохранён», результат проверки показывается отдельно.
Дополнительная правка теста A47: проверка памяти больше не требует навечно зафиксированный `80aab00`, а сверяет SHA, реально записанный в CURRENT_STATE. После обновления общей памяти другой задачей старая константа давала ложное падение при корректной памяти. Проверки существования коммита и свежести сохранены; код памяти A49 не менялся.