Skip to content

fix(xai): scope xAI HTTP credential resolution to the active profile - #39069

Closed
jonpol01 wants to merge 1 commit into
NousResearch:mainfrom
jonpol01:fix/xai-http-profile-credentials
Closed

fix(xai): scope xAI HTTP credential resolution to the active profile#39069
jonpol01 wants to merge 1 commit into
NousResearch:mainfrom
jonpol01:fix/xai-http-profile-credentials

Conversation

@jonpol01

@jonpol01 jonpol01 commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Problem

xAI credential probes — the boot-time gates behind x_search, video_gen, and the xAI web-search provider — resolve the auth store from get_hermes_home() / "auth.json", i.e. the root HERMES_HOME.

When a named profile is active but HERMES_HOME resolves to the root, the named profile's xAI credential at <root>/profiles/<name>/auth.json is missed. This happens in:

  • the Docker multi-profile layout (HERMES_HOME=/opt/data, profiles under /opt/data/profiles/<name>, gateways launched with -p <name>),
  • the multi-profile dashboard process (boots at the root, enumerates tools per profile), and
  • lazy tool-gate re-checks (registry._check_fn_cached, ~30s TTL) that re-resolve after the per-invocation profile env mutation is no longer in effect.

check_x_search_requirements() / check_video_generation_requirements() then return False, so x_search and video_generate are filtered out at boot — even though the chat model works, because it caches its bearer once at startup while still profile-scoped.

Fix

tools/xai_http.py:

  • Add _active_profile_home_scope(): when HERMES_HOME resolves to the root and a non-default profile is active (read from the sticky active_profile file), temporarily scope get_hermes_home() to the profile dir via the existing set_hermes_home_override ContextVar. The auth layer's existing profile→global fallback then resolves the right store. No-op when already profile-scoped, on the default profile, or on any error.
  • Wrap both resolve_xai_http_credentials() and the cheap has_xai_credentials() probe in that scope.
  • Make has_xai_credentials() also honor credential_pool["xai-oauth"] entries (e.g. hermes auth add, source manual), not just the providers.xai-oauth.tokens singleton — parity with the heavy resolver.

No behavior change for the standard single-home layout or the default profile.

Tests

Adds tests/tools/test_xai_http.py (6 tests): root-HERMES_HOME + active-profile credential resolution (credential_pool and singleton), the negative case (no credential anywhere), the classic single-home layout, the XAI_API_KEY short-circuit, and that the public resolver applies the scope before delegating.

All pass; existing test_x_search_tool, test_web_providers_xai, and test_auth_profile_fallback suites are unaffected.

Refs #18594.

xAI credential probes -- the gates behind x_search, video_gen, and the
xAI web-search provider -- resolved the auth store from
get_hermes_home()/auth.json (the root HERMES_HOME). When a named profile
is active but HERMES_HOME resolves to the root (the Docker multi-profile
layout, the multi-profile dashboard process, or a lazy tool-gate
re-check after the per-invocation profile env mutation is no longer in
effect), the named profile's xAI credential under
<root>/profiles/<name>/auth.json was missed. check_x_search_requirements()
and check_video_generation_requirements() then returned False and the
tools were filtered out at boot -- even though the chat model worked,
because it caches its bearer at startup while still profile-scoped.

Wrap resolve_xai_http_credentials() and has_xai_credentials() in a
profile-home scope: when HERMES_HOME resolves to the root, recover the
active profile from the sticky active_profile file and scope
get_hermes_home() to it via the existing set_hermes_home_override
ContextVar, so the auth layer's existing profile->global fallback
resolves the right store. Also make the cheap has_xai_credentials()
probe honor credential_pool["xai-oauth"] entries, not just the
providers.xai-oauth.tokens singleton (parity with the heavy resolver).

No-op for the standard single-home layout and the default profile.

Adds tests/tools/test_xai_http.py covering the root-HERMES_HOME +
active-profile cases (pool and singleton), the negative case, the
classic single-home layout, and that the resolver applies the scope.

Refs NousResearch#18594.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have area/auth Authentication, OAuth, credential pools provider/xai xAI (Grok) labels Jun 4, 2026
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Thanks for this, @jonpol01 — same symptom, addressed at a shared chokepoint instead.

This scopes resolve_xai_http_credentials / the boot-time xAI probes to the active profile (+215). #46614 (merged as 8844e09) fixes it at _read_xai_oauth_tokens, which resolve_xai_http_credentialsresolve_xai_oauth_runtime_credentials already routes through — so the profile/credential-pool/global-root fallback applies to x_search, video_gen, and the web-search probe via one path, and it also adds the rotating-refresh write-back to root (#43589).

Closing as superseded by #46614. Your write-up of the root-vs-profile HERMES_HOME resolution in the Docker/dashboard/lazy-gate cases was a useful map of where the probes go wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools P3 Low — cosmetic, nice to have provider/xai xAI (Grok) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants