From 77f2ce853f3de4cb4a8f6eb4e59ea1c08831b502 Mon Sep 17 00:00:00 2001 From: fangliquanflq Date: Thu, 10 Sep 2026 12:22:49 +0800 Subject: [PATCH] fix(agent): suppress detached fork session-end hooks --- agent/turn_finalizer.py | 25 ++++++++------- .../test_turn_finalizer_cleanup_guard.py | 31 +++++++++++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/agent/turn_finalizer.py b/agent/turn_finalizer.py index 1215791817..5cf658e388 100644 --- a/agent/turn_finalizer.py +++ b/agent/turn_finalizer.py @@ -623,18 +623,19 @@ def finalize_turn( # Memory provider on_session_end()/shutdown_all() are NOT called here: # run_conversation() runs once per message; CLI/gateway own session-end cleanup. - _invoke_hook_safely( - "on_session_end", logger, - session_id=agent.session_id, - task_id=effective_task_id, - turn_id=turn_id, - completed=completed, - failed=failed, - interrupted=interrupted, - turn_exit_reason=_turn_exit_reason, - model=agent.model, - platform=_platform, - ) + if not getattr(agent, "_persist_disabled", False): + _invoke_hook_safely( + "on_session_end", logger, + session_id=agent.session_id, + task_id=effective_task_id, + turn_id=turn_id, + completed=completed, + failed=failed, + interrupted=interrupted, + turn_exit_reason=_turn_exit_reason, + model=agent.model, + platform=_platform, + ) agent._turn_preflight_display_snapshot = None agent._turn_received_provider_response = False diff --git a/tests/agent/test_turn_finalizer_cleanup_guard.py b/tests/agent/test_turn_finalizer_cleanup_guard.py index 89e7ca04f9..25a76a079f 100644 --- a/tests/agent/test_turn_finalizer_cleanup_guard.py +++ b/tests/agent/test_turn_finalizer_cleanup_guard.py @@ -8,6 +8,8 @@ for must still be returned. Previously any of those raised straight out of traceback and lost the whole turn. """ +from unittest.mock import patch + import pytest from agent.turn_finalizer import finalize_turn @@ -164,3 +166,32 @@ def test_clean_turn_has_no_cleanup_errors_key(): assert "cleanup_errors" not in result +@pytest.mark.parametrize( + ("persist_disabled", "expected_calls"), + [ + (True, ["transform_llm_output"]), + (False, ["transform_llm_output", "post_llm_call", "on_session_end"]), + ], +) +def test_persist_disabled_turn_skips_session_end_hook( + persist_disabled, expected_calls +): + agent = _StubAgent(raise_in=()) + agent._persist_disabled = persist_disabled + calls = [] + + def capture(name, _logger, **_kwargs): + calls.append(name) + return [] + + with patch("agent.turn_finalizer._invoke_hook_safely", side_effect=capture): + _run( + agent, + final_response="done", + api_call_count=1, + turn_exit_reason="text_response(stop)", + ) + + assert calls == expected_calls + +