Skip to content

fix(gateway): honor nested gateway.multiplex_profiles in load_gateway_config (#51372 salvage) - #59320

Merged
teknium1 merged 1 commit into
mainfrom
salvage/51372-nested-multiplex-key
Jul 6, 2026
Merged

fix(gateway): honor nested gateway.multiplex_profiles in load_gateway_config (#51372 salvage)#59320
teknium1 merged 1 commit into
mainfrom
salvage/51372-nested-multiplex-key

Conversation

@teknium1

@teknium1 teknium1 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

gateway.multiplex_profiles: true in config.yaml — the exact form written by hermes config set gateway.multiplex_profiles true — now actually enables multiplexing; previously load_gateway_config() only surfaced the top-level key, so the documented path silently loaded multiplex_profiles=False.

Salvages #51372 by @davidgut1982 (clean cherry-pick, authorship preserved).

Root cause: from_dict() honors the nested fallback, but load_gateway_config() builds gw_data as a synthesized dict from top-level keys, so the nested gateway: section never reached it. Mirrors the existing nested handling for max_concurrent_sessions/streaming.

Changes

  • gateway/config.py: read gateway.multiplex_profiles into gw_data when the top-level key is absent
  • tests/gateway/test_config.py: regression test (fails without the fix)

Validation

Before After
gateway:\n multiplex_profiles: true flag ignored, multiplexing off flag honored
tests/gateway/test_config.py 84/84 pass

Third PR in the multiplex isolation cluster (#59310, #59315). The empirical premise check was re-verified today: from_dict resolves the nested form, the loader does not.

Infographic

nested-flag-fix

@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists labels Jul 6, 2026
load_gateway_config() only surfaced the top-level `multiplex_profiles`
key into gw_data before calling GatewayConfig.from_dict(). A config.yaml
that pinned the flag under the nested `gateway:` section -- the form
written by `hermes config set gateway.multiplex_profiles true` -- was
silently ignored, so the gateway loaded with multiplex_profiles=False.

from_dict() already honors the nested fallback, but load_gateway_config()
builds gw_data from top-level keys first, so the nested value never
reached it.

Read gateway.multiplex_profiles into gw_data when the top-level key is
absent, mirroring the existing nested fallback for max_concurrent_sessions.

Adds a load_gateway_config() regression test that writes a config.yaml
with `gateway.multiplex_profiles: true` and asserts the loaded config has
multiplex_profiles=True (fails without the fix).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@teknium1
teknium1 force-pushed the salvage/51372-nested-multiplex-key branch from 12fcc8f to 56d1385 Compare July 6, 2026 05:02
@teknium1
teknium1 merged commit d3602e6 into main Jul 6, 2026
31 checks passed
@teknium1
teknium1 deleted the salvage/51372-nested-multiplex-key branch July 6, 2026 05:11
teknium1 pushed a commit that referenced this pull request Jul 20, 2026
load_gateway_config() already accepted both the top-level key and the
nested gateway.<key> form (written by `hermes config set gateway.<key>
...`) for multiplex_profiles, max_concurrent_sessions, streaming, and
write_sessions_json — each fixed one at a time as users hit it (most
recently #59320 for multiplex_profiles). Nine sibling top-level keys
never got the same nested fallback: session_reset, quick_commands, stt,
stt_echo_transcripts, group_sessions_per_user, thread_sessions_per_user,
reset_triggers, always_log_local, and unauthorized_dm_behavior.

`hermes config set gateway.<any-of-these> ...` builds exactly this nested
shape (hermes_cli/config.py's _set_nested has no schema, so it accepts
any dotted path), so a user following the same pattern that legitimately
works for gateway.multiplex_profiles/gateway.streaming gets a silent
no-op for these nine keys instead.

Fix: read `gateway: {...}` into a single `gateway_section` variable once
(consolidating three separate `yaml_cfg.get("gateway")` calls already in
the function) and add the same top-level-wins/nested-fallback check for
each of the nine keys, mirroring the existing write_sessions_json
precedent exactly.

Note: because every fallback here is guarded by
`isinstance(gateway_section, dict)`, this also makes the streaming
fallback tolerate a scalar `gateway:` block (e.g. `gateway: disabled`)
without crashing — the same crash #40837 (open) targets specifically for
streaming. This change doesn't set out to fix that PR's issue, but the
consolidated guard covers it as a side effect; flagging it for the
reviewer rather than leaving it to be found in review.
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
load_gateway_config() already accepted both the top-level key and the
nested gateway.<key> form (written by `hermes config set gateway.<key>
...`) for multiplex_profiles, max_concurrent_sessions, streaming, and
write_sessions_json — each fixed one at a time as users hit it (most
recently NousResearch#59320 for multiplex_profiles). Nine sibling top-level keys
never got the same nested fallback: session_reset, quick_commands, stt,
stt_echo_transcripts, group_sessions_per_user, thread_sessions_per_user,
reset_triggers, always_log_local, and unauthorized_dm_behavior.

`hermes config set gateway.<any-of-these> ...` builds exactly this nested
shape (hermes_cli/config.py's _set_nested has no schema, so it accepts
any dotted path), so a user following the same pattern that legitimately
works for gateway.multiplex_profiles/gateway.streaming gets a silent
no-op for these nine keys instead.

Fix: read `gateway: {...}` into a single `gateway_section` variable once
(consolidating three separate `yaml_cfg.get("gateway")` calls already in
the function) and add the same top-level-wins/nested-fallback check for
each of the nine keys, mirroring the existing write_sessions_json
precedent exactly.

Note: because every fallback here is guarded by
`isinstance(gateway_section, dict)`, this also makes the streaming
fallback tolerate a scalar `gateway:` block (e.g. `gateway: disabled`)
without crashing — the same crash NousResearch#40837 (open) targets specifically for
streaming. This change doesn't set out to fix that PR's issue, but the
consolidated guard covers it as a side effect; flagging it for the
reviewer rather than leaving it to be found in review.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants