Skip to content

fix(responses): repair blank/orphan tool_call_id before provider dispatch#74

Merged
veerareddyvishal144 merged 3 commits into
mainfrom
fix/codex-responses-tool-call-id
Jun 15, 2026
Merged

fix(responses): repair blank/orphan tool_call_id before provider dispatch#74
veerareddyvishal144 merged 3 commits into
mainfrom
fix/codex-responses-tool-call-id

Conversation

@vishalveerareddy123

Copy link
Copy Markdown
Collaborator

Problem

Codex Desktop (via /v1/responses) was failing with:

provider: Moonshot, status: 400, "Invalid request: tool_call_id  is not found"

Note the double space — the tool_call_id was an empty string. Codex's bundled-plugin (@Browser / @Computer-use) function_call_output items and synthetic "unsupported call: shell" outputs arrive without a usable call_id. In convertResponsesToChat() both the assistant tool_calls[].id (call_id || id) and the tool message's tool_call_id (call_id) flattened to "", and the orchestrator forwarded the empty id to Moonshot.

The existing repair loop in openrouter-utils.js couldn't catch it because "" === "" counted as a match, and responses-format.js had no repair pass at all.

Fix

New shared helper src/clients/tool-call-repair.jsrepairToolCallIds(messages) (operates on OpenAI-format message arrays):

  1. Backfills a synthetic id (call_auto_N) onto any assistant tool_calls entry missing one.
  2. Re-links each tool message to an unused tool_call id on the nearest preceding assistant — treating a blank tool_call_id as a mismatch (the case the old loop missed).
  3. Drops any tool message with no assistant tool_call to attach to (a dangling id is a hard 400 — dropping is strictly safer than forwarding).

Wired into both conversion boundaries:

  • responses-format.js convertResponsesToChat() — fixes the ids at the source.
  • openrouter-utils.js convertAnthropicMessagesToOpenRouter() — last stop before Moonshot/OpenRouter (replaces the old broken repair loop).

Also updates the README Homebrew section (verify + upgrade steps).

Verification

  • Reproduced the exact log scenario (blank-id function_call/function_call_output pairs): every tool_call_id now comes out non-blank and matched; drifted ids re-link; true orphans drop.
  • node --test test/format-conversion.test.js test/passthrough-mode.test.js test/openrouter-error-resilience.test.js48 passing.
  • New module + changed lines lint clean (2 pre-existing lint errors in responses-format.js are unrelated).

🤖 Generated with Claude Code

vishal veerareddy and others added 3 commits June 14, 2026 21:35
…atch

Codex Desktop's bundled-plugin (Browser/Computer-use) function_call_output
items arrive without a usable call_id, which flattened to an empty
tool_call_id and 400'd at Moonshot ("Invalid request: tool_call_id  is not
found"). The old repair loop in openrouter-utils couldn't catch it because
"" === "" read as a match.

Add a shared repairToolCallIds() helper that backfills synthetic ids on
assistant tool_calls, re-links blank/drifted tool_call_ids to the nearest
preceding assistant tool_call, and drops true orphans. Wire it into both
convertResponsesToChat() and convertAnthropicMessagesToOpenRouter().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… tap)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the README: verify step + auto-tracked tap upgrade note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@veerareddyvishal144 veerareddyvishal144 merged commit f21ffd4 into main Jun 15, 2026
1 check passed
@veerareddyvishal144 veerareddyvishal144 deleted the fix/codex-responses-tool-call-id branch June 15, 2026 04:55
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.

2 participants