Skip to content

fix(ai): ignore a repeat TOOL_CALL_START for an already-tracked toolCallId - #1197

Open
citizen204 wants to merge 3 commits into
TanStack:mainfrom
citizen204:fix-1187-tool-call-manager-repeat-start
Open

fix(ai): ignore a repeat TOOL_CALL_START for an already-tracked toolCallId#1197
citizen204 wants to merge 3 commits into
TanStack:mainfrom
citizen204:fix-1187-tool-call-manager-repeat-start

Conversation

@citizen204

@citizen204 citizen204 commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Summary

ToolCallManager.addToolCallStartEvent keyed its internal map by index (event.index ?? map.size), but AG-UI's TOOL_CALL_START carries no index. A non-first-party or malformed producer sending a second START for a toolCallId already being tracked could either wipe accumulated TOOL_CALL_ARGS (same index — overwrites the slot, resetting arguments to '') or insert a duplicate row (missing/different index — getToolCalls() then returns the id twice and the engine runs the tool twice). First-party adapters emit START only once per call and are unaffected.

Fixes #1187

Changes

  • packages/ai/src/activities/chat/tools/tool-calls.ts: addToolCallStartEvent now skips the event if a tool call with the same toolCallId is already tracked.
  • packages/ai/tests/tool-call-manager.test.ts: two regression tests — a repeat START with the same explicit index (accumulated arguments must survive) and a repeat START with no index (must not duplicate the row).
  • .changeset/tool-call-manager-repeat-start.md: patch changeset.

Ran vitest run tests/tool-call-manager.test.ts in packages/ai — 31 passed (29 existing + 2 new).

Summary by CodeRabbit

  • Bug Fixes

    • Prevented repeated tool-call start events from creating duplicate calls.
    • Preserved arguments already accumulated for an in-progress tool call when a repeated start event is received.
  • Tests

    • Added coverage for repeated start events with and without an explicit index.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 47a5591a-432a-493a-972b-70e6ea63d1a4

📥 Commits

Reviewing files that changed from the base of the PR and between b899fe5 and 29aa341.

📒 Files selected for processing (3)
  • .changeset/tool-call-manager-repeat-start.md
  • packages/ai/src/activities/chat/tools/tool-calls.ts
  • packages/ai/tests/tool-call-manager.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/ai/src/activities/chat/tools/tool-calls.ts
  • .changeset/tool-call-manager-repeat-start.md
  • packages/ai/tests/tool-call-manager.test.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

ToolCallManager now ignores repeated TOOL_CALL_START events for tracked IDs. Regression tests cover indexed and unindexed repeats. A patch changeset documents the fix.

Changes

Repeated tool-call start handling

Layer / File(s) Summary
Guard repeated starts
packages/ai/src/activities/chat/tools/tool-calls.ts, packages/ai/tests/tool-call-manager.test.ts, .changeset/tool-call-manager-repeat-start.md
addToolCallStartEvent ignores tracked tool-call IDs. Tests verify preserved arguments and no duplicate entries for indexed and unindexed repeated starts. The changeset documents the patch.
Estimated code review effort: 2 (Simple) ~10 minutes

Merge Risk: ⚪ Minimal · up to 29aa3

The change ignores duplicate tool-call start events while preserving accumulated arguments and preventing duplicate execution entries; no actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary fix: ignoring repeated TOOL_CALL_START events for an already-tracked toolCallId.
Description check ✅ Passed The description explains the bug, the fix, the affected files, regression tests, changeset, linked issue, and test result. It does not use the template's Checklist or Release Impact headings, but the …
Linked Issues check ✅ Passed The implementation satisfies issue #1187 by skipping repeated TOOL_CALL_START events for an existing toolCallId. The regression tests cover both argument loss and duplicate tool-call entries.
Out of Scope Changes check ✅ Passed The changes are limited to the requested ToolCallManager fix, regression tests, and a patch changeset. No unrelated code changes are identified.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Full details: Description check

Explanation

The description explains the bug, the fix, the affected files, regression tests, changeset, linked issue, and test result. It does not use the template's Checklist or Release Impact headings, but the required change details are otherwise complete.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the waiting-on: maintainer The ball is in the maintainers’ court label Aug 22, 2026
@tombeckenham
tombeckenham force-pushed the fix-1187-tool-call-manager-repeat-start branch from 2eecfc8 to 8f93f0b Compare August 22, 2026 21:25
@nx-cloud

nx-cloud Bot commented Aug 22, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit dc73413

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 9m 59s View ↗
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 1m 38s View ↗

