@ai-sdk/openai 4.0.0-beta.30 → 4.0.0-beta.32

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/openai",
3
- "version": "4.0.0-beta.30",
3
+ "version": "4.0.0-beta.32",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -35,8 +35,8 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@ai-sdk/provider": "4.0.0-beta.11",
39
- "@ai-sdk/provider-utils": "5.0.0-beta.19"
38
+ "@ai-sdk/provider-utils": "5.0.0-beta.20",
39
+ "@ai-sdk/provider": "4.0.0-beta.12"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "20.17.24",
@@ -10,6 +10,10 @@ import {
10
10
  resolveProviderReference,
11
11
  } from '@ai-sdk/provider-utils';
12
12
 
13
+ function serializeToolCallArguments(input: unknown): string {
14
+ return JSON.stringify(input === undefined ? {} : input);
15
+ }
16
+
13
17
  export function convertToOpenAIChatMessages({
14
18
  prompt,
15
19
  systemMessageMode = 'system',
@@ -176,7 +180,7 @@ export function convertToOpenAIChatMessages({
176
180
  type: 'function',
177
181
  function: {
178
182
  name: part.toolName,
179
- arguments: JSON.stringify(part.input),
183
+ arguments: serializeToolCallArguments(part.input),
180
184
  },
181
185
  });
182
186
  break;
@@ -21,6 +21,9 @@ import {
21
21
  isParsableJson,
22
22
  parseProviderOptions,
23
23
  postJsonToApi,
24
+ serializeModelOptions,
25
+ WORKFLOW_DESERIALIZE,
26
+ WORKFLOW_SERIALIZE,
24
27
  } from '@ai-sdk/provider-utils';
25
28
  import { openaiFailedResponseHandler } from '../openai-error';
26
29
  import { getOpenAILanguageModelCapabilities } from '../openai-language-model-capabilities';
@@ -44,7 +47,7 @@ import { prepareChatTools } from './openai-chat-prepare-tools';
44
47
 
45
48
  type OpenAIChatConfig = {
46
49
  provider: string;
47
- headers: () => Record<string, string | undefined>;
50
+ headers?: () => Record<string, string | undefined>;
48
51
  url: (options: { modelId: string; path: string }) => string;
49
52
  fetch?: FetchFunction;
50
53
  };
@@ -60,6 +63,20 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
60
63
 
61
64
  private readonly config: OpenAIChatConfig;
62
65
 
66
+ static [WORKFLOW_SERIALIZE](model: OpenAIChatLanguageModel) {
67
+ return serializeModelOptions({
68
+ modelId: model.modelId,
69
+ config: model.config,
70
+ });
71
+ }
72
+
73
+ static [WORKFLOW_DESERIALIZE](options: {
74
+ modelId: OpenAIChatModelId;
75
+ config: OpenAIChatConfig;
76
+ }) {
77
+ return new OpenAIChatLanguageModel(options.modelId, options.config);
78
+ }
79
+
63
80
  constructor(modelId: OpenAIChatModelId, config: OpenAIChatConfig) {
64
81
  this.modelId = modelId;
65
82
  this.config = config;
@@ -335,7 +352,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
335
352
  path: '/chat/completions',
336
353
  modelId: this.modelId,
337
354
  }),
338
- headers: combineHeaders(this.config.headers(), options.headers),
355
+ headers: combineHeaders(this.config.headers?.(), options.headers),
339
356
  body,
340
357
  failedResponseHandler: openaiFailedResponseHandler,
341
358
  successfulResponseHandler: createJsonResponseHandler(
@@ -426,7 +443,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
426
443
  path: '/chat/completions',
427
444
  modelId: this.modelId,
428
445
  }),
429
- headers: combineHeaders(this.config.headers(), options.headers),
446
+ headers: combineHeaders(this.config.headers?.(), options.headers),
430
447
  body,
431
448
  failedResponseHandler: openaiFailedResponseHandler,
