Files
hermes-agent/hermes_cli/models_profile_cache.py
Teknium 5ff34f565e fix(multiplex): per-profile catalog, skin and guest-mint state in hermes_cli
DeepInfra catalog (fetched with the launch env's key via os.getenv), Copilot
context limits (api_key ignored on hit), Nous reasoning caps + once-per-process
guards, the curated OpenRouter list, the model-catalog in-process copy (mtime
without path), banner skills, the guest-mint back-off flag and the active skin
were single slots read under per-profile overrides by the gateway and the TUI
gateway; the SWR refresh thread ran without the caller's ContextVars.

Under an override each lives per home key (hermes_cli/models_profile_cache.py
holds the shared slot helper so models.py does not grow), credentials are read
through the scope-aware dotenv reader and keyed by fingerprint, and background
refreshes run under copy_context(). Unscoped behaviour is byte-identical.
2026-09-12 01:35:05 -07:00

33 lines
1.4 KiB
Python

"""Per-profile view of ``hermes_cli.models``' module-level catalog slots.
Several caches on the facade (curated OpenRouter list, reasoning-capability catalogs and their
once-per-process guards) hold values derived from ONE profile's config, ``.env`` and ``<home>/cache``
files. In a multiplexed gateway every turn runs under a HERMES_HOME override, so a single module slot
would hand the launch profile's value to every other profile. Under an override the slot is read and
written per home key (routed profiles start cold, never from the launch profile's warmed value);
without one the module attribute stays the slot, so single-profile behaviour and the tests that reset
``models._X = None`` are untouched. Same shape as ``tools.approval._permanent_set``.
"""
from __future__ import annotations
from typing import Any
from hermes_constants import get_hermes_home_override, hermes_home_key
_SLOTS_BY_HOME: dict[tuple[str, str], Any] = {}
def profile_slot_get(module: Any, attr: str, default: Any = None) -> Any:
"""``module.<attr>`` for the active profile; ``default`` is a routed profile's cold value."""
if get_hermes_home_override() is None:
return getattr(module, attr)
return _SLOTS_BY_HOME.get((hermes_home_key(), attr), default)
def profile_slot_set(module: Any, attr: str, value: Any) -> None:
if get_hermes_home_override() is None:
setattr(module, attr, value)
else:
_SLOTS_BY_HOME[(hermes_home_key(), attr)] = value