☁️ Nx Cloud last updated this comment at 2026-08-31 21:59:59 UTC

@tombeckenham
tombeckenham force-pushed the fix-1187-tool-call-manager-repeat-start branch from cf97e4a to c861e75 Compare August 24, 2026 21:22
@pkg-pr-new

pkg-pr-new Bot commented Aug 24, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

npm i https://pkg.pr.new/@tanstack/ai@1197

@tanstack/ai-acp

npm i https://pkg.pr.new/@tanstack/ai-acp@1197

@tanstack/ai-angular

npm i https://pkg.pr.new/@tanstack/ai-angular@1197

@tanstack/ai-anthropic

npm i https://pkg.pr.new/@tanstack/ai-anthropic@1197

@tanstack/ai-bedrock

npm i https://pkg.pr.new/@tanstack/ai-bedrock@1197

@tanstack/ai-byteplus

npm i https://pkg.pr.new/@tanstack/ai-byteplus@1197

@tanstack/ai-claude-code

npm i https://pkg.pr.new/@tanstack/ai-claude-code@1197

@tanstack/ai-client

npm i https://pkg.pr.new/@tanstack/ai-client@1197

@tanstack/ai-code-mode

npm i https://pkg.pr.new/@tanstack/ai-code-mode@1197

@tanstack/ai-code-mode-snippets

npm i https://pkg.pr.new/@tanstack/ai-code-mode-snippets@1197

@tanstack/ai-codex

npm i https://pkg.pr.new/@tanstack/ai-codex@1197

@tanstack/ai-cohere

npm i https://pkg.pr.new/@tanstack/ai-cohere@1197

@tanstack/ai-compaction

npm i https://pkg.pr.new/@tanstack/ai-compaction@1197

@tanstack/ai-devtools-core

npm i https://pkg.pr.new/@tanstack/ai-devtools-core@1197

@tanstack/ai-durable-stream

npm i https://pkg.pr.new/@tanstack/ai-durable-stream@1197

@tanstack/ai-elevenlabs

npm i https://pkg.pr.new/@tanstack/ai-elevenlabs@1197

@tanstack/ai-event-client

npm i https://pkg.pr.new/@tanstack/ai-event-client@1197

@tanstack/ai-fal

npm i https://pkg.pr.new/@tanstack/ai-fal@1197

@tanstack/ai-gemini

npm i https://pkg.pr.new/@tanstack/ai-gemini@1197

@tanstack/ai-grok

npm i https://pkg.pr.new/@tanstack/ai-grok@1197

@tanstack/ai-grok-build

npm i https://pkg.pr.new/@tanstack/ai-grok-build@1197

@tanstack/ai-groq

npm i https://pkg.pr.new/@tanstack/ai-groq@1197

@tanstack/ai-isolate-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-isolate-cloudflare@1197

@tanstack/ai-isolate-daytona

npm i https://pkg.pr.new/@tanstack/ai-isolate-daytona@1197

@tanstack/ai-isolate-node

npm i https://pkg.pr.new/@tanstack/ai-isolate-node@1197

@tanstack/ai-isolate-quickjs

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs@1197

@tanstack/ai-isolate-quickjs-bun

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs-bun@1197

@tanstack/ai-llmgateway

npm i https://pkg.pr.new/@tanstack/ai-llmgateway@1197

@tanstack/ai-lovable

npm i https://pkg.pr.new/@tanstack/ai-lovable@1197

@tanstack/ai-mcp

npm i https://pkg.pr.new/@tanstack/ai-mcp@1197

@tanstack/ai-memory

npm i https://pkg.pr.new/@tanstack/ai-memory@1197

@tanstack/ai-mistral

npm i https://pkg.pr.new/@tanstack/ai-mistral@1197

@tanstack/ai-octane

npm i https://pkg.pr.new/@tanstack/ai-octane@1197

@tanstack/ai-ollama

npm i https://pkg.pr.new/@tanstack/ai-ollama@1197

@tanstack/ai-openai

npm i https://pkg.pr.new/@tanstack/ai-openai@1197

@tanstack/ai-opencode

npm i https://pkg.pr.new/@tanstack/ai-opencode@1197

@tanstack/ai-openrouter

npm i https://pkg.pr.new/@tanstack/ai-openrouter@1197

@tanstack/ai-perplexity

npm i https://pkg.pr.new/@tanstack/ai-perplexity@1197

@tanstack/ai-persistence

npm i https://pkg.pr.new/@tanstack/ai-persistence@1197

@tanstack/ai-preact

