mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-24 16:54:43 +00:00
fix(gateway): honor explicit api_server enabled:false under env key
_apply_env_overrides() force-set ``api_server.enabled = True`` whenever
API_SERVER_KEY (or API_SERVER_ENABLED) was present in the environment.
In multiplex mode, a secondary profile pins
``platforms.api_server.enabled: false`` in its config.yaml so that it
shares the default profile's API-server listener instead of binding its
own port. That profile still inherits the process-level env, including
API_SERVER_KEY, so the unconditional re-enable flipped api_server back on
and tripped the MultiplexConfigError check.
Honor an explicit disable, flagged by ``_enabled_explicit`` in the
platform's extra. Use ``extra.pop("_enabled_explicit", False)``: the
api_server branch is terminal (unlike the migrated plugin platforms, no
later registry pass re-enables api_server), so popping consumes the flag
in a single read and avoids the double-read hazard, while the final
per-platform cleanup remains a no-op.
Adds a regression test asserting that with API_SERVER_KEY set, a config
with api_server explicitly enabled:false + _enabled_explicit:true survives
_apply_env_overrides() as enabled=False (fails without the fix), while the
key is still wired through for the shared listener.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
78312c192d
commit
c7fd3eb377
2 changed files with 46 additions and 1 deletions
|
|
@ -2011,7 +2011,19 @@ def _apply_env_overrides(config: GatewayConfig) -> None:
|
|||
if api_server_enabled or api_server_key:
|
||||
if Platform.API_SERVER not in config.platforms:
|
||||
config.platforms[Platform.API_SERVER] = PlatformConfig()
|
||||
config.platforms[Platform.API_SERVER].enabled = True
|
||||
# Respect an explicit ``enabled: false`` in config.yaml (flagged by
|
||||
# ``_enabled_explicit``). In multiplex mode a secondary profile's
|
||||
# config.yaml pins ``platforms.api_server.enabled: false`` so it shares
|
||||
# the default profile's listener instead of binding its own port. That
|
||||
# profile still inherits the process-level env (including
|
||||
# ``API_SERVER_KEY``); without this guard the env-var presence would
|
||||
# force-enable the listener and trip the MultiplexConfigError check.
|
||||
# Pop (don't read) the marker — the api_server branch is terminal (no
|
||||
# later registry pass re-enables it), so this both consumes the flag and
|
||||
# avoids reading it twice, matching the pop convention used elsewhere.
|
||||
api_server_explicit = config.platforms[Platform.API_SERVER].extra.pop("_enabled_explicit", False)
|
||||
if not api_server_explicit or config.platforms[Platform.API_SERVER].enabled:
|
||||
config.platforms[Platform.API_SERVER].enabled = True
|
||||
if api_server_key:
|
||||
config.platforms[Platform.API_SERVER].extra["key"] = api_server_key
|
||||
if api_server_cors_origins:
|
||||
|
|
|
|||
|
|
@ -2117,3 +2117,36 @@ class TestMultiplexProfilesConfig:
|
|||
"Explicit top-level false was overridden by nested true — "
|
||||
"loader must respect top-level precedence when key is present"
|
||||
)
|
||||
|
||||
|
||||
class TestApiServerEnvOverride:
|
||||
def test_env_key_does_not_reenable_explicitly_disabled_api_server(self):
|
||||
"""An explicit ``platforms.api_server.enabled: false`` must survive
|
||||
_apply_env_overrides() even when API_SERVER_KEY is present in the env.
|
||||
|
||||
Regression: _apply_env_overrides() force-set api_server.enabled = True
|
||||
whenever API_SERVER_KEY (or API_SERVER_ENABLED) was set. In multiplex
|
||||
mode a secondary profile pins ``api_server.enabled: false`` so it shares
|
||||
the default profile's listener instead of binding its own port, but it
|
||||
still inherits the process-level API_SERVER_KEY. The unconditional
|
||||
re-enable flipped it back on and tripped the MultiplexConfigError check.
|
||||
|
||||
The fix honors the explicit disable, flagged by ``_enabled_explicit`` in
|
||||
the platform's extra (set when the config.yaml pins enabled).
|
||||
"""
|
||||
config = GatewayConfig(
|
||||
platforms={
|
||||
Platform.API_SERVER: PlatformConfig(
|
||||
enabled=False,
|
||||
extra={"_enabled_explicit": True},
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
with patch.dict(os.environ, {"API_SERVER_KEY": "secret-key"}, clear=True):
|
||||
_apply_env_overrides(config)
|
||||
|
||||
# Explicit disable wins over the env-var presence.
|
||||
assert config.platforms[Platform.API_SERVER].enabled is False
|
||||
# The key is still wired through for the shared listener.
|
||||
assert config.platforms[Platform.API_SERVER].extra.get("key") == "secret-key"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue