Skip to content

Commit 17ee5b1

Browse files
[Bugfix] Set type/role explicitly in streaming message_start event (#45376)
Signed-off-by: Wayne Chiu <waynehacking8@gmail.com>
1 parent 1a36978 commit 17ee5b1

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

tests/entrypoints/anthropic/test_anthropic_messages_conversion.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,3 +996,39 @@ async def sse_input():
996996
assert "text" in block_starts
997997

998998
assert events[-1][0] == "message_stop"
999+
1000+
1001+
class TestMessageStartIncludesTypeAndRole:
1002+
"""Regression test for issue #45367: the streaming message_start event is
1003+
serialized with exclude_unset=True, which silently dropped the
1004+
default-valued ``type``/``role`` fields of the nested message object.
1005+
Strict Anthropic SDK clients (e.g. Claude Code) validate
1006+
``message_start.message.type``/``role`` and reject the whole stream when
1007+
they are missing.
1008+
"""
1009+
1010+
@pytest.mark.asyncio
1011+
async def test_message_start_contains_message_type_and_role(self):
1012+
async def sse_input():
1013+
yield _make_stream_chunk(
1014+
delta=DeltaMessage(content="Hello"),
1015+
usage=UsageInfo(
1016+
prompt_tokens=20,
1017+
total_tokens=20,
1018+
completion_tokens=0,
1019+
),
1020+
)
1021+
yield _make_stream_chunk(finish_reason="stop")
1022+
yield "data: [DONE]"
1023+
1024+
converter = _make_stream_converter()
1025+
output = []
1026+
async for event in converter.message_stream_converter(sse_input()):
1027+
output.append(event)
1028+
1029+
events = _parse_sse_events(output)
1030+
1031+
assert events[0][0] == "message_start"
1032+
message = events[0][1]["message"]
1033+
assert message["type"] == "message"
1034+
assert message["role"] == "assistant"

vllm/entrypoints/anthropic/serving.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,13 @@ def stop_and_flush() -> list[str]:
678678
type="message_start",
679679
message=AnthropicMessagesResponse(
680680
id=origin_chunk.id,
681+
# Set explicitly: this event is serialized
682+
# with exclude_unset=True, which drops
683+
# default-valued fields, while strict
684+
# Anthropic SDK clients require
685+
# message.type/role (issue #45367).
686+
type="message",
687+
role="assistant",
681688
content=[],
682689
model=origin_chunk.model,
683690
stop_reason=None,

0 commit comments

Comments
 (0)