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.
This commit is contained in:
@@ -342,6 +342,23 @@ _BUILTIN_SKINS: Dict[str, Dict[str, Any]] = {
|
||||
|
||||
_active_skin: Optional[SkinConfig] = None
|
||||
_active_skin_name: str = "default"
|
||||
# Routed multiplex profiles: (name, skin) per home key. ``display.skin`` and ``<home>/skins/*.yaml``
|
||||
# are per profile, and the relay display name / TUI skin payload are read under each profile's
|
||||
# override — one module slot would be last-writer-wins across profiles. Unscoped keeps the module slot.
|
||||
_active_skin_by_home: Dict[str, Tuple[str, SkinConfig]] = {}
|
||||
|
||||
|
||||
def _routed_home_key() -> Optional[str]:
|
||||
from hermes_constants import get_hermes_home_override, hermes_home_key
|
||||
return None if get_hermes_home_override() is None else hermes_home_key()
|
||||
|
||||
|
||||
def _profile_config() -> dict:
|
||||
try:
|
||||
from hermes_cli.config import load_config_readonly
|
||||
return load_config_readonly() or {}
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def _skins_dir() -> Path:
|
||||
@@ -414,6 +431,14 @@ def load_skin(name: str) -> SkinConfig:
|
||||
def get_active_skin() -> SkinConfig:
|
||||
"""Currently active skin config (cached)."""
|
||||
global _active_skin
|
||||
home_key = _routed_home_key()
|
||||
if home_key is not None:
|
||||
entry = _active_skin_by_home.get(home_key)
|
||||
if entry is None:
|
||||
# Cold routed profile: its own ``display.skin`` (nobody ran init_skin_from_config for it).
|
||||
init_skin_from_config(_profile_config())
|
||||
entry = _active_skin_by_home[home_key]
|
||||
return entry[1]
|
||||
if _active_skin is None:
|
||||
_active_skin = load_skin(_active_skin_name)
|
||||
return _active_skin
|
||||
@@ -422,12 +447,21 @@ def get_active_skin() -> SkinConfig:
|
||||
def set_active_skin(name: str) -> SkinConfig:
|
||||
"""Switch the active skin. Returns the new SkinConfig."""
|
||||
global _active_skin, _active_skin_name
|
||||
skin = load_skin(name)
|
||||
home_key = _routed_home_key()
|
||||
if home_key is not None:
|
||||
_active_skin_by_home[home_key] = (name, skin)
|
||||
return skin
|
||||
_active_skin_name = name
|
||||
_active_skin = load_skin(name)
|
||||
_active_skin = skin
|
||||
return _active_skin
|
||||
|
||||
|
||||
def get_active_skin_name() -> str:
|
||||
home_key = _routed_home_key()
|
||||
if home_key is not None:
|
||||
entry = _active_skin_by_home.get(home_key)
|
||||
return entry[0] if entry else "default"
|
||||
return _active_skin_name
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user