mistral-conversations: empty content deltas open text blocks (GLM 5.x trailing whitespace)
What happened?
Follow-up to #8069, closed as not_planned. The workarounds there route GLM 5.2 through openai-completions, which loses the native Mistral prompt cache. This is the fix on the mistral-conversations side.
Zero-length content: "" deltas open empty text blocks. Every zai-glm variant currently served by the API (zai-glm-5, zai-glm-5-2, zai-glm-5-3, zai-glm-latest) sends them with every tool_calls chunk and the final finish_reason. Each one becomes a text block, which shows up as trailing whitespace after the thinking block. With a long tool call (~80 argument chunks) a single assistant message accumulated ~80 empty text blocks.
GLM 5.3 can also send a non-empty content string in the same delta as the first tool_calls fragment:
data: {"choices":[{"index":0,"delta":{"tool_calls":[...],"index":0,"content":" that time."},"finish_reason":null}]}
I have a tested patch for this on 0.85.1.
Steps to reproduce
Reproduced on a plain pi -ne config, no extensions loaded.
Stream a tool call from zai-glm-5-2, or any other served zai-glm variant (needs a Mistral API key; the SSE excerpt below is enough to see the issue without one):
curl -sS https://api.mistral.ai/v1/chat/completions \
-H "Authorization: Bearer $MISTRAL_API_KEY" -H "Content-Type: application/json" -d '{
"model":"zai-glm-5-2","stream":true,"reasoning_effort":"high",
"messages":[{"role":"system","content":"Use the get_weather tool when asked about weather."},
{"role":"user","content":"What is the weather in Paris? Use the get_weather tool."}],
"tools":[{"type":"function","function":{"name":"get_weather",
"description":"Get current weather for a city.",
"parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}]
}'
Every tool_calls chunk carries "content":"". pi-ai opens an empty text block for each.
SSE excerpt (thinking block, then the first tool_calls chunk with its empty content):
data: {"choices":[{"index":0,"delta":{"index":0,"content":[{"type":"thinking","thinking":[{"type":"text","text":" the get_weather tool."}],"closed":true}]}}]}
data: {"choices":[{"index":0,"delta":{"tool_calls":[{"id":"chatcmpl-tool-...","type":"function","function":{"name":"get_weather","arguments":""},"index":0}],"index":0,"content":""}}]}
data: {"choices":[{"index":0,"delta":{"index":0,"content":""},"finish_reason":"tool_calls"}]}
Expected behavior
Zero-length content deltas do not produce text blocks, so there is no trailing whitespace after the thinking block.
Version
0.85.1
Source: earendil-works/pi