@ai-sdk/deepseek 3.0.56 → 3.0.57

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.
@@ -1,1246 +1,1025 @@
1
- // src/chat/deepseek-chat-language-model.ts
2
- import {
3
- InvalidResponseDataError
4
- } from "@ai-sdk/provider";
5
- import {
6
- combineHeaders,
7
- createEventSourceResponseHandler,
8
- createJsonErrorResponseHandler,
9
- createJsonResponseHandler,
10
- createProviderStreamError,
11
- generateId,
12
- isCustomReasoning,
13
- mapReasoningToProviderEffort,
14
- parseProviderOptions as parseProviderOptions2,
15
- postJsonToApi,
16
- serializeModelOptions,
17
- StreamingToolCallTracker,
18
- WORKFLOW_SERIALIZE,
19
- WORKFLOW_DESERIALIZE
20
- } from "@ai-sdk/provider-utils";
21
-
22
- // src/chat/convert-to-deepseek-chat-messages.ts
23
- import {
24
- InvalidPromptError,
25
- UnsupportedFunctionalityError
26
- } from "@ai-sdk/provider";
27
- import {
28
- convertToBase64,
29
- getTopLevelMediaType,
30
- parseProviderOptions,
31
- resolveFullMediaType,
32
- resolveProviderReference
33
- } from "@ai-sdk/provider-utils";
34
-
35
- // src/chat/deepseek-file-part-options.ts
1
+ import { InvalidPromptError, InvalidResponseDataError, UnsupportedFunctionalityError } from "@ai-sdk/provider";
2
+ import { StreamingToolCallTracker, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, convertToBase64, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonResponseHandler, createLanguageModelResponseMetadata as getResponseMetadata, createNullLanguageModelUsage, createProviderStreamError, generateId, getTopLevelMediaType, isCustomReasoning, lazySchema, mapReasoningToProviderEffort, parseProviderOptions, postJsonToApi, resolveFullMediaType, resolveProviderReference, serializeModelOptions, zodSchema } from "@ai-sdk/provider-utils";
36
3
  import { z } from "zod/v4";
37
- var deepseekFilePartProviderOptions = z.object({
38
- /**
39
- * Controls how DeepSeek processes an image sent as an `image_url` part.
40
- *
41
- * @see https://api-docs.deepseek.com/api/create-chat-completion/
42
- */
43
- imageDetail: z.enum(["low", "high", "original", "auto"]).optional(),
44
- /**
45
- * Sends inline image data as a DeepSeek `file` part using `file_data`
46
- * instead of an `image_url` data URL. When set, the file part's filename
47
- * is preserved.
48
- *
49
- * This option only applies to inline image data. It cannot be combined
50
- * with `imageDetail`.
51
- */
52
- fileData: z.literal(true).optional()
53
- });
54
-
55
- // src/chat/deepseek-chat-language-model-options.ts
56
- import { z as z2 } from "zod/v4";
57
- var deepseekLanguageModelChatOptions = z2.object({
58
- /**
59
- * Whether to return log probabilities for generated tokens.
60
- */
61
- logprobs: z2.boolean().optional(),
62
- /**
63
- * Number of most likely tokens to return at each token position.
64
- *
65
- * Setting this option automatically enables `logprobs`.
66
- */
67
- topLogprobs: z2.number().int().min(0).max(20).optional(),
68
- /**
69
- * An opaque identifier for the end user. DeepSeek uses this identifier for
70
- * content-safety tracing and request isolation.
71
- *
72
- * Must contain only ASCII letters, numbers, underscores, and hyphens, and
73
- * must be at most 512 characters long.
74
- */
75
- 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(),
76
- /**
77
- * Type of thinking to use. Defaults to `enabled`.
78
- */
79
- thinking: z2.object({
80
- // `adaptive` is accepted at runtime for backwards compatibility and
81
- // mapped to `enabled`, but is intentionally excluded from the exported
82
- // provider options type.
83
- type: z2.enum(["adaptive", "enabled", "disabled"]).optional()
84
- }).optional(),
85
- /**
86
- * Controls the thinking strength for DeepSeek V4 reasoning models.
87
- */
88
- // `medium` and `xhigh` are accepted at runtime for backwards compatibility
89
- // and mapped to canonical DeepSeek values, but are intentionally excluded
90
- // from the exported provider options type.
91
- reasoningEffort: z2.enum(["low", "medium", "high", "xhigh", "max"]).optional(),
92
- /**
93
- * Whether to use strict JSON schema validation for structured outputs.
94
- * Only applies when the serving endpoint supports JSON schema response
95
- * formats (e.g. Azure). Defaults to `true`.
96
- */
97
- strictJsonSchema: z2.boolean().optional()
4
+ //#region src/chat/deepseek-file-part-options.ts
5
+ const deepseekFilePartProviderOptions = z.object({
6
+ /**
7
+ * Controls how DeepSeek processes an image sent as an `image_url` part.
8
+ *
9
+ * @see https://api-docs.deepseek.com/api/create-chat-completion/
10
+ */
11
+ imageDetail: z.enum([
12
+ "low",
13
+ "high",
14
+ "original",
15
+ "auto"
16
+ ]).optional(),
17
+ /**
18
+ * Sends inline image data as a DeepSeek `file` part using `file_data`
19
+ * instead of an `image_url` data URL. When set, the file part's filename
20
+ * is preserved.
21
+ *
22
+ * This option only applies to inline image data. It cannot be combined
23
+ * with `imageDetail`.
24
+ */
25
+ fileData: z.literal(true).optional()
98
26
  });
99
- var deepseekMessageProviderOptions = z2.object({
100
- /**
101
- * The name of the participant represented by the message.
102
- *
103
- * Supported on system, user, and assistant messages.
104
- */
105
- name: z2.string().optional()
27
+ //#endregion
28
+ //#region src/chat/deepseek-chat-language-model-options.ts
29
+ const deepseekLanguageModelChatOptions = z.object({
30
+ /**
31
+ * Whether to return log probabilities for generated tokens.
32
+ */
33
+ logprobs: z.boolean().optional(),
34
+ /**
35
+ * Number of most likely tokens to return at each token position.
36
+ *
37
+ * Setting this option automatically enables `logprobs`.
38
+ */
39
+ topLogprobs: z.number().int().min(0).max(20).optional(),
40
+ /**
41
+ * An opaque identifier for the end user. DeepSeek uses this identifier for
42
+ * content-safety tracing and request isolation.
43
+ *
44
+ * Must contain only ASCII letters, numbers, underscores, and hyphens, and
45
+ * must be at most 512 characters long.
46
+ */
47
+ userId: z.string().regex(/^[a-zA-Z0-9_-]+$/, "userId must match /^[a-zA-Z0-9_-]+$/").max(512, "userId must be at most 512 characters long").optional(),
48
+ /**
49
+ * Type of thinking to use. Defaults to `enabled`.
50
+ */
51
+ thinking: z.object({ type: z.enum([
52
+ "adaptive",
53
+ "enabled",
54
+ "disabled"
55
+ ]).optional() }).optional(),
56
+ /**
57
+ * Controls the thinking strength for DeepSeek V4 reasoning models.
58
+ */
59
+ reasoningEffort: z.enum([
60
+ "low",
61
+ "medium",
62
+ "high",
63
+ "xhigh",
64
+ "max"
65
+ ]).optional(),
66
+ /**
67
+ * Whether to use strict JSON schema validation for structured outputs.
68
+ * Only applies when the serving endpoint supports JSON schema response
69
+ * formats (e.g. Azure). Defaults to `true`.
70
+ */
71
+ strictJsonSchema: z.boolean().optional()
106
72
  });
107
- var deepseekAssistantMessageProviderOptions = deepseekMessageProviderOptions.extend({
108
- /**
109
- * Whether the assistant message content is a prefix that DeepSeek should
110
- * continue. This beta feature is only supported on the final assistant
111
- * message when using a beta base URL.
112
- */
113
- prefix: z2.literal(true).optional()
114
- });
115
-
116
- // src/chat/is-deepseek-v4-model.ts
73
+ const deepseekMessageProviderOptions = z.object({
74
+ /**
75
+ * The name of the participant represented by the message.
76
+ *
77
+ * Supported on system, user, and assistant messages.
78
+ */
79
+ name: z.string().optional() });
80
+ const deepseekAssistantMessageProviderOptions = deepseekMessageProviderOptions.extend({
81
+ /**
82
+ * Whether the assistant message content is a prefix that DeepSeek should
83
+ * continue. This beta feature is only supported on the final assistant
84
+ * message when using a beta base URL.
85
+ */
86
+ prefix: z.literal(true).optional() });
87
+ //#endregion
88
+ //#region src/chat/is-deepseek-v4-model.ts
89
+ /**
90
+ * Whether a model id is a DeepSeek V4-generation model (thinking mode on by
91
+ * default, `reasoning_content` required on every assistant turn).
92
+ *
93
+ * DeepSeek publishes V4 models under both versioned ids (`deepseek-v4-pro`,
94
+ * `deepseek-v4-flash-*`) and unversioned aliases (`deepseek-flash`, currently
95
+ * serving V4.1 Flash). Only the legacy `deepseek-chat` / `deepseek-reasoner`
96
+ * ids predate V4.
97
+ */
117
98
  function isDeepSeekV4Model(modelId) {
118
- return modelId.includes("deepseek-v4") || modelId.startsWith("deepseek-flash") || modelId.startsWith("deepseek-pro");
99
+ return modelId.includes("deepseek-v4") || modelId.startsWith("deepseek-flash") || modelId.startsWith("deepseek-pro");
119
100
  }
120
-
121
- // src/chat/convert-to-deepseek-chat-messages.ts
122
- var supportedImageMediaTypes = /* @__PURE__ */ new Set([
123
- "image/gif",
124
- "image/jpeg",
125
- "image/jpg",
126
- "image/png",
127
- "image/webp"
101
+ //#endregion
102
+ //#region src/chat/convert-to-deepseek-chat-messages.ts
103
+ const supportedImageMediaTypes = /* @__PURE__ */ new Set([
104
+ "image/gif",
105
+ "image/jpeg",
106
+ "image/jpg",
107
+ "image/png",
108
+ "image/webp"
128
109
  ]);
129
110
  function resolveDeepSeekImageMediaType(part) {
130
- const resolvedMediaType = resolveFullMediaType({ part });
131
- if (!supportedImageMediaTypes.has(resolvedMediaType)) {
132
- throw new UnsupportedFunctionalityError({
133
- functionality: `DeepSeek image media type ${resolvedMediaType}`,
134
- message: "DeepSeek supports JPEG, PNG, GIF, and WebP image inputs."
135
- });
136
- }
137
- return resolvedMediaType;
111
+ const resolvedMediaType = resolveFullMediaType({ part });
112
+ if (!supportedImageMediaTypes.has(resolvedMediaType)) throw new UnsupportedFunctionalityError({
113
+ functionality: `DeepSeek image media type ${resolvedMediaType}`,
114
+ message: "DeepSeek supports JPEG, PNG, GIF, and WebP image inputs."
115
+ });
116
+ return resolvedMediaType;
138
117
  }
139
- function validateDeepSeekImageUrl({
140
- url,
141
- prompt
142
- }) {
143
- if (url.length > 8192) {
144
- throw new InvalidPromptError({
145
- prompt,
146
- message: "DeepSeek image URLs must not exceed 8192 characters."
147
- });
148
- }
118
+ function validateDeepSeekImageUrl({ url, prompt }) {
119
+ if (url.length > 8192) throw new InvalidPromptError({
120
+ prompt,
121
+ message: "DeepSeek image URLs must not exceed 8192 characters."
122
+ });
149
123
  }
150
- async function convertToDeepSeekChatMessages({
151
- prompt,
152
- responseFormat,
153
- modelId,
154
- providerOptionsName = "deepseek",
155
- supportsAssistantPrefixCompletion = false,
156
- supportsStructuredOutputs = false
157
- }) {
158
- const isDeepSeekV4 = isDeepSeekV4Model(modelId);
159
- const messages = [];
160
- const warnings = [];
161
- if (responseFormat?.type === "json") {
162
- if (responseFormat.schema == null) {
163
- messages.push({
164
- role: "system",
165
- content: "Return JSON."
166
- });
167
- } else if (!supportsStructuredOutputs) {
168
- messages.push({
169
- role: "system",
170
- content: "Return JSON that conforms to the following schema: " + JSON.stringify(responseFormat.schema)
171
- });
172
- warnings.push({
173
- type: "compatibility",
174
- feature: "responseFormat JSON schema",
175
- details: "JSON response schema is injected into the system message."
176
- });
177
- }
178
- }
179
- let lastUserMessageIndex = -1;
180
- for (let i = prompt.length - 1; i >= 0; i--) {
181
- if (prompt[i].role === "user") {
182
- lastUserMessageIndex = i;
183
- break;
184
- }
185
- }
186
- let index = -1;
187
- for (const { role, content, providerOptions } of prompt) {
188
- index++;
189
- const deepseekMessageOptions = await parseProviderOptions({
190
- provider: providerOptionsName,
191
- providerOptions,
192
- schema: deepseekAssistantMessageProviderOptions
193
- });
194
- if (deepseekMessageOptions?.prefix === true && role !== "assistant") {
195
- throw new InvalidPromptError({
196
- prompt,
197
- message: "DeepSeek assistant prefix completion requires `prefix: true` on an assistant message."
198
- });
199
- }
200
- switch (role) {
201
- case "system": {
202
- messages.push({
203
- role: "system",
204
- content,
205
- ...deepseekMessageOptions?.name != null && {
206
- name: deepseekMessageOptions.name
207
- }
208
- });
209
- break;
210
- }
211
- case "user": {
212
- const hasImagePart = content.some(
213
- (part) => part.type === "file" && (part.data.type === "reference" || part.data.type === "url" || part.data.type === "data") && getTopLevelMediaType(part.mediaType) === "image"
214
- );
215
- if (!hasImagePart) {
216
- let userContent2 = "";
217
- for (const part of content) {
218
- if (part.type === "text") {
219
- userContent2 += part.text;
220
- } else {
221
- warnings.push({
222
- type: "unsupported",
223
- feature: `user message part type: ${part.type}`
224
- });
225
- }
226
- }
227
- messages.push({
228
- role: "user",
229
- content: userContent2,
230
- ...deepseekMessageOptions?.name != null && {
231
- name: deepseekMessageOptions.name
232
- }
233
- });
234
- break;
235
- }
236
- const userContent = [];
237
- for (const part of content) {
238
- if (part.type === "text") {
239
- userContent.push({ type: "text", text: part.text });
240
- } else if (part.type === "file" && getTopLevelMediaType(part.mediaType) === "image") {
241
- const filePartOptions = await parseProviderOptions({
242
- provider: providerOptionsName,
243
- providerOptions: part.providerOptions,
244
- schema: deepseekFilePartProviderOptions
245
- });
246
- if (part.data.type === "reference") {
247
- userContent.push({
248
- type: "file",
249
- file_id: resolveProviderReference({
250
- reference: part.data.reference,
251
- provider: "deepseek"
252
- })
253
- });
254
- } else if (part.data.type === "url" || part.data.type === "data") {
255
- const resolvedMediaType = resolveDeepSeekImageMediaType(part);
256
- if (part.data.type === "url") {
257
- const url = part.data.url.toString();
258
- validateDeepSeekImageUrl({ url, prompt });
259
- if (filePartOptions?.fileData === true) {
260
- throw new InvalidPromptError({
261
- prompt,
262
- message: "DeepSeek `fileData` image parts require inline data, not a URL."
263
- });
264
- }
265
- userContent.push({
266
- type: "image_url",
267
- image_url: {
268
- url,
269
- ...filePartOptions?.imageDetail != null && {
270
- detail: filePartOptions.imageDetail
271
- }
272
- }
273
- });
274
- } else {
275
- const dataUrl = `data:${resolvedMediaType === "image/jpg" ? "image/jpeg" : resolvedMediaType};base64,${convertToBase64(part.data.data)}`;
276
- if (filePartOptions?.fileData === true) {
277
- if (filePartOptions.imageDetail != null) {
278
- throw new InvalidPromptError({
279
- prompt,
280
- message: "DeepSeek `imageDetail` cannot be combined with `fileData`."
281
- });
282
- }
283
- userContent.push({
284
- type: "file",
285
- file_data: dataUrl,
286
- ...part.filename != null && { filename: part.filename }
287
- });
288
- } else {
289
- userContent.push({
290
- type: "image_url",
291
- image_url: {
292
- url: dataUrl,
293
- ...filePartOptions?.imageDetail != null && {
294
- detail: filePartOptions.imageDetail
295
- }
296
- }
297
- });
298
- }
299
- }
300
- } else {
301
- warnings.push({
302
- type: "unsupported",
303
- feature: `user message part type: ${part.type}`
304
- });
305
- }
306
- } else {
307
- warnings.push({
308
- type: "unsupported",
309
- feature: `user message part type: ${part.type}`
310
- });
311
- }
312
- }
313
- messages.push({
314
- role: "user",
315
- content: userContent,
316
- ...deepseekMessageOptions?.name != null && {
317
- name: deepseekMessageOptions.name
318
- }
319
- });
320
- break;
321
- }
322
- case "assistant": {
323
- if (deepseekMessageOptions?.prefix === true) {
324
- if (index !== prompt.length - 1) {
325
- throw new InvalidPromptError({
326
- prompt,
327
- message: "DeepSeek assistant prefix completion requires the prefixed assistant message to be the final message."
328
- });
329
- }
330
- if (!supportsAssistantPrefixCompletion) {
331
- throw new UnsupportedFunctionalityError({
332
- functionality: "DeepSeek assistant prefix completion",
333
- message: "DeepSeek assistant prefix completion requires a beta base URL ending in `/beta`."
334
- });
335
- }
336
- }
337
- let text = "";
338
- let reasoning;
339
- const toolCalls = [];
340
- for (const part of content) {
341
- switch (part.type) {
342
- case "text": {
343
- text += part.text;
344
- break;
345
- }
346
- case "reasoning": {
347
- if (index <= lastUserMessageIndex && !isDeepSeekV4) {
348
- break;
349
- }
350
- if (reasoning == null) {
351
- reasoning = part.text;
352
- } else {
353
- reasoning += part.text;
354
- }
355
- break;
356
- }
357
- case "tool-call": {
358
- toolCalls.push({
359
- id: part.toolCallId,
360
- type: "function",
361
- function: {
362
- name: part.toolName,
363
- arguments: JSON.stringify(part.input)
364
- }
365
- });
366
- break;
367
- }
368
- }
369
- }
370
- messages.push({
371
- role: "assistant",
372
- content: text,
373
- ...deepseekMessageOptions?.name != null && {
374
- name: deepseekMessageOptions.name
375
- },
376
- ...deepseekMessageOptions?.prefix === true && {
377
- prefix: true
378
- },
379
- reasoning_content: reasoning ?? (isDeepSeekV4 ? "" : void 0),
380
- tool_calls: toolCalls.length > 0 ? toolCalls : void 0
381
- });
382
- break;
383
- }
384
- case "tool": {
385
- if (deepseekMessageOptions?.name != null) {
386
- warnings.push({
387
- type: "unsupported",
388
- feature: "message name on tool messages"
389
- });
390
- }
391
- for (const toolResponse of content) {
392
- if (toolResponse.type === "tool-approval-response") {
393
- continue;
394
- }
395
- const output = toolResponse.output;
396
- let contentValue;
397
- switch (output.type) {
398
- case "text":
399
- case "error-text":
400
- contentValue = output.value;
401
- break;
402
- case "execution-denied":
403
- contentValue = output.reason ?? "Tool call execution denied.";
404
- break;
405
- case "json":
406
- case "error-json":
407
- contentValue = JSON.stringify(output.value);
408
- break;
409
- case "content": {
410
- const hasImagePart = output.value.some(
411
- (part) => part.type === "file" && (part.data.type === "reference" || part.data.type === "url" || part.data.type === "data") && getTopLevelMediaType(part.mediaType) === "image"
412
- );
413
- if (!hasImagePart) {
414
- contentValue = JSON.stringify(output.value);
415
- break;
416
- }
417
- contentValue = [];
418
- for (const part of output.value) {
419
- if (part.type === "text") {
420
- contentValue.push({ type: "text", text: part.text });
421
- } else if (part.type === "file" && (part.data.type === "reference" || part.data.type === "url" || part.data.type === "data") && getTopLevelMediaType(part.mediaType) === "image") {
422
- if (part.data.type === "reference") {
423
- contentValue.push({
424
- type: "file",
425
- file_id: resolveProviderReference({
426
- reference: part.data.reference,
427
- provider: "deepseek"
428
- })
429
- });
430
- continue;
431
- }
432
- const filePartOptions = await parseProviderOptions({
433
- provider: providerOptionsName,
434
- providerOptions: part.providerOptions,
435
- schema: deepseekFilePartProviderOptions
436
- });
437
- const resolvedMediaType = resolveDeepSeekImageMediaType(part);
438
- let url;
439
- if (part.data.type === "url") {
440
- url = part.data.url.toString();
441
- validateDeepSeekImageUrl({ url, prompt });
442
- } else {
443
- url = `data:${resolvedMediaType === "image/jpg" ? "image/jpeg" : resolvedMediaType};base64,${convertToBase64(part.data.data)}`;
444
- }
445
- contentValue.push({
446
- type: "image_url",
447
- image_url: {
448
- url,
449
- ...filePartOptions?.imageDetail != null && {
450
- detail: filePartOptions.imageDetail
451
- }
452
- }
453
- });
454
- } else {
455
- warnings.push({
456
- type: "unsupported",
457
- feature: `tool result content part type: ${part.type}`
458
- });
459
- }
460
- }
461
- break;
462
- }
463
- }
464
- messages.push({
465
- role: "tool",
466
- tool_call_id: toolResponse.toolCallId,
467
- content: contentValue
468
- });
469
- }
470
- break;
471
- }
472
- default: {
473
- warnings.push({
474
- type: "unsupported",
475
- feature: `message role: ${role}`
476
- });
477
- break;
478
- }
479
- }
480
- }
481
- return { messages, warnings };
124
+ async function convertToDeepSeekChatMessages({ prompt, responseFormat, modelId, providerOptionsName = "deepseek", supportsAssistantPrefixCompletion = false, supportsStructuredOutputs = false }) {
125
+ const isDeepSeekV4 = isDeepSeekV4Model(modelId);
126
+ const messages = [];
127
+ const warnings = [];
128
+ if (responseFormat?.type === "json") {
129
+ if (responseFormat.schema == null) messages.push({
130
+ role: "system",
131
+ content: "Return JSON."
132
+ });
133
+ else if (!supportsStructuredOutputs) {
134
+ messages.push({
135
+ role: "system",
136
+ content: "Return JSON that conforms to the following schema: " + JSON.stringify(responseFormat.schema)
137
+ });
138
+ warnings.push({
139
+ type: "compatibility",
140
+ feature: "responseFormat JSON schema",
141
+ details: "JSON response schema is injected into the system message."
142
+ });
143
+ }
144
+ }
145
+ let lastUserMessageIndex = -1;
146
+ for (let i = prompt.length - 1; i >= 0; i--) if (prompt[i].role === "user") {
147
+ lastUserMessageIndex = i;
148
+ break;
149
+ }
150
+ let index = -1;
151
+ for (const { role, content, providerOptions } of prompt) {
152
+ index++;
153
+ const deepseekMessageOptions = await parseProviderOptions({
154
+ provider: providerOptionsName,
155
+ providerOptions,
156
+ schema: deepseekAssistantMessageProviderOptions
157
+ });
158
+ if (deepseekMessageOptions?.prefix === true && role !== "assistant") throw new InvalidPromptError({
159
+ prompt,
160
+ message: "DeepSeek assistant prefix completion requires `prefix: true` on an assistant message."
161
+ });
162
+ switch (role) {
163
+ case "system":
164
+ messages.push({
165
+ role: "system",
166
+ content,
167
+ ...deepseekMessageOptions?.name != null && { name: deepseekMessageOptions.name }
168
+ });
169
+ break;
170
+ case "user": {
171
+ if (!content.some((part) => part.type === "file" && (part.data.type === "reference" || part.data.type === "url" || part.data.type === "data") && getTopLevelMediaType(part.mediaType) === "image")) {
172
+ let userContent = "";
173
+ for (const part of content) if (part.type === "text") userContent += part.text;
174
+ else warnings.push({
175
+ type: "unsupported",
176
+ feature: `user message part type: ${part.type}`
177
+ });
178
+ messages.push({
179
+ role: "user",
180
+ content: userContent,
181
+ ...deepseekMessageOptions?.name != null && { name: deepseekMessageOptions.name }
182
+ });
183
+ break;
184
+ }
185
+ const userContent = [];
186
+ for (const part of content) if (part.type === "text") userContent.push({
187
+ type: "text",
188
+ text: part.text
189
+ });
190
+ else if (part.type === "file" && getTopLevelMediaType(part.mediaType) === "image") {
191
+ const filePartOptions = await parseProviderOptions({
192
+ provider: providerOptionsName,
193
+ providerOptions: part.providerOptions,
194
+ schema: deepseekFilePartProviderOptions
195
+ });
196
+ if (part.data.type === "reference") userContent.push({
197
+ type: "file",
198
+ file_id: resolveProviderReference({
199
+ reference: part.data.reference,
200
+ provider: "deepseek"
201
+ })
202
+ });
203
+ else if (part.data.type === "url" || part.data.type === "data") {
204
+ const resolvedMediaType = resolveDeepSeekImageMediaType(part);
205
+ if (part.data.type === "url") {
206
+ const url = part.data.url.toString();
207
+ validateDeepSeekImageUrl({
208
+ url,
209
+ prompt
210
+ });
211
+ if (filePartOptions?.fileData === true) throw new InvalidPromptError({
212
+ prompt,
213
+ message: "DeepSeek `fileData` image parts require inline data, not a URL."
214
+ });
215
+ userContent.push({
216
+ type: "image_url",
217
+ image_url: {
218
+ url,
219
+ ...filePartOptions?.imageDetail != null && { detail: filePartOptions.imageDetail }
220
+ }
221
+ });
222
+ } else {
223
+ const dataUrl = `data:${resolvedMediaType === "image/jpg" ? "image/jpeg" : resolvedMediaType};base64,${convertToBase64(part.data.data)}`;
224
+ if (filePartOptions?.fileData === true) {
225
+ if (filePartOptions.imageDetail != null) throw new InvalidPromptError({
226
+ prompt,
227
+ message: "DeepSeek `imageDetail` cannot be combined with `fileData`."
228
+ });
229
+ userContent.push({
230
+ type: "file",
231
+ file_data: dataUrl,
232
+ ...part.filename != null && { filename: part.filename }
233
+ });
234
+ } else userContent.push({
235
+ type: "image_url",
236
+ image_url: {
237
+ url: dataUrl,
238
+ ...filePartOptions?.imageDetail != null && { detail: filePartOptions.imageDetail }
239
+ }
240
+ });
241
+ }
242
+ } else warnings.push({
243
+ type: "unsupported",
244
+ feature: `user message part type: ${part.type}`
245
+ });
246
+ } else warnings.push({
247
+ type: "unsupported",
248
+ feature: `user message part type: ${part.type}`
249
+ });
250
+ messages.push({
251
+ role: "user",
252
+ content: userContent,
253
+ ...deepseekMessageOptions?.name != null && { name: deepseekMessageOptions.name }
254
+ });
255
+ break;
256
+ }
257
+ case "assistant": {
258
+ if (deepseekMessageOptions?.prefix === true) {
259
+ if (index !== prompt.length - 1) throw new InvalidPromptError({
260
+ prompt,
261
+ message: "DeepSeek assistant prefix completion requires the prefixed assistant message to be the final message."
262
+ });
263
+ if (!supportsAssistantPrefixCompletion) throw new UnsupportedFunctionalityError({
264
+ functionality: "DeepSeek assistant prefix completion",
265
+ message: "DeepSeek assistant prefix completion requires a beta base URL ending in `/beta`."
266
+ });
267
+ }
268
+ let text = "";
269
+ let reasoning;
270
+ const toolCalls = [];
271
+ for (const part of content) switch (part.type) {
272
+ case "text":
273
+ text += part.text;
274
+ break;
275
+ case "reasoning":
276
+ if (index <= lastUserMessageIndex && !isDeepSeekV4) break;
277
+ if (reasoning == null) reasoning = part.text;
278
+ else reasoning += part.text;
279
+ break;
280
+ case "tool-call": toolCalls.push({
281
+ id: part.toolCallId,
282
+ type: "function",
283
+ function: {
284
+ name: part.toolName,
285
+ arguments: JSON.stringify(part.input)
286
+ }
287
+ });
288
+ }
289
+ messages.push({
290
+ role: "assistant",
291
+ content: text,
292
+ ...deepseekMessageOptions?.name != null && { name: deepseekMessageOptions.name },
293
+ ...deepseekMessageOptions?.prefix === true && { prefix: true },
294
+ reasoning_content: reasoning ?? (isDeepSeekV4 ? "" : void 0),
295
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0
296
+ });
297
+ break;
298
+ }
299
+ case "tool":
300
+ if (deepseekMessageOptions?.name != null) warnings.push({
301
+ type: "unsupported",
302
+ feature: "message name on tool messages"
303
+ });
304
+ for (const toolResponse of content) {
305
+ if (toolResponse.type === "tool-approval-response") continue;
306
+ const output = toolResponse.output;
307
+ let contentValue;
308
+ switch (output.type) {
309
+ case "text":
310
+ case "error-text":
311
+ contentValue = output.value;
312
+ break;
313
+ case "execution-denied":
314
+ contentValue = output.reason ?? "Tool call execution denied.";
315
+ break;
316
+ case "json":
317
+ case "error-json":
318
+ contentValue = JSON.stringify(output.value);
319
+ break;
320
+ case "content":
321
+ if (!output.value.some((part) => part.type === "file" && (part.data.type === "reference" || part.data.type === "url" || part.data.type === "data") && getTopLevelMediaType(part.mediaType) === "image")) {
322
+ contentValue = JSON.stringify(output.value);
323
+ break;
324
+ }
325
+ contentValue = [];
326
+ for (const part of output.value) if (part.type === "text") contentValue.push({
327
+ type: "text",
328
+ text: part.text
329
+ });
330
+ else if (part.type === "file" && (part.data.type === "reference" || part.data.type === "url" || part.data.type === "data") && getTopLevelMediaType(part.mediaType) === "image") {
331
+ if (part.data.type === "reference") {
332
+ contentValue.push({
333
+ type: "file",
334
+ file_id: resolveProviderReference({
335
+ reference: part.data.reference,
336
+ provider: "deepseek"
337
+ })
338
+ });
339
+ continue;
340
+ }
341
+ const filePartOptions = await parseProviderOptions({
342
+ provider: providerOptionsName,
343
+ providerOptions: part.providerOptions,
344
+ schema: deepseekFilePartProviderOptions
345
+ });
346
+ const resolvedMediaType = resolveDeepSeekImageMediaType(part);
347
+ let url;
348
+ if (part.data.type === "url") {
349
+ url = part.data.url.toString();
350
+ validateDeepSeekImageUrl({
351
+ url,
352
+ prompt
353
+ });
354
+ } else url = `data:${resolvedMediaType === "image/jpg" ? "image/jpeg" : resolvedMediaType};base64,${convertToBase64(part.data.data)}`;
355
+ contentValue.push({
356
+ type: "image_url",
357
+ image_url: {
358
+ url,
359
+ ...filePartOptions?.imageDetail != null && { detail: filePartOptions.imageDetail }
360
+ }
361
+ });
362
+ } else warnings.push({
363
+ type: "unsupported",
364
+ feature: `tool result content part type: ${part.type}`
365
+ });
366
+ }
367
+ messages.push({
368
+ role: "tool",
369
+ tool_call_id: toolResponse.toolCallId,
370
+ content: contentValue
371
+ });
372
+ }
373
+ break;
374
+ default: warnings.push({
375
+ type: "unsupported",
376
+ feature: `message role: ${role}`
377
+ });
378
+ }
379
+ }
380
+ return {
381
+ messages,
382
+ warnings
383
+ };
482
384
  }
483
-
484
- // src/chat/convert-to-deepseek-usage.ts
485
- import { createNullLanguageModelUsage } from "@ai-sdk/provider-utils";
385
+ //#endregion
386
+ //#region src/chat/convert-to-deepseek-usage.ts
486
387
  function convertDeepSeekUsage(usage) {
487
- if (usage == null) {
488
- return createNullLanguageModelUsage();
489
- }
490
- const promptTokens = usage.prompt_tokens ?? 0;
491
- const completionTokens = usage.completion_tokens ?? 0;
492
- const cacheReadTokens = usage.prompt_cache_hit_tokens ?? 0;
493
- const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? 0;
494
- return {
495
- inputTokens: {
496
- total: promptTokens,
497
- noCache: promptTokens - cacheReadTokens,
498
- cacheRead: cacheReadTokens,
499
- cacheWrite: void 0
500
- },
501
- outputTokens: {
502
- total: completionTokens,
503
- text: Math.max(0, completionTokens - reasoningTokens),
504
- reasoning: reasoningTokens
505
- },
506
- raw: usage
507
- };
388
+ if (usage == null) return createNullLanguageModelUsage();
389
+ const promptTokens = usage.prompt_tokens ?? 0;
390
+ const completionTokens = usage.completion_tokens ?? 0;
391
+ const cacheReadTokens = usage.prompt_cache_hit_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? 0;
392
+ const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? 0;
393
+ return {
394
+ inputTokens: {
395
+ total: promptTokens,
396
+ noCache: promptTokens - cacheReadTokens,
397
+ cacheRead: cacheReadTokens,
398
+ cacheWrite: void 0
399
+ },
400
+ outputTokens: {
401
+ total: completionTokens,
402
+ text: Math.max(0, completionTokens - reasoningTokens),
403
+ reasoning: reasoningTokens
404
+ },
405
+ raw: usage
406
+ };
508
407
  }
509
-
510
- // src/chat/deepseek-chat-api-types.ts
511
- import { lazySchema, zodSchema } from "@ai-sdk/provider-utils";
512
- import { z as z3 } from "zod/v4";
513
- var tokenUsageSchema = z3.looseObject({
514
- prompt_tokens: z3.number().nullish(),
515
- completion_tokens: z3.number().nullish(),
516
- prompt_cache_hit_tokens: z3.number().nullish(),
517
- prompt_cache_miss_tokens: z3.number().nullish(),
518
- total_tokens: z3.number().nullish(),
519
- prompt_tokens_details: z3.looseObject({
520
- cached_tokens: z3.number().nullish()
521
- }).nullish(),
522
- completion_tokens_details: z3.looseObject({
523
- reasoning_tokens: z3.number().nullish()
524
- }).nullish()
408
+ //#endregion
409
+ //#region src/chat/deepseek-chat-api-types.ts
410
+ const tokenUsageSchema = z.looseObject({
411
+ prompt_tokens: z.number().nullish(),
412
+ completion_tokens: z.number().nullish(),
413
+ prompt_cache_hit_tokens: z.number().nullish(),
414
+ prompt_cache_miss_tokens: z.number().nullish(),
415
+ total_tokens: z.number().nullish(),
416
+ prompt_tokens_details: z.looseObject({ cached_tokens: z.number().nullish() }).nullish(),
417
+ completion_tokens_details: z.looseObject({ reasoning_tokens: z.number().nullish() }).nullish()
525
418
  }).nullish();
526
- var deepSeekErrorSchema = z3.object({
527
- error: z3.object({
528
- message: z3.string(),
529
- type: z3.string().nullish(),
530
- param: z3.any().nullish(),
531
- code: z3.union([z3.string(), z3.number()]).nullish()
532
- })
533
- });
534
- var deepseekChatLogprobSchema = z3.object({
535
- token: z3.string(),
536
- logprob: z3.number(),
537
- bytes: z3.array(z3.number()).nullable(),
538
- top_logprobs: z3.array(
539
- z3.object({
540
- token: z3.string(),
541
- logprob: z3.number(),
542
- bytes: z3.array(z3.number()).nullable()
543
- })
544
- )
419
+ const deepSeekErrorSchema = z.object({ error: z.object({
420
+ message: z.string(),
421
+ type: z.string().nullish(),
422
+ param: z.any().nullish(),
423
+ code: z.union([z.string(), z.number()]).nullish()
424
+ }) });
425
+ const deepseekChatLogprobSchema = z.object({
426
+ token: z.string(),
427
+ logprob: z.number(),
428
+ bytes: z.array(z.number()).nullable(),
429
+ top_logprobs: z.array(z.object({
430
+ token: z.string(),
431
+ logprob: z.number(),
432
+ bytes: z.array(z.number()).nullable()
433
+ }))
545
434
  });
546
- var deepseekChatLogprobsSchema = z3.object({
547
- content: z3.array(deepseekChatLogprobSchema).nullish(),
548
- reasoning_content: z3.array(deepseekChatLogprobSchema).nullish()
435
+ const deepseekChatLogprobsSchema = z.object({
436
+ content: z.array(deepseekChatLogprobSchema).nullish(),
437
+ reasoning_content: z.array(deepseekChatLogprobSchema).nullish()
549
438
  }).nullish();
550
- var deepseekChatResponseSchema = z3.object({
551
- id: z3.string().nullish(),
552
- created: z3.number().nullish(),
553
- model: z3.string().nullish(),
554
- object: z3.literal("chat.completion").nullish(),
555
- system_fingerprint: z3.string().nullish(),
556
- choices: z3.array(
557
- z3.object({
558
- index: z3.number().nullish(),
559
- message: z3.object({
560
- role: z3.literal("assistant").nullish(),
561
- content: z3.string().nullish(),
562
- reasoning_content: z3.string().nullish(),
563
- tool_calls: z3.array(
564
- z3.object({
565
- id: z3.string().nullish(),
566
- type: z3.literal("function").nullish(),
567
- function: z3.object({
568
- name: z3.string(),
569
- arguments: z3.string()
570
- })
571
- })
572
- ).nullish()
573
- }),
574
- logprobs: deepseekChatLogprobsSchema,
575
- finish_reason: z3.string().nullish()
576
- })
577
- ),
578
- usage: tokenUsageSchema
439
+ const deepseekChatResponseSchema = z.object({
440
+ id: z.string().nullish(),
441
+ created: z.number().nullish(),
442
+ model: z.string().nullish(),
443
+ object: z.literal("chat.completion").nullish(),
444
+ system_fingerprint: z.string().nullish(),
445
+ choices: z.array(z.object({
446
+ index: z.number().nullish(),
447
+ message: z.object({
448
+ role: z.literal("assistant").nullish(),
449
+ content: z.string().nullish(),
450
+ reasoning_content: z.string().nullish(),
451
+ tool_calls: z.array(z.object({
452
+ id: z.string().nullish(),
453
+ type: z.literal("function").nullish(),
454
+ function: z.object({
455
+ name: z.string(),
456
+ arguments: z.string()
457
+ })
458
+ })).nullish()
459
+ }),
460
+ logprobs: deepseekChatLogprobsSchema,
461
+ finish_reason: z.string().nullish()
462
+ })),
463
+ usage: tokenUsageSchema
579
464
  });
580
- var deepseekChatChunkSchema = lazySchema(
581
- () => zodSchema(
582
- z3.union([
583
- z3.object({
584
- id: z3.string().nullish(),
585
- created: z3.number().nullish(),
586
- model: z3.string().nullish(),
587
- object: z3.literal("chat.completion.chunk").nullish(),
588
- system_fingerprint: z3.string().nullish(),
589
- choices: z3.array(
590
- z3.object({
591
- index: z3.number().nullish(),
592
- delta: z3.object({
593
- role: z3.enum(["assistant"]).nullish(),
594
- content: z3.string().nullish(),
595
- reasoning_content: z3.string().nullish(),
596
- tool_calls: z3.array(
597
- z3.object({
598
- index: z3.number(),
599
- id: z3.string().nullish(),
600
- type: z3.literal("function").nullish(),
601
- function: z3.object({
602
- name: z3.string().nullish(),
603
- arguments: z3.string().nullish()
604
- })
605
- })
606
- ).nullish()
607
- }).nullish(),
608
- logprobs: deepseekChatLogprobsSchema,
609
- finish_reason: z3.string().nullish()
610
- })
611
- ),
612
- usage: tokenUsageSchema
613
- }),
614
- deepSeekErrorSchema
615
- ])
616
- )
617
- );
618
-
619
- // src/chat/deepseek-prepare-tools.ts
620
- import {
621
- UnsupportedFunctionalityError as UnsupportedFunctionalityError2
622
- } from "@ai-sdk/provider";
623
- function prepareTools({
624
- tools,
625
- toolChoice,
626
- supportsStrictToolCalls
627
- }) {
628
- tools = tools?.length ? tools : void 0;
629
- const toolWarnings = [];
630
- if (tools == null) {
631
- return { tools: void 0, toolChoice: void 0, toolWarnings };
632
- }
633
- const functionTools = tools.filter((tool) => tool.type === "function");
634
- const hasStrictTool = functionTools.some((tool) => tool.strict === true);
635
- if (hasStrictTool && supportsStrictToolCalls === false) {
636
- throw new UnsupportedFunctionalityError2({
637
- functionality: "DeepSeek strict tool calls",
638
- message: "DeepSeek strict tool calls require a beta base URL ending in `/beta`."
639
- });
640
- }
641
- if (hasStrictTool && supportsStrictToolCalls === true && functionTools.some((tool) => tool.strict !== true)) {
642
- throw new UnsupportedFunctionalityError2({
643
- functionality: "mixed DeepSeek strict and non-strict tool calls",
644
- message: "DeepSeek strict mode requires every function tool in the request to set `strict: true`."
645
- });
646
- }
647
- const deepseekTools = [];
648
- for (const tool of tools) {
649
- if (tool.type === "provider") {
650
- toolWarnings.push({
651
- type: "unsupported",
652
- feature: `provider-defined tool ${tool.id}`
653
- });
654
- } else {
655
- deepseekTools.push({
656
- type: "function",
657
- function: {
658
- name: tool.name,
659
- description: tool.description,
660
- parameters: tool.inputSchema,
661
- ...tool.strict != null ? { strict: tool.strict } : {}
662
- }
663
- });
664
- }
665
- }
666
- if (toolChoice == null) {
667
- return { tools: deepseekTools, toolChoice: void 0, toolWarnings };
668
- }
669
- const type = toolChoice?.type;
670
- switch (type) {
671
- case "auto":
672
- case "none":
673
- case "required":
674
- return { tools: deepseekTools, toolChoice: type, toolWarnings };
675
- case "tool":
676
- return {
677
- tools: deepseekTools,
678
- toolChoice: {
679
- type: "function",
680
- function: { name: toolChoice.toolName }
681
- },
682
- toolWarnings
683
- };
684
- default: {
685
- return {
686
- tools: deepseekTools,
687
- toolChoice: void 0,
688
- toolWarnings: [
689
- ...toolWarnings,
690
- {
691
- type: "unsupported",
692
- feature: `tool choice type: ${type}`
693
- }
694
- ]
695
- };
696
- }
697
- }
465
+ const deepseekChatChunkSchema = lazySchema(() => zodSchema(z.union([z.object({
466
+ id: z.string().nullish(),
467
+ created: z.number().nullish(),
468
+ model: z.string().nullish(),
469
+ object: z.literal("chat.completion.chunk").nullish(),
470
+ system_fingerprint: z.string().nullish(),
471
+ choices: z.array(z.object({
472
+ index: z.number().nullish(),
473
+ delta: z.object({
474
+ role: z.enum(["assistant"]).nullish(),
475
+ content: z.string().nullish(),
476
+ reasoning_content: z.string().nullish(),
477
+ tool_calls: z.array(z.object({
478
+ index: z.number(),
479
+ id: z.string().nullish(),
480
+ type: z.literal("function").nullish(),
481
+ function: z.object({
482
+ name: z.string().nullish(),
483
+ arguments: z.string().nullish()
484
+ })
485
+ })).nullish()
486
+ }).nullish(),
487
+ logprobs: deepseekChatLogprobsSchema,
488
+ finish_reason: z.string().nullish()
489
+ })),
490
+ usage: tokenUsageSchema
491
+ }), deepSeekErrorSchema])));
492
+ //#endregion
493
+ //#region src/chat/deepseek-prepare-tools.ts
494
+ function prepareTools({ tools, toolChoice, supportsStrictToolCalls }) {
495
+ tools = tools?.length ? tools : void 0;
496
+ const toolWarnings = [];
497
+ if (tools == null) return {
498
+ tools: void 0,
499
+ toolChoice: void 0,
500
+ toolWarnings
501
+ };
502
+ const functionTools = tools.filter((tool) => tool.type === "function");
503
+ const hasStrictTool = functionTools.some((tool) => tool.strict === true);
504
+ if (hasStrictTool && supportsStrictToolCalls === false) throw new UnsupportedFunctionalityError({
505
+ functionality: "DeepSeek strict tool calls",
506
+ message: "DeepSeek strict tool calls require a beta base URL ending in `/beta`."
507
+ });
508
+ if (hasStrictTool && supportsStrictToolCalls === true && functionTools.some((tool) => tool.strict !== true)) throw new UnsupportedFunctionalityError({
509
+ functionality: "mixed DeepSeek strict and non-strict tool calls",
510
+ message: "DeepSeek strict mode requires every function tool in the request to set `strict: true`."
511
+ });
512
+ const deepseekTools = [];
513
+ for (const tool of tools) if (tool.type === "provider") toolWarnings.push({
514
+ type: "unsupported",
515
+ feature: `provider-defined tool ${tool.id}`
516
+ });
517
+ else deepseekTools.push({
518
+ type: "function",
519
+ function: {
520
+ name: tool.name,
521
+ description: tool.description,
522
+ parameters: tool.inputSchema,
523
+ ...tool.strict != null ? { strict: tool.strict } : {}
524
+ }
525
+ });
526
+ if (toolChoice == null) return {
527
+ tools: deepseekTools,
528
+ toolChoice: void 0,
529
+ toolWarnings
530
+ };
531
+ const type = toolChoice?.type;
532
+ switch (type) {
533
+ case "auto":
534
+ case "none":
535
+ case "required": return {
536
+ tools: deepseekTools,
537
+ toolChoice: type,
538
+ toolWarnings
539
+ };
540
+ case "tool": return {
541
+ tools: deepseekTools,
542
+ toolChoice: {
543
+ type: "function",
544
+ function: { name: toolChoice.toolName }
545
+ },
546
+ toolWarnings
547
+ };
548
+ default: return {
549
+ tools: deepseekTools,
550
+ toolChoice: void 0,
551
+ toolWarnings: [...toolWarnings, {
552
+ type: "unsupported",
553
+ feature: `tool choice type: ${type}`
554
+ }]
555
+ };
556
+ }
698
557
  }
699
-
700
- // src/chat/get-response-metadata.ts
701
- import { createLanguageModelResponseMetadata } from "@ai-sdk/provider-utils";
702
-
703
- // src/chat/map-deepseek-finish-reason.ts
558
+ //#endregion
559
+ //#region src/chat/map-deepseek-finish-reason.ts
704
560
  function mapDeepSeekFinishReason(finishReason) {
705
- switch (finishReason) {
706
- case "stop":
707
- return "stop";
708
- case "length":
709
- return "length";
710
- case "content_filter":
711
- return "content-filter";
712
- case "tool_calls":
713
- return "tool-calls";
714
- case "insufficient_system_resource":
715
- return "error";
716
- default:
717
- return "other";
718
- }
561
+ switch (finishReason) {
562
+ case "stop": return "stop";
563
+ case "length": return "length";
564
+ case "content_filter": return "content-filter";
565
+ case "tool_calls": return "tool-calls";
566
+ case "insufficient_system_resource": return "error";
567
+ default: return "other";
568
+ }
719
569
  }
720
-
721
- // src/chat/deepseek-chat-language-model.ts
570
+ //#endregion
571
+ //#region src/chat/deepseek-chat-language-model.ts
722
572
  function createDeepSeekStreamError(error, data) {
723
- const metadata = getDeepSeekStreamErrorMetadata(error);
724
- return createProviderStreamError({
725
- message: error.message,
726
- type: error.type ?? void 0,
727
- code: error.code ?? void 0,
728
- ...metadata,
729
- data
730
- });
573
+ const metadata = getDeepSeekStreamErrorMetadata(error);
574
+ return createProviderStreamError({
575
+ message: error.message,
576
+ type: error.type ?? void 0,
577
+ code: error.code ?? void 0,
578
+ ...metadata,
579
+ data
580
+ });
731
581
  }
732
582
  function getDeepSeekStreamErrorMetadata(error) {
733
- if (error.code === "insufficient_quota" || error.type === "insufficient_quota") {
734
- return { statusCode: 429, isRetryable: false };
735
- }
736
- const explicitStatusCode = getHttpStatusCode(error.code);
737
- if (explicitStatusCode != null) {
738
- return {
739
- statusCode: explicitStatusCode,
740
- isRetryable: isRetryableStatusCode(explicitStatusCode)
741
- };
742
- }
743
- for (const discriminator of [error.code, error.type]) {
744
- switch (discriminator) {
745
- case "rate_limit_exceeded":
746
- case "rate_limit_error":
747
- return { statusCode: 429, isRetryable: true };
748
- case "server_error":
749
- case "api_error":
750
- case "internal_server_error":
751
- return { statusCode: 500, isRetryable: true };
752
- case "overloaded_error":
753
- case "service_unavailable":
754
- return { statusCode: 503, isRetryable: true };
755
- case "timeout":
756
- case "timeout_error":
757
- return { statusCode: 504, isRetryable: true };
758
- case "authentication_error":
759
- case "invalid_api_key":
760
- return { statusCode: 401, isRetryable: false };
761
- case "permission_error":
762
- return { statusCode: 403, isRetryable: false };
763
- case "not_found_error":
764
- case "model_not_found":
765
- return { statusCode: 404, isRetryable: false };
766
- case "bad_request":
767
- case "context_length_exceeded":
768
- case "invalid_request_error":
769
- return { statusCode: 400, isRetryable: false };
770
- }
771
- }
772
- return {};
583
+ if (error.code === "insufficient_quota" || error.type === "insufficient_quota") return {
584
+ statusCode: 429,
585
+ isRetryable: false
586
+ };
587
+ const explicitStatusCode = getHttpStatusCode(error.code);
588
+ if (explicitStatusCode != null) return {
589
+ statusCode: explicitStatusCode,
590
+ isRetryable: isRetryableStatusCode(explicitStatusCode)
591
+ };
592
+ for (const discriminator of [error.code, error.type]) switch (discriminator) {
593
+ case "rate_limit_exceeded":
594
+ case "rate_limit_error": return {
595
+ statusCode: 429,
596
+ isRetryable: true
597
+ };
598
+ case "server_error":
599
+ case "api_error":
600
+ case "internal_server_error": return {
601
+ statusCode: 500,
602
+ isRetryable: true
603
+ };
604
+ case "overloaded_error":
605
+ case "service_unavailable": return {
606
+ statusCode: 503,
607
+ isRetryable: true
608
+ };
609
+ case "timeout":
610
+ case "timeout_error": return {
611
+ statusCode: 504,
612
+ isRetryable: true
613
+ };
614
+ case "authentication_error":
615
+ case "invalid_api_key": return {
616
+ statusCode: 401,
617
+ isRetryable: false
618
+ };
619
+ case "permission_error": return {
620
+ statusCode: 403,
621
+ isRetryable: false
622
+ };
623
+ case "not_found_error":
624
+ case "model_not_found": return {
625
+ statusCode: 404,
626
+ isRetryable: false
627
+ };
628
+ case "bad_request":
629
+ case "context_length_exceeded":
630
+ case "invalid_request_error": return {
631
+ statusCode: 400,
632
+ isRetryable: false
633
+ };
634
+ }
635
+ return {};
773
636
  }
774
637
  function getHttpStatusCode(value) {
775
- const statusCode = typeof value === "string" && /^\d{3}$/.test(value) ? Number(value) : value;
776
- return typeof statusCode === "number" && Number.isInteger(statusCode) && statusCode >= 400 && statusCode <= 599 ? statusCode : void 0;
638
+ const statusCode = typeof value === "string" && /^\d{3}$/.test(value) ? Number(value) : value;
639
+ return typeof statusCode === "number" && Number.isInteger(statusCode) && statusCode >= 400 && statusCode <= 599 ? statusCode : void 0;
777
640
  }
778
641
  function isRetryableStatusCode(statusCode) {
779
- return statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500;
642
+ return statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500;
780
643
  }
781
- function mapDeepSeekProviderReasoningEffort({
782
- reasoningEffort,
783
- warnings
784
- }) {
785
- const mapped = reasoningEffort === "medium" ? "high" : reasoningEffort === "xhigh" ? "max" : reasoningEffort;
786
- if (mapped !== reasoningEffort) {
787
- warnings.push({
788
- type: "compatibility",
789
- feature: "reasoningEffort",
790
- details: `reasoningEffort "${reasoningEffort}" is not a canonical DeepSeek value. mapped to "${mapped}".`
791
- });
792
- }
793
- return mapped;
644
+ function mapDeepSeekProviderReasoningEffort({ reasoningEffort, warnings }) {
645
+ const mapped = reasoningEffort === "medium" ? "high" : reasoningEffort === "xhigh" ? "max" : reasoningEffort;
646
+ if (mapped !== reasoningEffort) warnings.push({
647
+ type: "compatibility",
648
+ feature: "reasoningEffort",
649
+ details: `reasoningEffort "${reasoningEffort}" is not a canonical DeepSeek value. mapped to "${mapped}".`
650
+ });
651
+ return mapped;
794
652
  }
795
- var DeepSeekChatLanguageModel = class _DeepSeekChatLanguageModel {
796
- constructor(modelId, config) {
797
- this.specificationVersion = "v4";
798
- this.supportedUrls = {
799
- "image/*": [/^https?:\/\/.*$/]
800
- };
801
- this.modelId = modelId;
802
- this.config = config;
803
- this.failedResponseHandler = createJsonErrorResponseHandler({
804
- errorSchema: deepSeekErrorSchema,
805
- errorToMessage: (error) => error.error.message
806
- });
807
- }
808
- static [WORKFLOW_SERIALIZE](model) {
809
- return serializeModelOptions({
810
- modelId: model.modelId,
811
- config: model.config
812
- });
813
- }
814
- static [WORKFLOW_DESERIALIZE](options) {
815
- return new _DeepSeekChatLanguageModel(options.modelId, options.config);
816
- }
817
- get provider() {
818
- return this.config.provider;
819
- }
820
- get providerOptionsName() {
821
- return this.config.provider.split(".")[0].trim();
822
- }
823
- async getArgs({
824
- prompt,
825
- maxOutputTokens,
826
- temperature,
827
- topP,
828
- topK,
829
- frequencyPenalty,
830
- presencePenalty,
831
- reasoning,
832
- providerOptions,
833
- stopSequences,
834
- responseFormat,
835
- seed,
836
- toolChoice,
837
- tools
838
- }) {
839
- const deepseekOptions = await parseProviderOptions2({
840
- provider: this.providerOptionsName,
841
- providerOptions,
842
- schema: deepseekLanguageModelChatOptions
843
- }) ?? {};
844
- const supportsStructuredOutputs = this.config.supportsStructuredOutputs === true;
845
- const supportsPenaltySampling = this.config.supportsPenaltySampling === true;
846
- const { messages, warnings } = await convertToDeepSeekChatMessages({
847
- prompt,
848
- responseFormat,
849
- modelId: this.modelId,
850
- providerOptionsName: this.providerOptionsName,
851
- supportsAssistantPrefixCompletion: this.config.supportsAssistantPrefixCompletion,
852
- supportsStructuredOutputs
853
- });
854
- const allWarnings = [...warnings];
855
- if (topK != null) {
856
- allWarnings.push({ type: "unsupported", feature: "topK" });
857
- }
858
- if (seed != null) {
859
- allWarnings.push({ type: "unsupported", feature: "seed" });
860
- }
861
- if (!supportsPenaltySampling && frequencyPenalty != null) {
862
- allWarnings.push({
863
- type: "deprecated",
864
- setting: "frequencyPenalty",
865
- message: "frequencyPenalty is deprecated by DeepSeek and has been omitted. Remove frequencyPenalty from the request."
866
- });
867
- }
868
- if (!supportsPenaltySampling && presencePenalty != null) {
869
- allWarnings.push({
870
- type: "deprecated",
871
- setting: "presencePenalty",
872
- message: "presencePenalty is deprecated by DeepSeek and has been omitted. Remove presencePenalty from the request."
873
- });
874
- }
875
- const {
876
- tools: deepseekTools,
877
- toolChoice: deepseekToolChoices,
878
- toolWarnings
879
- } = prepareTools({
880
- tools,
881
- toolChoice,
882
- supportsStrictToolCalls: this.config.supportsStrictToolCalls
883
- });
884
- const thinkingType = deepseekOptions.thinking?.type;
885
- if (thinkingType === "adaptive") {
886
- allWarnings.push({
887
- type: "compatibility",
888
- feature: "thinking.type",
889
- details: 'thinking.type "adaptive" is not a canonical DeepSeek value. mapped to "enabled".'
890
- });
891
- }
892
- const thinking = this.config.supportsThinking === false ? void 0 : thinkingType != null ? { type: thinkingType === "adaptive" ? "enabled" : thinkingType } : isCustomReasoning(reasoning) ? { type: reasoning === "none" ? "disabled" : "enabled" } : void 0;
893
- const isThinkingEnabled = this.config.supportsThinking !== false && thinking?.type !== "disabled" && (thinking != null || this.modelId === "deepseek-reasoner" || isDeepSeekV4Model(this.modelId));
894
- if (isThinkingEnabled && temperature != null) {
895
- allWarnings.push({
896
- type: "unsupported",
897
- feature: "temperature",
898
- details: "temperature has no effect when DeepSeek thinking is enabled. Set providerOptions.deepseek.thinking.type to 'disabled' to use temperature."
899
- });
900
- }
901
- if (isThinkingEnabled && topP != null) {
902
- allWarnings.push({
903
- type: "unsupported",
904
- feature: "topP",
905
- details: "topP has no effect when DeepSeek thinking is enabled. Set providerOptions.deepseek.thinking.type to 'disabled' to use topP."
906
- });
907
- }
908
- const reasoningEffort = deepseekOptions.reasoningEffort != null ? mapDeepSeekProviderReasoningEffort({
909
- reasoningEffort: deepseekOptions.reasoningEffort,
910
- warnings: allWarnings
911
- }) : isCustomReasoning(reasoning) && reasoning !== "none" ? mapReasoningToProviderEffort({
912
- reasoning,
913
- effortMap: {
914
- minimal: "low",
915
- low: "low",
916
- medium: "high",
917
- high: "high",
918
- xhigh: "max"
919
- },
920
- warnings: allWarnings
921
- }) : void 0;
922
- return {
923
- args: {
924
- model: this.modelId,
925
- ...(deepseekOptions.logprobs === true || deepseekOptions.topLogprobs != null) && { logprobs: true },
926
- ...deepseekOptions.topLogprobs != null && {
927
- top_logprobs: deepseekOptions.topLogprobs
928
- },
929
- max_tokens: maxOutputTokens,
930
- temperature: isThinkingEnabled ? void 0 : temperature,
931
- top_p: isThinkingEnabled ? void 0 : topP,
932
- frequency_penalty: supportsPenaltySampling ? frequencyPenalty : void 0,
933
- presence_penalty: supportsPenaltySampling ? presencePenalty : void 0,
934
- response_format: responseFormat?.type === "json" ? supportsStructuredOutputs && responseFormat.schema != null ? {
935
- type: "json_schema",
936
- json_schema: {
937
- schema: responseFormat.schema,
938
- strict: deepseekOptions.strictJsonSchema ?? true,
939
- name: responseFormat.name ?? "response",
940
- description: responseFormat.description
941
- }
942
- } : { type: "json_object" } : void 0,
943
- stop: stopSequences,
944
- messages,
945
- tools: deepseekTools,
946
- tool_choice: deepseekToolChoices,
947
- thinking,
948
- ...deepseekOptions.userId != null && {
949
- user_id: deepseekOptions.userId
950
- },
951
- ...thinking?.type !== "disabled" && reasoningEffort != null && {
952
- reasoning_effort: reasoningEffort
953
- }
954
- },
955
- warnings: [...allWarnings, ...toolWarnings]
956
- };
957
- }
958
- async doGenerate(options) {
959
- const { args, warnings } = await this.getArgs({ ...options });
960
- const {
961
- responseHeaders,
962
- value: responseBody,
963
- rawValue: rawResponse
964
- } = await postJsonToApi({
965
- url: this.config.url({
966
- path: "/chat/completions",
967
- modelId: this.modelId
968
- }),
969
- headers: combineHeaders(this.config.headers?.(), options.headers),
970
- body: args,
971
- failedResponseHandler: this.failedResponseHandler,
972
- successfulResponseHandler: createJsonResponseHandler(
973
- deepseekChatResponseSchema
974
- ),
975
- abortSignal: options.abortSignal,
976
- fetch: this.config.fetch
977
- });
978
- const choice = responseBody.choices[0];
979
- if (choice == null) {
980
- throw new InvalidResponseDataError({
981
- data: rawResponse,
982
- message: "Response did not contain any choices."
983
- });
984
- }
985
- const content = [];
986
- const reasoning = choice.message.reasoning_content;
987
- if (reasoning != null && reasoning.length > 0) {
988
- content.push({
989
- type: "reasoning",
990
- text: reasoning
991
- });
992
- }
993
- if (choice.message.tool_calls != null) {
994
- for (const toolCall of choice.message.tool_calls) {
995
- content.push({
996
- type: "tool-call",
997
- toolCallId: toolCall.id || generateId(),
998
- toolName: toolCall.function.name,
999
- input: toolCall.function.arguments
1000
- });
1001
- }
1002
- }
1003
- const text = choice.message.content;
1004
- if (text != null && text.length > 0) {
1005
- content.push({ type: "text", text });
1006
- }
1007
- return {
1008
- content,
1009
- finishReason: {
1010
- unified: mapDeepSeekFinishReason(choice.finish_reason),
1011
- raw: choice.finish_reason ?? void 0
1012
- },
1013
- usage: convertDeepSeekUsage(responseBody.usage),
1014
- providerMetadata: {
1015
- [this.providerOptionsName]: {
1016
- promptCacheHitTokens: responseBody.usage?.prompt_cache_hit_tokens,
1017
- promptCacheMissTokens: responseBody.usage?.prompt_cache_miss_tokens,
1018
- ...responseBody.object != null && {
1019
- responseObject: responseBody.object
1020
- },
1021
- ...choice.index != null && { choiceIndex: choice.index },
1022
- ...choice.message.role != null && {
1023
- messageRole: choice.message.role
1024
- },
1025
- ...choice.message.tool_calls != null && {
1026
- toolCallTypes: choice.message.tool_calls.map((toolCall) => toolCall.type).filter((type) => type != null)
1027
- },
1028
- ...choice.logprobs != null && { logprobs: choice.logprobs },
1029
- ...responseBody.system_fingerprint != null && {
1030
- systemFingerprint: responseBody.system_fingerprint
1031
- }
1032
- }
1033
- },
1034
- request: { body: args },
1035
- response: {
1036
- ...createLanguageModelResponseMetadata(responseBody),
1037
- headers: responseHeaders,
1038
- body: rawResponse
1039
- },
1040
- warnings
1041
- };
1042
- }
1043
- async doStream(options) {
1044
- const { args, warnings } = await this.getArgs({ ...options });
1045
- const body = {
1046
- ...args,
1047
- stream: true,
1048
- stream_options: { include_usage: true }
1049
- };
1050
- const { responseHeaders, value: response } = await postJsonToApi({
1051
- url: this.config.url({
1052
- path: "/chat/completions",
1053
- modelId: this.modelId
1054
- }),
1055
- headers: combineHeaders(this.config.headers?.(), options.headers),
1056
- body,
1057
- failedResponseHandler: this.failedResponseHandler,
1058
- successfulResponseHandler: createEventSourceResponseHandler(
1059
- deepseekChatChunkSchema
1060
- ),
1061
- abortSignal: options.abortSignal,
1062
- fetch: this.config.fetch
1063
- });
1064
- let toolCallTracker;
1065
- let finishReason = {
1066
- unified: "other",
1067
- raw: void 0
1068
- };
1069
- let usage = void 0;
1070
- let systemFingerprint = void 0;
1071
- let isFirstChunk = true;
1072
- const providerOptionsName = this.providerOptionsName;
1073
- let isActiveReasoning = false;
1074
- let isActiveText = false;
1075
- let responseObject;
1076
- let choiceIndex;
1077
- let messageRole;
1078
- const toolCallTypes = /* @__PURE__ */ new Map();
1079
- const contentLogprobs = [];
1080
- const reasoningLogprobs = [];
1081
- return {
1082
- stream: response.pipeThrough(
1083
- new TransformStream({
1084
- start(controller) {
1085
- toolCallTracker = new StreamingToolCallTracker(controller, {
1086
- generateId
1087
- });
1088
- controller.enqueue({ type: "stream-start", warnings });
1089
- },
1090
- transform(chunk, controller) {
1091
- if (options.includeRawChunks) {
1092
- controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
1093
- }
1094
- if (!chunk.success) {
1095
- finishReason = { unified: "error", raw: void 0 };
1096
- controller.enqueue({ type: "error", error: chunk.error });
1097
- return;
1098
- }
1099
- const value = chunk.value;
1100
- if ("error" in value) {
1101
- finishReason = { unified: "error", raw: void 0 };
1102
- controller.enqueue({
1103
- type: "error",
1104
- error: createDeepSeekStreamError(value.error, value)
1105
- });
1106
- return;
1107
- }
1108
- if (isFirstChunk) {
1109
- isFirstChunk = false;
1110
- controller.enqueue({
1111
- type: "response-metadata",
1112
- ...createLanguageModelResponseMetadata(value)
1113
- });
1114
- }
1115
- if (value.usage != null) {
1116
- usage = value.usage;
1117
- }
1118
- if (value.object != null) {
1119
- responseObject = value.object;
1120
- }
1121
- if (value.system_fingerprint != null) {
1122
- systemFingerprint = value.system_fingerprint;
1123
- }
1124
- const choice = value.choices[0];
1125
- if (choice?.index != null) {
1126
- choiceIndex = choice.index;
1127
- }
1128
- if (choice?.finish_reason != null) {
1129
- finishReason = {
1130
- unified: mapDeepSeekFinishReason(choice.finish_reason),
1131
- raw: choice.finish_reason
1132
- };
1133
- }
1134
- if (choice?.logprobs?.content != null) {
1135
- contentLogprobs.push(...choice.logprobs.content);
1136
- }
1137
- if (choice?.logprobs?.reasoning_content != null) {
1138
- reasoningLogprobs.push(...choice.logprobs.reasoning_content);
1139
- }
1140
- if (choice?.delta == null) {
1141
- return;
1142
- }
1143
- const delta = choice.delta;
1144
- if (delta.role != null) {
1145
- messageRole = delta.role;
1146
- }
1147
- const reasoningContent = delta.reasoning_content;
1148
- if (reasoningContent) {
1149
- if (!isActiveReasoning) {
1150
- controller.enqueue({
1151
- type: "reasoning-start",
1152
- id: "reasoning-0"
1153
- });
1154
- isActiveReasoning = true;
1155
- }
1156
- controller.enqueue({
1157
- type: "reasoning-delta",
1158
- id: "reasoning-0",
1159
- delta: reasoningContent
1160
- });
1161
- }
1162
- if (delta.content) {
1163
- if (!isActiveText) {
1164
- controller.enqueue({ type: "text-start", id: "txt-0" });
1165
- isActiveText = true;
1166
- }
1167
- if (isActiveReasoning) {
1168
- controller.enqueue({
1169
- type: "reasoning-end",
1170
- id: "reasoning-0"
1171
- });
1172
- isActiveReasoning = false;
1173
- }
1174
- controller.enqueue({
1175
- type: "text-delta",
1176
- id: "txt-0",
1177
- delta: delta.content
1178
- });
1179
- }
1180
- if (delta.tool_calls != null && delta.tool_calls.length > 0) {
1181
- if (isActiveReasoning) {
1182
- controller.enqueue({
1183
- type: "reasoning-end",
1184
- id: "reasoning-0"
1185
- });
1186
- isActiveReasoning = false;
1187
- }
1188
- for (const toolCallDelta of delta.tool_calls) {
1189
- if (toolCallDelta.type != null) {
1190
- toolCallTypes.set(toolCallDelta.index, toolCallDelta.type);
1191
- }
1192
- toolCallTracker.processDelta(toolCallDelta);
1193
- }
1194
- }
1195
- },
1196
- flush(controller) {
1197
- if (isActiveReasoning) {
1198
- controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
1199
- }
1200
- if (isActiveText) {
1201
- controller.enqueue({ type: "text-end", id: "txt-0" });
1202
- }
1203
- toolCallTracker.flush();
1204
- controller.enqueue({
1205
- type: "finish",
1206
- finishReason,
1207
- usage: convertDeepSeekUsage(usage),
1208
- providerMetadata: {
1209
- [providerOptionsName]: {
1210
- promptCacheHitTokens: usage?.prompt_cache_hit_tokens ?? void 0,
1211
- promptCacheMissTokens: usage?.prompt_cache_miss_tokens ?? void 0,
1212
- ...responseObject != null && { responseObject },
1213
- ...choiceIndex != null && { choiceIndex },
1214
- ...messageRole != null && { messageRole },
1215
- ...toolCallTypes.size > 0 && {
1216
- toolCallTypes: [...toolCallTypes.entries()].sort(([left], [right]) => left - right).map(([, type]) => type)
1217
- },
1218
- ...(contentLogprobs.length > 0 || reasoningLogprobs.length > 0) && {
1219
- logprobs: {
1220
- ...contentLogprobs.length > 0 && {
1221
- content: contentLogprobs
1222
- },
1223
- ...reasoningLogprobs.length > 0 && {
1224
- reasoning_content: reasoningLogprobs
1225
- }
1226
- }
1227
- },
1228
- ...systemFingerprint != null && { systemFingerprint }
1229
- }
1230
- }
1231
- });
1232
- }
1233
- })
1234
- ),
1235
- request: { body },
1236
- response: { headers: responseHeaders }
1237
- };
1238
- }
1239
- };
1240
- export {
1241
- DeepSeekChatLanguageModel,
1242
- deepseekAssistantMessageProviderOptions,
1243
- deepseekLanguageModelChatOptions,
1244
- deepseekMessageProviderOptions
653
+ var DeepSeekChatLanguageModel = class DeepSeekChatLanguageModel {
654
+ static [WORKFLOW_SERIALIZE](model) {
655
+ return serializeModelOptions({
656
+ modelId: model.modelId,
657
+ config: model.config
658
+ });
659
+ }
660
+ static [WORKFLOW_DESERIALIZE](options) {
661
+ return new DeepSeekChatLanguageModel(options.modelId, options.config);
662
+ }
663
+ constructor(modelId, config) {
664
+ this.specificationVersion = "v4";
665
+ this.supportedUrls = { "image/*": [/^https?:\/\/.*$/] };
666
+ this.modelId = modelId;
667
+ this.config = config;
668
+ this.failedResponseHandler = createJsonErrorResponseHandler({
669
+ errorSchema: deepSeekErrorSchema,
670
+ errorToMessage: (error) => error.error.message
671
+ });
672
+ }
673
+ get provider() {
674
+ return this.config.provider;
675
+ }
676
+ get providerOptionsName() {
677
+ return this.config.provider.split(".")[0].trim();
678
+ }
679
+ async getArgs({ prompt, maxOutputTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, reasoning, providerOptions, stopSequences, responseFormat, seed, toolChoice, tools }) {
680
+ const deepseekOptions = await parseProviderOptions({
681
+ provider: this.providerOptionsName,
682
+ providerOptions,
683
+ schema: deepseekLanguageModelChatOptions
684
+ }) ?? {};
685
+ const supportsStructuredOutputs = this.config.supportsStructuredOutputs === true;
686
+ const supportsPenaltySampling = this.config.supportsPenaltySampling === true;
687
+ const { messages, warnings } = await convertToDeepSeekChatMessages({
688
+ prompt,
689
+ responseFormat,
690
+ modelId: this.modelId,
691
+ providerOptionsName: this.providerOptionsName,
692
+ supportsAssistantPrefixCompletion: this.config.supportsAssistantPrefixCompletion,
693
+ supportsStructuredOutputs
694
+ });
695
+ const allWarnings = [...warnings];
696
+ if (topK != null) allWarnings.push({
697
+ type: "unsupported",
698
+ feature: "topK"
699
+ });
700
+ if (seed != null) allWarnings.push({
701
+ type: "unsupported",
702
+ feature: "seed"
703
+ });
704
+ if (!supportsPenaltySampling && frequencyPenalty != null) allWarnings.push({
705
+ type: "deprecated",
706
+ setting: "frequencyPenalty",
707
+ message: "frequencyPenalty is deprecated by DeepSeek and has been omitted. Remove frequencyPenalty from the request."
708
+ });
709
+ if (!supportsPenaltySampling && presencePenalty != null) allWarnings.push({
710
+ type: "deprecated",
711
+ setting: "presencePenalty",
712
+ message: "presencePenalty is deprecated by DeepSeek and has been omitted. Remove presencePenalty from the request."
713
+ });
714
+ const { tools: deepseekTools, toolChoice: deepseekToolChoices, toolWarnings } = prepareTools({
715
+ tools,
716
+ toolChoice,
717
+ supportsStrictToolCalls: this.config.supportsStrictToolCalls
718
+ });
719
+ const thinkingType = deepseekOptions.thinking?.type;
720
+ if (thinkingType === "adaptive") allWarnings.push({
721
+ type: "compatibility",
722
+ feature: "thinking.type",
723
+ details: "thinking.type \"adaptive\" is not a canonical DeepSeek value. mapped to \"enabled\"."
724
+ });
725
+ const thinking = this.config.supportsThinking === false ? void 0 : thinkingType != null ? { type: thinkingType === "adaptive" ? "enabled" : thinkingType } : isCustomReasoning(reasoning) ? { type: reasoning === "none" ? "disabled" : "enabled" } : void 0;
726
+ const isThinkingEnabled = this.config.supportsThinking !== false && thinking?.type !== "disabled" && (thinking != null || this.modelId === "deepseek-reasoner" || isDeepSeekV4Model(this.modelId));
727
+ if (isThinkingEnabled && temperature != null) allWarnings.push({
728
+ type: "unsupported",
729
+ feature: "temperature",
730
+ details: "temperature has no effect when DeepSeek thinking is enabled. Set providerOptions.deepseek.thinking.type to 'disabled' to use temperature."
731
+ });
732
+ if (isThinkingEnabled && topP != null) allWarnings.push({
733
+ type: "unsupported",
734
+ feature: "topP",
735
+ details: "topP has no effect when DeepSeek thinking is enabled. Set providerOptions.deepseek.thinking.type to 'disabled' to use topP."
736
+ });
737
+ const reasoningEffort = deepseekOptions.reasoningEffort != null ? mapDeepSeekProviderReasoningEffort({
738
+ reasoningEffort: deepseekOptions.reasoningEffort,
739
+ warnings: allWarnings
740
+ }) : isCustomReasoning(reasoning) && reasoning !== "none" ? mapReasoningToProviderEffort({
741
+ reasoning,
742
+ effortMap: {
743
+ minimal: "low",
744
+ low: "low",
745
+ medium: "high",
746
+ high: "high",
747
+ xhigh: "max"
748
+ },
749
+ warnings: allWarnings
750
+ }) : void 0;
751
+ return {
752
+ args: {
753
+ model: this.modelId,
754
+ ...(deepseekOptions.logprobs === true || deepseekOptions.topLogprobs != null) && { logprobs: true },
755
+ ...deepseekOptions.topLogprobs != null && { top_logprobs: deepseekOptions.topLogprobs },
756
+ max_tokens: maxOutputTokens,
757
+ temperature: isThinkingEnabled ? void 0 : temperature,
758
+ top_p: isThinkingEnabled ? void 0 : topP,
759
+ frequency_penalty: supportsPenaltySampling ? frequencyPenalty : void 0,
760
+ presence_penalty: supportsPenaltySampling ? presencePenalty : void 0,
761
+ response_format: responseFormat?.type === "json" ? supportsStructuredOutputs && responseFormat.schema != null ? {
762
+ type: "json_schema",
763
+ json_schema: {
764
+ schema: responseFormat.schema,
765
+ strict: deepseekOptions.strictJsonSchema ?? true,
766
+ name: responseFormat.name ?? "response",
767
+ description: responseFormat.description
768
+ }
769
+ } : { type: "json_object" } : void 0,
770
+ stop: stopSequences,
771
+ messages,
772
+ tools: deepseekTools,
773
+ tool_choice: deepseekToolChoices,
774
+ thinking,
775
+ ...deepseekOptions.userId != null && { user_id: deepseekOptions.userId },
776
+ ...thinking?.type !== "disabled" && reasoningEffort != null && { reasoning_effort: reasoningEffort }
777
+ },
778
+ warnings: [...allWarnings, ...toolWarnings]
779
+ };
780
+ }
781
+ async doGenerate(options) {
782
+ const { args, warnings } = await this.getArgs({ ...options });
783
+ const { responseHeaders, value: responseBody, rawValue: rawResponse } = await postJsonToApi({
784
+ url: this.config.url({
785
+ path: "/chat/completions",
786
+ modelId: this.modelId
787
+ }),
788
+ headers: combineHeaders(this.config.headers?.(), options.headers),
789
+ body: args,
790
+ failedResponseHandler: this.failedResponseHandler,
791
+ successfulResponseHandler: createJsonResponseHandler(deepseekChatResponseSchema),
792
+ abortSignal: options.abortSignal,
793
+ fetch: this.config.fetch
794
+ });
795
+ const choice = responseBody.choices[0];
796
+ if (choice == null) throw new InvalidResponseDataError({
797
+ data: rawResponse,
798
+ message: "Response did not contain any choices."
799
+ });
800
+ const content = [];
801
+ const reasoning = choice.message.reasoning_content;
802
+ if (reasoning != null && reasoning.length > 0) content.push({
803
+ type: "reasoning",
804
+ text: reasoning
805
+ });
806
+ if (choice.message.tool_calls != null) for (const toolCall of choice.message.tool_calls) content.push({
807
+ type: "tool-call",
808
+ toolCallId: toolCall.id || generateId(),
809
+ toolName: toolCall.function.name,
810
+ input: toolCall.function.arguments
811
+ });
812
+ const text = choice.message.content;
813
+ if (text != null && text.length > 0) content.push({
814
+ type: "text",
815
+ text
816
+ });
817
+ return {
818
+ content,
819
+ finishReason: {
820
+ unified: mapDeepSeekFinishReason(choice.finish_reason),
821
+ raw: choice.finish_reason ?? void 0
822
+ },
823
+ usage: convertDeepSeekUsage(responseBody.usage),
824
+ providerMetadata: { [this.providerOptionsName]: {
825
+ promptCacheHitTokens: responseBody.usage?.prompt_cache_hit_tokens,
826
+ promptCacheMissTokens: responseBody.usage?.prompt_cache_miss_tokens,
827
+ ...responseBody.object != null && { responseObject: responseBody.object },
828
+ ...choice.index != null && { choiceIndex: choice.index },
829
+ ...choice.message.role != null && { messageRole: choice.message.role },
830
+ ...choice.message.tool_calls != null && { toolCallTypes: choice.message.tool_calls.map((toolCall) => toolCall.type).filter((type) => type != null) },
831
+ ...choice.logprobs != null && { logprobs: choice.logprobs },
832
+ ...responseBody.system_fingerprint != null && { systemFingerprint: responseBody.system_fingerprint }
833
+ } },
834
+ request: { body: args },
835
+ response: {
836
+ ...getResponseMetadata(responseBody),
837
+ headers: responseHeaders,
838
+ body: rawResponse
839
+ },
840
+ warnings
841
+ };
842
+ }
843
+ async doStream(options) {
844
+ const { args, warnings } = await this.getArgs({ ...options });
845
+ const body = {
846
+ ...args,
847
+ stream: true,
848
+ stream_options: { include_usage: true }
849
+ };
850
+ const { responseHeaders, value: response } = await postJsonToApi({
851
+ url: this.config.url({
852
+ path: "/chat/completions",
853
+ modelId: this.modelId
854
+ }),
855
+ headers: combineHeaders(this.config.headers?.(), options.headers),
856
+ body,
857
+ failedResponseHandler: this.failedResponseHandler,
858
+ successfulResponseHandler: createEventSourceResponseHandler(deepseekChatChunkSchema),
859
+ abortSignal: options.abortSignal,
860
+ fetch: this.config.fetch
861
+ });
862
+ let toolCallTracker;
863
+ let finishReason = {
864
+ unified: "other",
865
+ raw: void 0
866
+ };
867
+ let usage = void 0;
868
+ let systemFingerprint = void 0;
869
+ let isFirstChunk = true;
870
+ const providerOptionsName = this.providerOptionsName;
871
+ let isActiveReasoning = false;
872
+ let isActiveText = false;
873
+ let responseObject;
874
+ let choiceIndex;
875
+ let messageRole;
876
+ const toolCallTypes = /* @__PURE__ */ new Map();
877
+ const contentLogprobs = [];
878
+ const reasoningLogprobs = [];
879
+ return {
880
+ stream: response.pipeThrough(new TransformStream({
881
+ start(controller) {
882
+ toolCallTracker = new StreamingToolCallTracker(controller, { generateId });
883
+ controller.enqueue({
884
+ type: "stream-start",
885
+ warnings
886
+ });
887
+ },
888
+ transform(chunk, controller) {
889
+ if (options.includeRawChunks) controller.enqueue({
890
+ type: "raw",
891
+ rawValue: chunk.rawValue
892
+ });
893
+ if (!chunk.success) {
894
+ finishReason = {
895
+ unified: "error",
896
+ raw: void 0
897
+ };
898
+ controller.enqueue({
899
+ type: "error",
900
+ error: chunk.error
901
+ });
902
+ return;
903
+ }
904
+ const value = chunk.value;
905
+ if ("error" in value) {
906
+ finishReason = {
907
+ unified: "error",
908
+ raw: void 0
909
+ };
910
+ controller.enqueue({
911
+ type: "error",
912
+ error: createDeepSeekStreamError(value.error, value)
913
+ });
914
+ return;
915
+ }
916
+ if (isFirstChunk) {
917
+ isFirstChunk = false;
918
+ controller.enqueue({
919
+ type: "response-metadata",
920
+ ...getResponseMetadata(value)
921
+ });
922
+ }
923
+ if (value.usage != null) usage = value.usage;
924
+ if (value.object != null) responseObject = value.object;
925
+ if (value.system_fingerprint != null) systemFingerprint = value.system_fingerprint;
926
+ const choice = value.choices[0];
927
+ if (choice?.index != null) choiceIndex = choice.index;
928
+ if (choice?.finish_reason != null) finishReason = {
929
+ unified: mapDeepSeekFinishReason(choice.finish_reason),
930
+ raw: choice.finish_reason
931
+ };
932
+ if (choice?.logprobs?.content != null) contentLogprobs.push(...choice.logprobs.content);
933
+ if (choice?.logprobs?.reasoning_content != null) reasoningLogprobs.push(...choice.logprobs.reasoning_content);
934
+ if (choice?.delta == null) return;
935
+ const delta = choice.delta;
936
+ if (delta.role != null) messageRole = delta.role;
937
+ const reasoningContent = delta.reasoning_content;
938
+ if (reasoningContent) {
939
+ if (!isActiveReasoning) {
940
+ controller.enqueue({
941
+ type: "reasoning-start",
942
+ id: "reasoning-0"
943
+ });
944
+ isActiveReasoning = true;
945
+ }
946
+ controller.enqueue({
947
+ type: "reasoning-delta",
948
+ id: "reasoning-0",
949
+ delta: reasoningContent
950
+ });
951
+ }
952
+ if (delta.content) {
953
+ if (!isActiveText) {
954
+ controller.enqueue({
955
+ type: "text-start",
956
+ id: "txt-0"
957
+ });
958
+ isActiveText = true;
959
+ }
960
+ if (isActiveReasoning) {
961
+ controller.enqueue({
962
+ type: "reasoning-end",
963
+ id: "reasoning-0"
964
+ });
965
+ isActiveReasoning = false;
966
+ }
967
+ controller.enqueue({
968
+ type: "text-delta",
969
+ id: "txt-0",
970
+ delta: delta.content
971
+ });
972
+ }
973
+ if (delta.tool_calls != null && delta.tool_calls.length > 0) {
974
+ if (isActiveReasoning) {
975
+ controller.enqueue({
976
+ type: "reasoning-end",
977
+ id: "reasoning-0"
978
+ });
979
+ isActiveReasoning = false;
980
+ }
981
+ for (const toolCallDelta of delta.tool_calls) {
982
+ if (toolCallDelta.type != null) toolCallTypes.set(toolCallDelta.index, toolCallDelta.type);
983
+ toolCallTracker.processDelta(toolCallDelta);
984
+ }
985
+ }
986
+ },
987
+ flush(controller) {
988
+ if (isActiveReasoning) controller.enqueue({
989
+ type: "reasoning-end",
990
+ id: "reasoning-0"
991
+ });
992
+ if (isActiveText) controller.enqueue({
993
+ type: "text-end",
994
+ id: "txt-0"
995
+ });
996
+ toolCallTracker.flush();
997
+ controller.enqueue({
998
+ type: "finish",
999
+ finishReason,
1000
+ usage: convertDeepSeekUsage(usage),
1001
+ providerMetadata: { [providerOptionsName]: {
1002
+ promptCacheHitTokens: usage?.prompt_cache_hit_tokens ?? void 0,
1003
+ promptCacheMissTokens: usage?.prompt_cache_miss_tokens ?? void 0,
1004
+ ...responseObject != null && { responseObject },
1005
+ ...choiceIndex != null && { choiceIndex },
1006
+ ...messageRole != null && { messageRole },
1007
+ ...toolCallTypes.size > 0 && { toolCallTypes: [...toolCallTypes.entries()].sort(([left], [right]) => left - right).map(([, type]) => type) },
1008
+ ...(contentLogprobs.length > 0 || reasoningLogprobs.length > 0) && { logprobs: {
1009
+ ...contentLogprobs.length > 0 && { content: contentLogprobs },
1010
+ ...reasoningLogprobs.length > 0 && { reasoning_content: reasoningLogprobs }
1011
+ } },
1012
+ ...systemFingerprint != null && { systemFingerprint }
1013
+ } }
1014
+ });
1015
+ }
1016
+ })),
1017
+ request: { body },
1018
+ response: { headers: responseHeaders }
1019
+ };
1020
+ }
1245
1021
  };
1022
+ //#endregion
1023
+ export { DeepSeekChatLanguageModel, deepseekAssistantMessageProviderOptions, deepseekLanguageModelChatOptions, deepseekMessageProviderOptions };
1024
+
1246
1025
  //# sourceMappingURL=index.js.map