From 48426d5022b99e6cf3668cfc9399042f0b411fc6 Mon Sep 17 00:00:00 2001 From: Enrico Ros Date: Wed, 15 Oct 2025 15:05:19 -0700 Subject: [PATCH] AIX: OpenAI: [Mistral, 2025-10-15]: non-standard delta.content for thinking blocks --- .../chatGenerate/parsers/openai.parser.ts | 20 +++++++++++++++++++ .../dispatch/wiretypes/openai.wiretypes.ts | 10 +++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/modules/aix/server/dispatch/chatGenerate/parsers/openai.parser.ts b/src/modules/aix/server/dispatch/chatGenerate/parsers/openai.parser.ts index f2ddc025b..dd1785fc6 100644 --- a/src/modules/aix/server/dispatch/chatGenerate/parsers/openai.parser.ts +++ b/src/modules/aix/server/dispatch/chatGenerate/parsers/openai.parser.ts @@ -212,6 +212,26 @@ export function createOpenAIChatCompletionsChunkParser(): ChatGenerateParseFunct pt.appendAutoText_weak(delta.content); } + + // [Mistral, 2025-10-15] SPEC-VIOLATION Text (array format from Mistral thinking models) + else if (Array.isArray(delta.content)) { + for (const contentBlock of delta.content) + if (contentBlock.type === 'thinking' && Array.isArray(contentBlock.thinking)) { + // Extract text from thinking blocks and send as reasoning + for (const thinkingPart of contentBlock.thinking) + if (thinkingPart.type === 'text' && typeof (thinkingPart.text as unknown) === 'string') { + pt.appendReasoningText(thinkingPart.text); + deltaHasReasoning = true; + } else { + // Handle other thinking part types if necessary + console.log('AIX: OpenAI-dispatch: unexpected thinking part type from Mistral:', thinkingPart); + } + } else { + // Handle other content types if necessary + console.log('AIX: OpenAI-dispatch: unexpected content block type from Mistral:', contentBlock); + } + } + // 2025-03-26: we don't have the full concurrency combinations of content/reasoning/reasoning_content yet // if (delta.content !== undefined && delta.content !== null) // throw new Error(`unexpected delta content type: ${typeof delta.content}`); diff --git a/src/modules/aix/server/dispatch/wiretypes/openai.wiretypes.ts b/src/modules/aix/server/dispatch/wiretypes/openai.wiretypes.ts index b38f3d93e..6efec7b06 100644 --- a/src/modules/aix/server/dispatch/wiretypes/openai.wiretypes.ts +++ b/src/modules/aix/server/dispatch/wiretypes/openai.wiretypes.ts @@ -560,7 +560,15 @@ export namespace OpenAIWire_API_Chat_Completions { role: z.literal('assistant').optional() .nullable(), // [Deepseek] added .nullable() // delta-text content - content: z.string().nullable().optional(), + content: z.string().nullish() + // [Mistral, 2025-10-15] Mistral SPEC-BREAKING thinking fragments + .or(z.array(z.object({ + type: z.string(), // 'thinking', but relaxed + thinking: z.array(z.object({ + type: z.string(), + text: z.string(), + })).optional(), + }))), // delta-reasoning content reasoning_content: z.string().nullable().optional(), // [Deepseek, 2025-01-20] reasoning: z.string().optional() // [OpenRouter, 2025-01-24]