Conversation
A client tool result set the tool-call part's UI state to `complete` via `processor.addToolResult`. #1233 made client-tool output validation async, which reordered that write relative to the finalize-stream safety net (`completeToolCall`, which writes `input-complete`). The visible state then depended on async ordering, flipping the terminal tool-call state from `input-complete` to `complete` and breaking three ai-client tests that had passed since the state was introduced. Make `addToolResult` keep the tool-call part at its terminal `input-complete` state on success (only an execution error makes it `error`). The completed result stays on the separate tool-result part. This removes the race so the state is deterministic regardless of ordering. Update two stream-processor unit tests that asserted the transient `complete` value to expect `input-complete`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Important Review skippedReview was skipped as selected files did not have any reviewable changes. ⚙️ Run configurationConfiguration used: Repository: TanStack/ai/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: TanStack/ai/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (3)
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review. 📝 WalkthroughWalkthroughThe stream processor now keeps a successful tool-call part in ChangesTool-result state
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~8 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to Successful tool results retain the documented call and result states, and the inspected consumers recognize that representation. No actionable merge risk remains. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to A successful tool call will remain in the input-complete state while its separate result is complete. The reviewed paths show no change to tool execution or authorization. Compatibility with consumers outside the repository remains unverified. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings
🧪 Generate unit tests (beta)
🛠️ Fix failing CI checks 💡
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. Comment |
|
View your CI Pipeline Execution ↗ for commit b13d781
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-cloudflare
@tanstack/ai-code-mode
@tanstack/ai-code-mode-snippets
@tanstack/ai-codex
@tanstack/ai-cohere
@tanstack/ai-compaction
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-llmgateway
@tanstack/ai-lovable
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-octane
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-perplexity
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-reactor
@tanstack/ai-remix
@tanstack/ai-sandbox
@tanstack/ai-sandbox-blaxel
@tanstack/ai-sandbox-boxd
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-e2b
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-upstash-box
@tanstack/ai-sandbox-vercel
@tanstack/ai-skills
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-typesafe
@tanstack/ai-utils
@tanstack/ai-vercel-gateway
@tanstack/ai-vertex
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/ai-worldlabs
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
@tanstack/svelte-ai-devtools
commit: |
A successful client tool left the assistant's tool-call part in
state: 'complete'instead of'input-complete', which broke three@tanstack/ai-clienttests onmain. This PR keeps the tool-call part at its terminal'input-complete'state; the completed result stays on the separate tool-result part.🎯 Changes
packages/ai/src/activities/chat/stream/processor.ts:addToolResultnow keeps the tool-call part at'input-complete'on success (only an execution error makes it'error').packages/ai/tests/stream-processor.test.ts: two unit tests that asserted the transient'complete'value now assert'input-complete'.@tanstack/aiand@tanstack/ai-client.✅ Checklist
pnpm run test:pr, or these tests do not apply to this pull request.docs/for this change, or this change is not user-facing.pnpm changeset), or this PR does not change a published package.🚀 Release Impact
Root cause
Issue. After a client tool runs successfully, the assistant's tool-call part ends in
state: 'complete'. It must stay'input-complete'(the model's request is complete; the result lives in the tool-result part). Three ai-client tests inchat-client-context.test.tsfail onmain.Cause. Two runtime paths write the tool-call part's UI state:
processor.addToolResultwrites'complete', and the finalize-stream safety netcompleteToolCallwrites'input-complete'. #1233 (8e8ee2695) made client-tool output validationsync → async(await validateClientToolOutput), which added a microtask beforeaddToolResult. That reordered the two writes, so'complete'now wins the race.git bisecton the pre-existing snapshot test points to8e8ee2695as the first bad commit.Fix.
addToolResultnow passes'input-complete'(not the default'complete') toupdateToolCallWithOutputon success. The tool-call terminal state is deterministic regardless of async ordering.Possible alternatives
chat-client. KeepaddToolResultat'complete'and make the client re-assert'input-complete'after continuation. Rejected: it re-creates the same order dependency and is fragile.updateToolCallWithOutput(line 238). Rejected: that default also serves the server streamed-result and snapshot-folding paths, which correctly end at'complete'; changing it breaks those.'complete'. Rejected: that ratifies an accidental breaking change to the tool-call state thatuseChatrenderers observe, with no intent behind it. The'input-complete'contract has held since the state was introduced (feat(ai): add typed runtime context #628).Testing
Commands run.
pnpm test:pr— all targets pass (test:sherif, test:knip, test:docs, test:kiira, test:maintainer, test:ai-review, test:oxlint, test:lib, test:types, test:build, build, 98 projects).@tanstack/ai1915,@tanstack/ai-client849,@tanstack/ai-react248,@tanstack/ai-vue143,@tanstack/ai-solid157,@tanstack/ai-svelte97 — all green.Gate 1 — repro on clean
main(1e066cbd0) fails:Gate 1 — same repro on this branch passes:
Manual test.
main, runpnpm --filter @tanstack/ai-client exec vitest run tests/chat-client-context.test.ts— 3 tests fail (stateiscomplete, expectedinput-complete).How this PR makes testing easy. The three failing tests in
packages/ai-client/tests/chat-client-context.test.tsare the regression tests; they were red onmainand are green here. Twostream-processor.test.tsunit tests pin the corrected processor contract.No E2E test is added: this is a client-side content-part state detail that is fully covered by the ai-client integration tests and the processor unit tests above; the aimock E2E flows do not assert this internal state.
Risk / rollback
Low. The change narrows one terminal state for locally-applied tool results (client tools and
addToolResultcallers); server streamed results and snapshot folding are untouched and still end at'complete'. To roll back, revert this PR.Public API change
The
stateon a tool-call content part is observable onuseChatmessages. Behavior for a successful client tool:Before
After
Summary by CodeRabbit