fix(codex): sanitize synthetic heartbeat tool outputs without call_id (#6995) - #7002
fix(codex): sanitize synthetic heartbeat tool outputs without call_id (#6995)#7002loulanyue wants to merge 1 commit into
Conversation
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 113cf9bd50
ℹ️ 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".
| // byte-for-byte equivalent to the pre-fix conversion. | ||
| match item.get("output") { | ||
| Some(Value::String(s)) => canonicalize_json_string_if_parseable(s), | ||
| if call_id.trim().is_empty() { |
There was a problem hiding this comment.
Apply the missing-ID fallback to every output type
When Chat Completions conversion receives a custom_tool_call_output or tool_search_output without a nonblank call_id, this new fallback is bypassed because it only covers function_call_output; the sibling branch still emits {"role":"tool","tool_call_id":""}, so strict chat upstreams continue rejecting those requests and replayed history remains unusable. Handle all three output variants consistently, as the native Responses sanitizer and Anthropic conversion now do.
Useful? React with 👍 / 👎.
Summary of Changes
When Codex Desktop runs with thread-targeted heartbeat automation (
kind = "heartbeat"), it periodically injects a synthetic heartbeat instruction as afunction_call_outputitem (e.g.name: "automation_update", containing<heartbeat>...\</heartbeat>) without acall_idfield.When forwarding to strict upstreams (such as DeepSeek
/responses), this triggered:HTTP 400: Failed to deserialize the JSON body into the target type: input: missing field call_idcall_idcaused empty tool IDs (tool_call_id: ""/tool_use_id: ""), failing upstream validation.Fix
sanitize_codex_responses_input_call_idsincodex.rsand invoked it inforwarder.rsfor Codex requests. Any syntheticfunction_call_output/custom_tool_call_output/tool_search_outputmissing a validcall_idis converted in-place to a standard{"type": "message", "role": "user", "content": [{"type": "input_text", "text": output}]}item.transform_codex_chat.rsandtransform_codex_anthropic.rs, any tool output item missingcall_idnow falls back cleanly to user message / text block, preventing invalid empty tool IDs.test_sanitize_codex_responses_input_call_ids_converts_missing_call_idincodex.rs.test_responses_to_chat_completions_synthetic_heartbeat_without_call_idintransform_codex_chat.rs.test_responses_to_anthropic_synthetic_heartbeat_without_call_idintransform_codex_anthropic.rs.Fixes #6995