fix(core): prevent cross-type content block merging in merge_lists

This commit is contained in:
Mason Daugherty
2026-03-16 23:29:50 -04:00
parent 69a7b9c808
commit ad64946130
2 changed files with 31 additions and 0 deletions

View File

@@ -120,6 +120,16 @@ def merge_lists(left: list | None, *others: list | None) -> list | None:
if (
"index" in e_left
and e_left["index"] == e["index"] # index matches
# Prevent text blocks from merging with non-text
# blocks that happen to share the same index (e.g.,
# streaming text at index 0 vs tool_call_chunk at
# index 0 from the API). This is a text-vs-
# everything-else partition; non-text blocks at the
# same index may still merge with each other.
and (
(e_left.get("type") == "text")
== (e.get("type") == "text")
)
and ( # IDs not inconsistent
e_left.get("id") in (None, "")
or e.get("id") in (None, "")

View File

@@ -433,6 +433,27 @@ def test_generation_chunk_addition_type_error() -> None:
[{"no_index": "b"}],
[{"no_index": "a"}, {"no_index": "b"}],
),
# Text and non-text blocks with same index should NOT merge
(
[{"index": 0, "type": "text", "text": "hello"}],
[{"index": 0, "type": "tool_call_chunk", "name": "foo", "args": "{}"}],
[
{"index": 0, "type": "text", "text": "hello"},
{"index": 0, "type": "tool_call_chunk", "name": "foo", "args": "{}"},
],
),
# Two text blocks with same index should still merge
(
[{"index": 0, "type": "text", "text": "hel"}],
[{"index": 0, "type": "text", "text": "lo"}],
[{"index": 0, "type": "text", "text": "hello"}],
),
# Two non-text blocks with same index should still merge
(
[{"index": 0, "type": "tool_call_chunk", "args": '{"a'}],
[{"index": 0, "type": "tool_call_chunk", "args": '": 1}'}],
[{"index": 0, "type": "tool_call_chunk", "args": '{"a": 1}'}],
),
],
)
def test_merge_lists(