fix(providers): ключ не доходил до адаптера; счётчик аккаунтов расходился

Ключ API. add_account сохраняет его через ProfileAuthManager, а адаптеры
NVIDIA и OpenRouter читали только profile.auth_config из
router_profiles.yaml — туда ключ не попадает. Запрос уходил без заголовка
Authorization, и провайдер отвечал «401: Header of type authorization was
missing», хотя список моделей тем же ключом получался: обнаружение читает
ключ из хранилища, а адаптер читал из конфигурации.

Проверено: auth_config в yaml пуст, адаптер теперь находит ключ в
хранилище учётных данных.

Счётчик аккаунтов. Значок в меню брал readiness.accounts_connected_count
(строго AUTHENTICATED), а карточка на странице считала профили правилом
«не NOT_CONFIGURED». Владелец видел 9 в меню и 3 на странице. Приведено к
одному определению — тому же, что у страницы.

609 passed, ruff clean, релизный гейт 10/10.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hermes Team 2026-09-01 01:46:46 +07:00
parent 4b6533281e
commit 266fc51adf
3 changed files with 33 additions and 3 deletions

View file

@ -38,6 +38,20 @@ class NvidiaAdapter(BaseProviderAdapter):
if key:
return str(key).strip()
# Ключ, введённый в мастере, сохраняется через ProfileAuthManager, а не в
# auth_config из router_profiles.yaml. Адаптер читал только второе место и
# уходил без заголовка Authorization: провайдер отвечал 401 «Header of type
# authorization was missing», хотя список моделей тем же ключом получался.
try:
from antigravity_provider.router.profile_manager import ProfileAuthManager
stored = ProfileAuthManager.load_profile_auth(profile.provider, profile.profile_id) or {}
key = stored.get("api_key") or stored.get("token")
if key:
return str(key).strip()
except Exception:
pass
suffix = profile.profile_id.upper().replace("-", "_")
for candidate in (f"NVIDIA_API_KEY_{suffix}", "NVIDIA_API_KEY", "NV_API_KEY"):
val = os.environ.get(candidate, "").strip()

View file

@ -41,6 +41,20 @@ class OpenRouterAdapter(BaseProviderAdapter):
if key:
return str(key).strip()
# Ключ, введённый в мастере, сохраняется через ProfileAuthManager, а не в
# auth_config из router_profiles.yaml. Адаптер читал только второе место и
# уходил без заголовка Authorization: провайдер отвечал 401 «Header of type
# authorization was missing», хотя список моделей тем же ключом получался.
try:
from antigravity_provider.router.profile_manager import ProfileAuthManager
stored = ProfileAuthManager.load_profile_auth(profile.provider, profile.profile_id) or {}
key = stored.get("api_key") or stored.get("token")
if key:
return str(key).strip()
except Exception:
pass
suffix = profile.profile_id.upper().replace("-", "_")
for candidate in (f"OPENROUTER_API_KEY_{suffix}", "OPENROUTER_API_KEY"):
val = os.environ.get(candidate, "").strip()

View file

@ -576,9 +576,11 @@ function updateGlobalHeader() {
const readiness = currentSnapshot.readiness || {};
renderAccountSummary(currentSnapshot);
const allProfiles = Object.values(currentSnapshot.all_profiles || {});
const connectedAccounts = readiness.accounts_connected_count ?? allProfiles.filter(
(p) => isConnectedProfile(p)
).length;
// Одно число — одно определение. Готовность считает строго AUTHENTICATED,
// а страница аккаунтов — всё, что не NOT_CONFIGURED. Из-за двух определений
// значок в меню показывал 9, а карточка на той же странице — 3.
// Берём то же правило, что и страница аккаунтов: расходиться они не должны.
const connectedAccounts = allProfiles.filter((p) => isConnectedProfile(p)).length;
if (elements.navAccountsCount) elements.navAccountsCount.textContent = connectedAccounts;