fix(agy): подстановка уровня усилия — gemini-3.7-flash работает как есть
Владелец возразил на моё утверждение, что gemini-3.7-flash не существует.
Он прав, утверждение было неверным, и я повторил его в четырёх заданиях.
gemini-3.7-flash — настоящее семейство, уровень усилия у неё отдельный
параметр. В интерфейсе Antigravity это видно прямо: пункт «Gemini 3.7
Flash» с вложенным выбором Low/Medium/High. В коде это отражено:
_display_to_cli разбирает «Gemini 3.7 Flash (High)» в пару
("gemini-3.7-flash", "high"). Меня ввела в заблуждение первая колонка
вывода agy models со склеенными идентификаторами.
Настоящий дефект был в коде: _model_supported_efforts вызывала
discover_models() БЕЗ профиля, то есть в глобальном окружении без входа.
Карта поддерживаемых усилий оставалась пустой, подстановка уровня по
умолчанию не срабатывала, и agy отвергал вызов с «requires --effort» —
при совершенно настоящей модели.
profile_id проведён через agy_generate в _model_supported_efforts.
Проверено исполнением: gemini-3.7-flash без указания усилия отрабатывает
и возвращает ответ.
Моки в test_antigravity_concurrency приведены к терпимости по kwargs.
Добавлена поправка agents/inbox/2026-08-24-CORRECTION-gemini-model-names.md:
ложное утверждение попало в A9, A11, A18 и B8, и без опровержения кто-то
чинил бы несуществующую проблему или сломал рабочую конфигурацию.
Тесты: 359 passed, ruff чисто.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
4545fbead2
commit
45fd01a15e
4 changed files with 64 additions and 9 deletions
48
agents/inbox/2026-08-24-CORRECTION-gemini-model-names.md
Normal file
48
agents/inbox/2026-08-24-CORRECTION-gemini-model-names.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Поправка: `gemini-3.7-flash` — настоящая модель
|
||||
|
||||
## Дата
|
||||
2026-08-24
|
||||
|
||||
## Кому
|
||||
Обоим исполнителям. Отменяет утверждение, повторённое в четырёх заданиях.
|
||||
|
||||
---
|
||||
|
||||
## Что было сказано неверно
|
||||
|
||||
В заданиях A9, A11, A18 и B8 ревьюер написал, что модели **`gemini-3.7-flash` у провайдера не существует** и что она «попала в конфигурацию через литерал в коде». Формулировки вроде:
|
||||
|
||||
> у живого провайдера **`gemini-3.7-flash` не существует**
|
||||
|
||||
**Это неверно.** Утверждение опровергнуто владельцем и проверено исполнением.
|
||||
|
||||
## Как есть на самом деле
|
||||
|
||||
`gemini-3.7-flash` — настоящее семейство моделей. Уровень усилия у неё **отдельный параметр**, а не часть имени. В интерфейсе Antigravity это видно прямо: пункт «Gemini 3.7 Flash» с вложенным выбором Low / Medium / High.
|
||||
|
||||
В коде это уже отражено: `_display_to_cli` разбирает `Gemini 3.7 Flash (High)` в пару `("gemini-3.7-flash", "high")`.
|
||||
|
||||
Меня ввёл в заблуждение вывод `agy models`: в первой колонке он печатает склеенные идентификаторы вида `gemini-3.7-flash-high`. Я принял их за настоящие имена моделей, а флаг `--model` ожидает базовое имя плюс `--effort`.
|
||||
|
||||
## Настоящий дефект — и он исправлен
|
||||
|
||||
Ошибка была не в конфигурации, а в коде.
|
||||
|
||||
`_model_supported_efforts` вызывала `discover_models()` **без профиля** — то есть в глобальном окружении, где вход `agy` не выполнен. Карта поддерживаемых усилий оставалась пустой, подстановка уровня по умолчанию не срабатывала, и `agy` отвергал вызов:
|
||||
|
||||
```
|
||||
invalid model selection (--model "gemini-3.7-flash" --effort ""):
|
||||
--model gemini-3.7-flash requires --effort (available: low, medium, high)
|
||||
```
|
||||
|
||||
Исправлено: `profile_id` проведён через `agy_generate` в `_model_supported_efforts`. Проверено исполнением — `gemini-3.7-flash` **без указания усилия** отрабатывает и возвращает ответ.
|
||||
|
||||
## Что из этого следует
|
||||
|
||||
1. **Конфигурацию владельца по этому поводу править не нужно.** `gemini-3.7-flash` у роли `orchestrator` и `gemini-3.6-flash-high` у роли `fast` — оба варианта допустимы.
|
||||
2. **Валидация моделей не должна отвергать базовые имена без суффикса усилия.** Если сравниваете с обнаруженным списком, учитывайте, что там склеенные идентификаторы, а в конфигурации может стоять базовое имя.
|
||||
3. Требование не подставлять модели литералом **остаётся в силе** — оно верное и связано с другим: списки вида `["grok-3","grok-2"]` и `["gemini-2.5-pro", …]` в коде действительно были выдуманы, и `gemini-2.5-*` у провайдера действительно нет.
|
||||
|
||||
## Почему это записано отдельным документом
|
||||
|
||||
Задания читаются как справочный материал, и ложное утверждение в четырёх из них означало бы, что кто-то починит несуществующую проблему или сломает рабочую конфигурацию. Ошибка ревьюера, а не исполнителей.
|
||||
|
|
@ -339,10 +339,16 @@ def check_profile_native_auth_status(profile_id: str) -> tuple[bool, str | None,
|
|||
return False, None, None
|
||||
|
||||
|
||||
def _model_supported_efforts(agy_model: str) -> set[str]:
|
||||
"""Return the set of effort levels supported by *agy_model*."""
|
||||
# Ensure discovery has run
|
||||
discover_models()
|
||||
def _model_supported_efforts(agy_model: str, profile_id: str | None = None) -> set[str]:
|
||||
"""Return the set of effort levels supported by *agy_model*.
|
||||
|
||||
Профиль обязателен: обнаружение читает учётные данные из HOME, и без
|
||||
подмены окружения оно выполняется в глобальном, где вход не сделан.
|
||||
Карта усилий тогда остаётся пустой, подстановка уровня по умолчанию не
|
||||
срабатывает, и agy отвергает вызов с «requires --effort» — при том что
|
||||
сама модель совершенно настоящая.
|
||||
"""
|
||||
discover_models(profile_id=profile_id)
|
||||
return _AGY_EFFORT_MAP.get(agy_model, set())
|
||||
|
||||
|
||||
|
|
@ -633,6 +639,7 @@ def _safe_env() -> dict[str, str]:
|
|||
def agy_generate(
|
||||
request: dict[str, Any],
|
||||
custom_env: dict[str, str] | None = None,
|
||||
profile_id: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Execute a chat completion via the ``agy`` subprocess."""
|
||||
exe = get_agy_exe()
|
||||
|
|
@ -660,7 +667,7 @@ def agy_generate(
|
|||
|
||||
# Smart effort selection based on model capabilities.
|
||||
# Some models (gemini) REQUIRE --effort, others (claude, gpt) DON'T SUPPORT it.
|
||||
supported = _model_supported_efforts(agy_model)
|
||||
supported = _model_supported_efforts(agy_model, profile_id=profile_id)
|
||||
if supported:
|
||||
# Model supports specific efforts
|
||||
if not agy_effort:
|
||||
|
|
|
|||
|
|
@ -78,9 +78,9 @@ class AntigravityAdapter(BaseProviderAdapter):
|
|||
)
|
||||
|
||||
with _AGY_INVOCATION_LOCK:
|
||||
res = agy_generate(req, custom_env=custom_env)
|
||||
res = agy_generate(req, custom_env=custom_env, profile_id=profile.profile_id)
|
||||
else:
|
||||
res = agy_generate(req, custom_env=custom_env)
|
||||
res = agy_generate(req, custom_env=custom_env, profile_id=profile.profile_id)
|
||||
|
||||
if isinstance(res, dict) and "error" in res:
|
||||
err_dict = res.get("error")
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ def test_concurrent_antigravity_credential_isolation(tmp_path, monkeypatch):
|
|||
def mock_load_profile_auth(prov, profile_id):
|
||||
return {"token": f"token_for_{profile_id}"}
|
||||
|
||||
def mock_agy_generate(req, custom_env=None):
|
||||
def mock_agy_generate(req, custom_env=None, **kwargs):
|
||||
user_prof = custom_env.get("USERPROFILE") if custom_env else None
|
||||
observed_envs_during_run.append((req.get("profile_id"), user_prof))
|
||||
time.sleep(0.05)
|
||||
|
|
@ -65,7 +65,7 @@ def test_credential_restoration_on_subprocess_exception(tmp_path, monkeypatch):
|
|||
def mock_load_profile_auth(prov, profile_id):
|
||||
return {"token": "valid_token"}
|
||||
|
||||
def mock_agy_generate_fail(req, custom_env=None):
|
||||
def mock_agy_generate_fail(req, custom_env=None, **kwargs):
|
||||
raise RuntimeError("CLI process crashed")
|
||||
|
||||
with patch.object(ProfileAuthManager, "load_profile_auth", side_effect=mock_load_profile_auth), \
|
||||
|
|
|
|||
Loading…
Reference in a new issue