test(translation): expect the EOF error frame when an Anthropic json_schema stream is cut (#49521)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Mateo Wang 2026-10-31 16:04:04 -07:00 • committed by GitHub
parent 22d0b1e443
commit ddab201d68
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 18 additions and 7 deletions

View file

@ -152,15 +152,14 @@ def _place_delta(partial_json: str) -> SSEFrame:
)
def _place_chunk(delta: dict[str, JsonValue], *, finish_reason: str | None = None) -> SSEFrame:
finish: Final = {} if finish_reason is None else {"finish_reason": finish_reason}
def _place_chunk(delta: dict[str, JsonValue]) -> SSEFrame:
return SSEFrame(
data={
"id": ANY,
"object": "chat.completion.chunk",
"created": ANY,
"model": "anthropic/claude-haiku-5-5",
"choices": [{"index": 0, "delta": delta, **finish}],
"choices": [{"index": 0, "delta": delta}],
}
)
@ -245,7 +244,19 @@ CLAUDE_HAIKU_5_5_JSON_SCHEMA_CUT_STREAM_TEST_CASE: Final = StreamingTranslationT
_place_chunk({"content": 'try": "'}),
_place_chunk({"content": 'France"'}),
_place_chunk({"content": "}"}),
_place_chunk({}, finish_reason="stop"),
SSEFrame(
data={
"error": {
"message": (
"litellm.APIConnectionError: AnthropicException - "
"Stream ended before a finish_reason was received"
),
"type": "internal_server_error",
"param": None,
"code": "500",
}
}
),
SSEFrame(data="[DONE]"),
),
expected_litellm_response={
@ -257,7 +268,6 @@ CLAUDE_HAIKU_5_5_JSON_SCHEMA_CUT_STREAM_TEST_CASE: Final = StreamingTranslationT
{
"index": 0,
"message": {"role": "assistant", "content": '{"city": "Paris", "country": "France"}'},
"finish_reason": "stop",
}
],
},

View file

@ -129,8 +129,9 @@ def _join_stream_frames(endpoint: str, frames: tuple[SSEFrame, ...]) -> Mapping[
case "/v1/chat/completions":
state: Final = ChatCompletionStreamState()
for frame in frames:
if frame.data != "[DONE]":
state.handle_chunk(ChatCompletionChunk.model_validate(frame.data))
if frame.data == "[DONE]" or (isinstance(frame.data, Mapping) and "error" in frame.data):
continue
state.handle_chunk(ChatCompletionChunk.model_validate(frame.data))
return JSON_OBJECT.validate_python(state.get_final_completion().model_dump(mode="json", exclude_none=True))
case _:
raise AssertionError(f"no stream accumulator for {endpoint}")