@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/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
- function convertToDeepSeekChatMessages({
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({ role: "system", content });
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({ role: "user", content: userContent2 });
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
- userContent.push({
112
- type: "image_url",
113
- image_url: {
114
- url: part.data.type === "url" ? part.data.url.toString() : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}`
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 = z.object({
250
- prompt_tokens: z.number().nullish(),
251
- completion_tokens: z.number().nullish(),
252
- prompt_cache_hit_tokens: z.number().nullish(),
253
- prompt_cache_miss_tokens: z.number().nullish(),
254
- total_tokens: z.number().nullish(),
255
- completion_tokens_details: z.object({
256
- reasoning_tokens: z.number().nullish()
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 = z.object({
260
- error: z.object({
261
- message: z.string(),
262
- type: z.string().nullish(),
263
- param: z.any().nullish(),
264
- code: z.union([z.string(), z.number()]).nullish()
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 deepseekChatResponseSchema = z.object({
268
- id: z.string().nullish(),
269
- created: z.number().nullish(),
270
- model: z.string().nullish(),
271
- choices: z.array(
272
- z.object({
273
- message: z.object({
274
- role: z.literal("assistant").nullish(),
275
- content: z.string().nullish(),
276
- reasoning_content: z.string().nullish(),
277
- tool_calls: z.array(
278
- z.object({
279
- id: z.string().nullish(),
280
- function: z.object({
281
- name: z.string(),
282
- arguments: z.string()
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
- finish_reason: z.string().nullish()
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
- z.union([
295
- z.object({
296
- id: z.string().nullish(),
297
- created: z.number().nullish(),
298
- model: z.string().nullish(),
299
- choices: z.array(
300
- z.object({
301
- delta: z.object({
302
- role: z.enum(["assistant"]).nullish(),
303
- content: z.string().nullish(),
304
- reasoning_content: z.string().nullish(),
305
- tool_calls: z.array(
306
- z.object({
307
- index: z.number(),
308
- id: z.string().nullish(),
309
- function: z.object({
310
- name: z.string().nullish(),
311
- arguments: z.string().nullish()
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
- finish_reason: z.string().nullish()
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, _e;
484
- const deepseekOptions = (_a = await parseProviderOptions({
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 { messages, warnings } = convertToDeepSeekChatMessages({
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 thinking = this.config.supportsThinking === false ? void 0 : ((_b = deepseekOptions.thinking) == null ? void 0 : _b.type) != null ? { type: deepseekOptions.thinking.type } : isCustomReasoning(reasoning) ? { type: reasoning === "none" ? "disabled" : "enabled" } : void 0;
512
- const reasoningEffort = (_c = deepseekOptions.reasoningEffort) != null ? _c : isCustomReasoning(reasoning) && reasoning !== "none" ? mapReasoningToProviderEffort({
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: "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: (_d = deepseekOptions.strictJsonSchema) != null ? _d : true,
536
- name: (_e = responseFormat.name) != null ? _e : "response",
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({ type: "error", error: value.error.message });
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
- parseProviderOptions as parseProviderOptions2,
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 z3 } from "zod/v4";
1195
+ import { z as z4 } from "zod/v4";
783
1196
  var deepSeekFilesResponseSchema = lazySchema2(
784
1197
  () => zodSchema2(
785
- z3.object({
786
- id: z3.string(),
787
- object: z3.string().nullish(),
788
- bytes: z3.number().nullish(),
789
- created_at: z3.number().nullish(),
790
- filename: z3.string().nullish(),
791
- purpose: z3.string().nullish(),
792
- expires_at: z3.number().nullish()
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 z4 } from "zod/v4";
1219
+ import { z as z5 } from "zod/v4";
803
1220
  var deepSeekFilesOptionsSchema = lazySchema3(
804
1221
  () => zodSchema3(
805
- z4.object({
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: z4.number().int().min(3600).max(2592e3).optional()
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 parseProviderOptions2({
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.31" : "0.0.0-test";
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({