@ai-sdk/moonshotai 2.0.51 → 2.0.54

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.
@@ -9,14 +9,31 @@ export type MoonshotAIMessage =
9
9
  | MoonshotAIAssistantMessage
10
10
  | MoonshotAIToolMessage;
11
11
 
12
- export interface MoonshotAISystemMessage {
13
- role: 'system';
14
- content: string;
12
+ export type MoonshotAISystemMessage =
13
+ | {
14
+ role: 'system';
15
+ content: string;
16
+ name?: string;
17
+ }
18
+ | {
19
+ role: 'system';
20
+ tools: Array<MoonshotAIFunctionTool>;
21
+ };
22
+
23
+ export interface MoonshotAIFunctionTool {
24
+ type: 'function';
25
+ function: {
26
+ name: string;
27
+ description: string | undefined;
28
+ parameters: unknown;
29
+ strict?: boolean;
30
+ };
15
31
  }
16
32
 
17
33
  export interface MoonshotAIUserMessage {
18
34
  role: 'user';
19
35
  content: string | Array<MoonshotAIContentPart>;
36
+ name?: string;
20
37
  }
21
38
 
22
39
  export type MoonshotAIContentPart =
@@ -42,6 +59,8 @@ export interface MoonshotAIContentPartVideo {
42
59
  export interface MoonshotAIAssistantMessage {
43
60
  role: 'assistant';
44
61
  content?: string | null;
62
+ name?: string;
63
+ partial?: true;
45
64
  reasoning_content?: string;
46
65
  tool_calls?: Array<MoonshotAIMessageToolCall>;
47
66
  }
@@ -64,19 +83,20 @@ export interface MoonshotAIToolMessage {
64
83
  // Schemas below are limited versions focused on what the implementation
65
84
  // needs. This limits breakages when the API changes and increases efficiency.
66
85
 
86
+ // Loose, nested objects included: the parsed value is returned as `usage.raw`.
67
87
  const tokenUsageSchema = z
68
- .object({
88
+ .looseObject({
69
89
  prompt_tokens: z.number().nullish(),
70
90
  completion_tokens: z.number().nullish(),
71
91
  cached_tokens: z.number().nullish(),
72
92
  total_tokens: z.number().nullish(),
73
93
  prompt_tokens_details: z
74
- .object({
94
+ .looseObject({
75
95
  cached_tokens: z.number().nullish(),
76
96
  })
77
97
  .nullish(),
78
98
  completion_tokens_details: z
79
- .object({
99
+ .looseObject({
80
100
  reasoning_tokens: z.number().nullish(),
81
101
  })
82
102
  .nullish(),
@@ -89,17 +109,41 @@ export const moonshotAIErrorSchema = z.object({
89
109
  error: z.object({
90
110
  message: z.string(),
91
111
  type: z.string().nullish(),
112
+ code: z.string().nullish(),
92
113
  }),
93
114
  });
94
115
 
95
116
  export type MoonshotAIErrorData = z.infer<typeof moonshotAIErrorSchema>;
96
117
 
118
+ const moonshotAIChatLogprobSchema = z.object({
119
+ token: z.string(),
120
+ logprob: z.number(),
121
+ bytes: z.array(z.number()).nullable(),
122
+ top_logprobs: z.array(
123
+ z.object({
124
+ token: z.string(),
125
+ logprob: z.number(),
126
+ bytes: z.array(z.number()).nullable(),
127
+ }),
128
+ ),
129
+ });
130
+
131
+ const moonshotAIChatLogprobsSchema = z
132
+ .object({
133
+ content: z.array(moonshotAIChatLogprobSchema).nullish(),
134
+ })
135
+ .nullish();
136
+
137
+ export type MoonshotAIChatLogprob = z.infer<typeof moonshotAIChatLogprobSchema>;
138
+
97
139
  export const moonshotAIChatResponseSchema = z.object({
98
140
  id: z.string().nullish(),
99
141
  created: z.number().nullish(),
100
142
  model: z.string().nullish(),
143
+ object: z.literal('chat.completion').nullish(),
101
144
  choices: z.array(
102
145
  z.object({
146
+ index: z.number().nullish(),
103
147
  message: z.object({
104
148
  role: z.literal('assistant').nullish(),
105
149
  content: z.string().nullish(),
@@ -108,6 +152,7 @@ export const moonshotAIChatResponseSchema = z.object({
108
152
  .array(
109
153
  z.object({
110
154
  id: z.string().nullish(),
155
+ type: z.literal('function').nullish(),
111
156
  function: z.object({
112
157
  name: z.string(),
113
158
  arguments: z.string(),
@@ -116,6 +161,7 @@ export const moonshotAIChatResponseSchema = z.object({
116
161
  )
117
162
  .nullish(),
118
163
  }),
164
+ logprobs: moonshotAIChatLogprobsSchema,
119
165
  finish_reason: z.string().nullish(),
120
166
  }),
121
167
  ),
@@ -129,8 +175,10 @@ export const moonshotAIChatChunkSchema = lazySchema(() =>
129
175
  id: z.string().nullish(),
130
176
  created: z.number().nullish(),
131
177
  model: z.string().nullish(),
178
+ object: z.literal('chat.completion.chunk').nullish(),
132
179
  choices: z.array(
133
180
  z.object({
181
+ index: z.number().nullish(),
134
182
  delta: z
135
183
  .object({
136
184
  role: z.literal('assistant').nullish(),
@@ -141,6 +189,7 @@ export const moonshotAIChatChunkSchema = lazySchema(() =>
141
189
  z.object({
142
190
  index: z.number().nullish(),
143
191
  id: z.string().nullish(),
192
+ type: z.literal('function').nullish(),
144
193
  function: z.object({
145
194
  name: z.string().nullish(),
146
195
  arguments: z.string().nullish(),
@@ -150,6 +199,7 @@ export const moonshotAIChatChunkSchema = lazySchema(() =>
150
199
  .nullish(),
151
200
  })
152
201
  .nullish(),
202
+ logprobs: moonshotAIChatLogprobsSchema,
153
203
  finish_reason: z.string().nullish(),
154
204
  usage: tokenUsageSchema,
155
205
  }),
@@ -31,6 +31,7 @@ import {
31
31
  moonshotAIChatChunkSchema,
32
32
  moonshotAIChatResponseSchema,
33
33
  moonshotAIErrorSchema,
34
+ type MoonshotAIChatLogprob,
34
35
  type MoonshotAIChatTokenUsage,
35
36
  } from './moonshotai-chat-api-types';
36
37
  import {
@@ -107,8 +108,6 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
107
108
  schema: moonshotaiLanguageModelOptions,
108
109
  })) ?? {};
109
110
 
110
- const messages = convertToMoonshotAIChatMessages(prompt);
111
-
112
111
  const allWarnings: SharedV3Warning[] = [];
113
112
  if (topK != null) {
114
113
  allWarnings.push({ type: 'unsupported', feature: 'topK' });
@@ -289,9 +288,23 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
289
288
  }
290
289
  }
291
290
 
291
+ const { messages, warnings: messageWarnings } =
292
+ convertToMoonshotAIChatMessages({
293
+ modelId: this.modelId,
294
+ prompt,
295
+ providerOptionsName: this.providerOptionsName,
296
+ responseFormat: response_format,
297
+ });
298
+ allWarnings.push(...messageWarnings);
299
+
292
300
  return {
293
301
  args: {
294
302
  model: this.modelId,
303
+ ...((moonshotOptions.logprobs === true ||
304
+ moonshotOptions.topLogprobs != null) && { logprobs: true }),
305
+ ...(moonshotOptions.topLogprobs != null && {
306
+ top_logprobs: moonshotOptions.topLogprobs,
307
+ }),
295
308
  max_completion_tokens: maxOutputTokens,
296
309
  temperature: supportsSamplingOptions ? temperature : undefined,
297
310
  top_p: supportsSamplingOptions ? topP : undefined,
@@ -304,6 +317,9 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
304
317
  messages,
305
318
  tools: moonshotTools,
306
319
  tool_choice: moonshotToolChoice,
320
+ ...(moonshotOptions.prediction != null && {
321
+ prediction: moonshotOptions.prediction,
322
+ }),
307
323
  ...(thinking != null ? { thinking } : {}),
308
324
  ...(reasoningEffort != null && {
309
325
  reasoning_effort: reasoningEffort,
@@ -377,6 +393,23 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
377
393
  raw: choice.finish_reason ?? undefined,
378
394
  },
379
395
  usage: convertMoonshotAIChatUsage(responseBody.usage),
396
+ providerMetadata: {
397
+ [this.providerOptionsName]: {
398
+ ...(responseBody.object != null && {
399
+ responseObject: responseBody.object,
400
+ }),
401
+ ...(choice.index != null && { choiceIndex: choice.index }),
402
+ ...(choice.message.role != null && {
403
+ messageRole: choice.message.role,
404
+ }),
405
+ ...(choice.message.tool_calls != null && {
406
+ toolCallTypes: choice.message.tool_calls
407
+ .map(toolCall => toolCall.type)
408
+ .filter(type => type != null),
409
+ }),
410
+ ...(choice.logprobs != null && { logprobs: choice.logprobs }),
411
+ },
412
+ },
380
413
  request: { body: args },
381
414
  response: {
382
415
  ...getResponseMetadata(responseBody),
@@ -428,9 +461,15 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
428
461
  };
429
462
  let topLevelUsage: MoonshotAIChatTokenUsage | undefined = undefined;
430
463
  let choiceUsage: MoonshotAIChatTokenUsage | undefined = undefined;
464
+ const contentLogprobs: MoonshotAIChatLogprob[] = [];
465
+ const providerOptionsName = this.providerOptionsName;
431
466
  let isFirstChunk = true;
432
467
  let isActiveReasoning = false;
433
468
  let isActiveText = false;
469
+ let responseObject: 'chat.completion.chunk' | undefined;
470
+ let choiceIndex: number | undefined;
471
+ let messageRole: 'assistant' | undefined;
472
+ const toolCallTypes = new Map<number, 'function'>();
434
473
 
435
474
  return {
436
475
  stream: response.pipeThrough(
@@ -459,7 +498,7 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
459
498
  // handle error chunks:
460
499
  if ('error' in value) {
461
500
  finishReason = { unified: 'error', raw: undefined };
462
- controller.enqueue({ type: 'error', error: value.error.message });
501
+ controller.enqueue({ type: 'error', error: value.error });
463
502
  return;
464
503
  }
465
504
 
@@ -476,12 +515,20 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
476
515
  topLevelUsage = value.usage;
477
516
  }
478
517
 
518
+ if (value.object != null) {
519
+ responseObject = value.object;
520
+ }
521
+
479
522
  const choice = value.choices[0];
480
523
 
481
524
  if (choice?.usage != null) {
482
525
  choiceUsage = choice.usage;
483
526
  }
484
527
 
528
+ if (choice?.index != null) {
529
+ choiceIndex = choice.index;
530
+ }
531
+
485
532
  if (choice?.finish_reason != null) {
486
533
  finishReason = {
487
534
  unified: mapMoonshotAIFinishReason(choice.finish_reason),
@@ -489,12 +536,20 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
489
536
  };
490
537
  }
491
538
 
539
+ if (choice?.logprobs?.content != null) {
540
+ contentLogprobs.push(...choice.logprobs.content);
541
+ }
542
+
492
543
  if (choice?.delta == null) {
493
544
  return;
494
545
  }
495
546
 
496
547
  const delta = choice.delta;
497
548
 
549
+ if (delta.role != null) {
550
+ messageRole = delta.role;
551
+ }
552
+
498
553
  // enqueue reasoning before text deltas:
499
554
  const reasoningContent = delta.reasoning_content;
500
555
  if (reasoningContent) {
@@ -551,6 +606,10 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
551
606
  ] of delta.tool_calls.entries()) {
552
607
  const index = toolCallDelta.index ?? fallbackIndex;
553
608
 
609
+ if (toolCallDelta.type != null) {
610
+ toolCallTypes.set(index, toolCallDelta.type);
611
+ }
612
+
554
613
  if (toolCalls[index] == null) {
555
614
  if (toolCallDelta.id == null) {
556
615
  throw new InvalidResponseDataError({
@@ -652,6 +711,23 @@ export class MoonshotAIChatLanguageModel implements LanguageModelV3 {
652
711
  type: 'finish',
653
712
  finishReason,
654
713
  usage: convertMoonshotAIChatUsage(topLevelUsage ?? choiceUsage),
714
+ providerMetadata: {
715
+ [providerOptionsName]: {
716
+ ...(responseObject != null && { responseObject }),
717
+ ...(choiceIndex != null && { choiceIndex }),
718
+ ...(messageRole != null && { messageRole }),
719
+ ...(toolCallTypes.size > 0 && {
720
+ toolCallTypes: [...toolCallTypes.entries()]
721
+ .sort(([left], [right]) => left - right)
722
+ .map(([, type]) => type),
723
+ }),
724
+ ...(contentLogprobs.length > 0 && {
725
+ logprobs: {
726
+ content: contentLogprobs,
727
+ },
728
+ }),
729
+ },
730
+ },
655
731
  });
656
732
  },
657
733
  }),
@@ -1,19 +1,18 @@
1
+ import type { LanguageModelV3FunctionTool } from '@ai-sdk/provider';
1
2
  import { z } from 'zod/v4';
2
3
 
3
4
  export type MoonshotAIChatModelId =
5
+ | 'moonshot-v1-auto'
4
6
  | 'moonshot-v1-8k'
5
7
  | 'moonshot-v1-32k'
6
8
  | 'moonshot-v1-128k'
7
- | 'moonshot-v1-auto'
8
9
  | 'moonshot-v1-8k-vision-preview'
9
10
  | 'moonshot-v1-32k-vision-preview'
10
11
  | 'moonshot-v1-128k-vision-preview'
11
- | 'kimi-k2'
12
- | 'kimi-k2-0905'
13
- | 'kimi-k2-thinking'
14
- | 'kimi-k2-thinking-turbo'
15
- | 'kimi-k2-turbo'
16
12
  | 'kimi-k2.5'
13
+ | 'kimi-k2.6'
14
+ | 'kimi-k2.7-code'
15
+ | 'kimi-k2.7-code-highspeed'
17
16
  | 'kimi-k3'
18
17
  | (string & {});
19
18
 
@@ -51,19 +50,60 @@ export const moonshotaiLanguageModelOptions = z.object({
51
50
  strictJsonSchema: z.boolean().optional(),
52
51
 
53
52
  /**
54
- * Reasoning effort for Kimi K3.
53
+ * Whether to return log probabilities for generated tokens.
54
+ */
55
+ logprobs: z.boolean().optional(),
56
+
57
+ /**
58
+ * Number of most likely tokens to return at each token position.
59
+ *
60
+ * Setting this option automatically enables `logprobs`.
61
+ */
62
+ topLogprobs: z.number().int().min(0).max(20).optional(),
63
+
64
+ /**
65
+ * Reasoning effort for Kimi K3. Supports `low`, `high`, and `max`;
66
+ * defaults to `max`.
55
67
  */
56
68
  reasoningEffort: z.enum(['low', 'high', 'max']).optional(),
57
69
 
70
+ /**
71
+ * Static predicted content that can accelerate responses when much of the
72
+ * output is known ahead of time.
73
+ */
74
+ prediction: z
75
+ .object({
76
+ type: z.literal('content'),
77
+ content: z.union([
78
+ z.string(),
79
+ z.array(z.object({ type: z.literal('text'), text: z.string() })),
80
+ ]),
81
+ })
82
+ .optional(),
83
+
84
+ /**
85
+ * Thinking configuration for Kimi K2.x models. Kimi K2.5 and K2.6 support
86
+ * enabling or disabling thinking. Kimi K2.7 Code always has thinking
87
+ * enabled.
88
+ */
58
89
  thinking: z
59
90
  .object({
60
91
  type: z.enum(['enabled', 'disabled']).optional(),
61
- // Accepted so existing callers receive a migration warning. It remains
62
- // in the public compatibility type below as a deprecated property.
92
+ /**
93
+ * @deprecated Moonshot Chat Completions does not support thinking
94
+ * budgets. Accepted for backwards compatibility, then omitted with a
95
+ * warning.
96
+ */
63
97
  budgetTokens: z.number().int().min(1024).optional(),
64
98
  })
65
99
  .optional(),
66
100
 
101
+ /**
102
+ * Controls preserved reasoning behavior in multi-turn conversations.
103
+ * `disabled` and `interleaved` are compatibility values that leave the
104
+ * request unchanged. `preserved` maps to `thinking.keep: 'all'` for Kimi
105
+ * K2.6. Kimi K2.7 and K3 preserve reasoning by default.
106
+ */
67
107
  reasoningHistory: z.enum(['disabled', 'interleaved', 'preserved']).optional(),
68
108
 
69
109
  /**
@@ -87,9 +127,27 @@ export type MoonshotAILanguageModelOptions = {
87
127
  */
88
128
  strictJsonSchema?: boolean;
89
129
 
130
+ /** Whether to return log probabilities for generated tokens. */
131
+ logprobs?: boolean;
132
+
133
+ /**
134
+ * Number of most likely tokens to return at each token position.
135
+ * Setting this option automatically enables `logprobs`.
136
+ */
137
+ topLogprobs?: number;
138
+
90
139
  /** Reasoning effort for Kimi K3. */
91
140
  reasoningEffort?: 'low' | 'high' | 'max';
92
141
 
142
+ /**
143
+ * Static predicted content that can accelerate responses when much of the
144
+ * output is known ahead of time.
145
+ */
146
+ prediction?: {
147
+ type: 'content';
148
+ content: string | Array<{ type: 'text'; text: string }>;
149
+ };
150
+
93
151
  /** Controls thinking on Kimi K2.5 and K2.6. K2.7 is always enabled. */
94
152
  thinking?: {
95
153
  type?: 'enabled' | 'disabled';
@@ -101,7 +159,65 @@ export type MoonshotAILanguageModelOptions = {
101
159
  budgetTokens?: number;
102
160
  };
103
161
 
162
+ /**
163
+ * Controls preserved reasoning behavior in multi-turn conversations.
164
+ * `disabled` and `interleaved` are compatibility values that leave the
165
+ * request unchanged. `preserved` maps to `thinking.keep: 'all'` for Kimi
166
+ * K2.6. Kimi K2.7 and K3 preserve reasoning by default.
167
+ */
104
168
  reasoningHistory?: 'disabled' | 'interleaved' | 'preserved';
105
169
  promptCacheKey?: string;
106
170
  safetyIdentifier?: string;
107
171
  };
172
+
173
+ export const moonshotaiMessageProviderOptions = z.object({
174
+ /**
175
+ * The name of the participant represented by the message.
176
+ *
177
+ * Supported on system, user, and assistant messages.
178
+ */
179
+ name: z.string().optional(),
180
+ });
181
+
182
+ export type MoonshotAIMessageProviderOptions = z.infer<
183
+ typeof moonshotaiMessageProviderOptions
184
+ >;
185
+
186
+ export const moonshotaiAssistantMessageProviderOptions =
187
+ moonshotaiMessageProviderOptions.extend({
188
+ /**
189
+ * Whether the assistant message content is a partial response that Moonshot
190
+ * should continue. Only supported on the final assistant message and cannot
191
+ * be combined with JSON object response format.
192
+ */
193
+ partial: z.literal(true).optional(),
194
+ });
195
+
196
+ export type MoonshotAIAssistantMessageProviderOptions = z.infer<
197
+ typeof moonshotaiAssistantMessageProviderOptions
198
+ >;
199
+
200
+ const moonshotaiDynamicToolSchema = z.object({
201
+ type: z.literal('function'),
202
+ name: z.string(),
203
+ description: z.string().optional(),
204
+ inputSchema: z.record(z.string(), z.unknown()),
205
+ strict: z.boolean().optional(),
206
+ });
207
+
208
+ export const moonshotaiAllMessageProviderOptions =
209
+ moonshotaiAssistantMessageProviderOptions.extend({
210
+ /** Function tools to load at this point in a Kimi K3 conversation. */
211
+ tools: z.array(moonshotaiDynamicToolSchema).optional(),
212
+ });
213
+
214
+ export type MoonshotAISystemMessageProviderOptions =
215
+ MoonshotAIMessageProviderOptions & {
216
+ /** Function tools to load at this point in a Kimi K3 conversation. */
217
+ tools?: Array<
218
+ Pick<
219
+ LanguageModelV3FunctionTool,
220
+ 'type' | 'name' | 'description' | 'inputSchema' | 'strict'
221
+ >
222
+ >;
223
+ };
@@ -3,6 +3,7 @@ import {
3
3
  type LanguageModelV3CallOptions,
4
4
  type SharedV3Warning,
5
5
  } from '@ai-sdk/provider';
6
+ import type { MoonshotAIFunctionTool } from './moonshotai-chat-api-types';
6
7
  import type { MoonshotAIChatModelId } from './moonshotai-chat-options';
7
8
  import { normalizeJsonSchemaForMFJS } from './normalize-json-schema-for-mfjs';
8
9
 
@@ -15,17 +16,7 @@ export function prepareTools({
15
16
  toolChoice?: LanguageModelV3CallOptions['toolChoice'];
16
17
  modelId: MoonshotAIChatModelId;
17
18
  }): {
18
- tools:
19
- | undefined
20
- | Array<{
21
- type: 'function';
22
- function: {
23
- name: string;
24
- description: string | undefined;
25
- parameters: unknown;
26
- strict?: boolean;
27
- };
28
- }>;
19
+ tools: undefined | Array<MoonshotAIFunctionTool>;
29
20
  toolChoice:
30
21
  | { type: 'function'; function: { name: string } }
31
22
  | 'auto'
@@ -43,15 +34,7 @@ export function prepareTools({
43
34
  return { tools: undefined, toolChoice: undefined, toolWarnings };
44
35
  }
45
36
 
46
- const moonshotTools: Array<{
47
- type: 'function';
48
- function: {
49
- name: string;
50
- description: string | undefined;
51
- parameters: unknown;
52
- strict?: boolean;
53
- };
54
- }> = [];
37
+ const moonshotTools: Array<MoonshotAIFunctionTool> = [];
55
38
 
56
39
  for (const tool of tools) {
57
40
  if (tool.type === 'provider') {