Skip to content

fix(translator): prevent doubled tool args in OpenAI-to-Claude - #5828

Merged
diegosouzapw merged 3 commits into
release/v3.8.43from
fix/port-pr-2279-doubled-tool-args
Jul 2, 2026
Merged

diegosouzapw merged 3 commits into
release/v3.8.43from
fix/port-pr-2279-doubled-tool-args

Conversation

@diegosouzapw

Copy link
Copy Markdown
Owner

Thanks to @vishalrajv for the original implementation.

Two one-line fixes in the OpenAI<->Claude translators:

  1. claude-to-openai.ts (request side): a Claude tool_use block whose input is already a JSON-encoded string was re-run through JSON.stringify, double-encoding the payload before it reached the OpenAI-compatible upstream. A string input is now passed through verbatim instead.
  2. openai-to-claude.ts (response side): a duplicate finish_reason chunk (some OpenAI-compatible upstreams resend the terminal chunk with an otherwise-empty delta) re-ran the entire finish block, emitting duplicate content_block_stop / message_delta / message_stop events downstream. The finish block now only runs once per stream, guarded by state.finishReason.

Test plan

  • Added a failing-then-passing test for each fix (TDD): tests/unit/translator-claude-to-openai.test.ts (string tool_use input passthrough) and tests/unit/translator-resp-openai-to-claude.test.ts (duplicate finish_reason chunk emits finish events exactly once).
  • node --import tsx/esm --test tests/unit/translator-claude-to-openai.test.ts tests/unit/translator-resp-openai-to-claude.test.ts — 23/23 passing.
  • Full related translator suite (10 additional files) — 57/57 passing.
  • npm run typecheck:core — clean.

Two one-line guards in the OpenAI<->Claude translators:

- claude-to-openai.ts: a Claude tool_use block whose `input` is already a
  JSON-encoded string was re-run through JSON.stringify, double-encoding the
  payload. Now a string input is passed through verbatim.
- openai-to-claude.ts: a duplicate finish_reason chunk (some
  OpenAI-compatible upstreams resend the terminal chunk) re-ran the entire
  finish block, emitting duplicate content_block_stop / message_delta /
  message_stop events. The guard now only runs the finish block once per
  stream via `state.finishReason`.

Co-authored-by: Vishal Raj V <vishalrajv3@gmail.com>
Inspired-by: decolua/9router#2279
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@diegosouzapw
diegosouzapw merged commit 8bba88c into release/v3.8.43 Jul 2, 2026
2 of 3 checks passed
@diegosouzapw
diegosouzapw deleted the fix/port-pr-2279-doubled-tool-args branch July 3, 2026 04:58
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
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