hermes-hub/agents/inbox/2026-08-24-A22-agy-native-login.md
Hermes Team f514b3e6de docs(task): A22 — вход в Antigravity силами самого agy
A20 закрыто как неверно поставленное. Синтез oauth_creds.json из
OAuth-потока Hub не работает в принципе: проверены и закрыты пять
гипотез (полнота полей, срок токенов, тот же OAuth-клиент, тот же
scope, согласованность активного аккаунта), а решающий опыт показал,
что agy отказывает даже РАБОЧИМ глобальным учётным данным владельца,
положенным в подменённый HOME. Ошибка в гипотезе автора задания.

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

A22 строит вход через родной механизм agy в окружении профиля. Первым
пунктом — разведка: есть ли неинтерактивный вход, что agy выводит,
как определить завершение. Установлено, что без аргументов это TUI:
в пайп ничего не пишет и виснет.

Приёмка только с тремя доказательствами исполнением: непустой вывод
agy models, успешный реальный вызов, route_request без ухода в резерв.

Плюс проверка побочной находки: в глобальном google_accounts.json
активен один аккаунт, а токен принадлежит другому — Hub мог писать
мимо каталога профиля и сломать владельцу обычный agy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 23:38:46 +07:00

146 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.

# Задание A22: вход в Antigravity силами самого `agy`
## Дата поступления
2026-08-24
## База
Проверочный HEAD на момент выдачи: **`bb4f6df`**.
## Ветка
`antigravity/agy-native-login`
## Приоритет
Выше всего остального. Маршрутизация через Antigravity не работает ни для одного из шести аккаунтов — это десять профилей из двадцати двух и основной провайдер владельца.
---
## Порядок работы с git
```
cd <каталог репозитория>; git fetch origin --prune; git status
git checkout main; git pull --ff-only origin main
git checkout -b antigravity/agy-native-login
git commit -m "..." <- сначала коммит
git push -u origin antigravity/agy-native-login
```
**В `main` напрямую не пушить.** Работа A20 ушла в основную ветку минуя ревью; в тот раз обошлось, но правка, ломающая сборку, попала бы к владельцу без проверки. Ветка существует именно для этого.
В конце — push и проверка `git log --oneline -1 origin/antigravity/agy-native-login`, `git status` чистый.
---
## Задание A20 закрыто как неверное. Ошибка в постановке, не в исполнении
A20 требовал сохранять `id_token` и `scope` и писать `<профиль>/.gemini/oauth_creds.json` в формате `agy`. **Это сделано, и сделано аккуратно** — атомарная запись через временный файл, поля не затираются при обновлении, 350 passed, ruff чисто.
**Но задача не решилась**, и подход в принципе не может её решить. Формулировал задание ревьюер, ошибка в гипотезе его.
Проверено исполнением, каждая гипотеза закрыта:
| Проверено | Результат |
|---|---|
| Все шесть полей в `oauth_creds.json` | на месте — отказ |
| Токены не просрочены | живы ещё 43 минуты — отказ |
| Тот же OAuth-клиент (`aud`, `azp`) | совпадают полностью — отказ |
| Тот же набор разрешений | 6 из 6, различий нет — отказ |
| Активный аккаунт согласован с владельцем токена | согласован — отказ |
И решающий опыт: в подменённый `HOME` положены **рабочие глобальные** учётные данные владельца, действительные ещё 40 минут, — `agy` отказал и им.
**Вывод: `agy` не принимает учётные данные, выпущенные не им самим.** Ни в каком расположении, ни с какими полями. Синтезировать их из OAuth-потока Hub нельзя.
### Что при этом выяснилось полезного
**`agy` уважает подмену `HOME`.** В каталогах профилей лежат его собственные файлы, созданные им же: `.gemini/antigravity-cli/conversation_summaries.db` и `installation_id` с отметкой 23 августа 12:19. Изоляция профилей работает — не работал только синтез учётных данных.
Значит путь один: **вход должен выполнять сам `agy`, в окружении нужного профиля.**
---
## P0-1. Разведка перед реализацией
Не повторяйте ошибку A20 — сначала проверьте, потом стройте.
Установлено: `agy` без аргументов — **интерактивный TUI**. Запущенный с перехваченными потоками он ничего не выводит в пайп и виснет; ему нужен настоящий терминал.
**Прежде чем писать код, выясните и напишите в отчёте:**
1. Есть ли у `agy` неинтерактивный вход — флаг, подкоманда, переменная окружения. В `agy --help` подкоманд входа нет (`agent`, `agents`, `changelog`, `help`, `install`, `mcp`, `models`, `plugin`, `plugins`, `update`), но проверьте `agy help <подкоманда>` и документацию.
2. Пишет ли `agy` при входе что-нибудь пригодное для автоматики — URL, код устройства — в файл или в stderr.
3. Как надёжно определить, что вход завершился: появление `oauth_creds.json` в каталоге профиля, изменение `google_accounts.json`, что-то ещё.
Если неинтерактивного входа нет — так и напишите. Это законный результат, и он определяет всё остальное.
## P0-2. Вход по профилям
Опираясь на разведку, сделать в Hub подключение аккаунта Antigravity **через родной вход `agy`**:
- окружение подменяется на каталог профиля (`USERPROFILE`, `HOME`, `HOMEPATH`) — механизм уже есть в `antigravity_adapter.get_profile_env_dir`, он проверен и работает;
- если неинтерактивного входа нет — открывать **видимое консольное окно** с этим окружением, чтобы владелец прошёл вход сам. Это честный путь: он ровно так и делал вручную;
- Hub дожидается завершения, определяя его признаком из разведки, и сообщает результат в интерфейсе;
- **шесть аккаунтов подряд**: мастер должен вести по ним, а не заставлять повторять всё руками для каждого.
**Ограничение по безопасности, без исключений.** Учётные данные вводит владелец в окне `agy`. Hub их не перехватывает, не читает из потоков, не логирует и не пересылает. Задача Hub — подготовить окружение и дождаться результата.
## P0-3. Веб-интерфейс должен сказать правду
На сервере без экрана консольный вход невозможен. Это уже зафиксировано в контракте: Antigravity и Claude требуют redirect на localhost и на headless не работают.
В вебе для Antigravity показывать не кнопку подключения, а объяснение и обходной путь: пройти вход на десктопе, либо пробросить порт по SSH. **Неработающая кнопка недопустима** — правило то же, что и с зелёным «Работает» на нерабочем аккаунте.
## P0-4. Проверить глобальную сессию владельца
Побочная находка, требует проверки: в глобальном `~/.gemini/google_accounts.json` активным записан `victor.trushenko@gmail.com`, а токен в `~/.gemini/oauth_creds.json` принадлежит `ochenstarik@gmail.com`.
Похоже, Hub где-то пишет **мимо каталога профиля**, в глобальное расположение, и мог сломать владельцу обычный `agy`.
Найти, откуда это, и убедиться, что Hub не трогает глобальные учётные данные ни при каких обстоятельствах. **Тест обязателен:** сохранение и обновление профиля не изменяет ни одного файла в `~/.gemini`.
## P0-5. Доказательство
Задание принимается **только с подтверждением исполнением**. Приложить:
1. вывод `agy models`, вернувший непустой список, через профиль Hub;
2. успешный реальный вызов модели через `adapter.invoke` — ответ модели, а не `AuthExpiredError`;
3. `route_request` на роли, ведущей на Antigravity, отработавший без ухода в резерв по причине авторизации.
Без этих трёх пунктов приёмки не будет. A20 был написан правильно по букве задания и всё равно не работал — цена ненадёжной гипотезы уже заплачена один раз.
## P1-6. Обнаружение моделей — после починки входа
Когда `agy models` заработает, доделать пропущенное в A18: кэш моделей на диске, переживающий перезапуск; фоновое обновление с таймаутом, не затирающим кэш; ручная кнопка обновления; при пустом кэше — «список ещё не получен» без литеральных подстановок.
Сейчас `set_model` отклоняет **любую** модель, включая настоящую, потому что сравнивать не с чем. Владелец хочет поставить двум кодерам `gemini-3.1-pro-high` и не может.
---
## Ограничения
- Параллельно идёт **A21** (четыре экрана веб-интерфейса). Его зона: `router/web/**` целиком. **Не заходить туда**, кроме честного объяснения для Antigravity по P0-3 — согласовать эту правку в отчёте.
- Ваши файлы: `oauth.py`, `router/profile_oauth.py`, `router/profile_manager.py`, `agy_subprocess.py`, `router/adapters/antigravity_adapter.py`, `model_discovery*`, `credentials.py`, `router/ui/add_account_wizard.py`.
- Учётные данные не логировать и не отдавать наружу; существующий тест на секреты должен продолжать проходить.
- Десктоп и веб не ломать. На `main` сейчас 350 passed, 2 skipped.
- Тег `v0.1.1` не создавать.
## Критерии приёмки
1. Ветка в `origin`, в `main` напрямую не пушилось, `git status` чист.
2. В отчёте есть результат разведки по трём вопросам P0-1.
3. Подключение аккаунта Antigravity проходит через родной вход `agy` в окружении профиля.
4. Мастер ведёт по нескольким аккаунтам подряд.
5. Hub не перехватывает и не логирует учётные данные.
6. **Приложен непустой вывод `agy models`** через профиль Hub.
7. **Приложен успешный реальный вызов модели.**
8. **Приложен `route_request`, не ушедший в резерв по авторизации.**
9. Тест: сохранение и обновление профиля не изменяет ни одного файла в `~/.gemini`.
10. В вебе Antigravity показан с объяснением и обходным путём, а не нерабочей кнопкой.
11. `ruff check .` чисто; релизный гейт не ухудшен.
12. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`.
## Главное
Продукт создан ради маршрутизации между аккаунтами Antigravity. Она не работает при полностью валидных токенах, и обойти это синтезом учётных данных уже пробовали — не выходит. Остаётся дать `agy` войти самому, а Hub должен это организовать и не мешать.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`. Сдано только после появления коммита в `origin`.