fix(agent): register explainer config key + shorten footer prefix

Follow-up to the salvaged #34452 turn-completion explainer:
- Register display.turn_completion_explainer: True in DEFAULT_CONFIG so the
  setting is discoverable, matching the file_mutation_verifier precedent.
- Shorten the repeated footer prefix from 'Turn ended without a usable
  reply: ' to 'No reply: ' so the 10 reason variants don't all open with
  the same 8-word boilerplate.
- Update the 7 assertions that referenced the old prefix.
This commit is contained in:
teknium1
2026-05-29 13:20:13 -07:00
committed by Teknium
parent de6d6023d7
commit fb0ab27649
4 changed files with 15 additions and 8 deletions

View File

@ -1202,6 +1202,13 @@ DEFAULT_CONFIG = {
# class of over-claim that otherwise forces users to run
# `git status` to verify edits landed. Set false to suppress.
"file_mutation_verifier": True,
# Turn-completion explainer. When true (default), the agent appends a
# one-line explanation to its final response whenever a turn ends
# abnormally with no usable reply — empty content after retries, a
# partial/truncated stream, a still-pending tool result, or an
# iteration/budget limit. Replaces the bare "(empty)" sentinel so the
# failure isn't silent from the UI's perspective. Set false to suppress.
"turn_completion_explainer": True,
"show_cost": False, # Show $ cost in the status bar (off by default)
"skin": "default",
# UI language for static user-facing messages (approval prompts, a

View File

@ -2189,7 +2189,7 @@ class AIAgent:
if reason.startswith("text_response"):
return ""
prefix = "⚠️ Turn ended without a usable reply: "
prefix = "⚠️ No reply: "
if reason == "empty_response_exhausted":
return (
prefix

View File

@ -3049,7 +3049,7 @@ class TestRunConversation:
# #34452: the bare "(empty)" sentinel is now replaced by a
# user-visible end-of-turn explanation so the failure isn't silent.
assert result["final_response"] != "(empty)"
assert "without a usable reply" in result["final_response"]
assert "No reply:" in result["final_response"]
assert result["turn_exit_reason"] == "empty_response_exhausted"
assert result["api_calls"] == 6 # 1 original + 2 prefill + 3 retries
@ -3072,7 +3072,7 @@ class TestRunConversation:
assert result["completed"] is True
# #34452: explanation replaces the bare "(empty)" sentinel.
assert result["final_response"] != "(empty)"
assert "without a usable reply" in result["final_response"]
assert "No reply:" in result["final_response"]
assert result["api_calls"] == 6 # 1 original + 2 prefill + 3 retries
def test_reasoning_only_prefill_succeeds_on_continuation(self, agent):
@ -3121,7 +3121,7 @@ class TestRunConversation:
assert result["completed"] is True
# #34452: explanation replaces the bare "(empty)" sentinel.
assert result["final_response"] != "(empty)"
assert "without a usable reply" in result["final_response"]
assert "No reply:" in result["final_response"]
assert result["api_calls"] == 4 # 1 original + 3 retries
def test_truly_empty_response_succeeds_on_nudge(self, agent):
@ -3219,7 +3219,7 @@ class TestRunConversation:
assert result["completed"] is True
# #34452: explanation replaces the bare "(empty)" sentinel.
assert result["final_response"] != "(empty)"
assert "without a usable reply" in result["final_response"]
assert "No reply:" in result["final_response"]
def test_empty_response_emits_status_for_gateway(self, agent):
"""_emit_status is called during empty retries so gateway users see feedback."""
@ -3248,7 +3248,7 @@ class TestRunConversation:
# #34452: explanation replaces the bare "(empty)" sentinel, but the
# status emissions during retries are unchanged.
assert result["final_response"] != "(empty)"
assert "without a usable reply" in result["final_response"]
assert "No reply:" in result["final_response"]
# Should have emitted retry statuses (3 retries) + final failure
retry_msgs = [m for m in status_messages if "retrying" in m.lower()]
assert len(retry_msgs) == 3, f"Expected 3 retry status messages, got {len(retry_msgs)}: {status_messages}"

View File

@ -159,7 +159,7 @@ def test_run_conversation_empty_exhausted_surfaces_explanation():
# The user must NOT be left with a bare sentinel; the explanation wins.
assert result["final_response"] != "(empty)"
assert result["final_response"].strip() != ""
assert "without a usable reply" in result["final_response"]
assert "No reply:" in result["final_response"]
def test_run_conversation_normal_reply_stays_quiet():
@ -178,4 +178,4 @@ def test_run_conversation_normal_reply_stays_quiet():
assert result["turn_exit_reason"].startswith("text_response")
assert result["final_response"] == "Done."
assert "without a usable reply" not in result["final_response"]
assert "No reply:" not in result["final_response"]