@core-ai/mistral 0.3.0 → 0.5.0

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.
Files changed (2) hide show
  1. package/dist/index.js +126 -18
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -31,11 +31,15 @@ function convertMessage(message) {
31
31
  };
32
32
  }
33
33
  if (message.role === "assistant") {
34
+ const text = message.parts.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
35
+ const toolCalls = message.parts.flatMap(
36
+ (part) => part.type === "tool-call" ? [part.toolCall] : []
37
+ );
34
38
  return {
35
39
  role: "assistant",
36
- content: message.content,
37
- ...message.toolCalls && message.toolCalls.length > 0 ? {
38
- toolCalls: message.toolCalls.map((toolCall) => ({
40
+ content: text.length > 0 ? text : null,
41
+ ...toolCalls.length > 0 ? {
42
+ toolCalls: toolCalls.map((toolCall) => ({
39
43
  id: toolCall.id,
40
44
  type: "function",
41
45
  function: {
@@ -117,6 +121,7 @@ function createStructuredOutputOptions(options) {
117
121
  type: "tool",
118
122
  toolName
119
123
  },
124
+ reasoning: options.reasoning,
120
125
  config: options.config,
121
126
  providerOptions: options.providerOptions,
122
127
  signal: options.signal
@@ -164,16 +169,25 @@ function mapGenerateResponse(response) {
164
169
  const firstChoice = response.choices[0];
165
170
  if (!firstChoice) {
166
171
  return {
172
+ parts: [],
167
173
  content: null,
174
+ reasoning: null,
168
175
  toolCalls: [],
169
176
  finishReason: "unknown",
170
177
  usage: mapUsage(response.usage)
171
178
  };
172
179
  }
173
- const toolCalls = parseToolCalls(firstChoice.message.toolCalls);
180
+ const parts = extractAssistantParts(firstChoice.message);
181
+ const toolCalls = parts.flatMap(
182
+ (part) => part.type === "tool-call" ? [part.toolCall] : []
183
+ );
184
+ const content = parts.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
185
+ const reasoning = parts.flatMap((part) => part.type === "reasoning" ? [part.text] : []).join("");
174
186
  const mappedFinishReason = mapFinishReason(firstChoice.finishReason);
175
187
  return {
176
- content: extractTextContent(firstChoice.message.content),
188
+ parts,
189
+ content: content.length > 0 ? content : null,
190
+ reasoning: reasoning.length > 0 ? reasoning : null,
177
191
  toolCalls,
178
192
  finishReason: toolCalls.length > 0 && mappedFinishReason !== "content-filter" ? "tool-calls" : mappedFinishReason,
179
193
  usage: mapUsage(response.usage)
@@ -183,11 +197,15 @@ async function* transformStream(stream) {
183
197
  const bufferedToolCalls = /* @__PURE__ */ new Map();
184
198
  const emittedToolCalls = /* @__PURE__ */ new Set();
185
199
  let finishReason = "unknown";
200
+ let reasoningOpen = false;
186
201
  let usage = {
187
202
  inputTokens: 0,
188
203
  outputTokens: 0,
189
- reasoningTokens: 0,
190
- totalTokens: 0
204
+ inputTokenDetails: {
205
+ cacheReadTokens: 0,
206
+ cacheWriteTokens: 0
207
+ },
208
+ outputTokenDetails: {}
191
209
  };
192
210
  for await (const event of stream) {
193
211
  const chunk = event.data;
@@ -198,13 +216,40 @@ async function* transformStream(stream) {
198
216
  if (!choice) {
199
217
  continue;
200
218
  }
219
+ const thinkingDeltas = extractThinkingDeltas(choice.delta.content);
220
+ if (thinkingDeltas.length > 0) {
221
+ if (!reasoningOpen) {
222
+ reasoningOpen = true;
223
+ yield {
224
+ type: "reasoning-start"
225
+ };
226
+ }
227
+ for (const thinkingDelta of thinkingDeltas) {
228
+ yield {
229
+ type: "reasoning-delta",
230
+ text: thinkingDelta
231
+ };
232
+ }
233
+ }
201
234
  for (const textDelta of extractTextDeltas(choice.delta.content)) {
235
+ if (reasoningOpen) {
236
+ reasoningOpen = false;
237
+ yield {
238
+ type: "reasoning-end"
239
+ };
240
+ }
202
241
  yield {
203
- type: "content-delta",
242
+ type: "text-delta",
204
243
  text: textDelta
205
244
  };
206
245
  }
207
246
  if (choice.delta.toolCalls) {
247
+ if (reasoningOpen) {
248
+ reasoningOpen = false;
249
+ yield {
250
+ type: "reasoning-end"
251
+ };
252
+ }
208
253
  for (const [
209
254
  position,
210
255
  partialToolCall
@@ -258,6 +303,11 @@ async function* transformStream(stream) {
258
303
  yield* emitBufferedToolCalls(bufferedToolCalls, emittedToolCalls);
259
304
  }
260
305
  }
306
+ if (reasoningOpen) {
307
+ yield {
308
+ type: "reasoning-end"
309
+ };
310
+ }
261
311
  yield* emitBufferedToolCalls(bufferedToolCalls, emittedToolCalls);
262
312
  yield {
263
313
  type: "finish",
@@ -307,19 +357,47 @@ function mapUsage(usage) {
307
357
  return {
308
358
  inputTokens: usage?.promptTokens ?? 0,
309
359
  outputTokens: usage?.completionTokens ?? 0,
310
- reasoningTokens: 0,
311
- totalTokens: usage?.totalTokens ?? 0
360
+ inputTokenDetails: {
361
+ cacheReadTokens: 0,
362
+ cacheWriteTokens: 0
363
+ },
364
+ outputTokenDetails: {}
312
365
  };
313
366
  }
314
- function extractTextContent(content) {
315
- if (typeof content === "string") {
316
- return content;
367
+ function extractAssistantParts(message) {
368
+ const parts = [];
369
+ if (typeof message.content === "string") {
370
+ if (message.content.length > 0) {
371
+ parts.push({
372
+ type: "text",
373
+ text: message.content
374
+ });
375
+ }
376
+ } else if (Array.isArray(message.content)) {
377
+ for (const chunk of message.content) {
378
+ if (chunk.type === "text") {
379
+ parts.push({
380
+ type: "text",
381
+ text: chunk.text
382
+ });
383
+ continue;
384
+ }
385
+ if (chunk.type === "thinking") {
386
+ const thinkingText = extractThinkingText(chunk.thinking);
387
+ parts.push({
388
+ type: "reasoning",
389
+ text: thinkingText
390
+ });
391
+ }
392
+ }
317
393
  }
318
- if (!content || content.length === 0) {
319
- return null;
394
+ for (const toolCall of parseToolCalls(message.toolCalls)) {
395
+ parts.push({
396
+ type: "tool-call",
397
+ toolCall
398
+ });
320
399
  }
321
- const text = content.flatMap((chunk) => chunk.type === "text" ? [chunk.text] : []).join("");
322
- return text.length > 0 ? text : null;
400
+ return parts;
323
401
  }
324
402
  function extractTextDeltas(content) {
325
403
  if (typeof content === "string") {
@@ -332,6 +410,36 @@ function extractTextDeltas(content) {
332
410
  (chunk) => chunk.type === "text" ? [chunk.text] : []
333
411
  );
334
412
  }
413
+ function extractThinkingDeltas(content) {
414
+ if (!content || typeof content === "string") {
415
+ return [];
416
+ }
417
+ return content.flatMap((chunk) => {
418
+ if (chunk.type !== "thinking") {
419
+ return [];
420
+ }
421
+ const thinkingText = extractThinkingText(chunk.thinking);
422
+ if (thinkingText.length === 0) {
423
+ return [];
424
+ }
425
+ return [thinkingText];
426
+ });
427
+ }
428
+ function extractThinkingText(value) {
429
+ if (typeof value === "string") {
430
+ return value;
431
+ }
432
+ if (!Array.isArray(value)) {
433
+ return "";
434
+ }
435
+ return value.flatMap((part) => {
436
+ if (!part || typeof part !== "object") {
437
+ return [];
438
+ }
439
+ const text = part.text;
440
+ return typeof text === "string" ? [text] : [];
441
+ }).join("");
442
+ }
335
443
  function serializeJsonObject(value) {
336
444
  const objectValue = asObject(value);
337
445
  return Object.keys(objectValue).length > 0 ? JSON.stringify(objectValue) : "";
@@ -462,7 +570,7 @@ async function* transformStructuredOutputStream(stream, schema, provider, toolNa
462
570
  let contentBuffer = "";
463
571
  const toolArgumentDeltas = /* @__PURE__ */ new Map();
464
572
  for await (const event of stream) {
465
- if (event.type === "content-delta") {
573
+ if (event.type === "text-delta") {
466
574
  contentBuffer += event.text;
467
575
  yield {
468
576
  type: "object-delta",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/mistral",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Mistral provider package for @core-ai/core-ai",
5
5
  "license": "MIT",
6
6
  "author": "Omnifact (https://omnifact.ai)",
@@ -42,7 +42,7 @@
42
42
  "test:watch": "vitest"
43
43
  },
44
44
  "dependencies": {
45
- "@core-ai/core-ai": "^0.3.0",
45
+ "@core-ai/core-ai": "^0.5.0",
46
46
  "@mistralai/mistralai": "^1.14.0",
47
47
  "zod-to-json-schema": "^3.25.1"
48
48
  },