Skip to content

refactor(ai): drop responses replay tombstones - #46965

Merged
rekram1-node merged 1 commit into
v2from
responses-replay-guards
Sep 3, 2026
Merged

refactor(ai): drop responses replay tombstones#46965
rekram1-node merged 1 commit into
v2from
responses-replay-guards

Conversation

@rekram1-node

Copy link
Copy Markdown
Collaborator

Why

ParserState carried two tombstone sets, completedMessages (#46064) and completedTools (#45789), that ignored output_item.added / output_item.done for item ids the parser had already finished. #46064 justified this with an OpenAI background-mode stream resumed via starting_after, where the resumed stream can replay events for already-completed items.

Our client never sends background: true or starting_after on Responses requests and never tracks sequence_number; parser state is built fresh per attempt via initial(request), and a disconnect is a new request rather than a resumed stream. The WebSocket channel continues between turns with previous_response_id, not mid-stream. So the replayed-event inputs these guards handle cannot reach the parser. The spec side agrees: a completed item receives no further updates and output_item.added is emitted once per item.

Neither Codex nor pi tracks completed ids or defends against replayed item events, for the same reason — neither resumes streams.

What changes

  • Remove completedMessages and completedTools from ParserState and initial, plus the branches that consulted or populated them.
  • onOutputItemDone for a message no longer early-returns when a different message is active; it finalizes its own item and clears state.message only if that item was the active one.
  • Kept: done-only messages and function calls still emit a full lifecycle from the terminal item (that part of fix(ai): preserve done-only response messages #46064 removed a condition rather than adding one, and matches how both peers treat output_item.done as authoritative). Duplicate added for a still-pending function call is still a no-op via state.tools. completedCompactions stays because response.completed.output legitimately re-lists compaction items during terminal recovery. Reasoning dedup via reasoningItems is unchanged.
  • Tests: removed the four tests whose fixtures were replayed or reused item ids; stripped duplicate done events from two fixtures whose remaining assertions still hold.

Verification

cd packages/ai
bun typecheck
bun run test   # 976 pass, 28 skip, 0 fail

@rekram1-node
rekram1-node merged commit f98a628 into v2 Sep 3, 2026
10 checks passed
@rekram1-node
rekram1-node deleted the responses-replay-guards branch September 3, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant