mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-19 21:52:21 +03:00
* fix(stream): synthesize terminal finish_reason chunk when upstream omits it (#7800) Some providers close the SSE stream without emitting a final chunk carrying a non-null finish_reason. The OpenAI spec requires the terminal chunk to include finish_reason (e.g. "stop"); strict clients (pi CLI) reject the stream with "Stream ended without finish_reason". In passthrough mode (OpenAI Chat Completions shape), track whether a chunk with non-null finish_reason was seen. If not, synthesize a terminal chunk with finish_reason "stop" (or "tool_calls" when tool calls were present) before emitting [DONE]. Translate mode is unaffected — translators (claude-to-openai, gemini- to-openai) already guarantee a terminal finish_reason chunk via finishReasonSent / fallback defaults. Tests: 3 new regression tests covering omission, no-op when upstream sends finish_reason, and tool_calls variant. * fix(stream): track finish_reason in flush path to avoid false synthesis (#7800) The synthetic finish_reason chunk fired even when the upstream DID emit a finish_reason chunk — but as the final buffered line without a trailing newline. The flush path (which handles the leftover buffer) normalized IDs but never set passthroughSawFinishReason, so the synthesis guard !passthroughSawFinishReason stayed true and emitted a spurious synthetic chunk with a chatcmpl-* id, breaking the numeric-id normalization test.