fix(hermes_cli): keep TTS/setup xAI OAuth from switching active chat provider

Save side-tool OAuth tokens without promoting xai-oauth via active_provider
or model.provider so hermes setup tts login no longer hijacks inference routing.
This commit is contained in:
Fangliquan 2026-07-25 20:41:57 +08:00 committed by Teknium
parent a54067a6fd
commit fce06e909d
5 changed files with 134 additions and 6 deletions

View file

@ -4452,7 +4452,15 @@ def _save_xai_oauth_tokens(
redirect_uri: str = "",
last_refresh: Optional[str] = None,
auth_mode: str = "oauth_device_code",
set_active: bool = True,
) -> None:
"""Persist xAI OAuth tokens into the auth store.
When *set_active* is True (default), also promote ``xai-oauth`` to
``active_provider`` appropriate for intentional model/auth login.
Pass ``set_active=False`` for side-tool credential bootstrap (TTS, STT,
dashboard token save, token refresh) so inference routing is unchanged.
"""
if last_refresh is None:
last_refresh = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
with _auth_store_lock():
@ -4470,7 +4478,9 @@ def _save_xai_oauth_tokens(
state["discovery"] = discovery
if redirect_uri:
state["redirect_uri"] = redirect_uri
_save_provider_state(auth_store, "xai-oauth", state)
_store_provider_state(
auth_store, "xai-oauth", state, set_active=set_active
)
_save_auth_store(auth_store)
if write_through_to_root:
_write_through_xai_oauth_to_global_root(state)
@ -4808,6 +4818,9 @@ def _refresh_xai_oauth_tokens(
redirect_uri=redirect_uri,
last_refresh=refreshed["last_refresh"],
auth_mode=auth_mode,
# Refresh must not flip active_provider — TTS/side tools can refresh
# xAI tokens while chat still routes through another provider.
set_active=False,
)
return updated_tokens

View file

@ -896,15 +896,17 @@ def _xai_oauth_logged_in_for_setup() -> bool:
def _run_xai_oauth_login_from_setup() -> bool:
"""Run the xAI Grok OAuth device-code login from inside the setup wizard.
Saves OAuth tokens only. Does **not** switch the active inference
provider or rewrite ``model.provider`` callers (TTS setup, tools
config) only need credentials for side tools.
Returns True on success, False on any failure (the caller falls back
to whatever the user picked next, e.g. Edge TTS).
"""
try:
from hermes_cli.auth import (
DEFAULT_XAI_OAUTH_BASE_URL,
_is_remote_session,
_save_xai_oauth_tokens,
_update_config_for_provider,
_xai_oauth_device_code_login,
)
except Exception as exc:
@ -922,9 +924,7 @@ def _run_xai_oauth_login_from_setup() -> bool:
redirect_uri=creds.get("redirect_uri", ""),
last_refresh=creds.get("last_refresh"),
auth_mode="oauth_device_code",
)
_update_config_for_provider(
"xai-oauth", creds.get("base_url", DEFAULT_XAI_OAUTH_BASE_URL)
set_active=False,
)
return True
except Exception as exc:

View file

@ -11153,6 +11153,9 @@ def _xai_device_poller(session_id: str) -> None:
discovery=discovery,
last_refresh=datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
auth_mode="oauth_device_code",
# Dashboard OAuth only bootstraps credentials for side tools;
# do not hijack the active chat inference provider.
set_active=False,
)
# The singleton write above is the single source of truth: the
# credential-pool load seeds it as the canonical ``device_code``