HERMES-GIELIE/api
Hermes Agent 70d391c44a fix(profiles): scope /api/providers + /api/models to the active profile (#3957)
On a non-default profile, Settings → Providers timed out and the model
picker showed only the default profile's models. WebUI profile switching is
per-client/cookie-scoped (#798), but two read-only paths resolved from the
process-global default profile:

- Facet A: /api/providers + /api/models did not apply the active profile's
  .env around the read, so get_auth_status() / provider_model_ids() / custom
  key lookups resolved the default profile's credentials. On a non-default
  profile the auth probes could stall past the 30s frontend abort.
- Facet B: the /api/models disk cache was a single import-time
  STATE_DIR/models_cache.json shared across every profile, while the cache
  fingerprint is profile-specific -> a non-default profile rejected the shared
  snapshot every read and cold-rebuilt (the slow serial-probe path).

Fix:
- api.profiles.profile_env_for_active_request(): applies the active
  per-request profile's .env for the duration of the read (delegates to the
  existing profile_env_for_background_worker used by streaming). No-op for the
  default/root profile, so single-profile deployments are byte-identical.
- api.config._get_models_cache_path(): profile-keys the disk cache filename
  (models_cache.<profile>.json) derived from the default path; default profile
  keeps models_cache.json unchanged (no file migration).
- routes.py: wrap both GET handlers in profile_env_for_active_request.
- conftest: restore api.profiles._active_profile + clear request-profile TLS
  after each test (a pre-existing isolation hole that profile-keyed cache
  paths newly surface under sharding).

Tested: 10 new regression tests; live before/after on isolated servers shows
a non-default profile now surfaces its configured provider (deepseek) with
its own credentials + its own cache file, where master showed only the
default profile's providers and one shared cache.

Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-06-11 01:17:22 +00:00
..
__init__.py
agent_health.py Release v0.51.260 — Release IB (stage-r8) (#3614) 2026-06-04 15:21:41 -07:00
agent_sessions.py fix(sidebar): prime idx_messages_session before CLI-session scan (#3887) (#3888) 2026-06-09 12:35:13 -07:00
auth.py Release v0.51.260 — Release IB (stage-r8) (#3614) 2026-06-04 15:21:41 -07:00
background.py
background_process.py [HELD — independent review pending] Release v0.51.340 — bg_task agent wakeup (trio #2968+#2971+#2979) (#3867) 2026-06-08 22:36:18 -07:00
clarify.py feat: add distinct attention request sound 2026-05-30 19:40:40 +00:00
commands.py Release v0.51.263 — Release IE (stage-r13) (#3625) 2026-06-04 23:56:44 -07:00
compression_anchor.py
config.py fix(profiles): scope /api/providers + /api/models to the active profile (#3957) 2026-06-11 01:17:22 +00:00
dashboard_probe.py
extensions.py
gateway_chat.py [HELD — independent review pending] Release v0.51.294 — stage-3401 (live-to-final redesign #3401 + 4 deep-review fixes) (#3741) 2026-06-06 12:12:37 -07:00
gateway_watcher.py Release v0.51.256 — Release HX (stage-r4) (#3596) 2026-06-04 12:28:06 -07:00
goals.py
helpers.py fix: preserve live stream output across session switches (cross-client) 2026-06-10 20:12:05 +00:00
kanban_bridge.py Release v0.51.348 — Release LL (Phase 0 hotfix: timeout regression + data-loss + leaks) (#3917) 2026-06-10 01:12:48 -07:00
metering.py
models.py Release v0.51.347 — Release LK (streaming & render reliability cluster #3892 #3898 #3885 #3882 #3868) (#3902) 2026-06-09 17:02:35 -07:00
oauth.py Release v0.51.330 — Release KT (#3716 api docstring backfill, partial) (#3841) 2026-06-08 12:22:22 -07:00
onboarding.py
passkeys.py Release v0.51.270 — Release IL (stage-u1 — un-hold batch: #3517 #3624 #3613) (#3674) 2026-06-05 11:35:26 -07:00
paths.py fix(profiles): avoid config import cycle 2026-06-01 05:05:16 +00:00
plugin_providers.py Release v0.51.270 — Release IL (stage-u1 — un-hold batch: #3517 #3624 #3613) (#3674) 2026-06-05 11:35:26 -07:00
plugins.py fix(#2622): plugin card UX — legible Open button, single badge, visible toggle + reject protocol-relative tab.path 2026-06-02 03:58:02 +00:00
profiles.py fix(profiles): scope /api/providers + /api/models to the active profile (#3957) 2026-06-11 01:17:22 +00:00
providers.py Release v0.51.318 — Release KH (Phase 3 light: warm account-usage probe worker pool, #3722) (#3792) 2026-06-07 12:07:13 -07:00
request_diagnostics.py
rollback.py
route_approvals.py Release v0.51.275 — Release IQ (stage-p3d — approval SSE state extraction #3575) (#3681) 2026-06-05 13:10:45 -07:00
routes.py fix(profiles): scope /api/providers + /api/models to the active profile (#3957) 2026-06-11 01:17:22 +00:00
run_journal.py Release v0.51.326 — Release KP (#3618 + #3802 + #3762 + #3810) (#3816) 2026-06-07 23:18:51 -07:00
runner_client.py harden: runner client rejects non-http(s) base_url + no redirect-follow (#3073) 2026-05-31 17:49:26 +00:00
runtime_adapter.py
session_discoverability.py
session_events.py Release v0.51.266 — Release IH (stage-r16) (#3641) 2026-06-05 00:44:03 -07:00
session_lifecycle.py Release v0.51.256 — Release HX (stage-r4) (#3596) 2026-06-04 12:28:06 -07:00
session_ops.py Release v0.51.276 — Release IR (stage-p3e — preserve manually-named session titles #3542) (#3682) 2026-06-05 13:34:54 -07:00
session_recovery.py Release v0.51.329 — Release KS (#3814 O(n) index map + #3815 startup recovery skip) (#3840) 2026-06-08 11:49:26 -07:00
skill_usage.py
startup.py
state_sync.py fix: use Optional[T] for default None parameters in state_sync.py 2026-06-01 17:20:17 +00:00
streaming.py fix(#3929): preserve partial work on turn-level errors 2026-06-10 19:11:58 +00:00
system_health.py
terminal.py Release v0.51.304 — Release JT (stage-p2a — un-held terminal reaper + opt-in Docker GPU) (#3757) 2026-06-06 18:04:16 -07:00
todo_state.py Release v0.51.261 — Release IC (stage-r11) (#3616) 2026-06-04 16:46:20 -07:00
turn_journal.py Release v0.51.326 — Release KP (#3618 + #3802 + #3762 + #3810) (#3816) 2026-06-07 23:18:51 -07:00
updates.py Release v0.51.312 — Release KB (brick-wave: purge stale __pycache__ after self-update, fixes #3774) (#3778) 2026-06-07 08:26:36 -07:00
upload.py Release v0.51.326 — Release KP (#3618 + #3802 + #3762 + #3810) (#3816) 2026-06-07 23:18:51 -07:00
usage.py
webui_session_db.py Release v0.51.305 — Release JU (stage-p2b — dormant unified-SessionDB adapter) (#3759) 2026-06-06 18:16:07 -07:00
workspace.py Release v0.51.296 — stage-3731 (remote-workspace blocked-root security fix #3731) (#3744) 2026-06-06 13:49:59 -07:00
workspace_git.py Release v0.51.311 — Release KA (brick-wave: workspace Git RCE hardening #3769 + stale-snapshot sidebar visibility #3770) (#3776) 2026-06-07 08:05:30 -07:00
worktrees.py