@ai-sdk/moonshotai 2.0.49 → 2.0.53
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.
- package/CHANGELOG.md +39 -0
- package/README.md +44 -11
- package/dist/index.d.mts +61 -24
- package/dist/index.d.ts +61 -24
- package/dist/index.js +720 -276
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +724 -278
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/convert-to-moonshotai-chat-messages.ts +203 -12
- package/src/index.ts +3 -0
- package/src/moonshotai-chat-api-types.ts +58 -7
- package/src/moonshotai-chat-language-model.ts +243 -47
- package/src/moonshotai-chat-options.ts +184 -22
- package/src/moonshotai-prepare-tools.ts +24 -20
- package/src/moonshotai-provider.ts +10 -2
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
InvalidArgumentError,
|
|
3
|
+
InvalidPromptError,
|
|
2
4
|
UnsupportedFunctionalityError,
|
|
3
5
|
type LanguageModelV3Prompt,
|
|
6
|
+
type SharedV3Warning,
|
|
4
7
|
} from '@ai-sdk/provider';
|
|
5
8
|
import {
|
|
6
9
|
convertBase64ToUint8Array,
|
|
@@ -8,18 +11,165 @@ import {
|
|
|
8
11
|
} from '@ai-sdk/provider-utils';
|
|
9
12
|
|
|
10
13
|
import type { MoonshotAIMessages } from './moonshotai-chat-api-types';
|
|
14
|
+
import {
|
|
15
|
+
getMoonshotAIModelFamily,
|
|
16
|
+
moonshotaiAllMessageProviderOptions,
|
|
17
|
+
type MoonshotAIChatModelId,
|
|
18
|
+
} from './moonshotai-chat-options';
|
|
19
|
+
import { prepareTools } from './moonshotai-prepare-tools';
|
|
20
|
+
|
|
21
|
+
function parseMoonshotAIMessageProviderOptions({
|
|
22
|
+
providerOptions,
|
|
23
|
+
providerOptionsName,
|
|
24
|
+
}: {
|
|
25
|
+
providerOptions: Record<string, unknown> | undefined;
|
|
26
|
+
providerOptionsName: string;
|
|
27
|
+
}) {
|
|
28
|
+
const value = providerOptions?.[providerOptionsName];
|
|
29
|
+
if (value == null) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const result = moonshotaiAllMessageProviderOptions.safeParse(value);
|
|
34
|
+
if (!result.success) {
|
|
35
|
+
throw new InvalidArgumentError({
|
|
36
|
+
argument: 'providerOptions',
|
|
37
|
+
message: `invalid ${providerOptionsName} provider options`,
|
|
38
|
+
cause: result.error,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return result.data;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const supportedImageMediaTypes = [
|
|
46
|
+
'image/jpeg',
|
|
47
|
+
'image/png',
|
|
48
|
+
'image/gif',
|
|
49
|
+
'image/webp',
|
|
50
|
+
'image/bmp',
|
|
51
|
+
'image/heic',
|
|
52
|
+
'image/heif',
|
|
53
|
+
] as const;
|
|
54
|
+
|
|
55
|
+
const supportedVideoMediaTypes = [
|
|
56
|
+
'video/mp4',
|
|
57
|
+
'video/mpeg',
|
|
58
|
+
'video/mov',
|
|
59
|
+
'video/avi',
|
|
60
|
+
'video/x-flv',
|
|
61
|
+
'video/mpg',
|
|
62
|
+
'video/webm',
|
|
63
|
+
'video/wmv',
|
|
64
|
+
'video/3gpp',
|
|
65
|
+
] as const;
|
|
66
|
+
|
|
67
|
+
function validateMediaType({
|
|
68
|
+
mediaType,
|
|
69
|
+
supportedMediaTypes,
|
|
70
|
+
topLevelMediaType,
|
|
71
|
+
}: {
|
|
72
|
+
mediaType: string;
|
|
73
|
+
supportedMediaTypes: readonly string[];
|
|
74
|
+
topLevelMediaType: 'image' | 'video';
|
|
75
|
+
}): string {
|
|
76
|
+
const normalizedMediaType =
|
|
77
|
+
mediaType === `${topLevelMediaType}/*`
|
|
78
|
+
? topLevelMediaType === 'image'
|
|
79
|
+
? 'image/jpeg'
|
|
80
|
+
: 'video/mp4'
|
|
81
|
+
: mediaType;
|
|
82
|
+
|
|
83
|
+
if (!supportedMediaTypes.includes(normalizedMediaType)) {
|
|
84
|
+
throw new UnsupportedFunctionalityError({
|
|
85
|
+
functionality: `file part media type ${normalizedMediaType}`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return normalizedMediaType;
|
|
90
|
+
}
|
|
11
91
|
|
|
12
92
|
// Moonshot AI chat completions accepts text, image_url, and video_url content
|
|
13
93
|
// parts only. Anything else (audio, PDF, other file types) throws here rather
|
|
14
94
|
// than being rejected by the API with a 400.
|
|
15
|
-
export function convertToMoonshotAIChatMessages(
|
|
16
|
-
|
|
17
|
-
|
|
95
|
+
export function convertToMoonshotAIChatMessages({
|
|
96
|
+
modelId,
|
|
97
|
+
prompt,
|
|
98
|
+
providerOptionsName = 'moonshotai',
|
|
99
|
+
responseFormat,
|
|
100
|
+
}: {
|
|
101
|
+
modelId?: MoonshotAIChatModelId;
|
|
102
|
+
prompt: LanguageModelV3Prompt;
|
|
103
|
+
providerOptionsName?: string;
|
|
104
|
+
responseFormat?: Record<string, unknown>;
|
|
105
|
+
}): {
|
|
106
|
+
messages: MoonshotAIMessages;
|
|
107
|
+
warnings: Array<SharedV3Warning>;
|
|
108
|
+
} {
|
|
18
109
|
const messages: MoonshotAIMessages = [];
|
|
19
|
-
|
|
110
|
+
const warnings: Array<SharedV3Warning> = [];
|
|
111
|
+
const modelFamily =
|
|
112
|
+
modelId == null ? 'unknown' : getMoonshotAIModelFamily(modelId);
|
|
113
|
+
|
|
114
|
+
for (const [index, { role, content, providerOptions }] of prompt.entries()) {
|
|
115
|
+
const moonshotMessageOptions = parseMoonshotAIMessageProviderOptions({
|
|
116
|
+
providerOptions,
|
|
117
|
+
providerOptionsName,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (moonshotMessageOptions?.partial === true && role !== 'assistant') {
|
|
121
|
+
throw new InvalidPromptError({
|
|
122
|
+
prompt,
|
|
123
|
+
message:
|
|
124
|
+
'Moonshot AI Partial Mode requires `partial: true` on an assistant message.',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (moonshotMessageOptions?.tools != null && role !== 'system') {
|
|
129
|
+
throw new InvalidPromptError({
|
|
130
|
+
prompt,
|
|
131
|
+
message:
|
|
132
|
+
'Moonshot dynamic tools must be configured on a system message.',
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
20
136
|
switch (role) {
|
|
21
137
|
case 'system': {
|
|
22
|
-
|
|
138
|
+
if (moonshotMessageOptions?.tools?.length) {
|
|
139
|
+
if (content.length > 0) {
|
|
140
|
+
throw new InvalidPromptError({
|
|
141
|
+
prompt,
|
|
142
|
+
message:
|
|
143
|
+
'A Moonshot dynamic-tool system message must use empty content because the API forbids content alongside tools.',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (modelFamily !== 'kimi-k3' && modelFamily !== 'unknown') {
|
|
148
|
+
warnings.push({
|
|
149
|
+
type: 'unsupported',
|
|
150
|
+
feature: `dynamic tool loading for model "${modelId}"`,
|
|
151
|
+
details:
|
|
152
|
+
'Moonshot documents dynamic tool loading only for Kimi K3. The dynamic system message has been omitted.',
|
|
153
|
+
});
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const { tools, toolWarnings } = prepareTools({
|
|
158
|
+
modelId: modelId ?? 'custom-model',
|
|
159
|
+
tools: moonshotMessageOptions.tools,
|
|
160
|
+
});
|
|
161
|
+
warnings.push(...toolWarnings);
|
|
162
|
+
messages.push({ role: 'system', tools: tools ?? [] });
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
messages.push({
|
|
167
|
+
role: 'system',
|
|
168
|
+
content,
|
|
169
|
+
...(moonshotMessageOptions?.name != null && {
|
|
170
|
+
name: moonshotMessageOptions.name,
|
|
171
|
+
}),
|
|
172
|
+
});
|
|
23
173
|
break;
|
|
24
174
|
}
|
|
25
175
|
|
|
@@ -28,6 +178,9 @@ export function convertToMoonshotAIChatMessages(
|
|
|
28
178
|
messages.push({
|
|
29
179
|
role: 'user',
|
|
30
180
|
content: content[0].text,
|
|
181
|
+
...(moonshotMessageOptions?.name != null && {
|
|
182
|
+
name: moonshotMessageOptions.name,
|
|
183
|
+
}),
|
|
31
184
|
});
|
|
32
185
|
break;
|
|
33
186
|
}
|
|
@@ -41,10 +194,11 @@ export function convertToMoonshotAIChatMessages(
|
|
|
41
194
|
}
|
|
42
195
|
case 'file': {
|
|
43
196
|
if (part.mediaType.startsWith('image/')) {
|
|
44
|
-
const mediaType =
|
|
45
|
-
part.mediaType
|
|
46
|
-
|
|
47
|
-
|
|
197
|
+
const mediaType = validateMediaType({
|
|
198
|
+
mediaType: part.mediaType,
|
|
199
|
+
supportedMediaTypes: supportedImageMediaTypes,
|
|
200
|
+
topLevelMediaType: 'image',
|
|
201
|
+
});
|
|
48
202
|
|
|
49
203
|
return {
|
|
50
204
|
type: 'image_url' as const,
|
|
@@ -58,8 +212,11 @@ export function convertToMoonshotAIChatMessages(
|
|
|
58
212
|
}
|
|
59
213
|
|
|
60
214
|
if (part.mediaType.startsWith('video/')) {
|
|
61
|
-
const mediaType =
|
|
62
|
-
|
|
215
|
+
const mediaType = validateMediaType({
|
|
216
|
+
mediaType: part.mediaType,
|
|
217
|
+
supportedMediaTypes: supportedVideoMediaTypes,
|
|
218
|
+
topLevelMediaType: 'video',
|
|
219
|
+
});
|
|
63
220
|
|
|
64
221
|
return {
|
|
65
222
|
type: 'video_url' as const,
|
|
@@ -94,12 +251,33 @@ export function convertToMoonshotAIChatMessages(
|
|
|
94
251
|
}
|
|
95
252
|
}
|
|
96
253
|
}),
|
|
254
|
+
...(moonshotMessageOptions?.name != null && {
|
|
255
|
+
name: moonshotMessageOptions.name,
|
|
256
|
+
}),
|
|
97
257
|
});
|
|
98
258
|
|
|
99
259
|
break;
|
|
100
260
|
}
|
|
101
261
|
|
|
102
262
|
case 'assistant': {
|
|
263
|
+
if (moonshotMessageOptions?.partial === true) {
|
|
264
|
+
if (index !== prompt.length - 1) {
|
|
265
|
+
throw new InvalidPromptError({
|
|
266
|
+
prompt,
|
|
267
|
+
message:
|
|
268
|
+
'Moonshot AI Partial Mode requires the partial assistant message to be the final message.',
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (responseFormat?.type === 'json_object') {
|
|
273
|
+
throw new InvalidPromptError({
|
|
274
|
+
prompt,
|
|
275
|
+
message:
|
|
276
|
+
'Moonshot AI Partial Mode cannot be combined with JSON object response format.',
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
103
281
|
let text = '';
|
|
104
282
|
let reasoning = '';
|
|
105
283
|
const toolCalls: Array<{
|
|
@@ -135,6 +313,12 @@ export function convertToMoonshotAIChatMessages(
|
|
|
135
313
|
messages.push({
|
|
136
314
|
role: 'assistant',
|
|
137
315
|
content: toolCalls.length > 0 ? text || null : text,
|
|
316
|
+
...(moonshotMessageOptions?.name != null && {
|
|
317
|
+
name: moonshotMessageOptions.name,
|
|
318
|
+
}),
|
|
319
|
+
...(moonshotMessageOptions?.partial === true && {
|
|
320
|
+
partial: true,
|
|
321
|
+
}),
|
|
138
322
|
...(reasoning.length > 0 ? { reasoning_content: reasoning } : {}),
|
|
139
323
|
tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
140
324
|
});
|
|
@@ -143,6 +327,13 @@ export function convertToMoonshotAIChatMessages(
|
|
|
143
327
|
}
|
|
144
328
|
|
|
145
329
|
case 'tool': {
|
|
330
|
+
if (moonshotMessageOptions?.name != null) {
|
|
331
|
+
warnings.push({
|
|
332
|
+
type: 'unsupported',
|
|
333
|
+
feature: 'message name on tool messages',
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
146
337
|
for (const toolResponse of content) {
|
|
147
338
|
if (toolResponse.type === 'tool-approval-response') {
|
|
148
339
|
continue;
|
|
@@ -182,5 +373,5 @@ export function convertToMoonshotAIChatMessages(
|
|
|
182
373
|
}
|
|
183
374
|
}
|
|
184
375
|
|
|
185
|
-
return messages;
|
|
376
|
+
return { messages, warnings };
|
|
186
377
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,8 +4,11 @@ export type {
|
|
|
4
4
|
MoonshotAIProviderSettings,
|
|
5
5
|
} from './moonshotai-provider';
|
|
6
6
|
export type {
|
|
7
|
+
MoonshotAIAssistantMessageProviderOptions,
|
|
7
8
|
MoonshotAIChatModelId,
|
|
8
9
|
MoonshotAILanguageModelOptions,
|
|
10
|
+
MoonshotAIMessageProviderOptions,
|
|
11
|
+
MoonshotAISystemMessageProviderOptions,
|
|
9
12
|
/** @deprecated Use `MoonshotAILanguageModelOptions` instead. */
|
|
10
13
|
MoonshotAILanguageModelOptions as MoonshotAIProviderOptions,
|
|
11
14
|
} from './moonshotai-chat-options';
|
|
@@ -9,14 +9,31 @@ export type MoonshotAIMessage =
|
|
|
9
9
|
| MoonshotAIAssistantMessage
|
|
10
10
|
| MoonshotAIToolMessage;
|
|
11
11
|
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
.
|
|
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
|
-
.
|
|
94
|
+
.looseObject({
|
|
75
95
|
cached_tokens: z.number().nullish(),
|
|
76
96
|
})
|
|
77
97
|
.nullish(),
|
|
78
98
|
completion_tokens_details: z
|
|
79
|
-
.
|
|
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(),
|
|
@@ -139,8 +187,9 @@ export const moonshotAIChatChunkSchema = lazySchema(() =>
|
|
|
139
187
|
tool_calls: z
|
|
140
188
|
.array(
|
|
141
189
|
z.object({
|
|
142
|
-
index: z.number(),
|
|
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,7 +199,9 @@ export const moonshotAIChatChunkSchema = lazySchema(() =>
|
|
|
150
199
|
.nullish(),
|
|
151
200
|
})
|
|
152
201
|
.nullish(),
|
|
202
|
+
logprobs: moonshotAIChatLogprobsSchema,
|
|
153
203
|
finish_reason: z.string().nullish(),
|
|
204
|
+
usage: tokenUsageSchema,
|
|
154
205
|
}),
|
|
155
206
|
),
|
|
156
207
|
usage: tokenUsageSchema,
|