diff --git a/agent/conversation_loop.py b/agent/conversation_loop.py index b6978abbc8..bc01fc2dea 100644 --- a/agent/conversation_loop.py +++ b/agent/conversation_loop.py @@ -8761,12 +8761,7 @@ def run_conversation( "answer:\n\n" + reasoning_preview ) else: - final_response = agent._format_turn_completion_explanation( - _turn_exit_reason - ) or ( - "⚠️ No reply: the model returned empty content after " - "all retries and fallback attempts." - ) + final_response = "(empty)" break # Reset retry counter/signature on successful content diff --git a/tests/run_agent/test_empty_terminal_reasoning_surface.py b/tests/run_agent/test_empty_terminal_reasoning_surface.py index 3b56144cfe..7cfd1aea02 100644 --- a/tests/run_agent/test_empty_terminal_reasoning_surface.py +++ b/tests/run_agent/test_empty_terminal_reasoning_surface.py @@ -11,7 +11,7 @@ Invariants pinned here: ``_empty_terminal_sentinel`` marker (replay semantics unchanged). - Raw reasoning is NEVER promoted earlier in the ladder — a reasoning-only response still goes through prefill continuation first. -- A truly empty exhaustion returns an actionable no-reply explanation. +- A truly empty exhaustion (no reasoning either) still returns "(empty)". """ from __future__ import annotations @@ -109,11 +109,11 @@ def test_exhausted_reasoning_only_delivers_labeled_excerpt(tmp_path, monkeypatch ) -def test_exhausted_truly_empty_delivers_no_reply_explanation(tmp_path, monkeypatch): - """No reasoning anywhere produces an honest terminal explanation even - when the downstream completion explainer is disabled.""" +def test_exhausted_truly_empty_keeps_existing_behavior(tmp_path, monkeypatch): + """No reasoning anywhere → behavior unchanged from main: the '(empty)' + terminal (possibly rewritten by the downstream turn-completion explainer) + is delivered, and no reasoning excerpt appears.""" agent = _build_agent(tmp_path, monkeypatch) - monkeypatch.setattr(agent, "_turn_completion_explainer_enabled", lambda: False) monkeypatch.setattr( agent, "_interruptible_api_call", lambda api_kwargs: _truly_empty_response(), @@ -122,7 +122,9 @@ def test_exhausted_truly_empty_delivers_no_reply_explanation(tmp_path, monkeypat result = agent.run_conversation("hello?") final = result["final_response"] - assert final.startswith("⚠️ No reply:") + # Either the raw sentinel (explainer off) or the explainer's rewrite — + # never the reasoning-excerpt frame, which requires reasoning to exist. + assert final == "(empty)" or final.startswith("⚠️ No reply:") assert "only internal reasoning" not in final diff --git a/tests/run_agent/test_run_agent.py b/tests/run_agent/test_run_agent.py index 3c03e5cde1..77128fd092 100644 --- a/tests/run_agent/test_run_agent.py +++ b/tests/run_agent/test_run_agent.py @@ -3601,16 +3601,12 @@ class TestRunConversation: patch.object(agent, "_persist_session"), patch.object(agent, "_save_trajectory"), patch.object(agent, "_cleanup_task_resources"), - patch.object( - agent, "_turn_completion_explainer_enabled", return_value=False - ), caplog.at_level(logging.INFO, logger="agent.conversation_loop"), ): result = agent.run_conversation("answer me") assert result["completed"] is True assert result["api_calls"] == 2 assert agent.session_api_calls == 2 - assert result["final_response"].startswith("⚠️ No reply:") assert caplog.text.count("usage=unavailable") == 2 def test_truly_empty_response_succeeds_on_nudge(self, agent):