@ai-sdk/mistral 4.0.68 → 4.0.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,9 @@ import type {
13
13
  SharedV4Warning,
14
14
  } from '@ai-sdk/provider';
15
15
  import {
16
+ lazySchema,
17
+ zodSchema,
18
+ type InferSchema,
16
19
  combineHeaders,
17
20
  createEventSourceResponseHandler,
18
21
  createJsonResponseHandler,
@@ -389,7 +392,7 @@ export class MistralConversationLanguageModel implements LanguageModelV4 {
389
392
  return {
390
393
  stream: response.pipeThrough(
391
394
  new TransformStream<
392
- ParseResult<z.infer<typeof mistralConversationChunkSchema>>,
395
+ ParseResult<InferSchema<typeof mistralConversationChunkSchema>>,
393
396
  LanguageModelV4StreamPart
394
397
  >({
395
398
  start(controller) {
@@ -573,7 +576,7 @@ function createContentConverter({
573
576
  return {
574
577
  toolNameMapping,
575
578
  convertChunk(
576
- chunk: z.infer<typeof mistralConversationContentSchema>,
579
+ chunk: z.infer<ReturnType<typeof mistralConversationContentSchema>>,
577
580
  ): Array<
578
581
  LanguageModelV4Text | LanguageModelV4Reasoning | LanguageModelV4Source
579
582
  > {
@@ -604,7 +607,9 @@ function createContentConverter({
604
607
  }
605
608
  },
606
609
  convertTool(
607
- output: z.infer<typeof mistralConversationToolExecutionSchema>,
610
+ output: z.infer<
611
+ ReturnType<typeof mistralConversationToolExecutionSchema>
612
+ >,
608
613
  ): [LanguageModelV4ToolCall, LanguageModelV4ToolResult] {
609
614
  const toolName = toolNameMapping.toCustomToolName(output.name);
610
615
  return [
@@ -633,98 +638,110 @@ function createContentConverter({
633
638
  };
634
639
  }
635
640
 
636
- const mistralConversationContentSchema = z.discriminatedUnion('type', [
637
- z.object({ type: z.literal('text'), text: z.string() }),
641
+ const mistralConversationContentSchema = () =>
642
+ z.discriminatedUnion('type', [
643
+ z.object({ type: z.literal('text'), text: z.string() }),
644
+ z.object({
645
+ type: z.literal('thinking'),
646
+ thinking: z.array(
647
+ z.object({ type: z.literal('text'), text: z.string() }),
648
+ ),
649
+ }),
650
+ z.object({
651
+ type: z.literal('tool_reference'),
652
+ tool: z.string().nullish(),
653
+ title: z.string().nullish(),
654
+ url: z.string().nullish(),
655
+ }),
656
+ ]);
657
+ const mistralConversationMessageContentSchema = () =>
658
+ z.union([z.string(), z.array(mistralConversationContentSchema())]);
659
+ const mistralConversationToolExecutionSchema = () =>
638
660
  z.object({
639
- type: z.literal('thinking'),
640
- thinking: z.array(z.object({ type: z.literal('text'), text: z.string() })),
641
- }),
661
+ type: z.literal('tool.execution'),
662
+ id: z.string(),
663
+ name: z.string(),
664
+ arguments: z.string(),
665
+ function: z.string().nullish(),
666
+ info: z.record(z.string(), z.json()).nullish(),
667
+ });
668
+ const mistralConversationFunctionCallSchema = () =>
642
669
  z.object({
643
- type: z.literal('tool_reference'),
644
- tool: z.string().nullish(),
645
- title: z.string().nullish(),
646
- url: z.string().nullish(),
647
- }),
648
- ]);
649
- const mistralConversationMessageContentSchema = z.union([
650
- z.string(),
651
- z.array(mistralConversationContentSchema),
652
- ]);
653
- const mistralConversationToolExecutionSchema = z.object({
654
- type: z.literal('tool.execution'),
655
- id: z.string(),
656
- name: z.string(),
657
- arguments: z.string(),
658
- function: z.string().nullish(),
659
- info: z.record(z.string(), z.json()).nullish(),
660
- });
661
- const mistralConversationFunctionCallSchema = z.object({
662
- type: z.literal('function.call'),
663
- tool_call_id: z.string(),
664
- name: z.string(),
665
- arguments: z.union([z.string(), z.record(z.string(), z.json())]),
666
- });
667
- const mistralConversationUsageSchema = mistralUsageSchema.extend({
668
- prompt_tokens: z.number().default(0),
669
- completion_tokens: z.number().default(0),
670
- total_tokens: z.number().default(0),
671
- });
672
- const mistralConversationResponseSchema = z.object({
673
- conversation_id: z.string(),
674
- outputs: z.array(
670
+ type: z.literal('function.call'),
671
+ tool_call_id: z.string(),
672
+ name: z.string(),
673
+ arguments: z.union([z.string(), z.record(z.string(), z.json())]),
674
+ });
675
+ const mistralConversationUsageSchema = () =>
676
+ mistralUsageSchema.extend({
677
+ prompt_tokens: z.number().default(0),
678
+ completion_tokens: z.number().default(0),
679
+ total_tokens: z.number().default(0),
680
+ });
681
+ const mistralConversationResponseSchema = lazySchema(() =>
682
+ zodSchema(
683
+ z.object({
684
+ conversation_id: z.string(),
685
+ outputs: z.array(
686
+ z.discriminatedUnion('type', [
687
+ mistralConversationToolExecutionSchema(),
688
+ mistralConversationFunctionCallSchema(),
689
+ z.object({
690
+ type: z.literal('message.output'),
691
+ content: mistralConversationMessageContentSchema(),
692
+ model: z.string().nullish(),
693
+ }),
694
+ ]),
695
+ ),
696
+ usage: mistralConversationUsageSchema().nullish(),
697
+ }),
698
+ ),
699
+ );
700
+ const mistralConversationChunkSchema = lazySchema(() =>
701
+ zodSchema(
675
702
  z.discriminatedUnion('type', [
676
- mistralConversationToolExecutionSchema,
677
- mistralConversationFunctionCallSchema,
678
703
  z.object({
679
- type: z.literal('message.output'),
680
- content: mistralConversationMessageContentSchema,
704
+ type: z.literal('conversation.response.started'),
705
+ conversation_id: z.string(),
706
+ created_at: z.string().nullish(),
707
+ }),
708
+ z.object({
709
+ type: z.literal('conversation.response.done'),
710
+ usage: mistralConversationUsageSchema().nullish(),
711
+ }),
712
+ z.object({
713
+ type: z.literal('conversation.response.error'),
714
+ message: z.string(),
715
+ code: z.number(),
716
+ }),
717
+ z.object({
718
+ type: z.literal('message.output.delta'),
719
+ id: z.string(),
720
+ content_index: z.number().nullish(),
721
+ content: z.union([z.string(), mistralConversationContentSchema()]),
681
722
  model: z.string().nullish(),
682
723
  }),
724
+ z.object({
725
+ type: z.literal('function.call.delta'),
726
+ tool_call_id: z.string(),
727
+ name: z.string(),
728
+ arguments: z.string(),
729
+ output_index: z.number().nullish(),
730
+ }),
731
+ z.object({
732
+ type: z.enum(['tool.execution.started', 'tool.execution.delta']),
733
+ id: z.string(),
734
+ name: z.string(),
735
+ arguments: z.string(),
736
+ function: z.string().nullish(),
737
+ }),
738
+ z.object({
739
+ type: z.literal('tool.execution.done'),
740
+ id: z.string(),
741
+ name: z.string(),
742
+ function: z.string().nullish(),
743
+ info: z.record(z.string(), z.json()).nullish(),
744
+ }),
683
745
  ]),
684
746
  ),
685
- usage: mistralConversationUsageSchema.nullish(),
686
- });
687
- const mistralConversationChunkSchema = z.discriminatedUnion('type', [
688
- z.object({
689
- type: z.literal('conversation.response.started'),
690
- conversation_id: z.string(),
691
- created_at: z.string().nullish(),
692
- }),
693
- z.object({
694
- type: z.literal('conversation.response.done'),
695
- usage: mistralConversationUsageSchema.nullish(),
696
- }),
697
- z.object({
698
- type: z.literal('conversation.response.error'),
699
- message: z.string(),
700
- code: z.number(),
701
- }),
702
- z.object({
703
- type: z.literal('message.output.delta'),
704
- id: z.string(),
705
- content_index: z.number().nullish(),
706
- content: z.union([z.string(), mistralConversationContentSchema]),
707
- model: z.string().nullish(),
708
- }),
709
- z.object({
710
- type: z.literal('function.call.delta'),
711
- tool_call_id: z.string(),
712
- name: z.string(),
713
- arguments: z.string(),
714
- output_index: z.number().nullish(),
715
- }),
716
- z.object({
717
- type: z.enum(['tool.execution.started', 'tool.execution.delta']),
718
- id: z.string(),
719
- name: z.string(),
720
- arguments: z.string(),
721
- function: z.string().nullish(),
722
- }),
723
- z.object({
724
- type: z.literal('tool.execution.done'),
725
- id: z.string(),
726
- name: z.string(),
727
- function: z.string().nullish(),
728
- info: z.record(z.string(), z.json()).nullish(),
729
- }),
730
- ]);
747
+ );
@@ -3,6 +3,8 @@ import {
3
3
  type EmbeddingModelV4,
4
4
  } from '@ai-sdk/provider';
5
5
  import {
6
+ lazySchema,
7
+ zodSchema,
6
8
  combineHeaders,
7
9
  createJsonResponseHandler,
8
10
  parseProviderOptions,
@@ -121,7 +123,11 @@ export class MistralEmbeddingModel implements EmbeddingModelV4 {
121
123
 
122
124
  // minimal version of the schema, focussed on what is needed for the implementation
123
125
  // this approach limits breakages when the API changes and increases efficiency
124
- const MistralTextEmbeddingResponseSchema = z.object({
125
- data: z.array(z.object({ embedding: z.array(z.number()) })),
126
- usage: z.object({ prompt_tokens: z.number() }).nullish(),
127
- });
126
+ const MistralTextEmbeddingResponseSchema = lazySchema(() =>
127
+ zodSchema(
128
+ z.object({
129
+ data: z.array(z.object({ embedding: z.array(z.number()) })),
130
+ usage: z.object({ prompt_tokens: z.number() }).nullish(),
131
+ }),
132
+ ),
133
+ );
@@ -1,15 +1,24 @@
1
- import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';
1
+ import {
2
+ lazySchema,
3
+ zodSchema,
4
+ type InferSchema,
5
+ createJsonErrorResponseHandler,
6
+ } from '@ai-sdk/provider-utils';
2
7
  import { z } from 'zod/v4';
3
8
 
4
- const mistralErrorDataSchema = z.object({
5
- object: z.literal('error'),
6
- message: z.string(),
7
- type: z.string(),
8
- param: z.string().nullable(),
9
- code: z.string().nullable(),
10
- });
9
+ const mistralErrorDataSchema = lazySchema(() =>
10
+ zodSchema(
11
+ z.object({
12
+ object: z.literal('error'),
13
+ message: z.string(),
14
+ type: z.string(),
15
+ param: z.string().nullable(),
16
+ code: z.string().nullable(),
17
+ }),
18
+ ),
19
+ );
11
20
 
12
- export type MistralErrorData = z.infer<typeof mistralErrorDataSchema>;
21
+ export type MistralErrorData = InferSchema<typeof mistralErrorDataSchema>;
13
22
 
14
23
  export const mistralFailedResponseHandler = createJsonErrorResponseHandler({
15
24
  errorSchema: mistralErrorDataSchema,
@@ -1,19 +1,44 @@
1
+ import {
2
+ lazySchema,
3
+ zodSchema,
4
+ type InferSchema,
5
+ } from '@ai-sdk/provider-utils';
1
6
  import { z } from 'zod/v4';
2
7
 
3
8
  export type MistralSpeechModelId =
4
9
  | 'voxtral-mini-tts-2603'
10
+ | 'voxtral-mini-tts-3-0'
11
+ | 'voxtral-mini-tts-3'
5
12
  | 'voxtral-mini-tts-latest'
6
13
  | (string & {});
7
14
 
8
- export const mistralSpeechModelOptions = z.object({
9
- /**
10
- * Base64-encoded reference audio for one-off voice cloning.
11
- *
12
- * When provided, this takes precedence over the standard `voice` option.
13
- */
14
- refAudio: z.string().min(1).optional(),
15
- });
15
+ export const mistralSpeechModelOptions = lazySchema(() =>
16
+ zodSchema(
17
+ z.object({
18
+ /**
19
+ * Base64-encoded reference audio for one-off voice cloning.
20
+ *
21
+ * When provided, this takes precedence over the standard `voice` option.
22
+ */
23
+ refAudio: z.string().min(1).optional(),
16
24
 
17
- export type MistralSpeechModelOptions = z.infer<
25
+ /**
26
+ * How expressive the speech is, from 1 to 5. Higher values trade voice
27
+ * similarity and stability for stronger delivery. Supported by Voxtral 3.
28
+ */
29
+ expressiveness: z.number().min(1).max(5).optional(),
30
+
31
+ /**
32
+ * Pronunciation hints mapping words to lists of IPA phonemes.
33
+ * Supported by Voxtral 3.
34
+ */
35
+ phonemeHints: z
36
+ .record(z.string().min(1), z.array(z.string().min(1)).min(1))
37
+ .optional(),
38
+ }),
39
+ ),
40
+ );
41
+
42
+ export type MistralSpeechModelOptions = InferSchema<
18
43
  typeof mistralSpeechModelOptions
19
44
  >;
@@ -1,5 +1,7 @@
1
1
  import type { SharedV4Warning, SpeechModelV4 } from '@ai-sdk/provider';
2
2
  import {
3
+ lazySchema,
4
+ zodSchema,
3
5
  combineHeaders,
4
6
  createJsonResponseHandler,
5
7
  parseProviderOptions,
@@ -116,6 +118,8 @@ export class MistralSpeechModel implements SpeechModelV4 {
116
118
  input: text,
117
119
  voice_id: refAudio == null ? voice : undefined,
118
120
  ref_audio: refAudio,
121
+ expressiveness: mistralOptions?.expressiveness,
122
+ phoneme_hints: mistralOptions?.phonemeHints,
119
123
  response_format: responseFormat,
120
124
  stream: false,
121
125
  };
@@ -174,6 +178,10 @@ export class MistralSpeechModel implements SpeechModelV4 {
174
178
  }
175
179
  }
176
180
 
177
- const mistralSpeechResponseSchema = z.object({
178
- audio_data: z.string(),
179
- });
181
+ const mistralSpeechResponseSchema = lazySchema(() =>
182
+ zodSchema(
183
+ z.object({
184
+ audio_data: z.string(),
185
+ }),
186
+ ),
187
+ );
@@ -8,6 +8,12 @@ import { z } from 'zod/v4';
8
8
  export type MistralTranscriptionModelId =
9
9
  | 'voxtral-mini-2602'
10
10
  | 'voxtral-mini-latest'
11
+ | 'voxtral-mini-transcribe-3-0'
12
+ | 'voxtral-mini-transcribe-3'
13
+ | 'voxtral-mini-transcribe-latest'
14
+ | 'voxtral-small-transcribe-3-0'
15
+ | 'voxtral-small-transcribe-3'
16
+ | 'voxtral-small-transcribe-latest'
11
17
  | (string & {});
12
18
 
13
19
  // https://docs.mistral.ai/api/endpoint/audio/transcriptions
@@ -20,6 +26,11 @@ export const mistralTranscriptionModelOptions = lazySchema(() =>
20
26
  */
21
27
  language: z.string().min(1).optional(),
22
28
 
29
+ /**
30
+ * Return the detected language. Cannot be combined with `language`.
31
+ */
32
+ returnLanguage: z.boolean().optional(),
33
+
23
34
  /**
24
35
  * The sampling temperature.
25
36
  */
@@ -27,6 +38,7 @@ export const mistralTranscriptionModelOptions = lazySchema(() =>
27
38
 
28
39
  /**
29
40
  * The timestamp granularities to include in the transcription response.
41
+ * Voxtral 3 supports segment timestamps only.
30
42
  */
31
43
  timestampGranularities: z
32
44
  .array(z.enum(['segment', 'word']))
@@ -35,6 +47,7 @@ export const mistralTranscriptionModelOptions = lazySchema(() =>
35
47
 
36
48
  /**
37
49
  * Whether to identify speakers in the transcription.
50
+ * Voxtral 3 requires segment timestamps when diarization is enabled.
38
51
  */
39
52
  diarize: z.boolean().optional(),
40
53
 
@@ -42,21 +55,11 @@ export const mistralTranscriptionModelOptions = lazySchema(() =>
42
55
  * Words or phrases to guide the model toward correct spellings of names,
43
56
  * technical terms, or domain-specific vocabulary.
44
57
  *
45
- * Mistral requires each item to omit commas and whitespace. Use
46
- * underscores to represent multi-word phrases.
58
+ * Voxtral 3 also accepts phrases and descriptions of the recording,
59
+ * including spaces and punctuation. Entries share the context window
60
+ * with the audio.
47
61
  */
48
- contextBias: z
49
- .array(
50
- z
51
- .string()
52
- .min(1)
53
- .regex(
54
- /^[^\s,]+$/,
55
- 'Context bias items must not contain commas or whitespace.',
56
- ),
57
- )
58
- .max(100)
59
- .optional(),
62
+ contextBias: z.array(z.string().min(1)).optional(),
60
63
  }),
61
64
  ),
62
65
  );
@@ -5,6 +5,8 @@ import {
5
5
  type TranscriptionModelV4,
6
6
  } from '@ai-sdk/provider';
7
7
  import {
8
+ lazySchema,
9
+ zodSchema,
8
10
  combineHeaders,
9
11
  convertBase64ToUint8Array,
10
12
  createJsonResponseHandler,
@@ -71,9 +73,14 @@ export class MistralTranscriptionModel implements TranscriptionModelV4 {
71
73
  schema: mistralTranscriptionModelOptions,
72
74
  });
73
75
 
74
- // Mistral documents these options as mutually incompatible. Rejecting the
75
- // combination locally provides a stable SDK error instead of an API 4xx.
76
+ // Restrict only known legacy models so future and custom models can combine
77
+ // a pinned language with timestamps without an SDK update.
76
78
  if (
79
+ [
80
+ 'voxtral-mini-2507',
81
+ 'voxtral-mini-2602',
82
+ 'voxtral-mini-latest',
83
+ ].includes(this.modelId) &&
77
84
  mistralOptions?.language != null &&
78
85
  mistralOptions.timestampGranularities != null
79
86
  ) {
@@ -84,6 +91,14 @@ export class MistralTranscriptionModel implements TranscriptionModelV4 {
84
91
  });
85
92
  }
86
93
 
94
+ if (mistralOptions?.language != null && mistralOptions.returnLanguage) {
95
+ throw new InvalidArgumentError({
96
+ argument: 'providerOptions',
97
+ message:
98
+ 'providerOptions.mistral.language cannot be combined with providerOptions.mistral.returnLanguage',
99
+ });
100
+ }
101
+
87
102
  const formData = new FormData();
88
103
  const blob =
89
104
  audio instanceof Uint8Array
@@ -99,6 +114,11 @@ export class MistralTranscriptionModel implements TranscriptionModelV4 {
99
114
 
100
115
  if (mistralOptions != null) {
101
116
  appendFormValue(formData, 'language', mistralOptions.language);
117
+ appendFormValue(
118
+ formData,
119
+ 'return_language',
120
+ mistralOptions.returnLanguage,
121
+ );
102
122
  appendFormValue(formData, 'temperature', mistralOptions.temperature);
103
123
  appendFormValue(
104
124
  formData,
@@ -229,29 +249,33 @@ function appendFormValue(
229
249
  formData.append(key, String(value));
230
250
  }
231
251
 
232
- const mistralTranscriptionResponseSchema = z.object({
233
- model: z.string(),
234
- text: z.string(),
235
- language: z.string().nullish(),
236
- segments: z
237
- .array(
238
- z.object({
239
- type: z.literal('transcription_segment').nullish(),
240
- text: z.string(),
241
- start: z.number(),
242
- end: z.number(),
243
- score: z.number().nullish(),
244
- speaker_id: z.string().nullish(),
245
- }),
246
- )
247
- .nullish(),
248
- usage: z
249
- .object({
250
- prompt_tokens: z.number().nullish(),
251
- completion_tokens: z.number().nullish(),
252
- total_tokens: z.number().nullish(),
253
- prompt_audio_seconds: z.number().nullish(),
254
- request_count: z.number().nullish(),
255
- })
256
- .nullish(),
257
- });
252
+ const mistralTranscriptionResponseSchema = lazySchema(() =>
253
+ zodSchema(
254
+ z.object({
255
+ model: z.string(),
256
+ text: z.string(),
257
+ language: z.string().nullish(),
258
+ segments: z
259
+ .array(
260
+ z.object({
261
+ type: z.literal('transcription_segment').nullish(),
262
+ text: z.string(),
263
+ start: z.number(),
264
+ end: z.number(),
265
+ score: z.number().nullish(),
266
+ speaker_id: z.string().nullish(),
267
+ }),
268
+ )
269
+ .nullish(),
270
+ usage: z
271
+ .object({
272
+ prompt_tokens: z.number().nullish(),
273
+ completion_tokens: z.number().nullish(),
274
+ total_tokens: z.number().nullish(),
275
+ prompt_audio_seconds: z.number().nullish(),
276
+ request_count: z.number().nullish(),
277
+ })
278
+ .nullish(),
279
+ }),
280
+ ),
281
+ );