@ai-sdk/mistral 4.0.58 → 4.0.60

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.
@@ -321,6 +321,109 @@ const result = await generateText({
321
321
  the standard structured-output APIs.
322
322
  </Note>
323
323
 
324
+ ### Conversations API
325
+
326
+ Use `mistral.conversation(modelId)` to create a model that calls Mistral's
327
+ Conversations API (`/v1/conversations`). It supports `generateText` and
328
+ `streamText`, including Mistral's built-in web search tools.
329
+
330
+ #### Web Search
331
+
332
+ The provider offers two tools:
333
+
334
+ - `mistral.tools.webSearch()`: searches the web.
335
+ - `mistral.tools.webSearchPremium()`: searches the web and accesses news articles
336
+ through Mistral's integrated news providers.
337
+
338
+ Mistral executes these tools on the server. No `execute` function is needed.
339
+ Search calls and results are available in `result.toolCalls` and
340
+ `result.toolResults`, and URL citations are available in `result.sources`.
341
+
342
+ ```ts
343
+ import { mistral } from '@ai-sdk/mistral';
344
+ import { generateText } from 'ai';
345
+
346
+ const result = await generateText({
347
+ model: mistral.conversation('mistral-medium-latest'),
348
+ tools: {
349
+ web_search: mistral.tools.webSearch(),
350
+ },
351
+ prompt:
352
+ "Use web search to find Mistral AI's official website. Cite your source.",
353
+ });
354
+
355
+ console.log(result.text);
356
+ console.log(result.sources);
357
+ ```
358
+
359
+ Replace `mistral.tools.webSearch()` with `mistral.tools.webSearchPremium()` to use
360
+ premium search.
361
+
362
+ <Note>
363
+ Web search requires `mistral.conversation()`. The default `mistral()` factory
364
+ and `mistral.chat()` use the Chat Completions API, which does not support
365
+ these tools. See [Mistral's web search
366
+ documentation](https://docs.mistral.ai/studio/agents/agent-tools/websearch).
367
+ </Note>
368
+
369
+ You can also stream the answer and access citations after the stream completes:
370
+
371
+ ```ts
372
+ import { mistral } from '@ai-sdk/mistral';
373
+ import { streamText } from 'ai';
374
+
375
+ const result = streamText({
376
+ model: mistral.conversation('mistral-medium-latest'),
377
+ tools: {
378
+ web_search: mistral.tools.webSearch(),
379
+ },
380
+ prompt:
381
+ "Use web search to find Mistral AI's official website. Cite your source.",
382
+ });
383
+
384
+ for await (const text of result.textStream) {
385
+ process.stdout.write(text);
386
+ }
387
+
388
+ console.log(await result.sources);
389
+ ```
390
+
391
+ #### Multi-Turn Conversations
392
+
393
+ Pass the previous user messages and `responseMessages` into the next call.
394
+ Keep the complete response history, including search calls and results, so
395
+ follow-up questions can use the retrieved information. The model does not
396
+ retain conversation history between calls.
397
+
398
+ ```ts
399
+ import { mistral } from '@ai-sdk/mistral';
400
+ import { generateText, type ModelMessage } from 'ai';
401
+
402
+ const model = mistral.conversation('mistral-medium-latest');
403
+ const tools = { web_search: mistral.tools.webSearch() };
404
+ const messages: ModelMessage[] = [
405
+ {
406
+ role: 'user',
407
+ content: "Use web search to find Mistral AI's official website.",
408
+ },
409
+ ];
410
+
411
+ const first = await generateText({ model, tools, messages });
412
+ messages.push(...first.responseMessages);
413
+ messages.push({
414
+ role: 'user',
415
+ content:
416
+ 'Where is that company headquartered? Use web search and cite your source.',
417
+ });
418
+
419
+ const second = await generateText({ model, tools, messages });
420
+ console.log(second.text);
421
+ console.log(second.sources);
422
+ ```
423
+
424
+ For `streamText`, consume the stream before appending
425
+ `await result.responseMessages` to your message history.
426
+
324
427
  ### Model Capabilities
325
428
 
326
429
  | Model | Image Input | Tool Usage |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/mistral",
3
- "version": "4.0.58",
3
+ "version": "4.0.60",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -29,8 +29,8 @@
29
29
  }
30
30
  },
31
31
  "dependencies": {
32
- "@ai-sdk/provider": "4.0.23",
33
- "@ai-sdk/provider-utils": "5.0.55"
32
+ "@ai-sdk/provider": "4.0.24",
33
+ "@ai-sdk/provider-utils": "5.0.56"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@ai-sdk/test-server": "2.0.4",
@@ -0,0 +1,165 @@
1
+ import {
2
+ UnsupportedFunctionalityError,
3
+ type JSONValue,
4
+ type LanguageModelV4Prompt,
5
+ type LanguageModelV4ToolResultPart,
6
+ } from '@ai-sdk/provider';
7
+ import type { ToolNameMapping } from '@ai-sdk/provider-utils';
8
+ import { convertToMistralChatMessages } from './convert-to-mistral-chat-messages';
9
+ import type {
10
+ MistralAssistantMessageContent,
11
+ MistralToolMessage,
12
+ MistralUserMessageContent,
13
+ } from './mistral-chat-prompt';
14
+
15
+ type ConversationInput =
16
+ | {
17
+ type: 'message.input';
18
+ role: 'user' | 'assistant';
19
+ content: Array<
20
+ MistralUserMessageContent | MistralAssistantMessageContent
21
+ >;
22
+ }
23
+ | {
24
+ type: 'function.call';
25
+ tool_call_id: string;
26
+ name: string;
27
+ arguments: string;
28
+ }
29
+ | { type: 'function.result'; tool_call_id: string; result: string };
30
+
31
+ export function convertToMistralConversationInputs(
32
+ prompt: LanguageModelV4Prompt,
33
+ toolNameMapping: ToolNameMapping,
34
+ ) {
35
+ const inputs: ConversationInput[] = [];
36
+ const instructions: string[] = [];
37
+ const executions = new Set<string>();
38
+ const appendToolResult = (part: LanguageModelV4ToolResultPart) => {
39
+ if (executions.has(part.toolCallId)) {
40
+ let result: JSONValue = null;
41
+ if (part.output.type === 'json') {
42
+ const value = part.output.value;
43
+ const info =
44
+ value != null && typeof value === 'object' && 'info' in value
45
+ ? value.info
46
+ : undefined;
47
+ if (info != null && typeof info === 'object' && !Array.isArray(info)) {
48
+ result = 'result' in info ? (info.result ?? info) : info;
49
+ }
50
+ }
51
+ inputs.push({
52
+ type: 'function.result',
53
+ tool_call_id: part.toolCallId,
54
+ result: typeof result === 'string' ? result : JSON.stringify(result),
55
+ });
56
+ return;
57
+ }
58
+ const converted = convertToMistralChatMessages([
59
+ { role: 'tool', content: [part] },
60
+ ])[0] as MistralToolMessage;
61
+ inputs.push({
62
+ type: 'function.result',
63
+ tool_call_id: part.toolCallId,
64
+ result: converted.content,
65
+ });
66
+ };
67
+
68
+ for (const message of prompt) {
69
+ switch (message.role) {
70
+ case 'system':
71
+ instructions.push(message.content);
72
+ break;
73
+ case 'user': {
74
+ const converted = convertToMistralChatMessages([message])[0];
75
+ if (converted.role === 'user') {
76
+ inputs.push({
77
+ type: 'message.input',
78
+ role: 'user',
79
+ content: converted.content,
80
+ });
81
+ }
82
+ break;
83
+ }
84
+ case 'assistant': {
85
+ let content: MistralAssistantMessageContent[] = [];
86
+ const flush = () => {
87
+ if (content.length > 0) {
88
+ inputs.push({ type: 'message.input', role: 'assistant', content });
89
+ content = [];
90
+ }
91
+ };
92
+ for (const part of message.content) {
93
+ switch (part.type) {
94
+ case 'text':
95
+ content.push({ type: 'text', text: part.text });
96
+ break;
97
+ case 'reasoning':
98
+ content.push({
99
+ type: 'thinking',
100
+ thinking: [{ type: 'text', text: part.text }],
101
+ closed: true,
102
+ });
103
+ break;
104
+ case 'tool-call': {
105
+ flush();
106
+ if (part.providerExecuted) {
107
+ const name =
108
+ part.providerOptions?.mistral?.function ??
109
+ part.providerOptions?.mistral?.name;
110
+ const args = part.input as { arguments?: unknown } | null;
111
+ // Replay built-in executions as calls and results. Entry IDs
112
+ // and tool.execution output entries cannot be sent as inputs.
113
+ inputs.push({
114
+ type: 'function.call',
115
+ tool_call_id: part.toolCallId,
116
+ name:
117
+ typeof name === 'string'
118
+ ? name
119
+ : toolNameMapping.toProviderToolName(part.toolName),
120
+ arguments:
121
+ typeof args?.arguments === 'string'
122
+ ? args.arguments
123
+ : JSON.stringify(part.input),
124
+ });
125
+ executions.add(part.toolCallId);
126
+ } else {
127
+ inputs.push({
128
+ type: 'function.call',
129
+ tool_call_id: part.toolCallId,
130
+ name: part.toolName,
131
+ arguments: JSON.stringify(part.input),
132
+ });
133
+ }
134
+ break;
135
+ }
136
+ case 'tool-result':
137
+ flush();
138
+ appendToolResult(part);
139
+ break;
140
+ default:
141
+ throw new UnsupportedFunctionalityError({
142
+ functionality: `assistant content type: ${part.type}`,
143
+ });
144
+ }
145
+ }
146
+ flush();
147
+ break;
148
+ }
149
+ case 'tool':
150
+ for (const part of message.content) {
151
+ if (part.type === 'tool-approval-response') {
152
+ continue;
153
+ }
154
+ appendToolResult(part);
155
+ }
156
+ break;
157
+ }
158
+ }
159
+
160
+ return {
161
+ inputs,
162
+ instructions:
163
+ instructions.length > 0 ? instructions.join('\n\n') : undefined,
164
+ };
165
+ }
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export type {
8
8
  /** @deprecated Use `MistralLanguageModelChatOptions` instead. */
9
9
  MistralLanguageModelChatOptions as MistralLanguageModelOptions,
10
10
  } from './mistral-chat-language-model-options';
11
+ export type { MistralLanguageModelConversationOptions } from './mistral-conversation-language-model-options';
11
12
  export type { MistralEmbeddingModelOptions } from './mistral-embedding-model-options';
12
13
  export type {
13
14
  MistralSpeechModelId,
@@ -17,6 +17,8 @@ export type MistralChatModelId =
17
17
  | 'ministral-8b-latest'
18
18
  | 'mistral-code-fim-latest'
19
19
  | 'mistral-code-latest'
20
+ | 'mistral-large-4'
21
+ | 'mistral-large-4-0'
20
22
  | 'mistral-large-latest'
21
23
  | 'mistral-large-2512'
22
24
  | 'mistral-medium'
@@ -50,13 +50,15 @@ type MistralChatConfig = {
50
50
  generateId?: () => string;
51
51
  };
52
52
 
53
- // https://api.mistral.ai/v1/models (2026-09-10)
53
+ // https://api.mistral.ai/v1/models (2026-10-06)
54
54
  const reasoningEffortModelIds = new Set<MistralChatModelId>([
55
55
  'glm-5-2',
56
56
  'labs-leanstral-1-5',
57
57
  'labs-leanstral-1-5-1',
58
58
  'magistral-medium-latest',
59
59
  'magistral-small-latest',
60
+ 'mistral-large-4',
61
+ 'mistral-large-4-0',
60
62
  'mistral-medium',
61
63
  'mistral-medium-2604',
62
64
  'mistral-medium-3',
@@ -0,0 +1,13 @@
1
+ import {
2
+ mistralLanguageModelChatOptions,
3
+ type MistralChatModelId,
4
+ type MistralLanguageModelChatOptions,
5
+ } from './mistral-chat-language-model-options';
6
+
7
+ export type MistralConversationModelId = MistralChatModelId;
8
+
9
+ export const mistralLanguageModelConversationOptions =
10
+ mistralLanguageModelChatOptions;
11
+
12
+ export type MistralLanguageModelConversationOptions =
13
+ MistralLanguageModelChatOptions;