Include the final agent message in turn completion summaries (#34777)

## Why

Streamed message deltas can be dropped when the transport is saturated, leaving
clients with a truncated final response.

## What changed

- Include the last non-empty final agent message in successful `turn/completed`
  notifications and mark the items as a summary.
- Treat completed message content as authoritative in the TUI, repairing an
  incomplete stream while avoiding duplicate messages when `item/completed` was
  already received.
- Continue backfilling full turn items for persisted `codex exec` threads when a
  completion contains only the summary view.

## Testing

Added coverage for completion summaries, dropped stream deltas, duplicate item
handling, and directive-only responses.

GitOrigin-RevId: ffe9d36d683d6b6690e4a468ff68aa9189fe6ab7
This commit is contained in:
Eric Traut
2026-07-22 15:26:38 +00:00
committed by copyberry
parent 730ec92003
commit 80f3c3141e
15 changed files with 275 additions and 56 deletions

View File

@@ -1397,7 +1397,7 @@ fn should_backfill_turn_completed_items(
return false;
};
!thread_ephemeral && payload.turn.items.is_empty()
!thread_ephemeral && payload.turn.items_view != codex_app_server_protocol::TurnItemsView::Full
}
fn turn_items_for_thread(

View File

@@ -396,13 +396,13 @@ fn turn_items_for_thread_returns_matching_turn_items() {
}
#[test]
fn should_backfill_turn_completed_items_skips_ephemeral_threads() {
fn should_backfill_turn_completed_items_backfills_persisted_summaries_only() {
let notification =
ServerNotification::TurnCompleted(codex_app_server_protocol::TurnCompletedNotification {
thread_id: "thread-1".to_string(),
turn: codex_app_server_protocol::Turn {
id: "turn-1".to_string(),
items_view: codex_app_server_protocol::TurnItemsView::Full,
items_view: codex_app_server_protocol::TurnItemsView::Summary,
items: Vec::new(),
status: codex_app_server_protocol::TurnStatus::Completed,
error: None,
@@ -416,6 +416,10 @@ fn should_backfill_turn_completed_items_skips_ephemeral_threads() {
/*thread_ephemeral*/ true,
&notification
));
assert!(should_backfill_turn_completed_items(
/*thread_ephemeral*/ false,
&notification
));
}
#[test]