@ai-sdk/deepseek 3.0.0-beta.3 → 3.0.0-beta.31

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,13 +1,12 @@
1
1
  import {
2
2
  APICallError,
3
- InvalidResponseDataError,
4
- LanguageModelV3,
5
- LanguageModelV3CallOptions,
6
- LanguageModelV3Content,
7
- LanguageModelV3FinishReason,
8
- LanguageModelV3GenerateResult,
9
- LanguageModelV3StreamPart,
10
- LanguageModelV3StreamResult,
3
+ LanguageModelV4,
4
+ LanguageModelV4CallOptions,
5
+ LanguageModelV4Content,
6
+ LanguageModelV4FinishReason,
7
+ LanguageModelV4GenerateResult,
8
+ LanguageModelV4StreamPart,
9
+ LanguageModelV4StreamResult,
11
10
  } from '@ai-sdk/provider';
12
11
  import {
13
12
  combineHeaders,
@@ -17,11 +16,15 @@ import {
17
16
  FetchFunction,
18
17
  generateId,
19
18
  InferSchema,
20
- isParsableJson,
19
+ isCustomReasoning,
21
20
  parseProviderOptions,
22
21
  ParseResult,
23
22
  postJsonToApi,
24
23
  ResponseHandler,
24
+ serializeModelOptions,
25
+ StreamingToolCallTracker,
26
+ WORKFLOW_SERIALIZE,
27
+ WORKFLOW_DESERIALIZE,
25
28
  } from '@ai-sdk/provider-utils';
26
29
  import { convertToDeepSeekChatMessages } from './convert-to-deepseek-chat-messages';
27
30
  import { convertDeepSeekUsage } from './convert-to-deepseek-usage';
@@ -41,13 +44,13 @@ import { mapDeepSeekFinishReason } from './map-deepseek-finish-reason';
41
44
 
42
45
  export type DeepSeekChatConfig = {
43
46
  provider: string;
44
- headers: () => Record<string, string | undefined>;
47
+ headers?: () => Record<string, string | undefined>;
45
48
  url: (options: { modelId: string; path: string }) => string;
46
49
  fetch?: FetchFunction;
47
50
  };
48
51
 
49
- export class DeepSeekChatLanguageModel implements LanguageModelV3 {
50
- readonly specificationVersion = 'v3';
52
+ export class DeepSeekChatLanguageModel implements LanguageModelV4 {
53
+ readonly specificationVersion = 'v4';
51
54
 
52
55
  readonly modelId: DeepSeekChatModelId;
53
56
  readonly supportedUrls = {};
@@ -55,6 +58,20 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
55
58
  private readonly config: DeepSeekChatConfig;
56
59
  private readonly failedResponseHandler: ResponseHandler<APICallError>;
57
60
 
61
+ static [WORKFLOW_SERIALIZE](model: DeepSeekChatLanguageModel) {
62
+ return serializeModelOptions({
63
+ modelId: model.modelId,
64
+ config: model.config,
65
+ });
66
+ }
67
+
68
+ static [WORKFLOW_DESERIALIZE](options: {
69
+ modelId: DeepSeekChatModelId;
70
+ config: DeepSeekChatConfig;
71
+ }) {
72
+ return new DeepSeekChatLanguageModel(options.modelId, options.config);
73
+ }
74
+
58
75
  constructor(modelId: DeepSeekChatModelId, config: DeepSeekChatConfig) {
59
76
  this.modelId = modelId;
60
77
  this.config = config;
@@ -82,13 +99,14 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
82
99
  topK,
83
100
  frequencyPenalty,
84
101
  presencePenalty,
102
+ reasoning,
85
103
  providerOptions,
86
104
  stopSequences,
87
105
  responseFormat,
88
106
  seed,
89
107
  toolChoice,
90
108
  tools,
91
- }: LanguageModelV3CallOptions) {
109
+ }: LanguageModelV4CallOptions) {
92
110
  const deepseekOptions =
93
111
  (await parseProviderOptions({
94
112
  provider: this.providerOptionsName,
@@ -99,6 +117,7 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
99
117
  const { messages, warnings } = convertToDeepSeekChatMessages({
100
118
  prompt,
101
119
  responseFormat,
120
+ modelId: this.modelId,
102
121
  });
103
122
 
104
123
  if (topK != null) {
@@ -135,15 +154,17 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
135
154
  thinking:
136
155
  deepseekOptions.thinking?.type != null
137
156
  ? { type: deepseekOptions.thinking.type }
138
- : undefined,
157
+ : isCustomReasoning(reasoning)
158
+ ? { type: reasoning === 'none' ? 'disabled' : 'enabled' }
159
+ : undefined,
139
160
  },
140
161
  warnings: [...warnings, ...toolWarnings],
141
162
  };
142
163
  }
143
164
 
144
165
  async doGenerate(
145
- options: LanguageModelV3CallOptions,
146
- ): Promise<LanguageModelV3GenerateResult> {
166
+ options: LanguageModelV4CallOptions,
167
+ ): Promise<LanguageModelV4GenerateResult> {
147
168
  const { args, warnings } = await this.getArgs({ ...options });
148
169
 
149
170
  const {
@@ -155,7 +176,7 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
155
176
  path: '/chat/completions',
156
177
  modelId: this.modelId,
157
178
  }),
158
- headers: combineHeaders(this.config.headers(), options.headers),
179
+ headers: combineHeaders(this.config.headers?.(), options.headers),
159
180
  body: args,
160
181
  failedResponseHandler: this.failedResponseHandler,
161
182
  successfulResponseHandler: createJsonResponseHandler(
@@ -166,7 +187,7 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
166
187
  });
167
188
 
168
189
  const choice = responseBody.choices[0];
169
- const content: Array<LanguageModelV3Content> = [];
190
+ const content: Array<LanguageModelV4Content> = [];
170
191
 
171
192
  // reasoning content (before text):
172
193
  const reasoning = choice.message.reasoning_content;
@@ -219,8 +240,8 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
219
240
  }
220
241
 
221
242
  async doStream(
222
- options: LanguageModelV3CallOptions,
223
- ): Promise<LanguageModelV3StreamResult> {
243
+ options: LanguageModelV4CallOptions,
244
+ ): Promise<LanguageModelV4StreamResult> {
224
245
  const { args, warnings } = await this.getArgs({ ...options });
225
246
 
226
247
  const body = {
@@ -234,7 +255,7 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
234
255
  path: '/chat/completions',
235
256
  modelId: this.modelId,
236
257
  }),
237
- headers: combineHeaders(this.config.headers(), options.headers),
258
+ headers: combineHeaders(this.config.headers?.(), options.headers),
238
259
  body,
239
260
  failedResponseHandler: this.failedResponseHandler,
240
261
  successfulResponseHandler: createEventSourceResponseHandler(
@@ -244,17 +265,9 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
244
265
  fetch: this.config.fetch,
245
266
  });
246
267
 
247
- const toolCalls: Array<{
248
- id: string;
249
- type: 'function';
250
- function: {
251
- name: string;
252
- arguments: string;
253
- };
254
- hasFinished: boolean;
255
- }> = [];
256
-
257
- let finishReason: LanguageModelV3FinishReason = {
268
+ let toolCallTracker: StreamingToolCallTracker;
269
+
270
+ let finishReason: LanguageModelV4FinishReason = {
258
271
  unified: 'other',
259
272
  raw: undefined,
260
273
  };
@@ -268,9 +281,12 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
268
281
  stream: response.pipeThrough(
269
282
  new TransformStream<
270
283
  ParseResult<InferSchema<typeof deepseekChatChunkSchema>>,
271
- LanguageModelV3StreamPart
284
+ LanguageModelV4StreamPart
272
285
  >({
273
286
  start(controller) {
287
+ toolCallTracker = new StreamingToolCallTracker(controller, {
288
+ generateId,
289
+ });
274
290
  controller.enqueue({ type: 'stream-start', warnings });
275
291
  },
276
292
 
@@ -374,113 +390,7 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
374
390
  }
375
391
 
376
392
  for (const toolCallDelta of delta.tool_calls) {
377
- const index = toolCallDelta.index;
378
-
379
- if (toolCalls[index] == null) {
380
- if (toolCallDelta.id == null) {
381
- throw new InvalidResponseDataError({
382
- data: toolCallDelta,
383
- message: `Expected 'id' to be a string.`,
384
- });
385
- }
386
-
387
- if (toolCallDelta.function?.name == null) {
388
- throw new InvalidResponseDataError({
389
- data: toolCallDelta,
390
- message: `Expected 'function.name' to be a string.`,
391
- });
392
- }
393
-
394
- controller.enqueue({
395
- type: 'tool-input-start',
396
- id: toolCallDelta.id,
397
- toolName: toolCallDelta.function.name,
398
- });
399
-
400
- toolCalls[index] = {
401
- id: toolCallDelta.id,
402
- type: 'function',
403
- function: {
404
- name: toolCallDelta.function.name,
405
- arguments: toolCallDelta.function.arguments ?? '',
406
- },
407
- hasFinished: false,
408
- };
409
-
410
- const toolCall = toolCalls[index];
411
-
412
- if (
413
- toolCall.function?.name != null &&
414
- toolCall.function?.arguments != null
415
- ) {
416
- // send delta if the argument text has already started:
417
- if (toolCall.function.arguments.length > 0) {
418
- controller.enqueue({
419
- type: 'tool-input-delta',
420
- id: toolCall.id,
421
- delta: toolCall.function.arguments,
422
- });
423
- }
424
-
425
- // check if tool call is complete
426
- // (some providers send the full tool call in one chunk):
427
- if (isParsableJson(toolCall.function.arguments)) {
428
- controller.enqueue({
429
- type: 'tool-input-end',
430
- id: toolCall.id,
431
- });
432
-
433
- controller.enqueue({
434
- type: 'tool-call',
435
- toolCallId: toolCall.id ?? generateId(),
436
- toolName: toolCall.function.name,
437
- input: toolCall.function.arguments,
438
- });
439
- toolCall.hasFinished = true;
440
- }
441
- }
442
-
443
- continue;
444
- }
445
-
446
- // existing tool call, merge if not finished
447
- const toolCall = toolCalls[index];
448
-
449
- if (toolCall.hasFinished) {
450
- continue;
451
- }
452
-
453
- if (toolCallDelta.function?.arguments != null) {
454
- toolCall.function!.arguments +=
455
- toolCallDelta.function?.arguments ?? '';
456
- }
457
-
458
- // send delta
459
- controller.enqueue({
460
- type: 'tool-input-delta',
461
- id: toolCall.id,
462
- delta: toolCallDelta.function.arguments ?? '',
463
- });
464
-
465
- // check if tool call is complete
466
- if (
467
- toolCall.function?.name != null &&
468
- toolCall.function?.arguments != null &&
469
- isParsableJson(toolCall.function.arguments)
470
- ) {
471
- controller.enqueue({
472
- type: 'tool-input-end',
473
- id: toolCall.id,
474
- });
475
-
476
- controller.enqueue({
477
- type: 'tool-call',
478
- toolCallId: toolCall.id ?? generateId(),
479
- toolName: toolCall.function.name,
480
- input: toolCall.function.arguments,
481
- });
482
- toolCall.hasFinished = true;
483
- }
393
+ toolCallTracker.processDelta(toolCallDelta);
484
394
  }
485
395
  }
486
396
  },
@@ -494,22 +404,7 @@ export class DeepSeekChatLanguageModel implements LanguageModelV3 {
494
404
  controller.enqueue({ type: 'text-end', id: 'txt-0' });
495
405
  }
496
406
 
497
- // go through all tool calls and send the ones that are not finished
498
- for (const toolCall of toolCalls.filter(
499
- toolCall => !toolCall.hasFinished,
500
- )) {
501
- controller.enqueue({
502
- type: 'tool-input-end',
503
- id: toolCall.id,
504
- });
505
-
506
- controller.enqueue({
507
- type: 'tool-call',
508
- toolCallId: toolCall.id ?? generateId(),
509
- toolName: toolCall.function.name,
510
- input: toolCall.function.arguments,
511
- });
512
- }
407
+ toolCallTracker.flush();
513
408
 
514
409
  controller.enqueue({
515
410
  type: 'finish',
@@ -1,4 +1,4 @@
1
- import { LanguageModelV3CallOptions, SharedV3Warning } from '@ai-sdk/provider';
1
+ import { LanguageModelV4CallOptions, SharedV4Warning } from '@ai-sdk/provider';
2
2
  import {
3
3
  DeepSeekFunctionTool,
4
4
  DeepSeekToolChoice,
@@ -8,17 +8,17 @@ export function prepareTools({
8
8
  tools,
9
9
  toolChoice,
10
10
  }: {
11
- tools: LanguageModelV3CallOptions['tools'];
12
- toolChoice?: LanguageModelV3CallOptions['toolChoice'];
11
+ tools: LanguageModelV4CallOptions['tools'];
12
+ toolChoice?: LanguageModelV4CallOptions['toolChoice'];
13
13
  }): {
14
14
  tools: undefined | Array<DeepSeekFunctionTool>;
15
15
  toolChoice: DeepSeekToolChoice;
16
- toolWarnings: SharedV3Warning[];
16
+ toolWarnings: SharedV4Warning[];
17
17
  } {
18
18
  // when the tools array is empty, change it to undefined to prevent errors:
19
19
  tools = tools?.length ? tools : undefined;
20
20
 
21
- const toolWarnings: SharedV3Warning[] = [];
21
+ const toolWarnings: SharedV4Warning[] = [];
22
22
 
23
23
  if (tools == null) {
24
24
  return { tools: undefined, toolChoice: undefined, toolWarnings };
@@ -1,8 +1,8 @@
1
- import { LanguageModelV3FinishReason } from '@ai-sdk/provider';
1
+ import { LanguageModelV4FinishReason } from '@ai-sdk/provider';
2
2
 
3
3
  export function mapDeepSeekFinishReason(
4
4
  finishReason: string | null | undefined,
5
- ): LanguageModelV3FinishReason['unified'] {
5
+ ): LanguageModelV4FinishReason['unified'] {
6
6
  switch (finishReason) {
7
7
  case 'stop':
8
8
  return 'stop';
@@ -1,7 +1,7 @@
1
1
  import {
2
- LanguageModelV3,
2
+ LanguageModelV4,
3
3
  NoSuchModelError,
4
- ProviderV3,
4
+ ProviderV4,
5
5
  } from '@ai-sdk/provider';
6
6
  import {
7
7
  FetchFunction,
@@ -36,21 +36,21 @@ export interface DeepSeekProviderSettings {
36
36
  fetch?: FetchFunction;
37
37
  }
38
38
 
39
- export interface DeepSeekProvider extends ProviderV3 {
39
+ export interface DeepSeekProvider extends ProviderV4 {
40
40
  /**
41
41
  * Creates a DeepSeek model for text generation.
42
42
  */
43
- (modelId: DeepSeekChatModelId): LanguageModelV3;
43
+ (modelId: DeepSeekChatModelId): LanguageModelV4;
44
44
 
45
45
  /**
46
46
  * Creates a DeepSeek model for text generation.
47
47
  */
48
- languageModel(modelId: DeepSeekChatModelId): LanguageModelV3;
48
+ languageModel(modelId: DeepSeekChatModelId): LanguageModelV4;
49
49
 
50
50
  /**
51
51
  * Creates a DeepSeek chat model for text generation.
52
52
  */
53
- chat(modelId: DeepSeekChatModelId): LanguageModelV3;
53
+ chat(modelId: DeepSeekChatModelId): LanguageModelV4;
54
54
 
55
55
  /**
56
56
  * @deprecated Use `embeddingModel` instead.
@@ -90,7 +90,7 @@ export function createDeepSeek(
90
90
  const provider = (modelId: DeepSeekChatModelId) =>
91
91
  createLanguageModel(modelId);
92
92
 
93
- provider.specificationVersion = 'v3' as const;
93
+ provider.specificationVersion = 'v4' as const;
94
94
  provider.languageModel = createLanguageModel;
95
95
  provider.chat = createLanguageModel;
96
96
 
package/dist/index.d.mts DELETED
@@ -1,68 +0,0 @@
1
- import { ProviderV3, LanguageModelV3 } from '@ai-sdk/provider';
2
- import { FetchFunction } from '@ai-sdk/provider-utils';
3
- import { z } from 'zod/v4';
4
-
5
- type DeepSeekChatModelId = 'deepseek-chat' | 'deepseek-reasoner' | (string & {});
6
- declare const deepseekLanguageModelOptions: z.ZodObject<{
7
- thinking: z.ZodOptional<z.ZodObject<{
8
- type: z.ZodOptional<z.ZodEnum<{
9
- enabled: "enabled";
10
- disabled: "disabled";
11
- }>>;
12
- }, z.core.$strip>>;
13
- }, z.core.$strip>;
14
- type DeepSeekLanguageModelOptions = z.infer<typeof deepseekLanguageModelOptions>;
15
-
16
- interface DeepSeekProviderSettings {
17
- /**
18
- * DeepSeek API key.
19
- */
20
- apiKey?: string;
21
- /**
22
- * Base URL for the API calls.
23
- */
24
- baseURL?: string;
25
- /**
26
- * Custom headers to include in the requests.
27
- */
28
- headers?: Record<string, string>;
29
- /**
30
- * Custom fetch implementation. You can use it as a middleware to intercept requests,
31
- * or to provide a custom fetch implementation for e.g. testing.
32
- */
33
- fetch?: FetchFunction;
34
- }
35
- interface DeepSeekProvider extends ProviderV3 {
36
- /**
37
- * Creates a DeepSeek model for text generation.
38
- */
39
- (modelId: DeepSeekChatModelId): LanguageModelV3;
40
- /**
41
- * Creates a DeepSeek model for text generation.
42
- */
43
- languageModel(modelId: DeepSeekChatModelId): LanguageModelV3;
44
- /**
45
- * Creates a DeepSeek chat model for text generation.
46
- */
47
- chat(modelId: DeepSeekChatModelId): LanguageModelV3;
48
- /**
49
- * @deprecated Use `embeddingModel` instead.
50
- */
51
- textEmbeddingModel(modelId: string): never;
52
- }
53
- declare function createDeepSeek(options?: DeepSeekProviderSettings): DeepSeekProvider;
54
- declare const deepseek: DeepSeekProvider;
55
-
56
- declare const VERSION: string;
57
-
58
- declare const deepSeekErrorSchema: z.ZodObject<{
59
- error: z.ZodObject<{
60
- message: z.ZodString;
61
- type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
62
- param: z.ZodOptional<z.ZodNullable<z.ZodAny>>;
63
- code: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
64
- }, z.core.$strip>;
65
- }, z.core.$strip>;
66
- type DeepSeekErrorData = z.infer<typeof deepSeekErrorSchema>;
67
-
68
- export { type DeepSeekLanguageModelOptions as DeepSeekChatOptions, type DeepSeekErrorData, type DeepSeekLanguageModelOptions, type DeepSeekProvider, type DeepSeekProviderSettings, VERSION, createDeepSeek, deepseek };