fix(fallback): named custom providers keep their configured identity after automatic fallback (#98739)
resolve_runtime_provider returns the bare billing class 'custom' for every named providers:/custom_providers: entry; the configured id only survives in requested_provider. All three fallback resolvers (gateway, TUI/desktop, cron) persisted runtime['provider'] as the agent identity, so an automatic fallback labeled the session 'custom' in the UI and billing rows, while a manual /model switch to the same provider showed the configured name. New shared helper hermes_cli.fallback_config.effective_runtime_provider() upgrades the bare class back to the entry's configured identity (ad-hoc provider: custom entries stay unchanged), applied at all three sites — same class as the delegate_tool fix.
This commit is contained in:
@@ -28,6 +28,38 @@ def resolve_entry_api_key(entry: dict[str, Any] | None) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def effective_runtime_provider(
|
||||
entry: dict[str, Any] | None, runtime: dict[str, Any] | None
|
||||
) -> str:
|
||||
"""Provider identity to persist/display for a resolved fallback entry.
|
||||
|
||||
``resolve_runtime_provider`` returns the bare billing class ``"custom"``
|
||||
for every named ``providers:`` / ``custom_providers:`` entry; the entry's
|
||||
configured id only survives in ``requested_provider``. Fallback resolvers
|
||||
that persist ``runtime["provider"]`` as the agent identity therefore label
|
||||
sessions/billing rows ``custom`` instead of the configured provider name —
|
||||
while the manual ``/model`` switch path correctly persists the named id
|
||||
(#98739). Same class as the delegation fix in ``tools/delegate_tool.py``.
|
||||
|
||||
Returns the entry's requested identity when the resolved provider is the
|
||||
bare ``custom`` class; a genuinely ad-hoc endpoint (requested provider IS
|
||||
``custom``) keeps the bare class unchanged.
|
||||
"""
|
||||
runtime = runtime or {}
|
||||
resolved = str(runtime.get("provider") or "").strip()
|
||||
if resolved.lower() != "custom":
|
||||
return resolved
|
||||
requested = str(
|
||||
runtime.get("requested_provider")
|
||||
or (entry or {}).get("provider")
|
||||
or ""
|
||||
).strip()
|
||||
if requested and requested.lower() != "custom":
|
||||
return requested
|
||||
return resolved
|
||||
|
||||
|
||||
|
||||
def _iter_fallback_entries(raw: Any) -> list[dict[str, Any]]:
|
||||
candidates = [raw] if isinstance(raw, dict) else raw if isinstance(raw, list) else []
|
||||
entries: list[dict[str, Any]] = []
|
||||
|
||||
Reference in New Issue
Block a user