diff --git a/src/antigravity_provider/router/action_handler.py b/src/antigravity_provider/router/action_handler.py index 5558e0d..22e360a 100644 --- a/src/antigravity_provider/router/action_handler.py +++ b/src/antigravity_provider/router/action_handler.py @@ -739,6 +739,9 @@ class ActionExecutor: valid, reason = AutoAssigner.validate_slot(prov_norm, slot) if not valid: return {'ok': False, 'message': reason} + existing_status = ProfileAuthManager.get_profile_status(prov_norm, slot) if slot else {} + if not token and prov_norm not in ('local', 'vllm', 'ollama') and not existing_status.get('authenticated'): + return {'ok': False, 'message': 'Не указан API-ключ или не завершена авторизация'} validation = None if token or prov_norm in ('local', 'vllm', 'ollama'): from .connection_preflight import validate_connection diff --git a/src/antigravity_provider/router/web/static/app.js b/src/antigravity_provider/router/web/static/app.js index 233ddcf..cdc2bcf 100644 --- a/src/antigravity_provider/router/web/static/app.js +++ b/src/antigravity_provider/router/web/static/app.js @@ -864,9 +864,9 @@ function renderAccountCheck(profile) { ${checking ? `
${escapeHtml(profile.display_name || profile.profile_id)}: идёт опрос провайдера, это может занять до минуты на этап.
` : ''}${escapeHtml(check.message || "Подключение ещё не проверялось")}
${escapeHtml(modelStatus)}
-Выше — модели указанного сервера Ollama.
Облачный каталог Ollama: ${meta.cloud?.error ? 'Н/Д — ' + escapeHtml(meta.cloud.error) : meta.cloud?.models ? escapeHtml(meta.cloud.models.join(', ')) : 'Н/Д — ещё не получен'}
Доступ аккаунта к облачным моделям: Н/Д до успешного вызова. Для прямого вызова нужен API-ключ Ollama; для локального клиента — вход через ollama signin.
` : ''} - + `; } diff --git a/tests/test_accounts_a54.py b/tests/test_accounts_a54.py index 0231318..5eaa30e 100644 --- a/tests/test_accounts_a54.py +++ b/tests/test_accounts_a54.py @@ -240,3 +240,10 @@ def test_bulk_protects_symlink_into_ag(services, tmp_path): assert preview['data']['targets'] == [] assert ActionExecutor.execute('clear_accounts', {'confirmed': True, 'targets': []})['ok'] assert target.read_text() == 'protected fixture' + + +@pytest.mark.parametrize('provider', ['openrouter', 'nvidia', 'claude']) +def test_empty_key_never_allocates_slot(services, provider): + result = ActionExecutor.execute('add_account', {'provider': provider, 'token': ''}) + assert not result['ok'] and result['message'] + assert not load_router_config().profiles