From ba80359cc01a0b1a79b3bd905068a512a19200b7 Mon Sep 17 00:00:00 2001 From: Xsidz Date: Mon, 17 Aug 2026 00:37:58 +0530 Subject: [PATCH] fix(streaming): merge duplicate-index entries in first tool_call chunk Fixes #3201: when the first streamed chunk contained multiple tool_call delta entries sharing the same index (e.g. two partial updates for index 0), accumulate_delta stored the raw list on the `key not in acc` fast-path, bypassing the index-based merge logic. Later deltas for the same index then only merged into the first physical entry, stranding the second and producing truncated/invalid arguments JSON. Fix: seed indexed-dict lists with [] on first sight and fall through to the existing merge path. Also guard the primitive-extend branch with `acc_value and ...` so the empty seed list doesn't short-circuit there. --- src/openai/lib/streaming/_deltas.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/openai/lib/streaming/_deltas.py b/src/openai/lib/streaming/_deltas.py index a5e1317612..2efdda31ce 100644 --- a/src/openai/lib/streaming/_deltas.py +++ b/src/openai/lib/streaming/_deltas.py @@ -6,8 +6,13 @@ def accumulate_delta(acc: dict[object, object], delta: dict[object, object]) -> dict[object, object]: for key, delta_value in delta.items(): if key not in acc: - acc[key] = delta_value - continue + # Seed indexed-dict lists with [] so duplicate-index entries in the + # first chunk are merged by the list path below instead of stored raw. + if is_list(delta_value) and delta_value and is_dict(delta_value[0]) and "index" in delta_value[0]: + acc[key] = [] + else: + acc[key] = delta_value + continue acc_value = acc[key] if acc_value is None: @@ -33,7 +38,7 @@ def accumulate_delta(acc: dict[object, object], delta: dict[object, object]) -> elif is_list(acc_value) and is_list(delta_value): # for lists of non-dictionary items we'll only ever get new entries # in the array, existing entries will never be changed - if all(isinstance(x, (str, int, float)) for x in acc_value): + if acc_value and all(isinstance(x, (str, int, float)) for x in acc_value): acc_value.extend(delta_value) continue