npm i https://pkg.pr.new/@tanstack/ai-preact@1197

@tanstack/ai-react

npm i https://pkg.pr.new/@tanstack/ai-react@1197

@tanstack/ai-react-ui

npm i https://pkg.pr.new/@tanstack/ai-react-ui@1197

@tanstack/ai-sandbox

npm i https://pkg.pr.new/@tanstack/ai-sandbox@1197

@tanstack/ai-sandbox-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-sandbox-cloudflare@1197

@tanstack/ai-sandbox-daytona

npm i https://pkg.pr.new/@tanstack/ai-sandbox-daytona@1197

@tanstack/ai-sandbox-docker

npm i https://pkg.pr.new/@tanstack/ai-sandbox-docker@1197

@tanstack/ai-sandbox-local-process

npm i https://pkg.pr.new/@tanstack/ai-sandbox-local-process@1197

@tanstack/ai-sandbox-sprites

npm i https://pkg.pr.new/@tanstack/ai-sandbox-sprites@1197

@tanstack/ai-sandbox-upstash-box

npm i https://pkg.pr.new/@tanstack/ai-sandbox-upstash-box@1197

@tanstack/ai-sandbox-vercel

npm i https://pkg.pr.new/@tanstack/ai-sandbox-vercel@1197

@tanstack/ai-skills

npm i https://pkg.pr.new/@tanstack/ai-skills@1197

@tanstack/ai-solid

npm i https://pkg.pr.new/@tanstack/ai-solid@1197

@tanstack/ai-solid-ui

npm i https://pkg.pr.new/@tanstack/ai-solid-ui@1197

@tanstack/ai-svelte

npm i https://pkg.pr.new/@tanstack/ai-svelte@1197

@tanstack/ai-utils

npm i https://pkg.pr.new/@tanstack/ai-utils@1197

@tanstack/ai-vercel-gateway

npm i https://pkg.pr.new/@tanstack/ai-vercel-gateway@1197

@tanstack/ai-vertex

npm i https://pkg.pr.new/@tanstack/ai-vertex@1197

@tanstack/ai-vue

npm i https://pkg.pr.new/@tanstack/ai-vue@1197

@tanstack/ai-vue-ui

npm i https://pkg.pr.new/@tanstack/ai-vue-ui@1197

@tanstack/openai-base

npm i https://pkg.pr.new/@tanstack/openai-base@1197

@tanstack/preact-ai-devtools

npm i https://pkg.pr.new/@tanstack/preact-ai-devtools@1197

@tanstack/react-ai-devtools

npm i https://pkg.pr.new/@tanstack/react-ai-devtools@1197

@tanstack/solid-ai-devtools

npm i https://pkg.pr.new/@tanstack/solid-ai-devtools@1197

@tanstack/svelte-ai-devtools

npm i https://pkg.pr.new/@tanstack/svelte-ai-devtools@1197

commit: 29aa341

@tombeckenham
tombeckenham force-pushed the fix-1187-tool-call-manager-repeat-start branch 2 times, most recently from 2bb5924 to b47be79 Compare August 26, 2026 21:25
@autofix-ci
autofix-ci Bot requested a review from a team as a code owner August 26, 2026 21:29
@tombeckenham
tombeckenham force-pushed the fix-1187-tool-call-manager-repeat-start branch 2 times, most recently from 4de69a1 to 29aa341 Compare August 30, 2026 21:07
@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

citizen204 and others added 3 commits September 1, 2026 07:24
…allId

AG-UI's TOOL_CALL_START carries no index, and a non-first-party or
malformed producer can send a second START for a toolCallId that is
already being tracked by ToolCallManager. Without a guard:
- a repeat with the same index overwrites the slot, wiping any
  TOOL_CALL_ARGS already accumulated (arguments reset to '')
- a repeat with a missing/different index inserts a duplicate map row,
  so getToolCalls() returns the id twice and the engine runs the tool
  twice

Skip the repeat instead. First-party adapters emit START only once per
call, so this only changes behavior for custom/malformed streams.

Fixes TanStack#1187
@tombeckenham
tombeckenham force-pushed the fix-1187-tool-call-manager-repeat-start branch from 29aa341 to dc73413 Compare August 31, 2026 21:24
@github-actions github-actions Bot added waiting-on: author Waiting for the author to respond or update and removed waiting-on: maintainer The ball is in the maintainers’ court labels Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-on: author Waiting for the author to respond or update

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ToolCallManager can run the same tool call twice on a repeat TOOL_CALL_START

1 participant