@ai-sdk/openai 4.0.0-beta.4 → 4.0.0-beta.41

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.
Files changed (66) hide show
  1. package/CHANGELOG.md +399 -22
  2. package/README.md +2 -0
  3. package/dist/index.d.ts +166 -49
  4. package/dist/index.js +2454 -1627
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +176 -53
  7. package/dist/internal/index.js +2220 -1648
  8. package/dist/internal/index.js.map +1 -1
  9. package/docs/03-openai.mdx +292 -22
  10. package/package.json +13 -14
  11. package/src/chat/convert-openai-chat-usage.ts +2 -2
  12. package/src/chat/convert-to-openai-chat-messages.ts +99 -71
  13. package/src/chat/map-openai-finish-reason.ts +2 -2
  14. package/src/chat/openai-chat-api.ts +6 -2
  15. package/src/chat/openai-chat-language-model.ts +68 -164
  16. package/src/chat/openai-chat-options.ts +10 -1
  17. package/src/chat/openai-chat-prepare-tools.ts +7 -7
  18. package/src/completion/convert-openai-completion-usage.ts +2 -2
  19. package/src/completion/convert-to-openai-completion-prompt.ts +2 -3
  20. package/src/completion/map-openai-finish-reason.ts +2 -2
  21. package/src/completion/openai-completion-api.ts +5 -2
  22. package/src/completion/openai-completion-language-model.ts +46 -30
  23. package/src/completion/openai-completion-options.ts +5 -1
  24. package/src/embedding/openai-embedding-model.ts +25 -8
  25. package/src/embedding/openai-embedding-options.ts +5 -1
  26. package/src/files/openai-files-api.ts +17 -0
  27. package/src/files/openai-files-options.ts +22 -0
  28. package/src/files/openai-files.ts +100 -0
  29. package/src/image/openai-image-model.ts +31 -15
  30. package/src/image/openai-image-options.ts +3 -0
  31. package/src/index.ts +2 -0
  32. package/src/openai-config.ts +7 -7
  33. package/src/openai-language-model-capabilities.ts +3 -2
  34. package/src/openai-provider.ts +63 -30
  35. package/src/openai-tools.ts +12 -1
  36. package/src/responses/convert-openai-responses-usage.ts +2 -2
  37. package/src/responses/convert-to-openai-responses-input.ts +244 -77
  38. package/src/responses/map-openai-responses-finish-reason.ts +2 -2
  39. package/src/responses/openai-responses-api.ts +141 -3
  40. package/src/responses/openai-responses-language-model.ts +274 -61
  41. package/src/responses/openai-responses-options.ts +29 -3
  42. package/src/responses/openai-responses-prepare-tools.ts +48 -15
  43. package/src/responses/openai-responses-provider-metadata.ts +12 -2
  44. package/src/skills/openai-skills-api.ts +31 -0
  45. package/src/skills/openai-skills.ts +83 -0
  46. package/src/speech/openai-speech-model.ts +28 -12
  47. package/src/speech/openai-speech-options.ts +5 -1
  48. package/src/tool/apply-patch.ts +33 -32
  49. package/src/tool/code-interpreter.ts +40 -41
  50. package/src/tool/custom.ts +2 -8
  51. package/src/tool/file-search.ts +3 -3
  52. package/src/tool/image-generation.ts +2 -2
  53. package/src/tool/local-shell.ts +2 -2
  54. package/src/tool/mcp.ts +3 -3
  55. package/src/tool/shell.ts +9 -4
  56. package/src/tool/tool-search.ts +98 -0
  57. package/src/tool/web-search-preview.ts +2 -2
  58. package/src/tool/web-search.ts +2 -2
  59. package/src/transcription/openai-transcription-model.ts +30 -14
  60. package/src/transcription/openai-transcription-options.ts +5 -1
  61. package/dist/index.d.mts +0 -1107
  62. package/dist/index.mjs +0 -6508
  63. package/dist/index.mjs.map +0 -1
  64. package/dist/internal/index.d.mts +0 -1137
  65. package/dist/internal/index.mjs +0 -6321
  66. package/dist/internal/index.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { LanguageModelV3Usage } from '@ai-sdk/provider';
1
+ import type { LanguageModelV4Usage } from '@ai-sdk/provider';
2
2
 
3
3
  export type OpenAICompletionUsage = {
4
4
  prompt_tokens?: number | null;
@@ -8,7 +8,7 @@ export type OpenAICompletionUsage = {
8
8
 
9
9
  export function convertOpenAICompletionUsage(
10
10
  usage: OpenAICompletionUsage | undefined | null,
11
- ): LanguageModelV3Usage {
11
+ ): LanguageModelV4Usage {
12
12
  if (usage == null) {
13
13
  return {
14
14
  inputTokens: {
@@ -1,15 +1,14 @@
1
1
  import {
2
2
  InvalidPromptError,
3
- LanguageModelV3Prompt,
4
3
  UnsupportedFunctionalityError,
4
+ type LanguageModelV4Prompt,
5
5
  } from '@ai-sdk/provider';
6
-
7
6
  export function convertToOpenAICompletionPrompt({
8
7
  prompt,
9
8
  user = 'user',
10
9
  assistant = 'assistant',
11
10
  }: {
12
- prompt: LanguageModelV3Prompt;
11
+ prompt: LanguageModelV4Prompt;
13
12
  user?: string;
14
13
  assistant?: string;
15
14
  }): {
@@ -1,8 +1,8 @@
1
- import { LanguageModelV3FinishReason } from '@ai-sdk/provider';
1
+ import type { LanguageModelV4FinishReason } from '@ai-sdk/provider';
2
2
 
3
3
  export function mapOpenAIFinishReason(
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,10 @@
1
1
  import { z } from 'zod/v4';
2
2
  import { openaiErrorDataSchema } from '../openai-error';
3
- import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils';
4
-
3
+ import {
4
+ lazySchema,
5
+ zodSchema,
6
+ type InferSchema,
7
+ } from '@ai-sdk/provider-utils';
5
8
  // limited version of the schema, focussed on what is needed for the implementation
6
9
  // this approach limits breakages when the API changes and increases efficiency
7
10
  export const openaiCompletionResponseSchema = lazySchema(() =>
@@ -1,49 +1,51 @@
1
- import {
2
- LanguageModelV3,
3
- LanguageModelV3CallOptions,
4
- LanguageModelV3FinishReason,
5
- LanguageModelV3GenerateResult,
6
- LanguageModelV3StreamPart,
7
- LanguageModelV3StreamResult,
8
- SharedV3ProviderMetadata,
9
- SharedV3Warning,
1
+ import type {
2
+ LanguageModelV4,
3
+ LanguageModelV4CallOptions,
4
+ LanguageModelV4FinishReason,
5
+ LanguageModelV4GenerateResult,
6
+ LanguageModelV4StreamPart,
7
+ LanguageModelV4StreamResult,
8
+ SharedV4ProviderMetadata,
9
+ SharedV4Warning,
10
10
  } from '@ai-sdk/provider';
11
11
  import {
12
12
  combineHeaders,
13
13
  createEventSourceResponseHandler,
14
14
  createJsonResponseHandler,
15
- FetchFunction,
16
15
  parseProviderOptions,
17
- ParseResult,
18
16
  postJsonToApi,
17
+ serializeModelOptions,
18
+ WORKFLOW_DESERIALIZE,
19
+ WORKFLOW_SERIALIZE,
20
+ type FetchFunction,
21
+ type ParseResult,
19
22
  } from '@ai-sdk/provider-utils';
20
23
  import { openaiFailedResponseHandler } from '../openai-error';
21
24
  import {
22
25
  convertOpenAICompletionUsage,
23
- OpenAICompletionUsage,
26
+ type OpenAICompletionUsage,
24
27
  } from './convert-openai-completion-usage';
25
28
  import { convertToOpenAICompletionPrompt } from './convert-to-openai-completion-prompt';
26
29
  import { getResponseMetadata } from './get-response-metadata';
27
30
  import { mapOpenAIFinishReason } from './map-openai-finish-reason';
28
31
  import {
29
- OpenAICompletionChunk,
30
32
  openaiCompletionChunkSchema,
31
33
  openaiCompletionResponseSchema,
34
+ type OpenAICompletionChunk,
32
35
  } from './openai-completion-api';
33
36
  import {
34
- OpenAICompletionModelId,
35
37
  openaiLanguageModelCompletionOptions,
38
+ type OpenAICompletionModelId,
36
39
  } from './openai-completion-options';
37
-
38
40
  type OpenAICompletionConfig = {
39
41
  provider: string;
40
- headers: () => Record<string, string | undefined>;
42
+ headers?: () => Record<string, string | undefined>;
41
43
  url: (options: { modelId: string; path: string }) => string;
42
44
  fetch?: FetchFunction;
43
45
  };
44
46
 
45
- export class OpenAICompletionLanguageModel implements LanguageModelV3 {
46
- readonly specificationVersion = 'v3';
47
+ export class OpenAICompletionLanguageModel implements LanguageModelV4 {
48
+ readonly specificationVersion = 'v4';
47
49
 
48
50
  readonly modelId: OpenAICompletionModelId;
49
51
 
@@ -53,6 +55,20 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
53
55
  return this.config.provider.split('.')[0].trim();
54
56
  }
55
57
 
58
+ static [WORKFLOW_SERIALIZE](model: OpenAICompletionLanguageModel) {
59
+ return serializeModelOptions({
60
+ modelId: model.modelId,
61
+ config: model.config,
62
+ });
63
+ }
64
+
65
+ static [WORKFLOW_DESERIALIZE](options: {
66
+ modelId: OpenAICompletionModelId;
67
+ config: OpenAICompletionConfig;
68
+ }) {
69
+ return new OpenAICompletionLanguageModel(options.modelId, options.config);
70
+ }
71
+
56
72
  constructor(
57
73
  modelId: OpenAICompletionModelId,
58
74
  config: OpenAICompletionConfig,
@@ -83,8 +99,8 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
83
99
  toolChoice,
84
100
  seed,
85
101
  providerOptions,
86
- }: LanguageModelV3CallOptions) {
87
- const warnings: SharedV3Warning[] = [];
102
+ }: LanguageModelV4CallOptions) {
103
+ const warnings: SharedV4Warning[] = [];
88
104
 
89
105
  // Parse provider options
90
106
  const openaiOptions = {
@@ -161,8 +177,8 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
161
177
  }
162
178
 
163
179
  async doGenerate(
164
- options: LanguageModelV3CallOptions,
165
- ): Promise<LanguageModelV3GenerateResult> {
180
+ options: LanguageModelV4CallOptions,
181
+ ): Promise<LanguageModelV4GenerateResult> {
166
182
  const { args, warnings } = await this.getArgs(options);
167
183
 
168
184
  const {
@@ -174,7 +190,7 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
174
190
  path: '/completions',
175
191
  modelId: this.modelId,
176
192
  }),
177
- headers: combineHeaders(this.config.headers(), options.headers),
193
+ headers: combineHeaders(this.config.headers?.(), options.headers),
178
194
  body: args,
179
195
  failedResponseHandler: openaiFailedResponseHandler,
180
196
  successfulResponseHandler: createJsonResponseHandler(
@@ -186,7 +202,7 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
186
202
 
187
203
  const choice = response.choices[0];
188
204
 
189
- const providerMetadata: SharedV3ProviderMetadata = { openai: {} };
205
+ const providerMetadata: SharedV4ProviderMetadata = { openai: {} };
190
206
 
191
207
  if (choice.logprobs != null) {
192
208
  providerMetadata.openai.logprobs = choice.logprobs;
@@ -211,8 +227,8 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
211
227
  }
212
228
 
213
229
  async doStream(
214
- options: LanguageModelV3CallOptions,
215
- ): Promise<LanguageModelV3StreamResult> {
230
+ options: LanguageModelV4CallOptions,
231
+ ): Promise<LanguageModelV4StreamResult> {
216
232
  const { args, warnings } = await this.getArgs(options);
217
233
 
218
234
  const body = {
@@ -229,7 +245,7 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
229
245
  path: '/completions',
230
246
  modelId: this.modelId,
231
247
  }),
232
- headers: combineHeaders(this.config.headers(), options.headers),
248
+ headers: combineHeaders(this.config.headers?.(), options.headers),
233
249
  body,
234
250
  failedResponseHandler: openaiFailedResponseHandler,
235
251
  successfulResponseHandler: createEventSourceResponseHandler(
@@ -239,11 +255,11 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
239
255
  fetch: this.config.fetch,
240
256
  });
241
257
 
242
- let finishReason: LanguageModelV3FinishReason = {
258
+ let finishReason: LanguageModelV4FinishReason = {
243
259
  unified: 'other',
244
260
  raw: undefined,
245
261
  };
246
- const providerMetadata: SharedV3ProviderMetadata = { openai: {} };
262
+ const providerMetadata: SharedV4ProviderMetadata = { openai: {} };
247
263
  let usage: OpenAICompletionUsage | undefined = undefined;
248
264
  let isFirstChunk = true;
249
265
 
@@ -251,7 +267,7 @@ export class OpenAICompletionLanguageModel implements LanguageModelV3 {
251
267
  stream: response.pipeThrough(
252
268
  new TransformStream<
253
269
  ParseResult<OpenAICompletionChunk>,
254
- LanguageModelV3StreamPart
270
+ LanguageModelV4StreamPart
255
271
  >({
256
272
  start(controller) {
257
273
  controller.enqueue({ type: 'stream-start', warnings });
@@ -1,4 +1,8 @@
1
- import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils';
1
+ import {
2
+ lazySchema,
3
+ zodSchema,
4
+ type InferSchema,
5
+ } from '@ai-sdk/provider-utils';
2
6
  import { z } from 'zod/v4';
3
7
 
4
8
  // https://platform.openai.com/docs/models
@@ -1,29 +1,46 @@
1
1
  import {
2
- EmbeddingModelV3,
3
2
  TooManyEmbeddingValuesForCallError,
3
+ type EmbeddingModelV4,
4
4
  } from '@ai-sdk/provider';
5
5
  import {
6
6
  combineHeaders,
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
- import { OpenAIConfig } from '../openai-config';
14
+ import type { OpenAIConfig } from '../openai-config';
12
15
  import { openaiFailedResponseHandler } from '../openai-error';
13
16
  import {
14
- OpenAIEmbeddingModelId,
15
17
  openaiEmbeddingModelOptions,
18
+ type OpenAIEmbeddingModelId,
16
19
  } from './openai-embedding-options';
17
20
  import { openaiTextEmbeddingResponseSchema } from './openai-embedding-api';
18
21
 
19
- export class OpenAIEmbeddingModel implements EmbeddingModelV3 {
20
- readonly specificationVersion = 'v3';
22
+ export class OpenAIEmbeddingModel implements EmbeddingModelV4 {
23
+ readonly specificationVersion = 'v4';
21
24
  readonly modelId: OpenAIEmbeddingModelId;
22
25
  readonly maxEmbeddingsPerCall = 2048;
23
26
  readonly supportsParallelCalls = true;
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
  }
@@ -38,8 +55,8 @@ export class OpenAIEmbeddingModel implements EmbeddingModelV3 {
38
55
  headers,
39
56
  abortSignal,
40
57
  providerOptions,
41
- }: Parameters<EmbeddingModelV3['doEmbed']>[0]): Promise<
42
- Awaited<ReturnType<EmbeddingModelV3['doEmbed']>>
58
+ }: Parameters<EmbeddingModelV4['doEmbed']>[0]): Promise<
59
+ Awaited<ReturnType<EmbeddingModelV4['doEmbed']>>
43
60
  > {
44
61
  if (values.length > this.maxEmbeddingsPerCall) {
45
62
  throw new TooManyEmbeddingValuesForCallError({
@@ -67,7 +84,7 @@ export class OpenAIEmbeddingModel implements EmbeddingModelV3 {
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,
@@ -1,4 +1,8 @@
1
- import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils';
1
+ import {
2
+ lazySchema,
3
+ zodSchema,
4
+ type InferSchema,
5
+ } from '@ai-sdk/provider-utils';
2
6
  import { z } from 'zod/v4';
3
7
 
4
8
  export type OpenAIEmbeddingModelId =
@@ -0,0 +1,17 @@
1
+ import { lazySchema, zodSchema } from '@ai-sdk/provider-utils';
2
+ import { z } from 'zod/v4';
3
+
4
+ export const openaiFilesResponseSchema = lazySchema(() =>
5
+ zodSchema(
6
+ z.object({
7
+ id: z.string(),
8
+ object: z.string().nullish(),
9
+ bytes: z.number().nullish(),
10
+ created_at: z.number().nullish(),
11
+ filename: z.string().nullish(),
12
+ purpose: z.string().nullish(),
13
+ status: z.string().nullish(),
14
+ expires_at: z.number().nullish(),
15
+ }),
16
+ ),
17
+ );
@@ -0,0 +1,22 @@
1
+ import {
2
+ lazySchema,
3
+ zodSchema,
4
+ type InferSchema,
5
+ } from '@ai-sdk/provider-utils';
6
+ import { z } from 'zod/v4';
7
+
8
+ export const openaiFilesOptionsSchema = lazySchema(() =>
9
+ zodSchema(
10
+ z.object({
11
+ /*
12
+ * Required by the OpenAI API, but optional here because
13
+ * the SDK defaults to "assistants" — by far the most common
14
+ * purpose when uploading files in this context.
15
+ */
16
+ purpose: z.string().optional(),
17
+ expiresAfter: z.number().optional(),
18
+ }),
19
+ ),
20
+ );
21
+
22
+ export type OpenAIFilesOptions = InferSchema<typeof openaiFilesOptionsSchema>;
@@ -0,0 +1,100 @@
1
+ import type {
2
+ FilesV4,
3
+ FilesV4UploadFileCallOptions,
4
+ FilesV4UploadFileResult,
5
+ } from '@ai-sdk/provider';
6
+ import {
7
+ combineHeaders,
8
+ convertInlineFileDataToUint8Array,
9
+ createJsonResponseHandler,
10
+ parseProviderOptions,
11
+ postFormDataToApi,
12
+ type FetchFunction,
13
+ } from '@ai-sdk/provider-utils';
14
+ import { openaiFailedResponseHandler } from '../openai-error';
15
+ import { openaiFilesResponseSchema } from './openai-files-api';
16
+ import {
17
+ openaiFilesOptionsSchema,
18
+ type OpenAIFilesOptions,
19
+ } from './openai-files-options';
20
+ interface OpenAIFilesConfig {
21
+ provider: string;
22
+ baseURL: string;
23
+ headers: () => Record<string, string | undefined>;
24
+ fetch?: FetchFunction;
25
+ }
26
+
27
+ export class OpenAIFiles implements FilesV4 {
28
+ readonly specificationVersion = 'v4';
29
+
30
+ get provider(): string {
31
+ return this.config.provider;
32
+ }
33
+
34
+ constructor(private readonly config: OpenAIFilesConfig) {}
35
+
36
+ async uploadFile({
37
+ data,
38
+ mediaType,
39
+ filename,
40
+ providerOptions,
41
+ }: FilesV4UploadFileCallOptions): Promise<FilesV4UploadFileResult> {
42
+ const openaiOptions = (await parseProviderOptions({
43
+ provider: 'openai',
44
+ providerOptions,
45
+ schema: openaiFilesOptionsSchema,
46
+ })) as OpenAIFilesOptions | undefined;
47
+
48
+ const fileBytes = convertInlineFileDataToUint8Array(data);
49
+
50
+ const blob = new Blob([fileBytes], {
51
+ type: mediaType,
52
+ });
53
+
54
+ const formData = new FormData();
55
+ if (filename != null) {
56
+ formData.append('file', blob, filename);
57
+ } else {
58
+ formData.append('file', blob);
59
+ }
60
+ formData.append('purpose', openaiOptions?.purpose ?? 'assistants');
61
+
62
+ if (openaiOptions?.expiresAfter != null) {
63
+ formData.append('expires_after', String(openaiOptions.expiresAfter));
64
+ }
65
+
66
+ const { value: response } = await postFormDataToApi({
67
+ url: `${this.config.baseURL}/files`,
68
+ headers: combineHeaders(this.config.headers()),
69
+ formData,
70
+ failedResponseHandler: openaiFailedResponseHandler,
71
+ successfulResponseHandler: createJsonResponseHandler(
72
+ openaiFilesResponseSchema,
73
+ ),
74
+ fetch: this.config.fetch,
75
+ });
76
+
77
+ return {
78
+ warnings: [],
79
+ providerReference: { openai: response.id },
80
+ ...((response.filename ?? filename)
81
+ ? { filename: response.filename ?? filename }
82
+ : {}),
83
+ ...(mediaType != null ? { mediaType } : {}),
84
+ providerMetadata: {
85
+ openai: {
86
+ ...(response.filename != null ? { filename: response.filename } : {}),
87
+ ...(response.purpose != null ? { purpose: response.purpose } : {}),
88
+ ...(response.bytes != null ? { bytes: response.bytes } : {}),
89
+ ...(response.created_at != null
90
+ ? { createdAt: response.created_at }
91
+ : {}),
92
+ ...(response.status != null ? { status: response.status } : {}),
93
+ ...(response.expires_at != null
94
+ ? { expiresAt: response.expires_at }
95
+ : {}),
96
+ },
97
+ },
98
+ };
99
+ }
100
+ }
@@ -1,7 +1,7 @@
1
- import {
2
- ImageModelV3,
3
- ImageModelV3File,
4
- SharedV3Warning,
1
+ import type {
2
+ ImageModelV4,
3
+ ImageModelV4File,
4
+ SharedV4Warning,
5
5
  } from '@ai-sdk/provider';
6
6
  import {
7
7
  combineHeaders,
@@ -11,24 +11,40 @@ 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
- import { OpenAIConfig } from '../openai-config';
18
+ import type { OpenAIConfig } from '../openai-config';
16
19
  import { openaiFailedResponseHandler } from '../openai-error';
17
20
  import { openaiImageResponseSchema } from './openai-image-api';
18
21
  import {
19
- OpenAIImageModelId,
20
22
  hasDefaultResponseFormat,
21
23
  modelMaxImagesPerCall,
24
+ type OpenAIImageModelId,
22
25
  } from './openai-image-options';
23
-
24
26
  interface OpenAIImageModelConfig extends OpenAIConfig {
25
27
  _internal?: {
26
28
  currentDate?: () => Date;
27
29
  };
28
30
  }
29
31
 
30
- export class OpenAIImageModel implements ImageModelV3 {
31
- readonly specificationVersion = 'v3';
32
+ export class OpenAIImageModel implements ImageModelV4 {
33
+ readonly specificationVersion = 'v4';
34
+
35
+ static [WORKFLOW_SERIALIZE](model: OpenAIImageModel) {
36
+ return serializeModelOptions({
37
+ modelId: model.modelId,
38
+ config: model.config,
39
+ });
40
+ }
41
+
42
+ static [WORKFLOW_DESERIALIZE](options: {
43
+ modelId: OpenAIImageModelId;
44
+ config: OpenAIImageModelConfig;
45
+ }) {
46
+ return new OpenAIImageModel(options.modelId, options.config);
47
+ }
32
48
 
33
49
  get maxImagesPerCall(): number {
34
50
  return modelMaxImagesPerCall[this.modelId] ?? 1;
@@ -54,10 +70,10 @@ export class OpenAIImageModel implements ImageModelV3 {
54
70
  providerOptions,
55
71
  headers,
56
72
  abortSignal,
57
- }: Parameters<ImageModelV3['doGenerate']>[0]): Promise<
58
- Awaited<ReturnType<ImageModelV3['doGenerate']>>
73
+ }: Parameters<ImageModelV4['doGenerate']>[0]): Promise<
74
+ Awaited<ReturnType<ImageModelV4['doGenerate']>>
59
75
  > {
60
- const warnings: Array<SharedV3Warning> = [];
76
+ const warnings: Array<SharedV4Warning> = [];
61
77
 
62
78
  if (aspectRatio != null) {
63
79
  warnings.push({
@@ -80,7 +96,7 @@ export class OpenAIImageModel implements ImageModelV3 {
80
96
  path: '/images/edits',
81
97
  modelId: this.modelId,
82
98
  }),
83
- headers: combineHeaders(this.config.headers(), headers),
99
+ headers: combineHeaders(this.config.headers?.(), headers),
84
100
  formData: convertToFormData<OpenAIImageEditInput>({
85
101
  model: this.modelId,
86
102
  prompt,
@@ -158,7 +174,7 @@ export class OpenAIImageModel implements ImageModelV3 {
158
174
  path: '/images/generations',
159
175
  modelId: this.modelId,
160
176
  }),
161
- headers: combineHeaders(this.config.headers(), headers),
177
+ headers: combineHeaders(this.config.headers?.(), headers),
162
178
  body: {
163
179
  model: this.modelId,
164
180
  prompt,
@@ -332,7 +348,7 @@ type OpenAIImageEditInput = {
332
348
  };
333
349
 
334
350
  async function fileToBlob(
335
- file: ImageModelV3File | undefined,
351
+ file: ImageModelV4File | undefined,
336
352
  ): Promise<Blob | undefined> {
337
353
  if (!file) return undefined;
338
354
 
@@ -4,6 +4,7 @@ export type OpenAIImageModelId =
4
4
  | 'gpt-image-1'
5
5
  | 'gpt-image-1-mini'
6
6
  | 'gpt-image-1.5'
7
+ | 'gpt-image-2'
7
8
  | 'chatgpt-image-latest'
8
9
  | (string & {});
9
10
 
@@ -14,6 +15,7 @@ export const modelMaxImagesPerCall: Record<OpenAIImageModelId, number> = {
14
15
  'gpt-image-1': 10,
15
16
  'gpt-image-1-mini': 10,
16
17
  'gpt-image-1.5': 10,
18
+ 'gpt-image-2': 10,
17
19
  'chatgpt-image-latest': 10,
18
20
  };
19
21
 
@@ -22,6 +24,7 @@ const defaultResponseFormatPrefixes = [
22
24
  'gpt-image-1-mini',
23
25
  'gpt-image-1.5',
24
26
  'gpt-image-1',
27
+ 'gpt-image-2',
25
28
  ];
26
29
 
27
30
  export function hasDefaultResponseFormat(modelId: string): boolean {
package/src/index.ts CHANGED
@@ -14,7 +14,9 @@ export type { OpenAILanguageModelCompletionOptions } from './completion/openai-c
14
14
  export type { OpenAIEmbeddingModelOptions } from './embedding/openai-embedding-options';
15
15
  export type { OpenAISpeechModelOptions } from './speech/openai-speech-options';
16
16
  export type { OpenAITranscriptionModelOptions } from './transcription/openai-transcription-options';
17
+ export type { OpenAIFilesOptions } from './files/openai-files-options';
17
18
  export type {
19
+ OpenaiResponsesCompactionProviderMetadata,
18
20
  OpenaiResponsesProviderMetadata,
19
21
  OpenaiResponsesReasoningProviderMetadata,
20
22
  OpenaiResponsesTextProviderMetadata,
@@ -1,18 +1,18 @@
1
- import { FetchFunction } from '@ai-sdk/provider-utils';
1
+ import type { FetchFunction } from '@ai-sdk/provider-utils';
2
2
 
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
  /**
10
- * File ID prefixes used to identify file IDs in Responses API.
11
- * When undefined, all file data is treated as base64 content.
10
+ * This is soft-deprecated. Use provider references (e.g. `{ openai: 'file-abc123' }`)
11
+ * in file part data instead. File ID prefixes used to identify file IDs
12
+ * in Responses API. When undefined, all string file data is treated as
13
+ * base64 content.
12
14
  *
13
- * Examples:
14
- * - OpenAI: ['file-'] for IDs like 'file-abc123'
15
- * - Azure OpenAI: ['assistant-'] for IDs like 'assistant-abc123'
15
+ * TODO: remove in v8
16
16
  */
17
17
  fileIdPrefixes?: readonly string[];
18
18
  };
@@ -20,10 +20,10 @@ export function getOpenAILanguageModelCapabilities(
20
20
 
21
21
  const supportsPriorityProcessing =
22
22
  modelId.startsWith('gpt-4') ||
23
- modelId.startsWith('gpt-5-mini') ||
24
23
  (modelId.startsWith('gpt-5') &&
25
24
  !modelId.startsWith('gpt-5-nano') &&
26
- !modelId.startsWith('gpt-5-chat')) ||
25
+ !modelId.startsWith('gpt-5-chat') &&
26
+ !modelId.startsWith('gpt-5.4-nano')) ||
27
27
  modelId.startsWith('o3') ||
28
28
  modelId.startsWith('o4-mini');
29
29
 
@@ -40,6 +40,7 @@ export function getOpenAILanguageModelCapabilities(
40
40
  const supportsNonReasoningParameters =
41
41
  modelId.startsWith('gpt-5.1') ||
42
42
  modelId.startsWith('gpt-5.2') ||
43
+ modelId.startsWith('gpt-5.3') ||
43
44
  modelId.startsWith('gpt-5.4');
44
45
 
45
46
  const systemMessageMode = isReasoningModel ? 'developer' : 'system';