432
449
  successfulResponseHandler: createEventSourceResponseHandler(
@@ -16,6 +16,9 @@ import {
16
16
  parseProviderOptions,
17
17
  ParseResult,
18
18
  postJsonToApi,
19
+ serializeModelOptions,
20
+ WORKFLOW_DESERIALIZE,
21
+ WORKFLOW_SERIALIZE,
19
22
  } from '@ai-sdk/provider-utils';
20
23
  import { openaiFailedResponseHandler } from '../openai-error';
21
24
  import {
@@ -37,7 +40,7 @@ import {
37
40
 
38
41
  type OpenAICompletionConfig = {
39
42
  provider: string;
40
- headers: () => Record<string, string | undefined>;
43
+ headers?: () => Record<string, string | undefined>;
41
44
  url: (options: { modelId: string; path: string }) => string;
42
45
  fetch?: FetchFunction;
43
46
  };
@@ -53,6 +56,20 @@ export class OpenAICompletionLanguageModel implements LanguageModelV4 {
53
56
  return this.config.provider.split('.')[0].trim();
54
57
  }
55
58
 
59
+ static [WORKFLOW_SERIALIZE](model: OpenAICompletionLanguageModel) {
60
+ return serializeModelOptions({
61
+ modelId: model.modelId,
62
+ config: model.config,
63
+ });
64
+ }
65
+
66
+ static [WORKFLOW_DESERIALIZE](options: {
67
+ modelId: OpenAICompletionModelId;
68
+ config: OpenAICompletionConfig;
69
+ }) {
70
+ return new OpenAICompletionLanguageModel(options.modelId, options.config);
71
+ }
72
+
56
73
  constructor(
57
74
  modelId: OpenAICompletionModelId,
58
75
  config: OpenAICompletionConfig,
@@ -174,7 +191,7 @@ export class OpenAICompletionLanguageModel implements LanguageModelV4 {
174
191
  path: '/completions',
175
192
  modelId: this.modelId,
176
193
  }),
177
- headers: combineHeaders(this.config.headers(), options.headers),
194
+ headers: combineHeaders(this.config.headers?.(), options.headers),
178
195
  body: args,
179
196
  failedResponseHandler: openaiFailedResponseHandler,
180
197
  successfulResponseHandler: createJsonResponseHandler(
@@ -229,7 +246,7 @@ export class OpenAICompletionLanguageModel implements LanguageModelV4 {
229
246
  path: '/completions',
230
247
  modelId: this.modelId,
231
248
  }),
232
- headers: combineHeaders(this.config.headers(), options.headers),
249
+ headers: combineHeaders(this.config.headers?.(), options.headers),
233
250
  body,
234
251
  failedResponseHandler: openaiFailedResponseHandler,
235
252
  successfulResponseHandler: createEventSourceResponseHandler(
@@ -7,6 +7,9 @@ import {
7
7
  createJsonResponseHandler,
8
8
  parseProviderOptions,
9
9
  postJsonToApi,
10
+ serializeModelOptions,
11
+ WORKFLOW_DESERIALIZE,
12
+ WORKFLOW_SERIALIZE,
10
13
  } from '@ai-sdk/provider-utils';
11
14
  import { OpenAIConfig } from '../openai-config';
12
15
  import { openaiFailedResponseHandler } from '../openai-error';
@@ -24,6 +27,20 @@ export class OpenAIEmbeddingModel implements EmbeddingModelV4 {
24
27
 
25
28
  private readonly config: OpenAIConfig;
26
29
 
30
+ static [WORKFLOW_SERIALIZE](model: OpenAIEmbeddingModel) {
31
+ return serializeModelOptions({
32
+ modelId: model.modelId,
33
+ config: model.config,
34
+ });
35
+ }
36
+
37
+ static [WORKFLOW_DESERIALIZE](options: {
38
+ modelId: OpenAIEmbeddingModelId;
39
+ config: OpenAIConfig;
40
+ }) {
41
+ return new OpenAIEmbeddingModel(options.modelId, options.config);
42
+ }
43
+
27
44
  get provider(): string {
28
45
  return this.config.provider;
29
46
  }
@@ -67,7 +84,7 @@ export class OpenAIEmbeddingModel implements EmbeddingModelV4 {
67
84
  path: '/embeddings',
68
85
  modelId: this.modelId,
69
86
  }),
70
- headers: combineHeaders(this.config.headers(), headers),
87
+ headers: combineHeaders(this.config.headers?.(), headers),
71
88
  body: {
72
89
  model: this.modelId,
73
90
  input: values,
@@ -11,6 +11,9 @@ import {
11
11
  downloadBlob,
12
12
  postFormDataToApi,
13
13
  postJsonToApi,
14
+ serializeModelOptions,
15
+ WORKFLOW_DESERIALIZE,
16
+ WORKFLOW_SERIALIZE,
14
17
  } from '@ai-sdk/provider-utils';
15
18
  import { OpenAIConfig } from '../openai-config';
16
19
  import { openaiFailedResponseHandler } from '../openai-error';
@@ -30,6 +33,20 @@ interface OpenAIImageModelConfig extends OpenAIConfig {
30
33
  export class OpenAIImageModel implements ImageModelV4 {
31
34
  readonly specificationVersion = 'v4';
32
35
 
36
+ static [WORKFLOW_SERIALIZE](model: OpenAIImageModel) {
37
+ return serializeModelOptions({
38
+ modelId: model.modelId,
39
+ config: model.config,
40
+ });
41
+ }
42
+
43
+ static [WORKFLOW_DESERIALIZE](options: {
44
+ modelId: OpenAIImageModelId;
45
+ config: OpenAIImageModelConfig;
46
+ }) {
47
+ return new OpenAIImageModel(options.modelId, options.config);
48
+ }
49
+
33
50
  get maxImagesPerCall(): number {
34
51
  return modelMaxImagesPerCall[this.modelId] ?? 1;
35
52
  }
@@ -80,7 +97,7 @@ export class OpenAIImageModel implements ImageModelV4 {
80
97
  path: '/images/edits',
81
98
  modelId: this.modelId,
82
99
  }),
83
- headers: combineHeaders(this.config.headers(), headers),
100
+ headers: combineHeaders(this.config.headers?.(), headers),
84
101
  formData: convertToFormData<OpenAIImageEditInput>({
85
102
  model: this.modelId,
86
103
  prompt,
@@ -158,7 +175,7 @@ export class OpenAIImageModel implements ImageModelV4 {
158
175
  path: '/images/generations',
159
176
  modelId: this.modelId,
160
177
  }),
161
- headers: combineHeaders(this.config.headers(), headers),
178
+ headers: combineHeaders(this.config.headers?.(), headers),
162
179
  body: {
163
180
  model: this.modelId,
164
181
  prompt,
@@ -3,7 +3,7 @@ import { FetchFunction } from '@ai-sdk/provider-utils';
3
3
  export type OpenAIConfig = {
4
4
  provider: string;
5
5
  url: (options: { modelId: string; path: string }) => string;
6
- headers: () => Record<string, string | undefined>;
6
+ headers?: () => Record<string, string | undefined>;
7
7
  fetch?: FetchFunction;
8
8
  generateId?: () => string;
9
9
  /**
@@ -36,6 +36,10 @@ import {
36
36
  toolSearchOutputSchema,
37
37
  } from '../tool/tool-search';
38
38
 
39
+ function serializeToolCallArguments(input: unknown): string {
40
+ return JSON.stringify(input === undefined ? {} : input);
41
+ }
42
+
39
43
  /**
40
44
  * This is soft-deprecated. Use provider references instead. Kept for backward compatibility
41
45
  * with the `fileIdPrefixes` option.
@@ -362,7 +366,7 @@ export async function convertToOpenAIResponsesInput({
362
366
  type: 'function_call',
363
367
  call_id: part.toolCallId,
364
368
  name: resolvedToolName,
365
- arguments: JSON.stringify(part.input),
369
+ arguments: serializeToolCallArguments(part.input),
366
370
  id,
367
371
  });
368
372
  break;
@@ -751,23 +755,25 @@ export async function convertToOpenAIResponsesInput({
751
755
  switch (item.type) {
752
756
  case 'text':
753
757
  return { type: 'input_text' as const, text: item.text };
754
- case 'image-data':
755
- return {
756
- type: 'input_image' as const,
757
- image_url: `data:${item.mediaType};base64,${item.data}`,
758
- };
759
- case 'image-url':
760
- return {
761
- type: 'input_image' as const,
762
- image_url: item.url,
763
- };
764
758
  case 'file-data':
759
+ if (item.mediaType.startsWith('image/')) {
760
+ return {
761
+ type: 'input_image' as const,
762
+ image_url: `data:${item.mediaType};base64,${item.data}`,
763
+ };
764
+ }
765
765
  return {
766
766
  type: 'input_file' as const,
767
767
  filename: item.filename ?? 'data',
768
768
  file_data: `data:${item.mediaType};base64,${item.data}`,
769
769
  };
770
770
  case 'file-url':
771
+ if (item.mediaType.startsWith('image/')) {
772
+ return {
773
+ type: 'input_image' as const,
774
+ image_url: item.url,
775
+ };
776
+ }
771
777
  return {
772
778
  type: 'input_file' as const,
773
779
  file_url: item.url,
@@ -814,21 +820,13 @@ export async function convertToOpenAIResponsesInput({
814
820
  return { type: 'input_text' as const, text: item.text };
815
821
  }
816
822
 
817
- case 'image-data': {
818
- return {
819
- type: 'input_image' as const,
820
- image_url: `data:${item.mediaType};base64,${item.data}`,
821
- };
822
- }
823
-
824
- case 'image-url': {
825
- return {
826
- type: 'input_image' as const,
827
- image_url: item.url,
828
- };
829
- }
830
-
831
823
  case 'file-data': {
824
+ if (item.mediaType.startsWith('image/')) {
825
+ return {
826
+ type: 'input_image' as const,
827
+ image_url: `data:${item.mediaType};base64,${item.data}`,
828
+ };
829
+ }
832
830
  return {
833
831
  type: 'input_file' as const,
834
832
  filename: item.filename ?? 'data',
@@ -837,6 +835,12 @@ export async function convertToOpenAIResponsesInput({
837
835
  }
838
836
 
839
837
  case 'file-url': {
838
+ if (item.mediaType.startsWith('image/')) {
839
+ return {
840
+ type: 'input_image' as const,
841
+ image_url: item.url,
842
+ };
843
+ }
840
844
  return {
841
845
  type: 'input_file' as const,
842
846
  file_url: item.url,
@@ -25,6 +25,9 @@ import {
25
25
  parseProviderOptions,
26
26
  ParseResult,
27
27
  postJsonToApi,
28
+ serializeModelOptions,
29
+ WORKFLOW_DESERIALIZE,
30
+ WORKFLOW_SERIALIZE,
28
31
  } from '@ai-sdk/provider-utils';
29
32
  import { OpenAIConfig } from '../openai-config';
30
33
  import { openaiFailedResponseHandler } from '../openai-error';
@@ -107,6 +110,20 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
107
110
 
108
111
  private readonly config: OpenAIConfig;
109
112
 
113
+ static [WORKFLOW_SERIALIZE](model: OpenAIResponsesLanguageModel) {
114
+ return serializeModelOptions({
115
+ modelId: model.modelId,
116
+ config: model.config,
117
+ });
118
+ }
119
+
120
+ static [WORKFLOW_DESERIALIZE](options: {
121
+ modelId: OpenAIResponsesModelId;
122
+ config: OpenAIConfig;
123
+ }) {
124
+ return new OpenAIResponsesLanguageModel(options.modelId, options.config);
125
+ }
126
+
110
127
  constructor(modelId: OpenAIResponsesModelId, config: OpenAIConfig) {
111
128
  this.modelId = modelId;
112
129
  this.config = config;
@@ -494,7 +511,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
494
511
  rawValue: rawResponse,
495
512
  } = await postJsonToApi({
496
513
  url,
497
- headers: combineHeaders(this.config.headers(), options.headers),
514
+ headers: combineHeaders(this.config.headers?.(), options.headers),
498
515
  body,
499
516
  failedResponseHandler: openaiFailedResponseHandler,
500
517
  successfulResponseHandler: createJsonResponseHandler(
@@ -1063,7 +1080,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
1063
1080
  path: '/responses',
1064
1081
  modelId: this.modelId,
1065
1082
  }),
1066
- headers: combineHeaders(this.config.headers(), options.headers),
1083
+ headers: combineHeaders(this.config.headers?.(), options.headers),
1067
1084
  body: {
1068
1085
  ...body,
1069
1086
  stream: true,
@@ -4,6 +4,9 @@ import {
4
4
  createBinaryResponseHandler,
5
5
  parseProviderOptions,
6
6
  postJsonToApi,
7
+ serializeModelOptions,
8
+ WORKFLOW_DESERIALIZE,
9
+ WORKFLOW_SERIALIZE,
7
10
  } from '@ai-sdk/provider-utils';
8
11
  import { OpenAIConfig } from '../openai-config';
9
12
  import { openaiFailedResponseHandler } from '../openai-error';
@@ -22,6 +25,20 @@ interface OpenAISpeechModelConfig extends OpenAIConfig {
22
25
  export class OpenAISpeechModel implements SpeechModelV4 {
23
26
  readonly specificationVersion = 'v4';
24
27
 
28
+ static [WORKFLOW_SERIALIZE](model: OpenAISpeechModel) {
29
+ return serializeModelOptions({
30
+ modelId: model.modelId,
31
+ config: model.config,
32
+ });
33
+ }
34
+
35
+ static [WORKFLOW_DESERIALIZE](options: {
36
+ modelId: OpenAISpeechModelId;
37
+ config: OpenAISpeechModelConfig;
38
+ }) {
39
+ return new OpenAISpeechModel(options.modelId, options.config);
40
+ }
41
+
25
42
  get provider(): string {
26
43
  return this.config.provider;
27
44
  }
@@ -112,7 +129,7 @@ export class OpenAISpeechModel implements SpeechModelV4 {
112
129
  path: '/audio/speech',
113
130
  modelId: this.modelId,
114
131
  }),
115
- headers: combineHeaders(this.config.headers(), options.headers),
132
+ headers: combineHeaders(this.config.headers?.(), options.headers),
116
133
  body: requestBody,
117
134
  failedResponseHandler: openaiFailedResponseHandler,
118
135
  successfulResponseHandler: createBinaryResponseHandler(),
@@ -10,6 +10,9 @@ import {
10
10
  mediaTypeToExtension,
11
11
  parseProviderOptions,
12
12
  postFormDataToApi,
13
+ serializeModelOptions,
14
+ WORKFLOW_DESERIALIZE,
15
+ WORKFLOW_SERIALIZE,
13
16
  } from '@ai-sdk/provider-utils';
14
17
  import { OpenAIConfig } from '../openai-config';
15
18
  import { openaiFailedResponseHandler } from '../openai-error';
@@ -99,6 +102,20 @@ const languageMap = {
99
102
  export class OpenAITranscriptionModel implements TranscriptionModelV4 {
100
103
  readonly specificationVersion = 'v4';
101
104
 
105
+ static [WORKFLOW_SERIALIZE](model: OpenAITranscriptionModel) {
106
+ return serializeModelOptions({
107
+ modelId: model.modelId,
108
+ config: model.config,
109
+ });
110
+ }
111
+
112
+ static [WORKFLOW_DESERIALIZE](options: {
113
+ modelId: OpenAITranscriptionModelId;
114
+ config: OpenAITranscriptionModelConfig;
115
+ }) {
116
+ return new OpenAITranscriptionModel(options.modelId, options.config);
117
+ }
118
+
102
119
  get provider(): string {
103
120
  return this.config.provider;
104
121
  }
@@ -189,7 +206,7 @@ export class OpenAITranscriptionModel implements TranscriptionModelV4 {
189
206
  path: '/audio/transcriptions',
190
207
  modelId: this.modelId,
191
208
  }),
192
- headers: combineHeaders(this.config.headers(), options.headers),
209
+ headers: combineHeaders(this.config.headers?.(), options.headers),
193
210
  formData,
194
211
  failedResponseHandler: openaiFailedResponseHandler,
195
212
  successfulResponseHandler: createJsonResponseHandler(