Eight secret readers wrapped the scoped get_secret() call in a broad except Exception / contextlib.suppress and fell through to os.environ. Under multiplex that env holds the default profile's value, so a bound scope whose resolution fails silently borrowed another profile's credential: the pairing allowlist reader could then persist the foreign list into the served profile's .env, and the proxy key, tool gateway token, OpenRouter and aux provider keys, ElevenLabs key, and Slack token probe had the same shape. Keep the deliberate UnscopedSecretError -> os.environ fallback (the unscoped default-profile path legitimately reads its own env) and let every other scoped-read failure propagate; the two availability probes fail closed instead. config._scoped_environ_get now propagates as its docstring already claimed.
43 lines
1.6 KiB
Python
43 lines
1.6 KiB
Python
"""OpenRouter API key probe shared by Hermes tools."""
|
|
|
|
import os
|
|
|
|
|
|
def check_api_key() -> bool:
|
|
"""Return True if OPENROUTER_API_KEY is present.
|
|
|
|
Scope-aware: an installed profile secret scope is authoritative under
|
|
multiplex; unscoped CLI probes fall back to the plain env read. Any other
|
|
scope failure propagates -- a failed scoped read must never silently
|
|
borrow another profile's key from ``os.environ``.
|
|
"""
|
|
from agent.secret_scope import UnscopedSecretError, get_secret
|
|
|
|
try:
|
|
return bool(get_secret("OPENROUTER_API_KEY"))
|
|
except UnscopedSecretError:
|
|
return bool(os.getenv("OPENROUTER_API_KEY"))
|
|
|
|
|
|
# ---- BEGIN PLUGIN-COMPAT (revert-scheduled; see COMPAT_MANIFEST.md) ----
|
|
# Names external plugins imported from this module before the Sep 2026 decomposition.
|
|
# Internal code MUST NOT use these (scripts/check_compat_pointers.py fails CI if it does).
|
|
# The whole block is removed by reverting the commit that added it.
|
|
|
|
def get_async_client():
|
|
"""Return a shared async OpenAI-compatible client for OpenRouter.
|
|
|
|
The client is created lazily on first call and reused thereafter.
|
|
Uses the centralized provider router for auth and client construction.
|
|
Raises ValueError if OPENROUTER_API_KEY is not set.
|
|
"""
|
|
global _client
|
|
if _client is None:
|
|
from agent.auxiliary_client import resolve_provider_client
|
|
client, _model = resolve_provider_client("openrouter", async_mode=True)
|
|
if client is None:
|
|
raise ValueError("OPENROUTER_API_KEY environment variable not set")
|
|
_client = client
|
|
return _client
|
|
# ---- END PLUGIN-COMPAT ----
|