Skip to content

fix(websocket): avoid fresh retry for tool-output deltas#1042

Open
zvladru wants to merge 2 commits into
Soju06:mainfrom
zvladru:fix/websocket-tool-output-delta-retry
Open

fix(websocket): avoid fresh retry for tool-output deltas#1042
zvladru wants to merge 2 commits into
Soju06:mainfrom
zvladru:fix/websocket-tool-output-delta-retry

Conversation

@zvladru

@zvladru zvladru commented Jun 17, 2026

Copy link
Copy Markdown

Problem

Codex Desktop can send a response.create request with previous_response_id and an input delta that contains only function_call_output items. That payload is valid only while the upstream response history remains anchored by previous_response_id.

The proxy's fresh retry preparation could previously treat a multi-item client resend as safe to replay without that upstream anchor. For tool-output-only deltas, that creates a fresh request containing function_call_output items without the matching prior function_call items, which can be rejected upstream with errors like:

No tool call found for function call output with call_id ...

Changes

  • Require tool-output items in a fresh replay candidate to be self-contained: each function_call_output, custom_tool_call_output, or apply_patch_call_output must have a matching earlier call item with the same call_id in the replayed input.
  • Reject tool-output-only deltas and output-before-call histories as fresh-retry candidates.
  • Preserve the normal anchored request path with previous_response_id; this only disables unsafe fresh replay construction.
  • Keep self-contained full histories retry-safe.

Impact

This prevents the proxy from manufacturing an invalid fresh retry for Codex tool-output deltas. Normal text requests and full self-contained replay payloads continue to behave as before.

Tests

  • uv run pytest -q tests/unit/test_proxy_utils.py::test_prepare_websocket_response_create_request_does_not_fresh_retry_tool_output_delta tests/unit/test_proxy_utils.py::test_prepare_websocket_response_create_request_captures_client_full_resend_anchor_replay tests/unit/test_proxy_utils.py::test_websocket_client_previous_response_full_resend_retry_rejects_tool_output_delta tests/unit/test_proxy_utils.py::test_websocket_client_previous_response_full_resend_retry_rejects_output_before_call tests/unit/test_proxy_utils.py::test_websocket_client_previous_response_full_resend_retry_allows_self_contained_tool_history

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d45ca221cb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/modules/proxy/_service/websocket/helpers.py
@Soju06 Soju06 added the 🤖 codex: needs work [@codex review] raised an issue label Jun 17, 2026
@zvladru

zvladru commented Jun 18, 2026

Copy link
Copy Markdown
Author

Addressed the automated review feedback in ad09257d by documenting the tool-output-only retry boundary in the OpenSpec source of truth.

@codex review

@Soju06 Soju06 removed the 🤖 codex: needs work [@codex review] raised an issue label Jun 18, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ad09257de2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +438 to +439
if not _websocket_input_items_are_self_contained_fresh_replay(input_items):
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply guard to injected-anchor fresh retries

This self-contained check only runs for client-supplied previous_response_id payloads. The Codex-session full-resend path still injects previous_response_id from session_anchor and then marks original_full_resend_payload retry-safe whenever the fresh text body exists; when that stored prefix is a tool-output delta, a later previous_response_not_found will still replay those function_call_output items without their matching calls and hit the same upstream rejection. Please apply the same guard before marking the injected-anchor fresh body safe.

Useful? React with 👍 / 👎.

@Soju06 Soju06 added the 🤖 codex: needs work [@codex review] raised an issue label Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖 codex: needs work [@codex review] raised an issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants