fix: guard against non-string content delta and thinking blocks#68855
fix: guard against non-string content delta and thinking blocks#68855tianhaocui wants to merge 3 commits intoopenclaw:mainfrom
Conversation
Mistral (and potentially other providers) may send thinking content as an object in choice.delta.content rather than a string. Without a type guard, the object is coerced to "[object Object]" when appended to the text buffer. Two fixes: 1. openai-transport-stream.ts: add typeof === "string" check on choice.delta.content before appending to the text buffer 2. message-extract.ts: handle object-form thinking blocks where the text lives in a .text property instead of being a plain string Fixes openclaw#68309
Greptile SummaryThis PR adds two defensive guards for non-standard Mistral (and similar provider) response shapes: a Confidence Score: 5/5Safe to merge — changes are narrow defensive guards with no regression risk on existing providers. Both changes are simple, targeted type-guards that prevent silent coercion bugs. The only finding is a P2 style nit about No files require special attention. Prompt To Fix All With AIThis is a comment left during a code review.
Path: ui/src/ui/chat/message-extract.ts
Line: 60
Comment:
**Empty string thinking silently dropped**
`if (thinkingValue)` is falsy for `""`, so a thinking block whose `.text` property is an empty string is silently discarded. This is likely fine in practice, but if `thinkingValue !== null` is the intended gate (to distinguish "present but empty" from "absent"), the check should be explicit.
```suggestion
if (thinkingValue !== null) {
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix: guard against non-string content de..." | Re-trigger Greptile |
| typeof (item.thinking as Record<string, unknown>).text === "string" | ||
| ? ((item.thinking as Record<string, unknown>).text as string) | ||
| : null; | ||
| if (thinkingValue) { |
There was a problem hiding this comment.
Empty string thinking silently dropped
if (thinkingValue) is falsy for "", so a thinking block whose .text property is an empty string is silently discarded. This is likely fine in practice, but if thinkingValue !== null is the intended gate (to distinguish "present but empty" from "absent"), the check should be explicit.
| if (thinkingValue) { | |
| if (thinkingValue !== null) { |
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/ui/chat/message-extract.ts
Line: 60
Comment:
**Empty string thinking silently dropped**
`if (thinkingValue)` is falsy for `""`, so a thinking block whose `.text` property is an empty string is silently discarded. This is likely fine in practice, but if `thinkingValue !== null` is the intended gate (to distinguish "present but empty" from "absent"), the check should be explicit.
```suggestion
if (thinkingValue !== null) {
```
How can I resolve this? If you propose a fix, please make it concise.|
Related work from PRtags group Title: Open PR duplicate: [Bug]: A problem with mistral small thinking enabled
|
|
Closing this as duplicate or superseded after Codex automated review. PR #68855 should close as superseded by open PR #68418. Current main still lacks the fix, but #68418 is the broader canonical parser-side fix for the same #68309 Mistral Small thinking bug, while #68855 only skips non-string content and adds UI extraction for one object-shaped thinking form. Best possible solution: Close #68855 as superseded and focus maintainer review on #68418. The right product/code path is to fix What I checked:
So I’m closing this here and keeping the remaining discussion on the canonical linked item. Codex Review notes: model gpt-5.5, reasoning high; reviewed against d54d2d6b9b8a. |
Fixes #68309
Summary
Mistral (and potentially other providers) may send thinking content as an object in
choice.delta.contentrather than a string. Without a type guard, the object is coerced to"[object Object]"when appended to the text buffer viaappendTextDelta.Changes
src/agents/openai-transport-stream.ts:1185— Addedtypeof === "string"check onchoice.delta.contentbefore appending to the text buffer. Non-string content (objects) is now skipped instead of being coerced.ui/src/ui/chat/message-extract.ts:51— ExtendedextractThinkingto handle object-form thinking blocks where the text lives in a.textproperty (e.g.{ type: "thinking", thinking: { text: "..." } }) in addition to plain string form.Test Plan
[object Object]