You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(litellm): handle reasoning_content and reasoning fields in streaming (#449)
* feat(litellm): handle reasoning_content and reasoning fields in streaming
LiteLLMHandler was not processing reasoning/thinking fields from the
stream delta, causing reasoning output from DeepSeek, QwQ, and other
reasoning models routed through LiteLLM to be silently dropped.
Mirrors the reasoning extraction already present in
BaseOpenAiCompatibleProvider: checks for `reasoning_content` first,
falls back to `reasoning`, skips empty/whitespace-only values.
* test(litellm): add reasoning field handling coverage
Add tests verifying that reasoning_content and reasoning delta fields
are correctly yielded as reasoning chunks, that reasoning_content takes
precedence when both fields are present, and that empty/whitespace-only
values are silently ignored.
* test(litellm): cover falsy reasoning field branch on line 241
Add a test case where reasoning_content is undefined and reasoning is an empty string. This exercises the `|| ""` fallback in the reasoning delta handler, which was previously uncovered.
* refactor(reasoning): extract delta reasoning helper and fix fallback bug
Replaces the for-of/break pattern in lite-llm.ts and
base-openai-compatible-provider.ts with a shared
extractReasoningFromDelta helper. The previous form short-circuited as
soon as the reasoning_content key existed, so a delta carrying
reasoning_content: null (or '') alongside a populated reasoning field
would drop the model's thinking output entirely. The helper picks the
first field that is both a string and non-blank, restoring the intended
fallback chain across LiteLLM and every base-OpenAI-compatible provider.
* fix(reasoning): preserve whitespace-only chunks in streamed deltas
The previous trim-based guard in extractReasoningFromDelta dropped any
delta whose reasoning_content / reasoning payload contained only
whitespace. OpenAI-compatible streams routinely emit single-character
chunks (a lone " " between words or "\n\n" between paragraphs), and
discarding them collapsed word and paragraph boundaries once callers
concatenated the chunks into the accumulated reasoning string.
Replace the trim guard with explicit length-based fallthrough so:
- " ", "\n\n", etc. flow through verbatim
- null / non-string / empty-string still cascade to the next field
- the original reasoning_content: null + reasoning: "real" fix is kept
* Revert "fix(reasoning): preserve whitespace-only chunks in streamed deltas"
This reverts commit 64c3fcf.
* Reapply "fix(reasoning): preserve whitespace-only chunks in streamed deltas"
This reverts commit 860d1f7.
* test(reasoning): align base-openai-compatible tests with whitespace-preserving extractor
The extractor now passes whitespace-only reasoning chunks through verbatim so
streamed word/paragraph boundaries survive concatenation. Update the two
expectations that still assumed the old trim-and-drop behavior.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Oh Daewoong <dw.oh@samsung.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
0 commit comments