fix(antigravity): рабочий аккаунт падал из-за незаданного уровня усилия
Новое сообщение об отказе agy показало причину. У рабочего аккаунта victor.trushenko@gmail.com каталог получался (11 моделей), а вызов падал: invalid model selection (--model "gemini-3.7-flash" --effort ""): gemini-3.7-flash requires --effort (available: low, medium, high) Каталог agy отдаёт идентификаторы с уровнем усилия внутри имени (gemini-3.7-flash-high, -medium, -low), а в профиле хранится голое имя. Вызов уходил с пустым --effort, и agy отказывался работать. Теперь уровень определяется: если он зашит в имени, отделяется от модели; если нет — берётся из каталога, предпочтительно medium. Проверено, что claude-sonnet-4-6 при этом не разбирается ошибочно: -6 уровнем не является. Отдельно: восемь профилей Antigravity отвечают «Please sign in to view available models» при HOME=~/.hermes/agy_profiles/<slot>. Это пустые заготовки без учётных данных, а не поломка: agy запускается с подменённым HOME ради изоляции аккаунтов, и в незаполненном каталоге ключей нет. Подписочные аккаунты Codex и Claude: отказ по API-ключу теперь объясняет, что такие аккаунты подключаются входом по ссылке, а не ключом. Проверка обращается к каталогу моделей, где платформенному ключу нужны права api.model.read, и подписочный токен там получает 401 или 403 при исправном аккаунте. 610 passed, ruff clean, релизный гейт 10/10. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9761362bc0
commit
9c57a7c607
2 changed files with 42 additions and 1 deletions
|
|
@ -756,6 +756,31 @@ def agy_generate(
|
|||
"--disable-slash-commands",
|
||||
"--print-timeout", f"{timeout}s",
|
||||
]
|
||||
# Каталог agy отдаёт идентификаторы с уровнем усилия: gemini-3.7-flash-high,
|
||||
# -medium, -low. В профиле же хранится голое имя, и вызов уходил с пустым
|
||||
# --effort: agy отвечал «gemini-3.7-flash requires --effort (available: low,
|
||||
# medium, high)» и работа не начиналась.
|
||||
if agy_model and not agy_effort:
|
||||
base, _, tail = str(agy_model).rpartition("-")
|
||||
if base and tail in ("low", "medium", "high"):
|
||||
# Уровень зашит в самом имени — отделяем его.
|
||||
agy_model, agy_effort = base, tail
|
||||
else:
|
||||
known = _AGY_EFFORT_MAP.get(agy_model) or set()
|
||||
if known:
|
||||
# Берём средний уровень, если он есть: он и по названию средний,
|
||||
# и по расходу квоты. Иначе — любой доступный, по порядку.
|
||||
for candidate in ("medium", "high", "low"):
|
||||
if candidate in known:
|
||||
agy_effort = candidate
|
||||
break
|
||||
if not agy_effort:
|
||||
agy_effort = sorted(known)[0]
|
||||
logger.info(
|
||||
"agy_generate: у модели %s не задан уровень усилия, выбран %s из %s",
|
||||
agy_model, agy_effort, sorted(known),
|
||||
)
|
||||
|
||||
if agy_model:
|
||||
cmd.extend(["--model", agy_model])
|
||||
if agy_effort:
|
||||
|
|
|
|||
|
|
@ -30,6 +30,20 @@ def validate_connection(provider, token="", base_url="", preferred_model=""):
|
|||
raise ValueError("Для этого провайдера используйте вход через авторизацию")
|
||||
if provider not in ("local", "vllm", "ollama") and not token:
|
||||
raise ValueError("Не указан API-ключ")
|
||||
|
||||
# Подписочные аккаунты Codex (ChatGPT) и Claude работают по OAuth, а не
|
||||
# по платформенному ключу. Проверка ниже обращается к каталогу моделей,
|
||||
# где платформенному ключу нужны права api.model.read: подписочный
|
||||
# токен там получает 403 или 401, хотя аккаунт исправен и в Hermes
|
||||
# работает. Предупреждаем об этом заранее, чтобы отказ не выглядел
|
||||
# поломкой аккаунта.
|
||||
subscription_note = ""
|
||||
if provider in ("openai-codex", "codex", "claude", "anthropic"):
|
||||
subscription_note = (
|
||||
" Если это аккаунт по подписке (ChatGPT Plus/Pro или Claude Max), "
|
||||
"ключ здесь не подойдёт: такие аккаунты подключаются входом по ссылке "
|
||||
"на предыдущем шаге мастера, а не API-ключом."
|
||||
)
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if provider == "claude":
|
||||
headers.update({"x-api-key": token, "anthropic-version": "2023-06-01"})
|
||||
|
|
@ -139,7 +153,9 @@ def validate_connection(provider, token="", base_url="", preferred_model=""):
|
|||
"data": {"models": []},
|
||||
}
|
||||
if isinstance(exc, urllib.error.HTTPError):
|
||||
reason = exc.reason or 'провайдер отклонил запрос'
|
||||
reason = (exc.reason or 'провайдер отклонил запрос')
|
||||
if exc.code in (401, 403) and subscription_note:
|
||||
reason = str(reason) + subscription_note
|
||||
try:
|
||||
body = json.loads(exc.read(4096).decode('utf-8', errors='replace'))
|
||||
detail = body.get('error') or body.get('detail')
|
||||
|
|
|
|||
Loading…
Reference in a new issue