feat(core): store turn_id on ResponseItem metadata (#28360)

## Description

This PR is a followup to https://github.com/openai/codex/pull/28355 and
starts assigning `internal_chat_message_metadata_passthrough.turn_id` to
durable Responses API items created during a turn.

The goal is that those items keep the `turn_id` that introduced them
when Codex resends stateless HTTP context, reconstructs history for
resume/fork paths, or reuses websocket response state.

## What changed

- Set `internal_chat_message_metadata_passthrough.turn_id` when missing
as response items enter durable history, initial/replacement history,
inter-agent communication history, and local compaction summaries.
- Preserve existing item turn IDs instead of overwriting them during
persistence, resume reconstruction, compaction, forked history, and
websocket incremental reuse.
- Keep `compaction_trigger` fieldless because it is a request control,
not a durable response item.
- Update focused history/request assertions and fixtures for stateless
requests, websocket incrementals, compaction, thread injection, prompt
debug, and related CI coverage.
This commit is contained in:
Owen Lin
2026-06-22 16:45:14 -07:00
committed by GitHub
parent 7153affa0f
commit 4a82ecc3c9
27 changed files with 317 additions and 167 deletions
@@ -86,7 +86,7 @@ async fn thread_inject_items_adds_raw_response_items_to_thread_history() -> Resu
resumed_history
.history
.iter()
.any(|item| matches!(item, RolloutItem::ResponseItem(response_item) if response_item == &injected_item)),
.any(|item| matches!(item, RolloutItem::ResponseItem(response_item) if responses::strip_metadata(response_item.clone()) == injected_item)),
"injected item should be persisted in rollout history"
);
@@ -156,8 +156,10 @@ async fn standalone_web_search_round_trips_output() -> Result<()> {
search_body["input"]
.as_array()
.context("search input should be an array")?
.last(),
Some(&json!({
.last()
.cloned()
.map(responses::strip_metadata_from_json),
Some(json!({
"type": "message",
"role": "user",
"content": [{"type": "input_text", "text": "Search the web"}],
@@ -165,7 +167,7 @@ async fn standalone_web_search_round_trips_output() -> Result<()> {
);
assert_eq!(
requests[1].function_call_output(call_id),
responses::strip_metadata_from_json(requests[1].function_call_output(call_id)),
json!({
"type": "function_call_output",
"call_id": call_id,