From 8ff5f13c09eca2b861a2bac6639f0d904c6b487b Mon Sep 17 00:00:00 2001 From: SHT <1373636680@qq.com> Date: Sat, 15 Aug 2026 19:05:24 +0800 Subject: [PATCH] fix(auth): resolve provider auto-detection keys through the profile scope (#86917) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit resolve_provider's auto path read provider API keys with bare os.getenv — under multiplex a secondary profile's keys live only in its secret scope, so auto-detection found nothing and every secondary profile with model.provider: auto failed with 'No LLM provider configured' at agent init (reproduced on a live 7-profile gateway). Route both env-key reads (the OPENAI/OPENROUTER tier and the PROVIDER_REGISTRY loop) through _scoped_key_env, the scope-aware helper auxiliary_client already uses: secret scope wins under multiplex, UnscopedSecretError falls back to os.environ (default-profile/CLI paths unchanged). Same bug class as #86905. Verified in a gateway-accurate simulation (hermes_home_override + profile scope): resolve_provider('auto') now returns the secondary profile's own provider (deepseek) instead of erroring. --- hermes_cli/auth.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/hermes_cli/auth.py b/hermes_cli/auth.py index c10032c305..211340b477 100644 --- a/hermes_cli/auth.py +++ b/hermes_cli/auth.py @@ -2180,7 +2180,18 @@ def resolve_provider( except Exception as e: logger.debug("Could not read config.yaml model.provider for auto-resolution: %s", e) - if has_usable_secret(os.getenv("OPENAI_API_KEY")) or has_usable_secret(os.getenv("OPENROUTER_API_KEY")): + # Scope-aware key reads: under multiplex a secondary profile's API keys + # live only in its secret scope, not os.environ — a bare getenv here + # would find nothing and auto-resolution would report "No LLM provider + # configured" for every secondary profile (same class as #86905). + try: + from agent.auxiliary_client import _scoped_key_env + except Exception: # pragma: no cover — defensive + _scoped_key_env = lambda name: os.getenv(name) or "" + + if has_usable_secret(_scoped_key_env("OPENAI_API_KEY")) or has_usable_secret( + _scoped_key_env("OPENROUTER_API_KEY") + ): return "openrouter" # Auto-detect an OpenRouter credential added via `hermes auth add openrouter` @@ -2223,7 +2234,7 @@ def resolve_provider( if pid in {"copilot", "lmstudio"}: continue for env_var in pconfig.api_key_env_vars: - if has_usable_secret(os.getenv(env_var, "")): + if has_usable_secret(_scoped_key_env(env_var)): # An exported API key now wins over a logged-in OAuth provider # (the #29285 fix). Surface that so a user who deliberately uses # OAuth but has a stale key in ~/.hermes/.env isn't silently