@@ -11,19 +11,14 @@ import { ApiStream } from "../transform/stream"
1111import { BaseProvider } from "./base-provider"
1212import type { SingleCompletionHandler , ApiHandlerCreateMessageMetadata } from "../index"
1313
14- // Define TypeScript interfaces for Mistral content types
15- interface MistralTextContent {
16- type : "text"
17- text : string
14+ // Type helper to handle thinking chunks from Mistral API
15+ // The SDK includes ThinkChunk but TypeScript has trouble with the discriminated union
16+ type ContentChunkWithThinking = {
17+ type : string
18+ text ?: string
19+ thinking ?: Array < { type : string ; text ?: string } >
1820}
1921
20- interface MistralThinkingContent {
21- type : "thinking"
22- text : string
23- }
24-
25- type MistralContent = MistralTextContent | MistralThinkingContent | string
26-
2722export class MistralHandler extends BaseProvider implements SingleCompletionHandler {
2823 protected options : ApiHandlerOptions
2924 private client : Mistral
@@ -61,34 +56,38 @@ export class MistralHandler extends BaseProvider implements SingleCompletionHand
6156 temperature,
6257 } )
6358
64- for await ( const chunk of response ) {
65- const delta = chunk . data . choices [ 0 ] ?. delta
59+ for await ( const event of response ) {
60+ const delta = event . data . choices [ 0 ] ?. delta
6661
6762 if ( delta ?. content ) {
6863 if ( typeof delta . content === "string" ) {
6964 // Handle string content as text
7065 yield { type : "text" , text : delta . content }
7166 } else if ( Array . isArray ( delta . content ) ) {
72- // Handle array of content blocks
73- for ( const c of delta . content as MistralContent [ ] ) {
74- if ( typeof c === "object" && c !== null ) {
75- if ( c . type === "thinking" && c . text ) {
76- // Handle thinking content as reasoning chunks
77- yield { type : "reasoning" , text : c . text }
78- } else if ( c . type === "text" && c . text ) {
79- // Handle text content normally
80- yield { type : "text" , text : c . text }
67+ // Handle array of content chunks
68+ // The SDK v1.9.18 supports ThinkChunk with type "thinking"
69+ for ( const chunk of delta . content as ContentChunkWithThinking [ ] ) {
70+ if ( chunk . type === "thinking" && chunk . thinking ) {
71+ // Handle thinking content as reasoning chunks
72+ // ThinkChunk has a 'thinking' property that contains an array of text/reference chunks
73+ for ( const thinkingPart of chunk . thinking ) {
74+ if ( thinkingPart . type === "text" && thinkingPart . text ) {
75+ yield { type : "reasoning" , text : thinkingPart . text }
76+ }
8177 }
78+ } else if ( chunk . type === "text" && chunk . text ) {
79+ // Handle text content normally
80+ yield { type : "text" , text : chunk . text }
8281 }
8382 }
8483 }
8584 }
8685
87- if ( chunk . data . usage ) {
86+ if ( event . data . usage ) {
8887 yield {
8988 type : "usage" ,
90- inputTokens : chunk . data . usage . promptTokens || 0 ,
91- outputTokens : chunk . data . usage . completionTokens || 0 ,
89+ inputTokens : event . data . usage . promptTokens || 0 ,
90+ outputTokens : event . data . usage . completionTokens || 0 ,
9291 }
9392 }
9493 }
@@ -119,9 +118,9 @@ export class MistralHandler extends BaseProvider implements SingleCompletionHand
119118
120119 if ( Array . isArray ( content ) ) {
121120 // Only return text content, filter out thinking content for non-streaming
122- return content
123- . filter ( ( c : any ) => typeof c === "object " && c !== null && c . type === " text" )
124- . map ( ( c : any ) => c . text || "" )
121+ return ( content as ContentChunkWithThinking [ ] )
122+ . filter ( ( c ) => c . type === "text " && c . text )
123+ . map ( ( c ) => c . text || "" )
125124 . join ( "" )
126125 }
127126
0 commit comments