mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-07-16 20:50:18 +00:00
fix(config): reasoning toggle for nested Gemini custom provider routes (#3431)
Version-gated the nested-gateway allow to 2.5-series/3-era (reviewer fix: gemini-1.5/1.0 have no thinking controls -> selector would fail on send) + pre-2.5 exclusion regression tests. Stamped v0.51.408 (Release NU). Co-authored-by: b3nw <b3nw@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,12 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.51.408] — 2026-06-14 — Release NU (reasoning selector for nested Gemini custom-provider routes, #3431)
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Custom provider model ids with nested Gemini gateway routes (e.g. `vertex/gemini-2.5-…`, `gemini_cli/gemini-2.5-…`) now expose the reasoning effort selector when the underlying model supports thinking.** Extends the heuristic fallback used for bare and dot-separated custom names; embedding and image-only Gemini routes stay excluded, and the allow is version-gated to the reasoning-capable families (Gemini 2.5 series and 3-era) so pre-2.5 routes like `vertex/gemini-1.5-pro` — which have no thinking controls — don't get a selector that would fail on send. OpenRouter-style `x-ai/…` ids continue to use the existing slash-prefix list. (#3431)
|
||||
|
||||
## [v0.51.407] — 2026-06-14 — Release NT (nest forked sessions under their parent in the sidebar, #3224)
|
||||
|
||||
### Added
|
||||
|
||||
@@ -2482,6 +2482,49 @@ def _candidate_supports_reasoning(candidate: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _nested_route_reasoning_denied(model: str) -> bool:
|
||||
"""Hard deny for nested Gemini gateway routes that must never show a reasoning toggle."""
|
||||
lower = str(model or "").strip().lower()
|
||||
if not lower:
|
||||
return False
|
||||
for prefix in ("vertex/gemini-", "gemini_cli/gemini-"):
|
||||
if lower.startswith(prefix):
|
||||
tail = lower[len(prefix) :]
|
||||
if tail.startswith("embedding") or "image" in tail or "imagine" in tail:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _nested_gateway_route_reasoning(model: str) -> bool:
|
||||
"""Recognize nested ``vertex/gemini-`` and ``gemini_cli/gemini-`` routes on custom providers.
|
||||
|
||||
The slash-prefix heuristic list includes ``google/gemini-2`` but not gateway-prefixed
|
||||
Gemini ids, so capable models behind custom aggregators stayed hidden.
|
||||
"""
|
||||
lower = str(model or "").strip().lower()
|
||||
if not lower:
|
||||
return False
|
||||
for prefix in ("vertex/gemini-", "gemini_cli/gemini-"):
|
||||
if lower.startswith(prefix):
|
||||
tail = lower[len(prefix) :]
|
||||
if tail.startswith("embedding") or "image" in tail or "imagine" in tail:
|
||||
return False
|
||||
# Gemini thinking/reasoning controls are documented for the 2.5
|
||||
# series and 3-era models only — 1.5 (and earlier) have no thinking
|
||||
# support, so a reasoning selector on e.g. ``vertex/gemini-1.5-pro``
|
||||
# would let a user pick an effort that the route then rejects.
|
||||
# Version-gate the allow to the reasoning-capable families.
|
||||
if (
|
||||
tail == "2.5"
|
||||
or tail.startswith(("2.5-", "2.5.", "3-", "3."))
|
||||
or "thinking" in tail
|
||||
or "reasoning" in tail
|
||||
):
|
||||
return True
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def _filter_reasoning_efforts_for_provider(
|
||||
efforts: list[str],
|
||||
model_id: str,
|
||||
@@ -2535,6 +2578,8 @@ def _heuristic_reasoning_efforts(model_id: str, provider_id: str) -> list[str]:
|
||||
)
|
||||
if any(model.startswith(prefix) for prefix in prefixes):
|
||||
return list(VALID_REASONING_EFFORTS)
|
||||
if _nested_gateway_route_reasoning(model):
|
||||
return list(VALID_REASONING_EFFORTS)
|
||||
# Named custom providers often rewrite model ids with dots, underscores, or
|
||||
# extra vendor namespaces. Normalize those shapes before applying family-level
|
||||
# reasoning heuristics so "deepseek.v3.2", "deepseek_v4_flash", and
|
||||
@@ -2602,6 +2647,9 @@ def resolve_model_reasoning_efforts(
|
||||
|
||||
hinted_model = _strip_provider_hint_for_reasoning(model)
|
||||
|
||||
if _nested_route_reasoning_denied(hinted_model):
|
||||
return []
|
||||
|
||||
try:
|
||||
from hermes_cli.models import (
|
||||
github_model_reasoning_efforts,
|
||||
|
||||
@@ -248,3 +248,58 @@ def test_deepseek_non_reasoning_variants_excluded(model_id):
|
||||
)
|
||||
|
||||
|
||||
# ── custom provider nested Gemini routes (vertex/, gemini_cli/) ───────────────
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model_id",
|
||||
[
|
||||
"vertex/gemini-3.1-pro-preview",
|
||||
"vertex/gemini-3-pro-preview",
|
||||
"gemini_cli/gemini-3-pro-preview",
|
||||
],
|
||||
)
|
||||
def test_custom_nested_gemini_routes_expose_reasoning(model_id):
|
||||
efforts = cfg.resolve_model_reasoning_efforts(
|
||||
model_id,
|
||||
provider_id="custom:newapi",
|
||||
)
|
||||
assert set(efforts) >= {"low", "medium", "high"}, (
|
||||
f"{model_id} via custom:newapi should expose reasoning efforts"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model_id",
|
||||
[
|
||||
"vertex/gemini-embedding-001",
|
||||
"vertex/gemini-3-pro-image-preview",
|
||||
],
|
||||
)
|
||||
def test_custom_nested_gemini_routes_exclude_non_reasoning(model_id):
|
||||
assert cfg.resolve_model_reasoning_efforts(
|
||||
model_id,
|
||||
provider_id="custom:newapi",
|
||||
) == [], f"{model_id} must not expose reasoning efforts"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model_id",
|
||||
[
|
||||
"vertex/gemini-1.5-pro",
|
||||
"vertex/gemini-1.5-flash",
|
||||
"gemini_cli/gemini-1.5-pro",
|
||||
"vertex/gemini-1.0-pro",
|
||||
],
|
||||
)
|
||||
def test_custom_nested_gemini_pre_2_5_routes_exclude_reasoning(model_id):
|
||||
"""Gemini thinking/reasoning controls are documented for the 2.5 series and
|
||||
3-era models only — 1.5 (and earlier) have no thinking support, so the
|
||||
nested-gateway detection must not expose a reasoning selector for them
|
||||
(a user could otherwise pick an effort the route then rejects)."""
|
||||
assert cfg.resolve_model_reasoning_efforts(
|
||||
model_id,
|
||||
provider_id="custom:newapi",
|
||||
) == [], f"{model_id} (pre-2.5 Gemini) must not expose reasoning efforts"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user