Skip to content

🧩 fix: Keep Text and Tool Calls From Mistral Typed Delta Chunks - #604

Open
jordanmarques wants to merge 1 commit into
LibreChat-AI:mainfrom
jordanmarques:fix/mistral-typed-delta-content
Open

jordanmarques wants to merge 1 commit into
LibreChat-AI:mainfrom
jordanmarques:fix/mistral-typed-delta-content

Conversation

@jordanmarques

Copy link
Copy Markdown

Summary

When a Mistral model reasons (Mistral Large 4, or GLM 5.3 served by Mistral), its Chat Completions
stream sends delta.content as a list of typed chunks instead of a string:

{"delta": {"content": [
  {"type": "thinking", "thinking": [{"type": "text", "text": " done."}], "closed": true},
  {"type": "text", "text": "A freelancer"}
]}}

The chunk that closes the reasoning also carries the first words of the answer, and sometimes the
first tool-call delta, the only one with the call's id and name. _streamResponseChunks skips
every chunk whose content is not a string ([WARNING]: Received non-string content from OpenAI),
so:

  • answers start mid-word ("ancer is a self-employed…");
  • tool calls lose their name and id, so no tool runs and the agent ends with an empty response.

This format is Mistral's documented streaming behavior for reasoning models; only
reasoning_effort: "none" returns plain strings, and some models (GLM 5.3) refuse that value.

Change

LibreChatOpenAICompletions._convertCompletionsDeltaToBaseMessageChunk flattens a list
delta.content before the LangChain conversion:

  • text blocks become the string content;
  • thinking blocks become delta.reasoning, which attachLibreChatDeltaFields already maps to
    additional_kwargs.reasoning_content.

String content and other providers are unchanged.

Testing

  • New src/llm/openai/mistralContentChunks.test.ts: mixed reasoning + text chunk, reasoning +
    tool-call chunk, reasoning-only chunk.
  • src/llm/openai suite: 211 tests pass; tsc --noEmit and ESLint clean.
  • End to end against a Mistral-backed OpenAI-compatible gateway, 10 tool-calling runs per model:
Tool calls lost (GLM 5.3) Answer start
Before 2 / 10 truncated
After 0 / 10 complete, GLM 5.3 and Mistral Large 4

🤖 Generated with Claude Code

@jordanmarques
jordanmarques marked this pull request as ready for review October 9, 2026 09:09
Mistral's Chat Completions stream sends delta.content as a list of typed
chunks (thinking, text) while the model reasons. The chunk that ends the
reasoning also carries the first words of the answer, and sometimes the
first tool-call delta with its id and name. _streamResponseChunks skips any
chunk whose content is not a string, so answers lost their first words and
tool calls lost their name, which ended the run with an empty response.

Flatten those chunks before the LangChain conversion: text blocks become the
string content, thinking blocks become the reasoning delta.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jordanmarques
jordanmarques force-pushed the fix/mistral-typed-delta-content branch from 38888fa to 402ec96 Compare October 9, 2026 09:10

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant