@ai-sdk/deepseek 3.0.31 → 3.0.34
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 +41 -0
- package/README.md +1 -1
- package/dist/index.d.ts +57 -19
- package/dist/index.js +626 -124
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +54 -4
- package/dist/internal/index.js +520 -109
- package/dist/internal/index.js.map +1 -1
- package/docs/30-deepseek.mdx +306 -23
- package/package.json +6 -6
- package/src/chat/convert-to-deepseek-chat-messages.ts +166 -19
- package/src/chat/convert-to-deepseek-usage.ts +1 -1
- package/src/chat/deepseek-chat-api-types.ts +50 -5
- package/src/chat/deepseek-chat-language-model-options.ts +102 -11
- package/src/chat/deepseek-chat-language-model.ts +293 -20
- package/src/chat/deepseek-file-part-options.ts +24 -0
- package/src/chat/deepseek-prepare-tools.ts +29 -3
- package/src/deepseek-provider.ts +2 -0
- package/src/files/deepseek-files-api.ts +9 -5
- package/src/files/deepseek-files.ts +129 -4
- package/src/index.ts +3 -0
package/dist/index.js
CHANGED
|
@@ -14,10 +14,11 @@ import {
|
|
|
14
14
|
createEventSourceResponseHandler,
|
|
15
15
|
createJsonErrorResponseHandler,
|
|
16
16
|
createJsonResponseHandler,
|
|
17
|
+
createProviderStreamError,
|
|
17
18
|
generateId,
|
|
18
19
|
isCustomReasoning,
|
|
19
20
|
mapReasoningToProviderEffort,
|
|
20
|
-
parseProviderOptions,
|
|
21
|
+
parseProviderOptions as parseProviderOptions2,
|
|
21
22
|
postJsonToApi,
|
|
22
23
|
serializeModelOptions,
|
|
23
24
|
StreamingToolCallTracker,
|
|
@@ -26,16 +27,113 @@ import {
|
|
|
26
27
|
} from "@ai-sdk/provider-utils";
|
|
27
28
|
|
|
28
29
|
// src/chat/convert-to-deepseek-chat-messages.ts
|
|
30
|
+
import {
|
|
31
|
+
InvalidPromptError,
|
|
32
|
+
UnsupportedFunctionalityError
|
|
33
|
+
} from "@ai-sdk/provider";
|
|
29
34
|
import {
|
|
30
35
|
convertToBase64,
|
|
31
36
|
getTopLevelMediaType,
|
|
37
|
+
parseProviderOptions,
|
|
32
38
|
resolveFullMediaType,
|
|
33
39
|
resolveProviderReference
|
|
34
40
|
} from "@ai-sdk/provider-utils";
|
|
35
|
-
|
|
41
|
+
|
|
42
|
+
// src/chat/deepseek-file-part-options.ts
|
|
43
|
+
import { z } from "zod/v4";
|
|
44
|
+
var deepseekFilePartProviderOptions = z.object({
|
|
45
|
+
/**
|
|
46
|
+
* Controls how DeepSeek processes an image sent as an `image_url` part.
|
|
47
|
+
*
|
|
48
|
+
* @see https://api-docs.deepseek.com/api/create-chat-completion/
|
|
49
|
+
*/
|
|
50
|
+
imageDetail: z.enum(["low", "high", "original", "auto"]).optional(),
|
|
51
|
+
/**
|
|
52
|
+
* Sends inline image data as a DeepSeek `file` part using `file_data`
|
|
53
|
+
* instead of an `image_url` data URL. When set, the file part's filename
|
|
54
|
+
* is preserved.
|
|
55
|
+
*
|
|
56
|
+
* This option only applies to inline image data. It cannot be combined
|
|
57
|
+
* with `imageDetail`.
|
|
58
|
+
*/
|
|
59
|
+
fileData: z.literal(true).optional()
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// src/chat/deepseek-chat-language-model-options.ts
|
|
63
|
+
import { z as z2 } from "zod/v4";
|
|
64
|
+
var deepseekLanguageModelChatOptions = z2.object({
|
|
65
|
+
/**
|
|
66
|
+
* Whether to return log probabilities for generated tokens.
|
|
67
|
+
*/
|
|
68
|
+
logprobs: z2.boolean().optional(),
|
|
69
|
+
/**
|
|
70
|
+
* Number of most likely tokens to return at each token position.
|
|
71
|
+
*
|
|
72
|
+
* Setting this option automatically enables `logprobs`.
|
|
73
|
+
*/
|
|
74
|
+
topLogprobs: z2.number().int().min(0).max(20).optional(),
|
|
75
|
+
/**
|
|
76
|
+
* An opaque identifier for the end user. DeepSeek uses this identifier for
|
|
77
|
+
* content-safety tracing and request isolation.
|
|
78
|
+
*
|
|
79
|
+
* Must contain only ASCII letters, numbers, underscores, and hyphens, and
|
|
80
|
+
* must be at most 512 characters long.
|
|
81
|
+
*/
|
|
82
|
+
userId: z2.string().regex(/^[a-zA-Z0-9_-]+$/, "userId must match /^[a-zA-Z0-9_-]+$/").max(512, "userId must be at most 512 characters long").optional(),
|
|
83
|
+
/**
|
|
84
|
+
* Type of thinking to use. Defaults to `enabled`.
|
|
85
|
+
*/
|
|
86
|
+
thinking: z2.object({
|
|
87
|
+
// `adaptive` is accepted at runtime for backwards compatibility and
|
|
88
|
+
// mapped to `enabled`, but is intentionally excluded from the exported
|
|
89
|
+
// provider options type.
|
|
90
|
+
type: z2.enum(["adaptive", "enabled", "disabled"]).optional()
|
|
91
|
+
}).optional(),
|
|
92
|
+
/**
|
|
93
|
+
* Controls the thinking strength for DeepSeek V4 reasoning models.
|
|
94
|
+
*/
|
|
95
|
+
// `medium` and `xhigh` are accepted at runtime for backwards compatibility
|
|
96
|
+
// and mapped to canonical DeepSeek values, but are intentionally excluded
|
|
97
|
+
// from the exported provider options type.
|
|
98
|
+
reasoningEffort: z2.enum(["low", "medium", "high", "xhigh", "max"]).optional(),
|
|
99
|
+
/**
|
|
100
|
+
* Whether to use strict JSON schema validation for structured outputs.
|
|
101
|
+
* Only applies when the serving endpoint supports JSON schema response
|
|
102
|
+
* formats (e.g. Azure). Defaults to `true`.
|
|
103
|
+
*/
|
|
104
|
+
strictJsonSchema: z2.boolean().optional()
|
|
105
|
+
});
|
|
106
|
+
var deepseekMessageProviderOptions = z2.object({
|
|
107
|
+
/**
|
|
108
|
+
* The name of the participant represented by the message.
|
|
109
|
+
*
|
|
110
|
+
* Supported on system, user, and assistant messages.
|
|
111
|
+
*/
|
|
112
|
+
name: z2.string().optional()
|
|
113
|
+
});
|
|
114
|
+
var deepseekAssistantMessageProviderOptions = deepseekMessageProviderOptions.extend({
|
|
115
|
+
/**
|
|
116
|
+
* Whether the assistant message content is a prefix that DeepSeek should
|
|
117
|
+
* continue. This beta feature is only supported on the final assistant
|
|
118
|
+
* message when using a beta base URL.
|
|
119
|
+
*/
|
|
120
|
+
prefix: z2.literal(true).optional()
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// src/chat/convert-to-deepseek-chat-messages.ts
|
|
124
|
+
var supportedImageMediaTypes = /* @__PURE__ */ new Set([
|
|
125
|
+
"image/gif",
|
|
126
|
+
"image/jpeg",
|
|
127
|
+
"image/jpg",
|
|
128
|
+
"image/png",
|
|
129
|
+
"image/webp"
|
|
130
|
+
]);
|
|
131
|
+
async function convertToDeepSeekChatMessages({
|
|
36
132
|
prompt,
|
|
37
133
|
responseFormat,
|
|
38
134
|
modelId,
|
|
135
|
+
providerOptionsName = "deepseek",
|
|
136
|
+
supportsAssistantPrefixCompletion = false,
|
|
39
137
|
supportsStructuredOutputs = false
|
|
40
138
|
}) {
|
|
41
139
|
var _a;
|
|
@@ -68,11 +166,28 @@ function convertToDeepSeekChatMessages({
|
|
|
68
166
|
}
|
|
69
167
|
}
|
|
70
168
|
let index = -1;
|
|
71
|
-
for (const { role, content } of prompt) {
|
|
169
|
+
for (const { role, content, providerOptions } of prompt) {
|
|
72
170
|
index++;
|
|
171
|
+
const deepseekMessageOptions = await parseProviderOptions({
|
|
172
|
+
provider: providerOptionsName,
|
|
173
|
+
providerOptions,
|
|
174
|
+
schema: deepseekAssistantMessageProviderOptions
|
|
175
|
+
});
|
|
176
|
+
if ((deepseekMessageOptions == null ? void 0 : deepseekMessageOptions.prefix) === true && role !== "assistant") {
|
|
177
|
+
throw new InvalidPromptError({
|
|
178
|
+
prompt,
|
|
179
|
+
message: "DeepSeek assistant prefix completion requires `prefix: true` on an assistant message."
|
|
180
|
+
});
|
|
181
|
+
}
|
|
73
182
|
switch (role) {
|
|
74
183
|
case "system": {
|
|
75
|
-
messages.push({
|
|
184
|
+
messages.push({
|
|
185
|
+
role: "system",
|
|
186
|
+
content,
|
|
187
|
+
...(deepseekMessageOptions == null ? void 0 : deepseekMessageOptions.name) != null && {
|
|
188
|
+
name: deepseekMessageOptions.name
|
|
189
|
+
}
|
|
190
|
+
});
|
|
76
191
|
break;
|
|
77
192
|
}
|
|
78
193
|
case "user": {
|
|
@@ -91,7 +206,13 @@ function convertToDeepSeekChatMessages({
|
|
|
91
206
|
});
|
|
92
207
|
}
|
|
93
208
|
}
|
|
94
|
-
messages.push({
|
|
209
|
+
messages.push({
|
|
210
|
+
role: "user",
|
|
211
|
+
content: userContent2,
|
|
212
|
+
...(deepseekMessageOptions == null ? void 0 : deepseekMessageOptions.name) != null && {
|
|
213
|
+
name: deepseekMessageOptions.name
|
|
214
|
+
}
|
|
215
|
+
});
|
|
95
216
|
break;
|
|
96
217
|
}
|
|
97
218
|
const userContent = [];
|
|
@@ -99,6 +220,11 @@ function convertToDeepSeekChatMessages({
|
|
|
99
220
|
if (part.type === "text") {
|
|
100
221
|
userContent.push({ type: "text", text: part.text });
|
|
101
222
|
} else if (part.type === "file" && getTopLevelMediaType(part.mediaType) === "image") {
|
|
223
|
+
const filePartOptions = await parseProviderOptions({
|
|
224
|
+
provider: providerOptionsName,
|
|
225
|
+
providerOptions: part.providerOptions,
|
|
226
|
+
schema: deepseekFilePartProviderOptions
|
|
227
|
+
});
|
|
102
228
|
if (part.data.type === "reference") {
|
|
103
229
|
userContent.push({
|
|
104
230
|
type: "file",
|
|
@@ -108,12 +234,62 @@ function convertToDeepSeekChatMessages({
|
|
|
108
234
|
})
|
|
109
235
|
});
|
|
110
236
|
} else if (part.data.type === "url" || part.data.type === "data") {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
237
|
+
const resolvedMediaType = resolveFullMediaType({ part });
|
|
238
|
+
if (!supportedImageMediaTypes.has(resolvedMediaType)) {
|
|
239
|
+
throw new UnsupportedFunctionalityError({
|
|
240
|
+
functionality: `DeepSeek image media type ${resolvedMediaType}`,
|
|
241
|
+
message: "DeepSeek supports JPEG, PNG, GIF, and WebP image inputs."
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
if (part.data.type === "url") {
|
|
245
|
+
const url = part.data.url.toString();
|
|
246
|
+
if (url.length > 8192) {
|
|
247
|
+
throw new InvalidPromptError({
|
|
248
|
+
prompt,
|
|
249
|
+
message: "DeepSeek image URLs must not exceed 8192 characters."
|
|
250
|
+
});
|
|
115
251
|
}
|
|
116
|
-
|
|
252
|
+
if ((filePartOptions == null ? void 0 : filePartOptions.fileData) === true) {
|
|
253
|
+
throw new InvalidPromptError({
|
|
254
|
+
prompt,
|
|
255
|
+
message: "DeepSeek `fileData` image parts require inline data, not a URL."
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
userContent.push({
|
|
259
|
+
type: "image_url",
|
|
260
|
+
image_url: {
|
|
261
|
+
url,
|
|
262
|
+
...(filePartOptions == null ? void 0 : filePartOptions.imageDetail) != null && {
|
|
263
|
+
detail: filePartOptions.imageDetail
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
} else {
|
|
268
|
+
const dataUrl = `data:${resolvedMediaType === "image/jpg" ? "image/jpeg" : resolvedMediaType};base64,${convertToBase64(part.data.data)}`;
|
|
269
|
+
if ((filePartOptions == null ? void 0 : filePartOptions.fileData) === true) {
|
|
270
|
+
if (filePartOptions.imageDetail != null) {
|
|
271
|
+
throw new InvalidPromptError({
|
|
272
|
+
prompt,
|
|
273
|
+
message: "DeepSeek `imageDetail` cannot be combined with `fileData`."
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
userContent.push({
|
|
277
|
+
type: "file",
|
|
278
|
+
file_data: dataUrl,
|
|
279
|
+
...part.filename != null && { filename: part.filename }
|
|
280
|
+
});
|
|
281
|
+
} else {
|
|
282
|
+
userContent.push({
|
|
283
|
+
type: "image_url",
|
|
284
|
+
image_url: {
|
|
285
|
+
url: dataUrl,
|
|
286
|
+
...(filePartOptions == null ? void 0 : filePartOptions.imageDetail) != null && {
|
|
287
|
+
detail: filePartOptions.imageDetail
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
117
293
|
} else {
|
|
118
294
|
warnings.push({
|
|
119
295
|
type: "unsupported",
|
|
@@ -129,11 +305,28 @@ function convertToDeepSeekChatMessages({
|
|
|
129
305
|
}
|
|
130
306
|
messages.push({
|
|
131
307
|
role: "user",
|
|
132
|
-
content: userContent
|
|
308
|
+
content: userContent,
|
|
309
|
+
...(deepseekMessageOptions == null ? void 0 : deepseekMessageOptions.name) != null && {
|
|
310
|
+
name: deepseekMessageOptions.name
|
|
311
|
+
}
|
|
133
312
|
});
|
|
134
313
|
break;
|
|
135
314
|
}
|
|
136
315
|
case "assistant": {
|
|
316
|
+
if ((deepseekMessageOptions == null ? void 0 : deepseekMessageOptions.prefix) === true) {
|
|
317
|
+
if (index !== prompt.length - 1) {
|
|
318
|
+
throw new InvalidPromptError({
|
|
319
|
+
prompt,
|
|
320
|
+
message: "DeepSeek assistant prefix completion requires the prefixed assistant message to be the final message."
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
if (!supportsAssistantPrefixCompletion) {
|
|
324
|
+
throw new UnsupportedFunctionalityError({
|
|
325
|
+
functionality: "DeepSeek assistant prefix completion",
|
|
326
|
+
message: "DeepSeek assistant prefix completion requires a beta base URL ending in `/beta`."
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
137
330
|
let text = "";
|
|
138
331
|
let reasoning;
|
|
139
332
|
const toolCalls = [];
|
|
@@ -170,12 +363,24 @@ function convertToDeepSeekChatMessages({
|
|
|
170
363
|
messages.push({
|
|
171
364
|
role: "assistant",
|
|
172
365
|
content: text,
|
|
366
|
+
...(deepseekMessageOptions == null ? void 0 : deepseekMessageOptions.name) != null && {
|
|
367
|
+
name: deepseekMessageOptions.name
|
|
368
|
+
},
|
|
369
|
+
...(deepseekMessageOptions == null ? void 0 : deepseekMessageOptions.prefix) === true && {
|
|
370
|
+
prefix: true
|
|
371
|
+
},
|
|
173
372
|
reasoning_content: reasoning != null ? reasoning : isDeepSeekV4 ? "" : void 0,
|
|
174
373
|
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
175
374
|
});
|
|
176
375
|
break;
|
|
177
376
|
}
|
|
178
377
|
case "tool": {
|
|
378
|
+
if ((deepseekMessageOptions == null ? void 0 : deepseekMessageOptions.name) != null) {
|
|
379
|
+
warnings.push({
|
|
380
|
+
type: "unsupported",
|
|
381
|
+
feature: "message name on tool messages"
|
|
382
|
+
});
|
|
383
|
+
}
|
|
179
384
|
for (const toolResponse of content) {
|
|
180
385
|
if (toolResponse.type === "tool-approval-response") {
|
|
181
386
|
continue;
|
|
@@ -236,7 +441,7 @@ function convertDeepSeekUsage(usage) {
|
|
|
236
441
|
},
|
|
237
442
|
outputTokens: {
|
|
238
443
|
total: completionTokens,
|
|
239
|
-
text: completionTokens - reasoningTokens,
|
|
444
|
+
text: Math.max(0, completionTokens - reasoningTokens),
|
|
240
445
|
reasoning: reasoningTokens
|
|
241
446
|
},
|
|
242
447
|
raw: usage
|
|
@@ -245,75 +450,101 @@ function convertDeepSeekUsage(usage) {
|
|
|
245
450
|
|
|
246
451
|
// src/chat/deepseek-chat-api-types.ts
|
|
247
452
|
import { lazySchema, zodSchema } from "@ai-sdk/provider-utils";
|
|
248
|
-
import { z } from "zod/v4";
|
|
249
|
-
var tokenUsageSchema =
|
|
250
|
-
prompt_tokens:
|
|
251
|
-
completion_tokens:
|
|
252
|
-
prompt_cache_hit_tokens:
|
|
253
|
-
prompt_cache_miss_tokens:
|
|
254
|
-
total_tokens:
|
|
255
|
-
completion_tokens_details:
|
|
256
|
-
reasoning_tokens:
|
|
453
|
+
import { z as z3 } from "zod/v4";
|
|
454
|
+
var tokenUsageSchema = z3.object({
|
|
455
|
+
prompt_tokens: z3.number().nullish(),
|
|
456
|
+
completion_tokens: z3.number().nullish(),
|
|
457
|
+
prompt_cache_hit_tokens: z3.number().nullish(),
|
|
458
|
+
prompt_cache_miss_tokens: z3.number().nullish(),
|
|
459
|
+
total_tokens: z3.number().nullish(),
|
|
460
|
+
completion_tokens_details: z3.object({
|
|
461
|
+
reasoning_tokens: z3.number().nullish()
|
|
257
462
|
}).nullish()
|
|
258
463
|
}).nullish();
|
|
259
|
-
var deepSeekErrorSchema =
|
|
260
|
-
error:
|
|
261
|
-
message:
|
|
262
|
-
type:
|
|
263
|
-
param:
|
|
264
|
-
code:
|
|
464
|
+
var deepSeekErrorSchema = z3.object({
|
|
465
|
+
error: z3.object({
|
|
466
|
+
message: z3.string(),
|
|
467
|
+
type: z3.string().nullish(),
|
|
468
|
+
param: z3.any().nullish(),
|
|
469
|
+
code: z3.union([z3.string(), z3.number()]).nullish()
|
|
265
470
|
})
|
|
266
471
|
});
|
|
267
|
-
var
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
472
|
+
var deepseekChatLogprobSchema = z3.object({
|
|
473
|
+
token: z3.string(),
|
|
474
|
+
logprob: z3.number(),
|
|
475
|
+
bytes: z3.array(z3.number()).nullable(),
|
|
476
|
+
top_logprobs: z3.array(
|
|
477
|
+
z3.object({
|
|
478
|
+
token: z3.string(),
|
|
479
|
+
logprob: z3.number(),
|
|
480
|
+
bytes: z3.array(z3.number()).nullable()
|
|
481
|
+
})
|
|
482
|
+
)
|
|
483
|
+
});
|
|
484
|
+
var deepseekChatLogprobsSchema = z3.object({
|
|
485
|
+
content: z3.array(deepseekChatLogprobSchema).nullish(),
|
|
486
|
+
reasoning_content: z3.array(deepseekChatLogprobSchema).nullish()
|
|
487
|
+
}).nullish();
|
|
488
|
+
var deepseekChatResponseSchema = z3.object({
|
|
489
|
+
id: z3.string().nullish(),
|
|
490
|
+
created: z3.number().nullish(),
|
|
491
|
+
model: z3.string().nullish(),
|
|
492
|
+
object: z3.literal("chat.completion").nullish(),
|
|
493
|
+
system_fingerprint: z3.string().nullish(),
|
|
494
|
+
choices: z3.array(
|
|
495
|
+
z3.object({
|
|
496
|
+
index: z3.number().nullish(),
|
|
497
|
+
message: z3.object({
|
|
498
|
+
role: z3.literal("assistant").nullish(),
|
|
499
|
+
content: z3.string().nullish(),
|
|
500
|
+
reasoning_content: z3.string().nullish(),
|
|
501
|
+
tool_calls: z3.array(
|
|
502
|
+
z3.object({
|
|
503
|
+
id: z3.string().nullish(),
|
|
504
|
+
type: z3.literal("function").nullish(),
|
|
505
|
+
function: z3.object({
|
|
506
|
+
name: z3.string(),
|
|
507
|
+
arguments: z3.string()
|
|
283
508
|
})
|
|
284
509
|
})
|
|
285
510
|
).nullish()
|
|
286
511
|
}),
|
|
287
|
-
|
|
512
|
+
logprobs: deepseekChatLogprobsSchema,
|
|
513
|
+
finish_reason: z3.string().nullish()
|
|
288
514
|
})
|
|
289
515
|
),
|
|
290
516
|
usage: tokenUsageSchema
|
|
291
517
|
});
|
|
292
518
|
var deepseekChatChunkSchema = lazySchema(
|
|
293
519
|
() => zodSchema(
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
id:
|
|
297
|
-
created:
|
|
298
|
-
model:
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
520
|
+
z3.union([
|
|
521
|
+
z3.object({
|
|
522
|
+
id: z3.string().nullish(),
|
|
523
|
+
created: z3.number().nullish(),
|
|
524
|
+
model: z3.string().nullish(),
|
|
525
|
+
object: z3.literal("chat.completion.chunk").nullish(),
|
|
526
|
+
system_fingerprint: z3.string().nullish(),
|
|
527
|
+
choices: z3.array(
|
|
528
|
+
z3.object({
|
|
529
|
+
index: z3.number().nullish(),
|
|
530
|
+
delta: z3.object({
|
|
531
|
+
role: z3.enum(["assistant"]).nullish(),
|
|
532
|
+
content: z3.string().nullish(),
|
|
533
|
+
reasoning_content: z3.string().nullish(),
|
|
534
|
+
tool_calls: z3.array(
|
|
535
|
+
z3.object({
|
|
536
|
+
index: z3.number(),
|
|
537
|
+
id: z3.string().nullish(),
|
|
538
|
+
type: z3.literal("function").nullish(),
|
|
539
|
+
function: z3.object({
|
|
540
|
+
name: z3.string().nullish(),
|
|
541
|
+
arguments: z3.string().nullish()
|
|
312
542
|
})
|
|
313
543
|
})
|
|
314
544
|
).nullish()
|
|
315
545
|
}).nullish(),
|
|
316
|
-
|
|
546
|
+
logprobs: deepseekChatLogprobsSchema,
|
|
547
|
+
finish_reason: z3.string().nullish()
|
|
317
548
|
})
|
|
318
549
|
),
|
|
319
550
|
usage: tokenUsageSchema
|
|
@@ -323,44 +554,34 @@ var deepseekChatChunkSchema = lazySchema(
|
|
|
323
554
|
)
|
|
324
555
|
);
|
|
325
556
|
|
|
326
|
-
// src/chat/deepseek-chat-language-model-options.ts
|
|
327
|
-
import { z as z2 } from "zod/v4";
|
|
328
|
-
var deepseekLanguageModelChatOptions = z2.object({
|
|
329
|
-
/**
|
|
330
|
-
* Type of thinking to use. Defaults to `enabled`.
|
|
331
|
-
*
|
|
332
|
-
* See https://api-docs.deepseek.com/guides/thinking_mode for the
|
|
333
|
-
* `adaptive` option, which lets the model decide when to think.
|
|
334
|
-
*/
|
|
335
|
-
thinking: z2.object({
|
|
336
|
-
type: z2.enum(["adaptive", "enabled", "disabled"]).optional()
|
|
337
|
-
}).optional(),
|
|
338
|
-
/**
|
|
339
|
-
* Controls the thinking strength for DeepSeek V4 reasoning models.
|
|
340
|
-
*
|
|
341
|
-
* DeepSeek's API accepts `low`, `medium`, `high`, `xhigh`, and `max`.
|
|
342
|
-
* Per their docs, `low` and `medium` are mapped to `high`, and `xhigh`
|
|
343
|
-
* is mapped to `max` server-side for compatibility with other providers.
|
|
344
|
-
*/
|
|
345
|
-
reasoningEffort: z2.enum(["low", "medium", "high", "xhigh", "max"]).optional(),
|
|
346
|
-
/**
|
|
347
|
-
* Whether to use strict JSON schema validation for structured outputs.
|
|
348
|
-
* Only applies when the serving endpoint supports JSON schema response
|
|
349
|
-
* formats (e.g. Azure). Defaults to `true`.
|
|
350
|
-
*/
|
|
351
|
-
strictJsonSchema: z2.boolean().optional()
|
|
352
|
-
});
|
|
353
|
-
|
|
354
557
|
// src/chat/deepseek-prepare-tools.ts
|
|
558
|
+
import {
|
|
559
|
+
UnsupportedFunctionalityError as UnsupportedFunctionalityError2
|
|
560
|
+
} from "@ai-sdk/provider";
|
|
355
561
|
function prepareTools({
|
|
356
562
|
tools,
|
|
357
|
-
toolChoice
|
|
563
|
+
toolChoice,
|
|
564
|
+
supportsStrictToolCalls
|
|
358
565
|
}) {
|
|
359
566
|
tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
|
|
360
567
|
const toolWarnings = [];
|
|
361
568
|
if (tools == null) {
|
|
362
569
|
return { tools: void 0, toolChoice: void 0, toolWarnings };
|
|
363
570
|
}
|
|
571
|
+
const functionTools = tools.filter((tool) => tool.type === "function");
|
|
572
|
+
const hasStrictTool = functionTools.some((tool) => tool.strict === true);
|
|
573
|
+
if (hasStrictTool && supportsStrictToolCalls === false) {
|
|
574
|
+
throw new UnsupportedFunctionalityError2({
|
|
575
|
+
functionality: "DeepSeek strict tool calls",
|
|
576
|
+
message: "DeepSeek strict tool calls require a beta base URL ending in `/beta`."
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
if (hasStrictTool && supportsStrictToolCalls === true && functionTools.some((tool) => tool.strict !== true)) {
|
|
580
|
+
throw new UnsupportedFunctionalityError2({
|
|
581
|
+
functionality: "mixed DeepSeek strict and non-strict tool calls",
|
|
582
|
+
message: "DeepSeek strict mode requires every function tool in the request to set `strict: true`."
|
|
583
|
+
});
|
|
584
|
+
}
|
|
364
585
|
const deepseekTools = [];
|
|
365
586
|
for (const tool of tools) {
|
|
366
587
|
if (tool.type === "provider") {
|
|
@@ -436,6 +657,80 @@ function mapDeepSeekFinishReason(finishReason) {
|
|
|
436
657
|
}
|
|
437
658
|
|
|
438
659
|
// src/chat/deepseek-chat-language-model.ts
|
|
660
|
+
function createDeepSeekStreamError(error, data) {
|
|
661
|
+
var _a, _b;
|
|
662
|
+
const metadata = getDeepSeekStreamErrorMetadata(error);
|
|
663
|
+
return createProviderStreamError({
|
|
664
|
+
message: error.message,
|
|
665
|
+
type: (_a = error.type) != null ? _a : void 0,
|
|
666
|
+
code: (_b = error.code) != null ? _b : void 0,
|
|
667
|
+
...metadata,
|
|
668
|
+
data
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
function getDeepSeekStreamErrorMetadata(error) {
|
|
672
|
+
if (error.code === "insufficient_quota" || error.type === "insufficient_quota") {
|
|
673
|
+
return { statusCode: 429, isRetryable: false };
|
|
674
|
+
}
|
|
675
|
+
const explicitStatusCode = getHttpStatusCode(error.code);
|
|
676
|
+
if (explicitStatusCode != null) {
|
|
677
|
+
return {
|
|
678
|
+
statusCode: explicitStatusCode,
|
|
679
|
+
isRetryable: isRetryableStatusCode(explicitStatusCode)
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
for (const discriminator of [error.code, error.type]) {
|
|
683
|
+
switch (discriminator) {
|
|
684
|
+
case "rate_limit_exceeded":
|
|
685
|
+
case "rate_limit_error":
|
|
686
|
+
return { statusCode: 429, isRetryable: true };
|
|
687
|
+
case "server_error":
|
|
688
|
+
case "api_error":
|
|
689
|
+
case "internal_server_error":
|
|
690
|
+
return { statusCode: 500, isRetryable: true };
|
|
691
|
+
case "overloaded_error":
|
|
692
|
+
case "service_unavailable":
|
|
693
|
+
return { statusCode: 503, isRetryable: true };
|
|
694
|
+
case "timeout":
|
|
695
|
+
case "timeout_error":
|
|
696
|
+
return { statusCode: 504, isRetryable: true };
|
|
697
|
+
case "authentication_error":
|
|
698
|
+
case "invalid_api_key":
|
|
699
|
+
return { statusCode: 401, isRetryable: false };
|
|
700
|
+
case "permission_error":
|
|
701
|
+
return { statusCode: 403, isRetryable: false };
|
|
702
|
+
case "not_found_error":
|
|
703
|
+
case "model_not_found":
|
|
704
|
+
return { statusCode: 404, isRetryable: false };
|
|
705
|
+
case "bad_request":
|
|
706
|
+
case "context_length_exceeded":
|
|
707
|
+
case "invalid_request_error":
|
|
708
|
+
return { statusCode: 400, isRetryable: false };
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
return {};
|
|
712
|
+
}
|
|
713
|
+
function getHttpStatusCode(value) {
|
|
714
|
+
const statusCode = typeof value === "string" && /^\d{3}$/.test(value) ? Number(value) : value;
|
|
715
|
+
return typeof statusCode === "number" && Number.isInteger(statusCode) && statusCode >= 400 && statusCode <= 599 ? statusCode : void 0;
|
|
716
|
+
}
|
|
717
|
+
function isRetryableStatusCode(statusCode) {
|
|
718
|
+
return statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500;
|
|
719
|
+
}
|
|
720
|
+
function mapDeepSeekProviderReasoningEffort({
|
|
721
|
+
reasoningEffort,
|
|
722
|
+
warnings
|
|
723
|
+
}) {
|
|
724
|
+
const mapped = reasoningEffort === "medium" ? "high" : reasoningEffort === "xhigh" ? "max" : reasoningEffort;
|
|
725
|
+
if (mapped !== reasoningEffort) {
|
|
726
|
+
warnings.push({
|
|
727
|
+
type: "compatibility",
|
|
728
|
+
feature: "reasoningEffort",
|
|
729
|
+
details: `reasoningEffort "${reasoningEffort}" is not a canonical DeepSeek value. mapped to "${mapped}".`
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
return mapped;
|
|
733
|
+
}
|
|
439
734
|
var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
440
735
|
constructor(modelId, config) {
|
|
441
736
|
this.specificationVersion = "v4";
|
|
@@ -480,17 +775,20 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
480
775
|
toolChoice,
|
|
481
776
|
tools
|
|
482
777
|
}) {
|
|
483
|
-
var _a, _b, _c, _d
|
|
484
|
-
const deepseekOptions = (_a = await
|
|
778
|
+
var _a, _b, _c, _d;
|
|
779
|
+
const deepseekOptions = (_a = await parseProviderOptions2({
|
|
485
780
|
provider: this.providerOptionsName,
|
|
486
781
|
providerOptions,
|
|
487
782
|
schema: deepseekLanguageModelChatOptions
|
|
488
783
|
})) != null ? _a : {};
|
|
489
784
|
const supportsStructuredOutputs = this.config.supportsStructuredOutputs === true;
|
|
490
|
-
const
|
|
785
|
+
const supportsPenaltySampling = this.config.supportsPenaltySampling === true;
|
|
786
|
+
const { messages, warnings } = await convertToDeepSeekChatMessages({
|
|
491
787
|
prompt,
|
|
492
788
|
responseFormat,
|
|
493
789
|
modelId: this.modelId,
|
|
790
|
+
providerOptionsName: this.providerOptionsName,
|
|
791
|
+
supportsAssistantPrefixCompletion: this.config.supportsAssistantPrefixCompletion,
|
|
494
792
|
supportsStructuredOutputs
|
|
495
793
|
});
|
|
496
794
|
const allWarnings = [...warnings];
|
|
@@ -500,21 +798,62 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
500
798
|
if (seed != null) {
|
|
501
799
|
allWarnings.push({ type: "unsupported", feature: "seed" });
|
|
502
800
|
}
|
|
801
|
+
if (!supportsPenaltySampling && frequencyPenalty != null) {
|
|
802
|
+
allWarnings.push({
|
|
803
|
+
type: "deprecated",
|
|
804
|
+
setting: "frequencyPenalty",
|
|
805
|
+
message: "frequencyPenalty is deprecated by DeepSeek and has been omitted. Remove frequencyPenalty from the request."
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
if (!supportsPenaltySampling && presencePenalty != null) {
|
|
809
|
+
allWarnings.push({
|
|
810
|
+
type: "deprecated",
|
|
811
|
+
setting: "presencePenalty",
|
|
812
|
+
message: "presencePenalty is deprecated by DeepSeek and has been omitted. Remove presencePenalty from the request."
|
|
813
|
+
});
|
|
814
|
+
}
|
|
503
815
|
const {
|
|
504
816
|
tools: deepseekTools,
|
|
505
817
|
toolChoice: deepseekToolChoices,
|
|
506
818
|
toolWarnings
|
|
507
819
|
} = prepareTools({
|
|
508
820
|
tools,
|
|
509
|
-
toolChoice
|
|
821
|
+
toolChoice,
|
|
822
|
+
supportsStrictToolCalls: this.config.supportsStrictToolCalls
|
|
510
823
|
});
|
|
511
|
-
const
|
|
512
|
-
|
|
824
|
+
const thinkingType = (_b = deepseekOptions.thinking) == null ? void 0 : _b.type;
|
|
825
|
+
if (thinkingType === "adaptive") {
|
|
826
|
+
allWarnings.push({
|
|
827
|
+
type: "compatibility",
|
|
828
|
+
feature: "thinking.type",
|
|
829
|
+
details: 'thinking.type "adaptive" is not a canonical DeepSeek value. mapped to "enabled".'
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
const thinking = this.config.supportsThinking === false ? void 0 : thinkingType != null ? { type: thinkingType === "adaptive" ? "enabled" : thinkingType } : isCustomReasoning(reasoning) ? { type: reasoning === "none" ? "disabled" : "enabled" } : void 0;
|
|
833
|
+
const isThinkingEnabled = this.config.supportsThinking !== false && (thinking == null ? void 0 : thinking.type) !== "disabled" && (thinking != null || this.modelId === "deepseek-reasoner" || this.modelId.includes("deepseek-v4"));
|
|
834
|
+
if (isThinkingEnabled && temperature != null) {
|
|
835
|
+
allWarnings.push({
|
|
836
|
+
type: "unsupported",
|
|
837
|
+
feature: "temperature",
|
|
838
|
+
details: "temperature has no effect when DeepSeek thinking is enabled. Set providerOptions.deepseek.thinking.type to 'disabled' to use temperature."
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
if (isThinkingEnabled && topP != null) {
|
|
842
|
+
allWarnings.push({
|
|
843
|
+
type: "unsupported",
|
|
844
|
+
feature: "topP",
|
|
845
|
+
details: "topP has no effect when DeepSeek thinking is enabled. Set providerOptions.deepseek.thinking.type to 'disabled' to use topP."
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
const reasoningEffort = deepseekOptions.reasoningEffort != null ? mapDeepSeekProviderReasoningEffort({
|
|
849
|
+
reasoningEffort: deepseekOptions.reasoningEffort,
|
|
850
|
+
warnings: allWarnings
|
|
851
|
+
}) : isCustomReasoning(reasoning) && reasoning !== "none" ? mapReasoningToProviderEffort({
|
|
513
852
|
reasoning,
|
|
514
853
|
effortMap: {
|
|
515
854
|
minimal: "low",
|
|
516
855
|
low: "low",
|
|
517
|
-
medium: "
|
|
856
|
+
medium: "high",
|
|
518
857
|
high: "high",
|
|
519
858
|
xhigh: "max"
|
|
520
859
|
},
|
|
@@ -523,17 +862,21 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
523
862
|
return {
|
|
524
863
|
args: {
|
|
525
864
|
model: this.modelId,
|
|
865
|
+
...(deepseekOptions.logprobs === true || deepseekOptions.topLogprobs != null) && { logprobs: true },
|
|
866
|
+
...deepseekOptions.topLogprobs != null && {
|
|
867
|
+
top_logprobs: deepseekOptions.topLogprobs
|
|
868
|
+
},
|
|
526
869
|
max_tokens: maxOutputTokens,
|
|
527
|
-
temperature,
|
|
528
|
-
top_p: topP,
|
|
529
|
-
frequency_penalty: frequencyPenalty,
|
|
530
|
-
presence_penalty: presencePenalty,
|
|
870
|
+
temperature: isThinkingEnabled ? void 0 : temperature,
|
|
871
|
+
top_p: isThinkingEnabled ? void 0 : topP,
|
|
872
|
+
frequency_penalty: supportsPenaltySampling ? frequencyPenalty : void 0,
|
|
873
|
+
presence_penalty: supportsPenaltySampling ? presencePenalty : void 0,
|
|
531
874
|
response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? supportsStructuredOutputs && responseFormat.schema != null ? {
|
|
532
875
|
type: "json_schema",
|
|
533
876
|
json_schema: {
|
|
534
877
|
schema: responseFormat.schema,
|
|
535
|
-
strict: (
|
|
536
|
-
name: (
|
|
878
|
+
strict: (_c = deepseekOptions.strictJsonSchema) != null ? _c : true,
|
|
879
|
+
name: (_d = responseFormat.name) != null ? _d : "response",
|
|
537
880
|
description: responseFormat.description
|
|
538
881
|
}
|
|
539
882
|
} : { type: "json_object" } : void 0,
|
|
@@ -542,6 +885,9 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
542
885
|
tools: deepseekTools,
|
|
543
886
|
tool_choice: deepseekToolChoices,
|
|
544
887
|
thinking,
|
|
888
|
+
...deepseekOptions.userId != null && {
|
|
889
|
+
user_id: deepseekOptions.userId
|
|
890
|
+
},
|
|
545
891
|
...(thinking == null ? void 0 : thinking.type) !== "disabled" && reasoningEffort != null && {
|
|
546
892
|
reasoning_effort: reasoningEffort
|
|
547
893
|
}
|
|
@@ -603,7 +949,21 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
603
949
|
providerMetadata: {
|
|
604
950
|
[this.providerOptionsName]: {
|
|
605
951
|
promptCacheHitTokens: (_d = responseBody.usage) == null ? void 0 : _d.prompt_cache_hit_tokens,
|
|
606
|
-
promptCacheMissTokens: (_e = responseBody.usage) == null ? void 0 : _e.prompt_cache_miss_tokens
|
|
952
|
+
promptCacheMissTokens: (_e = responseBody.usage) == null ? void 0 : _e.prompt_cache_miss_tokens,
|
|
953
|
+
...responseBody.object != null && {
|
|
954
|
+
responseObject: responseBody.object
|
|
955
|
+
},
|
|
956
|
+
...choice.index != null && { choiceIndex: choice.index },
|
|
957
|
+
...choice.message.role != null && {
|
|
958
|
+
messageRole: choice.message.role
|
|
959
|
+
},
|
|
960
|
+
...choice.message.tool_calls != null && {
|
|
961
|
+
toolCallTypes: choice.message.tool_calls.map((toolCall) => toolCall.type).filter((type) => type != null)
|
|
962
|
+
},
|
|
963
|
+
...choice.logprobs != null && { logprobs: choice.logprobs },
|
|
964
|
+
...responseBody.system_fingerprint != null && {
|
|
965
|
+
systemFingerprint: responseBody.system_fingerprint
|
|
966
|
+
}
|
|
607
967
|
}
|
|
608
968
|
},
|
|
609
969
|
request: { body: args },
|
|
@@ -643,10 +1003,17 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
643
1003
|
raw: void 0
|
|
644
1004
|
};
|
|
645
1005
|
let usage = void 0;
|
|
1006
|
+
let systemFingerprint = void 0;
|
|
646
1007
|
let isFirstChunk = true;
|
|
647
1008
|
const providerOptionsName = this.providerOptionsName;
|
|
648
1009
|
let isActiveReasoning = false;
|
|
649
1010
|
let isActiveText = false;
|
|
1011
|
+
let responseObject;
|
|
1012
|
+
let choiceIndex;
|
|
1013
|
+
let messageRole;
|
|
1014
|
+
const toolCallTypes = /* @__PURE__ */ new Map();
|
|
1015
|
+
const contentLogprobs = [];
|
|
1016
|
+
const reasoningLogprobs = [];
|
|
650
1017
|
return {
|
|
651
1018
|
stream: response.pipeThrough(
|
|
652
1019
|
new TransformStream({
|
|
@@ -657,6 +1024,7 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
657
1024
|
controller.enqueue({ type: "stream-start", warnings });
|
|
658
1025
|
},
|
|
659
1026
|
transform(chunk, controller) {
|
|
1027
|
+
var _a2, _b2;
|
|
660
1028
|
if (options.includeRawChunks) {
|
|
661
1029
|
controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
|
|
662
1030
|
}
|
|
@@ -668,7 +1036,10 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
668
1036
|
const value = chunk.value;
|
|
669
1037
|
if ("error" in value) {
|
|
670
1038
|
finishReason = { unified: "error", raw: void 0 };
|
|
671
|
-
controller.enqueue({
|
|
1039
|
+
controller.enqueue({
|
|
1040
|
+
type: "error",
|
|
1041
|
+
error: createDeepSeekStreamError(value.error, value)
|
|
1042
|
+
});
|
|
672
1043
|
return;
|
|
673
1044
|
}
|
|
674
1045
|
if (isFirstChunk) {
|
|
@@ -681,17 +1052,35 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
681
1052
|
if (value.usage != null) {
|
|
682
1053
|
usage = value.usage;
|
|
683
1054
|
}
|
|
1055
|
+
if (value.object != null) {
|
|
1056
|
+
responseObject = value.object;
|
|
1057
|
+
}
|
|
1058
|
+
if (value.system_fingerprint != null) {
|
|
1059
|
+
systemFingerprint = value.system_fingerprint;
|
|
1060
|
+
}
|
|
684
1061
|
const choice = value.choices[0];
|
|
1062
|
+
if ((choice == null ? void 0 : choice.index) != null) {
|
|
1063
|
+
choiceIndex = choice.index;
|
|
1064
|
+
}
|
|
685
1065
|
if ((choice == null ? void 0 : choice.finish_reason) != null) {
|
|
686
1066
|
finishReason = {
|
|
687
1067
|
unified: mapDeepSeekFinishReason(choice.finish_reason),
|
|
688
1068
|
raw: choice.finish_reason
|
|
689
1069
|
};
|
|
690
1070
|
}
|
|
1071
|
+
if (((_a2 = choice == null ? void 0 : choice.logprobs) == null ? void 0 : _a2.content) != null) {
|
|
1072
|
+
contentLogprobs.push(...choice.logprobs.content);
|
|
1073
|
+
}
|
|
1074
|
+
if (((_b2 = choice == null ? void 0 : choice.logprobs) == null ? void 0 : _b2.reasoning_content) != null) {
|
|
1075
|
+
reasoningLogprobs.push(...choice.logprobs.reasoning_content);
|
|
1076
|
+
}
|
|
691
1077
|
if ((choice == null ? void 0 : choice.delta) == null) {
|
|
692
1078
|
return;
|
|
693
1079
|
}
|
|
694
1080
|
const delta = choice.delta;
|
|
1081
|
+
if (delta.role != null) {
|
|
1082
|
+
messageRole = delta.role;
|
|
1083
|
+
}
|
|
695
1084
|
const reasoningContent = delta.reasoning_content;
|
|
696
1085
|
if (reasoningContent) {
|
|
697
1086
|
if (!isActiveReasoning) {
|
|
@@ -734,6 +1123,9 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
734
1123
|
isActiveReasoning = false;
|
|
735
1124
|
}
|
|
736
1125
|
for (const toolCallDelta of delta.tool_calls) {
|
|
1126
|
+
if (toolCallDelta.type != null) {
|
|
1127
|
+
toolCallTypes.set(toolCallDelta.index, toolCallDelta.type);
|
|
1128
|
+
}
|
|
737
1129
|
toolCallTracker.processDelta(toolCallDelta);
|
|
738
1130
|
}
|
|
739
1131
|
}
|
|
@@ -754,7 +1146,24 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
754
1146
|
providerMetadata: {
|
|
755
1147
|
[providerOptionsName]: {
|
|
756
1148
|
promptCacheHitTokens: (_a2 = usage == null ? void 0 : usage.prompt_cache_hit_tokens) != null ? _a2 : void 0,
|
|
757
|
-
promptCacheMissTokens: (_b2 = usage == null ? void 0 : usage.prompt_cache_miss_tokens) != null ? _b2 : void 0
|
|
1149
|
+
promptCacheMissTokens: (_b2 = usage == null ? void 0 : usage.prompt_cache_miss_tokens) != null ? _b2 : void 0,
|
|
1150
|
+
...responseObject != null && { responseObject },
|
|
1151
|
+
...choiceIndex != null && { choiceIndex },
|
|
1152
|
+
...messageRole != null && { messageRole },
|
|
1153
|
+
...toolCallTypes.size > 0 && {
|
|
1154
|
+
toolCallTypes: [...toolCallTypes.entries()].sort(([left], [right]) => left - right).map(([, type]) => type)
|
|
1155
|
+
},
|
|
1156
|
+
...(contentLogprobs.length > 0 || reasoningLogprobs.length > 0) && {
|
|
1157
|
+
logprobs: {
|
|
1158
|
+
...contentLogprobs.length > 0 && {
|
|
1159
|
+
content: contentLogprobs
|
|
1160
|
+
},
|
|
1161
|
+
...reasoningLogprobs.length > 0 && {
|
|
1162
|
+
reasoning_content: reasoningLogprobs
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
...systemFingerprint != null && { systemFingerprint }
|
|
758
1167
|
}
|
|
759
1168
|
}
|
|
760
1169
|
});
|
|
@@ -768,28 +1177,36 @@ var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
|
|
|
768
1177
|
};
|
|
769
1178
|
|
|
770
1179
|
// src/files/deepseek-files.ts
|
|
1180
|
+
import {
|
|
1181
|
+
InvalidArgumentError
|
|
1182
|
+
} from "@ai-sdk/provider";
|
|
771
1183
|
import {
|
|
772
1184
|
combineHeaders as combineHeaders2,
|
|
773
1185
|
convertInlineFileDataToUint8Array,
|
|
774
1186
|
createJsonErrorResponseHandler as createJsonErrorResponseHandler2,
|
|
775
1187
|
createJsonResponseHandler as createJsonResponseHandler2,
|
|
776
|
-
|
|
1188
|
+
detectMediaType,
|
|
1189
|
+
parseProviderOptions as parseProviderOptions3,
|
|
777
1190
|
postFormDataToApi
|
|
778
1191
|
} from "@ai-sdk/provider-utils";
|
|
779
1192
|
|
|
780
1193
|
// src/files/deepseek-files-api.ts
|
|
781
1194
|
import { lazySchema as lazySchema2, zodSchema as zodSchema2 } from "@ai-sdk/provider-utils";
|
|
782
|
-
import { z as
|
|
1195
|
+
import { z as z4 } from "zod/v4";
|
|
783
1196
|
var deepSeekFilesResponseSchema = lazySchema2(
|
|
784
1197
|
() => zodSchema2(
|
|
785
|
-
|
|
786
|
-
id:
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1198
|
+
z4.object({
|
|
1199
|
+
id: z4.string(),
|
|
1200
|
+
// These fields are required by DeepSeek's OpenAPI schema, but they are
|
|
1201
|
+
// not needed to construct the provider reference. Keep them nullish so
|
|
1202
|
+
// uploads remain resilient to incomplete responses while validating any
|
|
1203
|
+
// returned values precisely enough to avoid misleading metadata.
|
|
1204
|
+
object: z4.literal("file").nullish(),
|
|
1205
|
+
bytes: z4.number().int().nonnegative().nullish(),
|
|
1206
|
+
created_at: z4.number().int().nonnegative().nullish(),
|
|
1207
|
+
filename: z4.string().nullish(),
|
|
1208
|
+
purpose: z4.literal("user_data").nullish(),
|
|
1209
|
+
expires_at: z4.number().int().nonnegative().nullish()
|
|
793
1210
|
})
|
|
794
1211
|
)
|
|
795
1212
|
);
|
|
@@ -799,15 +1216,15 @@ import {
|
|
|
799
1216
|
lazySchema as lazySchema3,
|
|
800
1217
|
zodSchema as zodSchema3
|
|
801
1218
|
} from "@ai-sdk/provider-utils";
|
|
802
|
-
import { z as
|
|
1219
|
+
import { z as z5 } from "zod/v4";
|
|
803
1220
|
var deepSeekFilesOptionsSchema = lazySchema3(
|
|
804
1221
|
() => zodSchema3(
|
|
805
|
-
|
|
1222
|
+
z5.object({
|
|
806
1223
|
/**
|
|
807
1224
|
* Number of seconds after creation before the file expires.
|
|
808
1225
|
* Must be between 1 hour and 30 days.
|
|
809
1226
|
*/
|
|
810
|
-
expiresAfter:
|
|
1227
|
+
expiresAfter: z5.number().int().min(3600).max(2592e3).optional()
|
|
811
1228
|
})
|
|
812
1229
|
)
|
|
813
1230
|
);
|
|
@@ -817,6 +1234,30 @@ var deepSeekFailedResponseHandler = createJsonErrorResponseHandler2({
|
|
|
817
1234
|
errorSchema: deepSeekErrorSchema,
|
|
818
1235
|
errorToMessage: (error) => error.error.message
|
|
819
1236
|
});
|
|
1237
|
+
var MAX_FILE_SIZE_BYTES = 64 * 1024 * 1024;
|
|
1238
|
+
var MAX_FILENAME_LENGTH = 512;
|
|
1239
|
+
var supportedMediaTypes = /* @__PURE__ */ new Set([
|
|
1240
|
+
"image/gif",
|
|
1241
|
+
"image/jpeg",
|
|
1242
|
+
"image/jpg",
|
|
1243
|
+
"image/png",
|
|
1244
|
+
"image/webp"
|
|
1245
|
+
]);
|
|
1246
|
+
var genericMediaTypes = /* @__PURE__ */ new Set([
|
|
1247
|
+
"",
|
|
1248
|
+
"application/binary",
|
|
1249
|
+
"application/octet-stream",
|
|
1250
|
+
"binary/octet-stream",
|
|
1251
|
+
"image",
|
|
1252
|
+
"image/*"
|
|
1253
|
+
]);
|
|
1254
|
+
var supportedFilenameExtensions = /* @__PURE__ */ new Set([
|
|
1255
|
+
"gif",
|
|
1256
|
+
"jpeg",
|
|
1257
|
+
"jpg",
|
|
1258
|
+
"png",
|
|
1259
|
+
"webp"
|
|
1260
|
+
]);
|
|
820
1261
|
var DeepSeekFiles = class {
|
|
821
1262
|
constructor(config) {
|
|
822
1263
|
this.config = config;
|
|
@@ -832,12 +1273,13 @@ var DeepSeekFiles = class {
|
|
|
832
1273
|
providerOptions
|
|
833
1274
|
}) {
|
|
834
1275
|
var _a, _b;
|
|
835
|
-
const deepSeekOptions = await
|
|
1276
|
+
const deepSeekOptions = await parseProviderOptions3({
|
|
836
1277
|
provider: "deepseek",
|
|
837
1278
|
providerOptions,
|
|
838
1279
|
schema: deepSeekFilesOptionsSchema
|
|
839
1280
|
});
|
|
840
1281
|
const fileBytes = convertInlineFileDataToUint8Array(data);
|
|
1282
|
+
validateFileUpload({ fileBytes, mediaType, filename });
|
|
841
1283
|
const blob = new Blob([fileBytes], { type: mediaType });
|
|
842
1284
|
const formData = new FormData();
|
|
843
1285
|
if (filename != null) {
|
|
@@ -870,6 +1312,7 @@ var DeepSeekFiles = class {
|
|
|
870
1312
|
...mediaType != null ? { mediaType } : {},
|
|
871
1313
|
providerMetadata: {
|
|
872
1314
|
deepseek: {
|
|
1315
|
+
...response.object != null ? { object: response.object } : {},
|
|
873
1316
|
...response.filename != null ? { filename: response.filename } : {},
|
|
874
1317
|
...response.purpose != null ? { purpose: response.purpose } : {},
|
|
875
1318
|
...response.bytes != null ? { bytes: response.bytes } : {},
|
|
@@ -880,9 +1323,66 @@ var DeepSeekFiles = class {
|
|
|
880
1323
|
};
|
|
881
1324
|
}
|
|
882
1325
|
};
|
|
1326
|
+
function validateFileUpload({
|
|
1327
|
+
fileBytes,
|
|
1328
|
+
mediaType,
|
|
1329
|
+
filename
|
|
1330
|
+
}) {
|
|
1331
|
+
if (fileBytes.length > MAX_FILE_SIZE_BYTES) {
|
|
1332
|
+
throw new InvalidArgumentError({
|
|
1333
|
+
argument: "data",
|
|
1334
|
+
message: `DeepSeek file uploads must not exceed 64 MiB (${MAX_FILE_SIZE_BYTES.toLocaleString("en-US")} bytes). Received ${fileBytes.length.toLocaleString("en-US")} bytes.`
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
if (filename != null) {
|
|
1338
|
+
const filenameLength = Array.from(filename).length;
|
|
1339
|
+
if (filenameLength > MAX_FILENAME_LENGTH) {
|
|
1340
|
+
throw new InvalidArgumentError({
|
|
1341
|
+
argument: "filename",
|
|
1342
|
+
message: `DeepSeek filenames must not exceed ${MAX_FILENAME_LENGTH} characters. Received ${filenameLength} characters.`
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
const normalizedMediaType = normalizeMediaType(mediaType);
|
|
1347
|
+
const detectedMediaType = detectMediaType({ data: fileBytes });
|
|
1348
|
+
if (detectedMediaType != null && !supportedMediaTypes.has(detectedMediaType)) {
|
|
1349
|
+
throw new InvalidArgumentError({
|
|
1350
|
+
argument: "data",
|
|
1351
|
+
message: `DeepSeek file uploads support JPEG, PNG, GIF, and WebP images. Detected unsupported file content type "${detectedMediaType}".`
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
if (supportedMediaTypes.has(normalizedMediaType)) {
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
if (!genericMediaTypes.has(normalizedMediaType)) {
|
|
1358
|
+
throw new InvalidArgumentError({
|
|
1359
|
+
argument: "mediaType",
|
|
1360
|
+
message: `DeepSeek file uploads support JPEG, PNG, GIF, and WebP images. Received unsupported media type "${mediaType}".`
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
if (detectedMediaType != null || hasSupportedFilenameExtension(filename)) {
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
throw new InvalidArgumentError({
|
|
1367
|
+
argument: "mediaType",
|
|
1368
|
+
message: `DeepSeek file uploads support JPEG, PNG, GIF, and WebP images. Provide a supported media type or a filename ending in .jpg, .jpeg, .png, .gif, or .webp. Received "${mediaType}".`
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1371
|
+
function normalizeMediaType(mediaType) {
|
|
1372
|
+
return mediaType.split(";", 1)[0].trim().toLowerCase();
|
|
1373
|
+
}
|
|
1374
|
+
function hasSupportedFilenameExtension(filename) {
|
|
1375
|
+
if (filename == null) {
|
|
1376
|
+
return false;
|
|
1377
|
+
}
|
|
1378
|
+
const extensionSeparatorIndex = filename.lastIndexOf(".");
|
|
1379
|
+
return extensionSeparatorIndex !== -1 && supportedFilenameExtensions.has(
|
|
1380
|
+
filename.slice(extensionSeparatorIndex + 1).toLowerCase()
|
|
1381
|
+
);
|
|
1382
|
+
}
|
|
883
1383
|
|
|
884
1384
|
// src/version.ts
|
|
885
|
-
var VERSION = true ? "3.0.
|
|
1385
|
+
var VERSION = true ? "3.0.34" : "0.0.0-test";
|
|
886
1386
|
|
|
887
1387
|
// src/deepseek-provider.ts
|
|
888
1388
|
function createDeepSeek(options = {}) {
|
|
@@ -904,7 +1404,9 @@ function createDeepSeek(options = {}) {
|
|
|
904
1404
|
provider: `deepseek.chat`,
|
|
905
1405
|
url: ({ path }) => `${baseURL}${path}`,
|
|
906
1406
|
headers: getHeaders,
|
|
907
|
-
fetch: options.fetch
|
|
1407
|
+
fetch: options.fetch,
|
|
1408
|
+
supportsAssistantPrefixCompletion: baseURL.endsWith("/beta"),
|
|
1409
|
+
supportsStrictToolCalls: baseURL.endsWith("/beta")
|
|
908
1410
|
});
|
|
909
1411
|
};
|
|
910
1412
|
const createFiles = () => new DeepSeekFiles({
|