@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.
- package/CHANGELOG.md +399 -22
- package/README.md +2 -0
- package/dist/index.d.ts +166 -49
- package/dist/index.js +2454 -1627
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +176 -53
- package/dist/internal/index.js +2220 -1648
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +292 -22
- package/package.json +13 -14
- package/src/chat/convert-openai-chat-usage.ts +2 -2
- package/src/chat/convert-to-openai-chat-messages.ts +99 -71
- package/src/chat/map-openai-finish-reason.ts +2 -2
- package/src/chat/openai-chat-api.ts +6 -2
- package/src/chat/openai-chat-language-model.ts +68 -164
- package/src/chat/openai-chat-options.ts +10 -1
- package/src/chat/openai-chat-prepare-tools.ts +7 -7
- package/src/completion/convert-openai-completion-usage.ts +2 -2
- package/src/completion/convert-to-openai-completion-prompt.ts +2 -3
- package/src/completion/map-openai-finish-reason.ts +2 -2
- package/src/completion/openai-completion-api.ts +5 -2
- package/src/completion/openai-completion-language-model.ts +46 -30
- package/src/completion/openai-completion-options.ts +5 -1
- package/src/embedding/openai-embedding-model.ts +25 -8
- package/src/embedding/openai-embedding-options.ts +5 -1
- package/src/files/openai-files-api.ts +17 -0
- package/src/files/openai-files-options.ts +22 -0
- package/src/files/openai-files.ts +100 -0
- package/src/image/openai-image-model.ts +31 -15
- package/src/image/openai-image-options.ts +3 -0
- package/src/index.ts +2 -0
- package/src/openai-config.ts +7 -7
- package/src/openai-language-model-capabilities.ts +3 -2
- package/src/openai-provider.ts +63 -30
- package/src/openai-tools.ts +12 -1
- package/src/responses/convert-openai-responses-usage.ts +2 -2
- package/src/responses/convert-to-openai-responses-input.ts +244 -77
- package/src/responses/map-openai-responses-finish-reason.ts +2 -2
- package/src/responses/openai-responses-api.ts +141 -3
- package/src/responses/openai-responses-language-model.ts +274 -61
- package/src/responses/openai-responses-options.ts +29 -3
- package/src/responses/openai-responses-prepare-tools.ts +48 -15
- package/src/responses/openai-responses-provider-metadata.ts +12 -2
- package/src/skills/openai-skills-api.ts +31 -0
- package/src/skills/openai-skills.ts +83 -0
- package/src/speech/openai-speech-model.ts +28 -12
- package/src/speech/openai-speech-options.ts +5 -1
- package/src/tool/apply-patch.ts +33 -32
- package/src/tool/code-interpreter.ts +40 -41
- package/src/tool/custom.ts +2 -8
- package/src/tool/file-search.ts +3 -3
- package/src/tool/image-generation.ts +2 -2
- package/src/tool/local-shell.ts +2 -2
- package/src/tool/mcp.ts +3 -3
- package/src/tool/shell.ts +9 -4
- package/src/tool/tool-search.ts +98 -0
- package/src/tool/web-search-preview.ts +2 -2
- package/src/tool/web-search.ts +2 -2
- package/src/transcription/openai-transcription-model.ts +30 -14
- package/src/transcription/openai-transcription-options.ts +5 -1
- package/dist/index.d.mts +0 -1107
- package/dist/index.mjs +0 -6508
- package/dist/index.mjs.map +0 -1
- package/dist/internal/index.d.mts +0 -1137
- package/dist/internal/index.mjs +0 -6321
- package/dist/internal/index.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
-
):
|
|
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:
|
|
11
|
+
prompt: LanguageModelV4Prompt;
|
|
13
12
|
user?: string;
|
|
14
13
|
assistant?: string;
|
|
15
14
|
}): {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LanguageModelV4FinishReason } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
export function mapOpenAIFinishReason(
|
|
4
4
|
finishReason: string | null | undefined,
|
|
5
|
-
):
|
|
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 {
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
|
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
|
|
46
|
-
readonly specificationVersion = '
|
|
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
|
-
}:
|
|
87
|
-
const warnings:
|
|
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:
|
|
165
|
-
): Promise<
|
|
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:
|
|
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:
|
|
215
|
-
): Promise<
|
|
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:
|
|
258
|
+
let finishReason: LanguageModelV4FinishReason = {
|
|
243
259
|
unified: 'other',
|
|
244
260
|
raw: undefined,
|
|
245
261
|
};
|
|
246
|
-
const providerMetadata:
|
|
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
|
-
|
|
270
|
+
LanguageModelV4StreamPart
|
|
255
271
|
>({
|
|
256
272
|
start(controller) {
|
|
257
273
|
controller.enqueue({ type: 'stream-start', warnings });
|
|
@@ -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
|
|
20
|
-
readonly specificationVersion = '
|
|
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<
|
|
42
|
-
Awaited<ReturnType<
|
|
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,
|
|
@@ -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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
|
31
|
-
readonly specificationVersion = '
|
|
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<
|
|
58
|
-
Awaited<ReturnType<
|
|
73
|
+
}: Parameters<ImageModelV4['doGenerate']>[0]): Promise<
|
|
74
|
+
Awaited<ReturnType<ImageModelV4['doGenerate']>>
|
|
59
75
|
> {
|
|
60
|
-
const warnings: Array<
|
|
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:
|
|
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,
|
package/src/openai-config.ts
CHANGED
|
@@ -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
|
|
6
|
+
headers?: () => Record<string, string | undefined>;
|
|
7
7
|
fetch?: FetchFunction;
|
|
8
8
|
generateId?: () => string;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
-
*
|
|
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';
|