fix(codex): recover final app-server text without completion

This commit is contained in:
luyifan 2026-07-05 02:17:11 +08:00 committed by Teknium
parent 55e7986896
commit 70dffb6f1f
2 changed files with 40 additions and 0 deletions

View file

@ -604,6 +604,19 @@ class CodexAppServerSession:
f"turn ended status={turn_status}", err_msg
)
if (
not turn_complete
and not result.interrupted
and result.final_text
and result.error is None
):
logger.warning(
"codex app-server turn reached deadline after a completed "
"assistant message but before turn/completed; accepting "
"the assistant text as the terminal response"
)
turn_complete = True
if not turn_complete and not result.interrupted:
# Hit the deadline. Issue interrupt to stop wasted compute, and
# tell the caller to retire the session — a turn that never

View file

@ -728,6 +728,33 @@ class TestSessionRetirement:
r = s.run_turn("hi", turn_timeout=1.0)
assert r.should_retire is False
def test_final_agent_message_without_turn_completed_is_recovered(self):
"""A completed assistant item is still a usable terminal response when
codex omits turn/completed and then goes quiet.
"""
client = FakeClient()
client.queue_notification(
"item/completed",
item={"type": "agentMessage", "id": "m1", "text": "done"},
threadId="t",
turnId="tu1",
)
s = make_session(client)
r = s.run_turn(
"hi",
turn_timeout=0.05,
notification_poll_timeout=0.01,
)
assert r.final_text == "done"
assert r.interrupted is False
assert r.error is None
assert r.should_retire is False
assert any(
msg["role"] == "assistant" and msg.get("content") == "done"
for msg in r.projected_messages
)
assert not any(method == "turn/interrupt" for method, _ in client.requests)
def test_post_tool_quiet_watchdog_trips_and_retires(self):
client = FakeClient()
# One tool completion, then total silence — no further events,