fix(antigravity): вход через терминал не регистрировал аккаунт
Владелец: «в программе нет аккаунтов. я добавил первый… аккаунты так и не появились». При этом вход проходил, и agy отдавал одиннадцать моделей. Список аккаунтов строится по конфигурации маршрутизатора. Вход через терминал завершается своим путём, мимо add_account, и записи в конфигурации не создаёт: учётные данные на диске, get_profile_status отвечает «подключён», а в интерфейсе пусто. Воспроизведено исполнением — профиль с ключами agy и нулём записей в конфигурации не виден нигде. Теперь при успешном завершении входа профиль регистрируется, и только потом идёт обновление состояния. Неудача регистрации возвращается отказом с причиной, а не молчаливым успехом: аккаунт, о котором сказано «подключён», но которого нигде нет, — та же слепота, что и зависший мастер. Проверено исполнением до и после правки: было «профилей в конфиге: 0, видно: ничего», стало «профилей: 1 [ag-5], видно: antigravity[ag-5]». 708 passed, 2 skipped; ruff чисто; релизный гейт пройден. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
7b36538ded
commit
58cb88e529
5 changed files with 126 additions and 2 deletions
|
|
@ -18,7 +18,7 @@ namespace HermesHubSetup
|
|||
// Подставляется сборщиком из фактического git-коммита. Раньше здесь
|
||||
// жил зашитый "8cddc9f", то есть манифест сообщал неправду о том, из
|
||||
// какого кода собран установщик.
|
||||
public const string BuildCommit = "90aeceb";
|
||||
public const string BuildCommit = "e431e39";
|
||||
public const string MIN_HERMES_VERSION = "0.20.0";
|
||||
public const string MAX_TESTED_HERMES = "0.20.4";
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -952,7 +952,21 @@ class ActionExecutor:
|
|||
|
||||
ok, msg, res_data = poll_native_agy_login(session_id)
|
||||
if ok and res_data.get('status') == 'completed':
|
||||
_rescan_after_auth('antigravity', res_data.get('profile_id'))
|
||||
slot = res_data.get('profile_id')
|
||||
# Вход через терминал завершается своим путём и мимо add_account.
|
||||
# Учётные данные при этом на диске, профиль числится
|
||||
# подключённым — но записи о нём в конфигурации маршрутизатора
|
||||
# нет, а список аккаунтов строится по ней. Владелец входил
|
||||
# успешно и видел пустой экран.
|
||||
if slot:
|
||||
def_ok, def_msg = AutoAssigner.ensure_profile_definition('antigravity', slot)
|
||||
if not def_ok:
|
||||
return {
|
||||
'ok': False,
|
||||
'message': f'Вход выполнен, но аккаунт не зарегистрирован: {def_msg}',
|
||||
'data': res_data,
|
||||
}
|
||||
_rescan_after_auth('antigravity', slot)
|
||||
return {'ok': ok, 'message': msg, 'data': res_data}
|
||||
|
||||
if action in ('cancel_native_auth', 'cancel_native_agy_login', 'cancel_terminal_auth'):
|
||||
|
|
|
|||
110
tests/test_native_login_registers_account.py
Normal file
110
tests/test_native_login_registers_account.py
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
"""Вход через терминал должен регистрировать аккаунт, а не только записывать ключи.
|
||||
|
||||
Владелец: «в программе нет аккаунтов. я добавил первый… аккаунты так и не
|
||||
появились». При этом вход проходил, agy отдавал одиннадцать моделей.
|
||||
|
||||
Причина: список аккаунтов строится по конфигурации маршрутизатора, а вход через
|
||||
терминал завершается своим путём, мимо add_account, и записи в конфигурации не
|
||||
создаёт. Учётные данные на диске, профиль числится подключённым — и его нигде
|
||||
не видно.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from antigravity_provider import paths
|
||||
from antigravity_provider.router.action_handler import ActionExecutor
|
||||
from antigravity_provider.router.router_config import load_router_config
|
||||
from antigravity_provider.router.unified_health import UnifiedHealthService
|
||||
|
||||
|
||||
def _profile_with_agy_credentials(slot: str = "ag-5"):
|
||||
pdir = paths.get_profile_dir(slot, "antigravity", create=True)
|
||||
cli = pdir / ".gemini" / "antigravity-cli"
|
||||
cli.mkdir(parents=True, exist_ok=True)
|
||||
(cli / "antigravity-oauth-token").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"auth_method": "consumer",
|
||||
"token": {"access_token": "ya29.TEST", "refresh_token": "1//TEST"},
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return pdir
|
||||
|
||||
|
||||
def _completed(slot: str = "ag-5"):
|
||||
return (
|
||||
True,
|
||||
"Авторизация успешно завершена через agy CLI",
|
||||
{"status": "completed", "profile_id": slot, "email": "owner@gmail.com"},
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_completed_login_registers_the_profile():
|
||||
_profile_with_agy_credentials()
|
||||
|
||||
with patch(
|
||||
"antigravity_provider.agy_subprocess.poll_native_agy_login",
|
||||
return_value=_completed(),
|
||||
):
|
||||
res = ActionExecutor.execute("poll_native_auth", {"session_id": "s1"})
|
||||
|
||||
assert res["ok"], res
|
||||
assert "ag-5" in load_router_config().profiles, (
|
||||
"без записи в конфигурации аккаунт нигде не появится"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_registered_profile_is_visible_in_the_interface():
|
||||
_profile_with_agy_credentials()
|
||||
|
||||
with patch(
|
||||
"antigravity_provider.agy_subprocess.poll_native_agy_login",
|
||||
return_value=_completed(),
|
||||
):
|
||||
ActionExecutor.execute("poll_native_auth", {"session_id": "s1"})
|
||||
|
||||
shown = [
|
||||
view.profile_id
|
||||
for group in UnifiedHealthService.get().scan_all(force=True).values()
|
||||
for view in group
|
||||
]
|
||||
assert "ag-5" in shown
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_failed_registration_is_reported_not_swallowed():
|
||||
"""Молчаливый успех при незарегистрированном аккаунте — то же зависание вслепую."""
|
||||
_profile_with_agy_credentials()
|
||||
|
||||
with patch(
|
||||
"antigravity_provider.agy_subprocess.poll_native_agy_login",
|
||||
return_value=_completed(),
|
||||
), patch(
|
||||
"antigravity_provider.router.auto_assigner.AutoAssigner.ensure_profile_definition",
|
||||
return_value=(False, "слот занят другим провайдером"),
|
||||
):
|
||||
res = ActionExecutor.execute("poll_native_auth", {"session_id": "s1"})
|
||||
|
||||
assert not res["ok"]
|
||||
assert "не зарегистрирован" in res["message"]
|
||||
assert "слот занят другим провайдером" in res["message"]
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_login_still_in_progress_registers_nothing():
|
||||
with patch(
|
||||
"antigravity_provider.agy_subprocess.poll_native_agy_login",
|
||||
return_value=(True, "Ожидание завершения авторизации в терминале...", {"status": "pending"}),
|
||||
):
|
||||
res = ActionExecutor.execute("poll_native_auth", {"session_id": "s1"})
|
||||
|
||||
assert res["ok"]
|
||||
assert not load_router_config().profiles
|
||||
Loading…
Reference in a new issue