refactor(agent/aux): lift max_tokens forwarding policy and Nous dual-wire check out of _build_call_kwargs

This commit is contained in:
Teknium
2026-09-02 11:35:28 -07:00
parent dcbf263a09
commit 4022e69e69
+67 -69
View File
@@ -7711,6 +7711,58 @@ def _contains_profile_reasoning_fields(value: Any) -> bool:
return False
_NOUS_PROVIDER_NAMES = frozenset({"nous", "nous-portal", "nousresearch"})
def _nous_on_messages_wire(provider_norm: str, model: str) -> bool:
"""True when a Nous Portal route serves ``model`` over /v1/messages (dual-wire catalog)."""
if provider_norm not in _NOUS_PROVIDER_NAMES:
return False
from hermes_cli.providers import nous_api_mode
return nous_api_mode(model) == "anthropic_messages"
def _forwards_max_tokens(
provider: str, provider_norm: str, model: str, effective_base: str, task: Optional[str],
) -> bool:
"""Whether an explicit max_tokens is forwarded on this route.
No default output cap: omitted max_tokens means "model's max output" on most
providers and sidesteps wire quirks (max_completion_tokens on GPT-5/Copilot,
ZAI vision rejecting it). Forward only where mandatory or meaningfully honored:
Anthropic Messages wire (hard 400 without it); NVIDIA NIM (some models return
200 with empty choices[] when omitted); MoA reference slots; Gemini native
(fixed 65,535 ceiling when omitted, so MoA reference_max_tokens needs the cap);
OpenRouter (budgets credit against the FULL output window when omitted → 402
on low-credit accounts); managed local llama-server (uncapped decode with no
EOS burns the GPU to the full context window).
"""
if _is_anthropic_compat_endpoint(provider, effective_base):
return True
if _nous_on_messages_wire(provider_norm, model):
return True
if (
provider_norm in {"nvidia", "nvidia-nim", "nim", "build-nvidia", "nemotron"}
or base_url_host_matches(effective_base, "integrate.api.nvidia.com")
):
return True
if bool(task) and str(task) == "moa_reference":
return True
is_gemini_native = provider_norm in {"gemini", "google", "google-gemini", "google-ai-studio"}
if not is_gemini_native and effective_base:
try:
from agent.gemini_native_adapter import is_native_gemini_base_url
is_gemini_native = is_native_gemini_base_url(effective_base)
except Exception:
pass
if is_gemini_native:
return True
if provider_norm == "openrouter" or base_url_host_matches(effective_base, "openrouter.ai"):
return True
return _is_managed_local_endpoint(effective_base)
def _build_call_kwargs(
provider: str,
model: str,
@@ -7747,60 +7799,16 @@ def _build_call_kwargs(
if temperature is not None:
kwargs["temperature"] = temperature
if max_tokens is not None:
# No default output cap: omitted max_tokens means "model's max output" on
# most providers and sidesteps wire quirks (max_completion_tokens on
# GPT-5/Copilot, ZAI vision rejecting it). Forward the cap only where it
# is mandatory or meaningfully honored, enumerated below.
_effective_base = base_url or (
_current_custom_base_url() if provider == "custom" else ""
)
_provider_norm = str(provider or "").strip().lower()
# NVIDIA NIM: some models (minimaxai/minimax-m3) return 200 with empty
# choices[] when max_tokens is omitted.
_is_nvidia_nim = (
_provider_norm in {"nvidia", "nvidia-nim", "nim", "build-nvidia", "nemotron"}
or base_url_host_matches(_effective_base, "integrate.api.nvidia.com")
)
_is_moa = bool(task) and str(task) == "moa_reference"
# Gemini native maps max_tokens → maxOutputTokens with a fixed 65,535
# ceiling when omitted; an explicit cap is the only way MoA's
# reference_max_tokens takes effect for gemini advisors.
_is_gemini_native = _provider_norm in {
"gemini", "google", "google-gemini", "google-ai-studio",
}
if not _is_gemini_native and _effective_base:
try:
from agent.gemini_native_adapter import is_native_gemini_base_url
_is_gemini_native = is_native_gemini_base_url(_effective_base)
except Exception:
pass
_nous_on_messages = False
if _provider_norm in {"nous", "nous-portal", "nousresearch"}:
from hermes_cli.providers import nous_api_mode
effective_base = base_url or (
_current_custom_base_url() if provider == "custom" else ""
)
provider_norm = str(provider or "").strip().lower()
_nous_on_messages = nous_api_mode(model) == "anthropic_messages"
# OpenRouter budgets credit against the requested cap and assumes the
# model's FULL output window when omitted, so low-credit accounts 402.
_is_openrouter = (
_provider_norm == "openrouter"
or base_url_host_matches(_effective_base, "openrouter.ai")
)
# Managed local llama-server: an uncapped decode with no EOS burns the
# user's GPU to the full context window, so explicit caps are honored.
_is_managed_local = _is_managed_local_endpoint(_effective_base)
if (
_is_anthropic_compat_endpoint(provider, _effective_base)
or _nous_on_messages
or _is_nvidia_nim
or _is_moa
or _is_gemini_native
or _is_openrouter
or _is_managed_local
):
# Anthropic Messages wire requires max_tokens (hard 400 if omitted).
# auxiliary_max_tokens_param() picks max_completion_tokens where needed.
kwargs.update(auxiliary_max_tokens_param(max_tokens, model=model))
if max_tokens is not None and _forwards_max_tokens(
provider, provider_norm, model, effective_base, task,
):
# auxiliary_max_tokens_param() picks max_completion_tokens where needed.
kwargs.update(auxiliary_max_tokens_param(max_tokens, model=model))
if tools:
# Vertex/Azure/Bedrock 400 on duplicate tool names; upstream dedups
@@ -7824,9 +7832,6 @@ def _build_call_kwargs(
# Provider profiles are the source of truth for reasoning wire shapes
# (top-level, nested body, or extra_body.reasoning); providers without a
# reasoning-aware profile keep the generic ``extra_body.reasoning`` fallback.
effective_base = base_url or (
_current_custom_base_url() if provider == "custom" else ""
)
profile_body: Dict[str, Any] = {}
profile_reasoning_extra: Dict[str, Any] = {}
profile_top_level: Dict[str, Any] = {}
@@ -7835,7 +7840,7 @@ def _build_call_kwargs(
from providers import get_provider_profile
from providers.base import ProviderProfile
profile = get_provider_profile(str(provider or "").strip().lower())
profile = get_provider_profile(provider_norm)
if profile is not None:
profile_body = profile.build_extra_body(
model=model,
@@ -7883,8 +7888,7 @@ def _build_call_kwargs(
# Portal tags + sticky session_id fallback when the profile didn't supply
# them; session_id keeps aux calls on the main turn's upstream instance
# (cache warmth) — tags alone are not enough on /v1/messages.
_provider_for_portal = str(provider or "").strip().lower()
if _provider_for_portal in {"nous", "nous-portal", "nousresearch"}:
if provider_norm in _NOUS_PROVIDER_NAMES:
if "tags" not in merged_extra:
merged_extra["tags"] = _nous_portal_tags()
if "session_id" not in merged_extra:
@@ -7903,18 +7907,12 @@ def _build_call_kwargs(
# OpenAI SDK clients would reject; Portal Claude is dual-wire, so include it
# only when the catalog id selects /v1/messages.
if reasoning_config and isinstance(reasoning_config, dict):
provider_norm = str(provider or "").strip().lower()
effective_base = base_url or ""
_nous_on_messages = False
if provider_norm in {"nous", "nous-portal", "nousresearch"}:
from hermes_cli.providers import nous_api_mode
_nous_on_messages = nous_api_mode(model) == "anthropic_messages"
raw_base = base_url or ""
if (
provider_norm == "anthropic"
or _nous_on_messages
or _endpoint_speaks_anthropic_messages(effective_base)
or _is_anthropic_compat_endpoint(provider_norm, effective_base)
or _nous_on_messages_wire(provider_norm, model)
or _endpoint_speaks_anthropic_messages(raw_base)
or _is_anthropic_compat_endpoint(provider_norm, raw_base)
):
kwargs["_reasoning_config"] = dict(reasoning_config)