Skip to content

fix(streaming): handle duplicate tool call index from API gateways #1443

Merged
joshua-mo-143 merged 1 commit into0xPlaygrounds:mainfrom
Phoenix500526:fix/sharing-tool-call
Feb 26, 2026
Merged

fix(streaming): handle duplicate tool call index from API gateways #1443
joshua-mo-143 merged 1 commit into0xPlaygrounds:mainfrom
Phoenix500526:fix/sharing-tool-call

Conversation

@Phoenix500526
Copy link
Copy Markdown
Contributor

@Phoenix500526 Phoenix500526 commented Feb 26, 2026

Summary

Some API gateways (e.g. LiteLLM, OneAPI) do not follow the OpenAI streaming convention of assigning each parallel tool call a unique index. Instead, they emit multiple distinct tool calls all at index 0, distinguishing them only by their id field.

The previous accumulation logic keyed solely on index, causing later tool calls to overwrite and corrupt earlier ones — merging names and arguments into a single broken entry.

Changes

  • Detect index reuse by comparing id: when a new non-empty id arrives at an index that already holds a different id, flush the old entry as a completed tool call before starting fresh accumulation
  • Add regression test: test_duplicate_index_different_id_tool_calls reproduces the exact gateway behavior with two tool calls both at index 0
  • Extract MockStreamingClient into http_client::mock to deduplicate test boilerplate
  • Remove dead final_tool_calls accumulator that was pushed to but never read
  • Fix inconsistent indentation in tool call delta handling

Test plan

  • cargo test --lib providers::openai::completion::streaming::tests — all 8 tests pass
  • Verify with a real LiteLLM/OneAPI gateway that parallel tool calls are no longer merged

…PI gateways

Some API gateways (e.g. LiteLLM, OneAPI) do not follow the OpenAI
streaming convention of assigning each parallel tool call a unique
index. Instead, they emit multiple distinct tool calls all at index 0,
distinguishing them only by their `id` field. The previous accumulation
logic keyed solely on index, causing later tool calls to overwrite and
corrupt earlier ones into a single merged entry.

Detect this by comparing the incoming `id` against the existing entry
at the same index; when a new id appears, flush the old entry as a
completed tool call before starting a fresh accumulation.

Also:
- Extract shared MockStreamingClient into http_client::mock
- Remove unused final_tool_calls accumulator
- Fix inconsistent indentation in tool call delta handling

Signed-off-by: Jiawei Zhao <Phoenix500526@163.com>
Copy link
Copy Markdown
Contributor

@joshua-mo-143 joshua-mo-143 left a comment

Choose a reason for hiding this comment

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

lgtm - thanks for your hard work @Phoenix500526 !

@joshua-mo-143 joshua-mo-143 added this pull request to the merge queue Feb 26, 2026
Merged via the queue into 0xPlaygrounds:main with commit 862d724 Feb 26, 2026
6 checks passed
@github-actions github-actions Bot mentioned this pull request Feb 26, 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.

2 participants