fix: make reasoning part text optional in generated types (#23249)

Go serializes ChatMessagePart.Text with omitempty, so empty
reasoning text (from reasoning_start with no delta) is omitted
from JSON. The frontend receives {type: "reasoning"} with text
as undefined, crashing on .trim() calls.

Mark Text as optional in the reasoning variant via the variants
struct tag. This generates ChatReasoningPart with text?: string
and the frontend falls back to "" via nullish coalescing.

Closes #23245
This commit is contained in:
Mathias Fredriksson
2026-03-18 18:10:35 +00:00
committed by GitHub
parent 90cf4f0a91
commit dbb7aee65b
3 changed files with 5 additions and 4 deletions
+1 -1
View File
@@ -127,7 +127,7 @@ func AllChatMessagePartTypes() []ChatMessagePartType {
// scripts/apitypings/main.go for the codegen that reads these.
type ChatMessagePart struct {
Type ChatMessagePartType `json:"type"`
Text string `json:"text,omitempty" variants:"text,reasoning"`
Text string `json:"text,omitempty" variants:"text,reasoning?"`
Signature string `json:"signature,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty" variants:"tool-call?,tool-result?"`
ToolName string `json:"tool_name,omitempty" variants:"tool-call?,tool-result?"`
+1 -1
View File
@@ -1682,7 +1682,7 @@ export interface ChatQueuedMessage {
// From codersdk/chats.go
export interface ChatReasoningPart {
readonly type: "reasoning";
readonly text: string;
readonly text?: string;
}
// From codersdk/chats.go
@@ -131,8 +131,9 @@ export const parseMessageContent = (
break;
}
case "reasoning": {
parsed.reasoning = appendText(parsed.reasoning, part.text);
parsed.blocks = appendTextBlock(parsed.blocks, "thinking", part.text);
const text = part.text ?? "";
parsed.reasoning = appendText(parsed.reasoning, text);
parsed.blocks = appendTextBlock(parsed.blocks, "thinking", text);
break;
}
case "tool-call": {