fix(tests): isolate model-selection env vars so the suite passes on any runner (#6395)
The suite failed 6 tests (test_sprint12 default-model, test_issue1538 Nous catalog, test_issue1567 picker capacity/symmetry) whenever it ran on a box that exports HERMES_MODEL (e.g. inside a live Hermes agent session where HERMES_MODEL is the agent's runtime model). Root cause: get_effective_default_model() in api/config.py treats HERMES_MODEL / OPENAI_MODEL / LLM_MODEL as the highest-priority default-model source — above the isolated test config — so a runner-exported value overrode the sandbox config and polluted the model picker/catalog (e.g. injecting "opus-4.8" and breaking the @nous: prefix invariant / default-model readback). Fix: scrub the three model-selection env vars at conftest module level (before any product module imports, covering in-process tests) and again in the out-of-process test_server subprocess env, and add them to the per-test _scrub_provider_env helpers in the two Nous test modules. The isolated config / HERMES_WEBUI_DEFAULT_MODEL is now authoritative regardless of the runner env. Verified: with HERMES_MODEL=opus-4.8 set, the full suite goes from 6 failed to 0 failed (13550 passed); non-vacuity confirmed (disabling the scrub reproduces the failures). Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
This commit is contained in:
1 parent
c0d9d81512
commit
1dd5cc43ce
3 files changed
+32
No files matched your search
@@ -181,6 +181,20 @@ os.environ['HERMES_BASE_HOME'] = str(TEST_STATE_DIR)
|
||||
# tests that read/write config.yaml stay inside the isolated test home.
|
||||
os.environ['HERMES_CONFIG_PATH'] = str(TEST_STATE_DIR / 'config.yaml')
|
||||
|
||||
# Model-selection env overrides must NOT leak from the runner into tests.
|
||||
# get_effective_default_model() (api/config.py) treats HERMES_MODEL / OPENAI_MODEL
|
||||
# / LLM_MODEL as the highest-priority default-model source — above the isolated
|
||||
# test config. When the pytest process runs inside a live Hermes agent session,
|
||||
# HERMES_MODEL is exported to the agent's runtime model (e.g. "opus-4.8"), which
|
||||
# then overrides the sandbox config and pollutes the model picker/catalog. That
|
||||
# broke test_sprint12 (default-model readback), test_issue1538 (Nous @nous:
|
||||
# prefix invariant) and test_issue1567 (picker capacity/symmetry) whenever the
|
||||
# suite ran on a box with HERMES_MODEL set. Strip them at module level so the
|
||||
# isolated config is authoritative for the pytest process; the out-of-process
|
||||
# test server env is scrubbed identically in the test_server fixture below.
|
||||
for _model_env in ('HERMES_MODEL', 'OPENAI_MODEL', 'LLM_MODEL'):
|
||||
os.environ.pop(_model_env, None)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _isolate_hermes_config_path():
|
||||
@@ -987,6 +1001,13 @@ def test_server():
|
||||
for _k in list(env):
|
||||
if any(_k.startswith(p) for p in _CRED_ENV_PREFIXES):
|
||||
del env[_k]
|
||||
# Model-selection overrides must not reach the test server either. They are
|
||||
# already popped from the pytest process env at module level, but strip them
|
||||
# explicitly here so the subprocess default model comes only from the isolated
|
||||
# config / HERMES_WEBUI_DEFAULT_MODEL below — never a runner-exported
|
||||
# HERMES_MODEL (get_effective_default_model gives these env vars top priority).
|
||||
for _model_env in ('HERMES_MODEL', 'OPENAI_MODEL', 'LLM_MODEL'):
|
||||
env.pop(_model_env, None)
|
||||
# Belt-and-suspenders: keep IMDS disabled in the spawn env too (we set it
|
||||
# at module level above for the pytest process, but make it explicit here
|
||||
# so it's never accidentally cleared by an env.update later).
|
||||
|
||||
@@ -129,6 +129,12 @@ def _scrub_provider_env(monkeypatch):
|
||||
"XIAOMI_API_KEY",
|
||||
"OPENCODE_ZEN_API_KEY", "OPENCODE_GO_API_KEY",
|
||||
"NOUS_API_KEY", "NVIDIA_API_KEY", "LM_API_KEY", "LMSTUDIO_API_KEY",
|
||||
# Model-selection overrides: get_effective_default_model() treats these
|
||||
# as the highest-priority default-model source, above config. A runner
|
||||
# that exports HERMES_MODEL (e.g. a live agent session set to "opus-4.8")
|
||||
# injects that id into the picker/catalog and breaks the @nous: prefix
|
||||
# invariant below. Scrub so detection sees only the installed stubs.
|
||||
"HERMES_MODEL", "OPENAI_MODEL", "LLM_MODEL",
|
||||
):
|
||||
monkeypatch.delenv(var, raising=False)
|
||||
|
||||
|
||||
@@ -130,6 +130,11 @@ def _scrub_provider_env(monkeypatch):
|
||||
"XIAOMI_API_KEY",
|
||||
"OPENCODE_ZEN_API_KEY", "OPENCODE_GO_API_KEY",
|
||||
"NOUS_API_KEY", "NVIDIA_API_KEY", "LM_API_KEY", "LMSTUDIO_API_KEY",
|
||||
# Model-selection overrides: get_effective_default_model() treats these
|
||||
# as the highest-priority default-model source, above config. A runner
|
||||
# exporting HERMES_MODEL (e.g. a live agent session on "opus-4.8") injects
|
||||
# that id into the picker/catalog and breaks capacity/symmetry assertions.
|
||||
"HERMES_MODEL", "OPENAI_MODEL", "LLM_MODEL",
|
||||
):
|
||||
monkeypatch.delenv(var, raising=False)
|
||||
|
||||
|
||||
Reference in new issue
Block a user