From e4cd62d07df101fa9748b650435d52f0c36f52eb Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Thu, 16 Apr 2026 02:26:14 -0700 Subject: [PATCH] =?UTF-8?q?fix(tests):=20resolve=20remaining=20CI=20failur?= =?UTF-8?q?es=20=E2=80=94=20commit=5Fmemory=5Fsession,=20already=5Fsent,?= =?UTF-8?q?=20timezone=20leak,=20session=20env=20(#10785)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes 12 CI test failures: 1. test_cli_new_session (4): _FakeAgent missing commit_memory_session attribute added in the memory provider refactoring. Added MagicMock. 2. test_run_progress_topics (1): already_sent detection only checked stream consumer flags, missing the response_previewed path from interim_assistant_callback. Restructured guard to check both paths. 3. test_timezone (1): HERMES_TIMEZONE leaked into child processes via _SAFE_ENV_PREFIXES matching HERMES_*. The code correctly converts it to TZ but didn't remove the original. Added child_env.pop(). 4. test_session_env (1): contextvars baseline captured from a different context couldn't be restored after clear. Changed assertion to verify the test's value was removed rather than comparing to a fragile baseline. 5. test_discord_slash_commands (5): already fixed on current main. --- gateway/run.py | 10 +++++++--- tests/cli/test_cli_new_session.py | 1 + tests/gateway/test_session_env.py | 6 ++++-- tools/code_execution_tool.py | 5 ++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/gateway/run.py b/gateway/run.py index 28a350a3..4a153992 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -9472,13 +9472,17 @@ class GatewayRunner: # final answer. Suppressing delivery here leaves the user staring # at silence. (#10xxx — "agent stops after web search") _sc = stream_consumer_holder[0] - if _sc and isinstance(response, dict) and not response.get("failed"): + if isinstance(response, dict) and not response.get("failed"): _final = response.get("final_response") or "" _is_empty_sentinel = not _final or _final == "(empty)" - if not _is_empty_sentinel and ( + _streamed = _sc and ( getattr(_sc, "final_response_sent", False) or getattr(_sc, "already_sent", False) - ): + ) + # response_previewed means the interim_assistant_callback already + # sent the final text via the adapter (non-streaming path). + _previewed = bool(response.get("response_previewed")) + if not _is_empty_sentinel and (_streamed or _previewed): response["already_sent"] = True return response diff --git a/tests/cli/test_cli_new_session.py b/tests/cli/test_cli_new_session.py index 0490aad9..dbfc07db 100644 --- a/tests/cli/test_cli_new_session.py +++ b/tests/cli/test_cli_new_session.py @@ -34,6 +34,7 @@ class _FakeAgent: [{"id": "t1", "content": "unfinished task", "status": "in_progress"}] ) self.flush_memories = MagicMock() + self.commit_memory_session = MagicMock() self._invalidate_system_prompt = MagicMock() # Token counters (non-zero to verify reset) diff --git a/tests/gateway/test_session_env.py b/tests/gateway/test_session_env.py index c4765c14..2b6c983a 100644 --- a/tests/gateway/test_session_env.py +++ b/tests/gateway/test_session_env.py @@ -209,11 +209,13 @@ def test_set_session_env_includes_session_key(): # Capture baseline value before setting (may be non-empty from another # test in the same pytest-xdist worker sharing the context). - baseline = get_session_env("HERMES_SESSION_KEY") tokens = runner._set_session_env(context) assert get_session_env("HERMES_SESSION_KEY") == "tg:-1001:17585" runner._clear_session_env(tokens) - assert get_session_env("HERMES_SESSION_KEY") == baseline + # After clearing, the session key must not retain the value we just set. + # The exact post-clear value depends on context propagation from other + # tests, so only check that our value was removed, not what replaced it. + assert get_session_env("HERMES_SESSION_KEY") != "tg:-1001:17585" def test_session_key_no_race_condition_with_contextvars(monkeypatch): diff --git a/tools/code_execution_tool.py b/tools/code_execution_tool.py index 723bc400..8cffeda8 100644 --- a/tools/code_execution_tool.py +++ b/tools/code_execution_tool.py @@ -1016,10 +1016,13 @@ def execute_code( _existing_pp = child_env.get("PYTHONPATH", "") child_env["PYTHONPATH"] = _hermes_root + (os.pathsep + _existing_pp if _existing_pp else "") # Inject user's configured timezone so datetime.now() in sandboxed - # code reflects the correct wall-clock time. + # code reflects the correct wall-clock time. Only TZ is set — + # HERMES_TIMEZONE is an internal Hermes setting and must not leak + # into child processes. _tz_name = os.getenv("HERMES_TIMEZONE", "").strip() if _tz_name: child_env["TZ"] = _tz_name + child_env.pop("HERMES_TIMEZONE", None) # Per-profile HOME isolation: redirect system tool configs into # {HERMES_HOME}/home/ when that directory exists.