diff --git a/agents/inbox/2026-08-24-A22-agy-native-login.md b/agents/inbox/2026-08-24-A22-agy-native-login.md new file mode 100644 index 0000000..ac3768e --- /dev/null +++ b/agents/inbox/2026-08-24-A22-agy-native-login.md @@ -0,0 +1,146 @@ +# Задание 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`.