fix(ai): produce new object references in tool-call message updaters#395
fix(ai): produce new object references in tool-call message updaters#395braden-w wants to merge 1 commit intoTanStack:mainfrom
Conversation
Four message-updater functions mutated tool-call parts in-place after spreading the parts array. The shallow copy preserved original object references, breaking change detection in frameworks using proxies (Svelte 5, Vue 3). Replace in-place mutations with spread copies at the found index, matching the immutable pattern used by updateToolCallPart, updateTextPart, and updateThinkingPart. Add immutability tests for all four fixed functions.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe PR updates tool-call message updater functions to prevent in-place object mutations. Four updater functions ( Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Four message-updater functions mutated tool-call parts in-place after shallow-copying the parts array, breaking proxy-based reactivity in Svelte 5. Bun patch replaces mutations with immutable spread copies. Upstream PR: TanStack/ai#395
I ran into this while building a Svelte 5 chat UI with tool-call approvals. Svelte 5 uses proxies for reactivity, and
$derived(part.state === 'approval-requested')never fired because the part object identity didn't change.The root cause is four functions in
message-updaters.tsthat mutate tool-call parts in-place after[...msg.parts]. The shallow copy creates a new array but the elements are the same references, sotoolCallPart.state = 'approval-requested'changes the original object in both arrays. This affects any framework using proxy-based reactivity (Svelte 5, Vue 3).The other updaters (
updateToolCallPart,updateTextPart,updateThinkingPart) already produce new objects via spread. This PR aligns the four remaining functions to the same pattern:Functions fixed:
updateToolCallApproval,updateToolCallState,updateToolCallWithOutput,updateToolCallApprovalResponse. Four immutability tests added.Checklist
Summary by CodeRabbit
Bug Fixes
Tests