Wait for terminal goal status

This commit is contained in:
Ahmed Ibrahim
2026-06-08 18:54:22 -07:00
parent e2b8a734d7
commit c48bd03994
2 changed files with 17 additions and 5 deletions
+6 -1
View File
@@ -250,8 +250,13 @@ class _GoalStreamCursor:
if isinstance(payload, TurnCompletedNotification):
self.active = False
self.last_completed = payload
if payload.turn.status in {TurnStatus.failed, TurnStatus.interrupted}:
if payload.turn.status == TurnStatus.interrupted:
return [self._completion(notification.method, payload)], True
if payload.turn.status == TurnStatus.failed:
if self.cleared or _terminal_goal_status(self.status):
self.state.finish()
return [self._completion(notification.method, payload)], True
return [], False
if self.status is None and not self.cleared:
raise RuntimeError(
"the connected Codex runtime did not activate goal mode for this turn"
+11 -4
View File
@@ -514,15 +514,20 @@ def test_cancel_goal_retries_the_server_reported_active_turn(tmp_path) -> None:
@pytest.mark.parametrize(
("error_code", "expected_status"),
("error_code", "expected_error", "expected_status"),
[
("server_error", ThreadGoalStatus.blocked),
("insufficient_quota", ThreadGoalStatus.usage_limited),
("server_error", "goal model failed", ThreadGoalStatus.blocked),
(
"insufficient_quota",
"Quota exceeded. Check your plan and billing details.",
ThreadGoalStatus.usage_limited,
),
],
)
def test_terminal_goal_failure_preserves_status_and_releases_routing(
tmp_path,
error_code,
expected_error,
expected_status,
) -> None:
"""A failed server turn should stop rollover work and leave the thread usable."""
@@ -541,7 +546,7 @@ def test_terminal_goal_failure_preserves_status_and_releases_routing(
)
with Codex(config=harness.app_server_config()) as codex:
thread = codex.thread_start()
with pytest.raises(RuntimeError, match="goal model failed"):
with pytest.raises(RuntimeError) as error:
thread.run_goal("Fail this goal turn")
persisted = codex._client.request(
@@ -558,11 +563,13 @@ def test_terminal_goal_failure_preserves_status_and_releases_routing(
requests = harness.responses.requests()
assert {
"error": str(error.value),
"goal_status": persisted.status if persisted else None,
"follow_up": (follow_up.status, follow_up.final_response),
"request_count": len(requests),
"follow_up_input": requests[1].message_input_texts("user")[-1:],
} == {
"error": expected_error,
"goal_status": expected_status,
"follow_up": (TurnStatus.completed, "Recovered with an ordinary turn."),
"request_count": 2,