stepResponses() currently advances codex_sent_upto whenever a WS is live, but only replaces codex_prev_id when the parsed response contains a new response.id.
If parseResponses() returns .ok from output items without a terminal response ID (it accepts items.items.len > 0), the old ID remains while the boundary advances. The next delta request references the old server response but slices local input after the new boundary, omitting state the referenced response never held.
Relevant paths:
src/agent_request.zig: parseResponses() accepts output items without response.completed/ID.
src/agent_steps.zig: codex_sent_upto advances before/without requiring a new ID.
src/agent_request.zig: buildBody() then pairs stale previous_response_id with the advanced slice.
Safe behavior: only advance the delta boundary when a new response ID is installed atomically; otherwise close/reset the WS continuation state so the next request fully re-anchors.
stepResponses()currently advancescodex_sent_uptowhenever a WS is live, but only replacescodex_prev_idwhen the parsed response contains a newresponse.id.If
parseResponses()returns.okfrom output items without a terminal response ID (it acceptsitems.items.len > 0), the old ID remains while the boundary advances. The next delta request references the old server response but slices local input after the new boundary, omitting state the referenced response never held.Relevant paths:
src/agent_request.zig:parseResponses()accepts output items withoutresponse.completed/ID.src/agent_steps.zig:codex_sent_uptoadvances before/without requiring a new ID.src/agent_request.zig:buildBody()then pairs staleprevious_response_idwith the advanced slice.Safe behavior: only advance the delta boundary when a new response ID is installed atomically; otherwise close/reset the WS continuation state so the next request fully re-anchors.