Владелец: «стоит опенкод аккаунт, который не подключен, у него кончились лимиты и аккаунт не работает». Лимиты ни при чём. Мастер подключения сохраняет ключ через ProfileAuthManager, а _resolve_api_key смотрел только в auth_config из YAML и в переменные окружения. Хранилище профилей он не читал вовсе — в отличие от grok, claude и codex, где такая проверка есть. Следствие: любой аккаунт OpenCode Go, подключённый через интерфейс, был нерабочим. Маршрутизация падала с «No API key found for OpenCode Go profile», и эта строка уже попадалась в следе отказов оркестратора. Проверено на живом профиле владельца: до правки health_check=False и тест профиля возвращал «локальный runtime недоступен», хотя api_key лежал в auth.json. После — health_check=True, тест проходит. Закрыто тестами, включая проверку, что пустое хранилище по-прежнему даёт отказ, а не ложноположительный результат. Тесты: 331 passed, ruff чисто. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
66 lines
2.8 KiB
Python
66 lines
2.8 KiB
Python
"""Адаптер OpenCode Go обязан читать ключ из хранилища профилей.
|
||
|
||
Дефект: мастер подключения сохраняет ключ через ProfileAuthManager, а
|
||
_resolve_api_key смотрел только в auth_config из YAML и в переменные
|
||
окружения. Аккаунт, подключённый через интерфейс, не работал никогда —
|
||
маршрутизация падала с «No API key found», хотя ключ лежал на диске, а
|
||
карточка показывала «Работает».
|
||
|
||
Остальные адаптеры (grok, claude, codex) хранилище читают; этот — нет.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from types import SimpleNamespace
|
||
|
||
import pytest
|
||
|
||
from antigravity_provider.router.adapters.opencode_adapter import OpenCodeGoAdapter
|
||
|
||
|
||
@pytest.fixture
|
||
def profile():
|
||
return SimpleNamespace(profile_id="opengo-1", account_id="acc-1", auth_config={})
|
||
|
||
|
||
def test_api_key_is_read_from_profile_store(monkeypatch, profile):
|
||
import antigravity_provider.router.profile_manager as pm
|
||
|
||
monkeypatch.setattr(
|
||
pm.ProfileAuthManager,
|
||
"load_profile_auth",
|
||
staticmethod(lambda provider, pid: {"api_key": "stored-key-123", "auth_mode": "api_key"}),
|
||
)
|
||
for var in ("OPENCODE_GO_API_KEY", "OPENCODE_ZEN_API_KEY", "OPENCODE_API_KEY"):
|
||
monkeypatch.delenv(var, raising=False)
|
||
|
||
assert OpenCodeGoAdapter()._resolve_api_key(profile) == "stored-key-123"
|
||
|
||
|
||
def test_health_check_passes_when_only_profile_store_has_key(monkeypatch, profile):
|
||
"""Именно это расхождение показывало «Работает» на нерабочем аккаунте."""
|
||
import antigravity_provider.router.profile_manager as pm
|
||
|
||
monkeypatch.setattr(
|
||
pm.ProfileAuthManager,
|
||
"load_profile_auth",
|
||
staticmethod(lambda provider, pid: {"api_key": "stored-key-123"}),
|
||
)
|
||
for var in ("OPENCODE_GO_API_KEY", "OPENCODE_ZEN_API_KEY", "OPENCODE_API_KEY"):
|
||
monkeypatch.delenv(var, raising=False)
|
||
|
||
assert OpenCodeGoAdapter().health_check(profile) is True
|
||
|
||
|
||
def test_missing_credentials_still_report_no_key(monkeypatch, profile):
|
||
"""Пустое хранилище не должно давать ложноположительный результат."""
|
||
import antigravity_provider.router.profile_manager as pm
|
||
|
||
monkeypatch.setattr(
|
||
pm.ProfileAuthManager, "load_profile_auth", staticmethod(lambda provider, pid: {})
|
||
)
|
||
for var in ("OPENCODE_GO_API_KEY", "OPENCODE_ZEN_API_KEY", "OPENCODE_API_KEY"):
|
||
monkeypatch.delenv(var, raising=False)
|
||
|
||
assert OpenCodeGoAdapter()._resolve_api_key(profile) is None
|
||
assert OpenCodeGoAdapter().health_check(profile) is False
|