@ai-sdk/openai 3.0.77 → 3.0.79
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 +14 -0
- package/dist/index.js +39 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +39 -6
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +38 -5
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +38 -5
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-openai.mdx +18 -11
- package/package.json +3 -3
- package/src/responses/openai-responses-language-model.ts +61 -5
package/docs/03-openai.mdx
CHANGED
|
@@ -54,6 +54,10 @@ You can use the following optional settings to customize the OpenAI provider ins
|
|
|
54
54
|
|
|
55
55
|
Use a different URL prefix for API calls, e.g. to use proxy servers.
|
|
56
56
|
The default prefix is `https://api.openai.com/v1`.
|
|
57
|
+
The default OpenAI model factory (`openai('model-id')`) uses the Responses
|
|
58
|
+
API. If your custom base URL only supports the Chat Completions API, create
|
|
59
|
+
chat models with `openai.chat('model-id')` instead, or use the
|
|
60
|
+
[OpenAI-compatible provider](/providers/openai-compatible-providers).
|
|
57
61
|
|
|
58
62
|
- **apiKey** _string_
|
|
59
63
|
|
|
@@ -1601,6 +1605,8 @@ for (const part of result.content) {
|
|
|
1601
1605
|
You can create models that call the [OpenAI chat API](https://platform.openai.com/docs/api-reference/chat) using the `.chat()` factory method.
|
|
1602
1606
|
The first argument is the model id, e.g. `gpt-4`.
|
|
1603
1607
|
The OpenAI chat models support tool calls and some have multi-modal capabilities.
|
|
1608
|
+
Use this factory when a custom `baseURL` points at an OpenAI-compatible endpoint
|
|
1609
|
+
that implements Chat Completions but not the Responses API.
|
|
1604
1610
|
|
|
1605
1611
|
```ts
|
|
1606
1612
|
const model = openai.chat('gpt-5');
|
|
@@ -2358,7 +2364,7 @@ const model = openai.image('dall-e-3');
|
|
|
2358
2364
|
|
|
2359
2365
|
### Image Editing
|
|
2360
2366
|
|
|
2361
|
-
OpenAI's `gpt-image
|
|
2367
|
+
OpenAI's `gpt-image-*` models support powerful image editing capabilities. Pass input images via `prompt.images` to transform, combine, or edit existing images.
|
|
2362
2368
|
|
|
2363
2369
|
#### Basic Image Editing
|
|
2364
2370
|
|
|
@@ -2368,7 +2374,7 @@ Transform an existing image using text prompts:
|
|
|
2368
2374
|
const imageBuffer = readFileSync('./input-image.png');
|
|
2369
2375
|
|
|
2370
2376
|
const { images } = await generateImage({
|
|
2371
|
-
model: openai.image('gpt-image-
|
|
2377
|
+
model: openai.image('gpt-image-2'),
|
|
2372
2378
|
prompt: {
|
|
2373
2379
|
text: 'Turn the cat into a dog but retain the style of the original image',
|
|
2374
2380
|
images: [imageBuffer],
|
|
@@ -2385,7 +2391,7 @@ const image = readFileSync('./input-image.png');
|
|
|
2385
2391
|
const mask = readFileSync('./mask.png'); // Transparent areas = edit regions
|
|
2386
2392
|
|
|
2387
2393
|
const { images } = await generateImage({
|
|
2388
|
-
model: openai.image('gpt-image-
|
|
2394
|
+
model: openai.image('gpt-image-2'),
|
|
2389
2395
|
prompt: {
|
|
2390
2396
|
text: 'A sunlit indoor lounge area with a pool containing a flamingo',
|
|
2391
2397
|
images: [image],
|
|
@@ -2396,7 +2402,7 @@ const { images } = await generateImage({
|
|
|
2396
2402
|
|
|
2397
2403
|
#### Background Removal
|
|
2398
2404
|
|
|
2399
|
-
Remove the background from an image by setting `background` to `transparent
|
|
2405
|
+
Remove the background from an image by setting `background` to `transparent` on a model that supports transparent backgrounds:
|
|
2400
2406
|
|
|
2401
2407
|
```ts
|
|
2402
2408
|
import { openai, type OpenAIImageModelEditOptions } from '@ai-sdk/openai';
|
|
@@ -2405,7 +2411,7 @@ import { generateImage } from 'ai';
|
|
|
2405
2411
|
const imageBuffer = readFileSync('./input-image.png');
|
|
2406
2412
|
|
|
2407
2413
|
const { images } = await generateImage({
|
|
2408
|
-
model: openai.image('gpt-image-1'),
|
|
2414
|
+
model: openai.image('gpt-image-1.5'),
|
|
2409
2415
|
prompt: {
|
|
2410
2416
|
text: 'do not change anything',
|
|
2411
2417
|
images: [imageBuffer],
|
|
@@ -2421,7 +2427,7 @@ const { images } = await generateImage({
|
|
|
2421
2427
|
|
|
2422
2428
|
#### Multi-Image Combining
|
|
2423
2429
|
|
|
2424
|
-
Combine multiple reference images into a single output. `gpt-image
|
|
2430
|
+
Combine multiple reference images into a single output. `gpt-image-*` models support up to 16 input images:
|
|
2425
2431
|
|
|
2426
2432
|
```ts
|
|
2427
2433
|
const cat = readFileSync('./cat.png');
|
|
@@ -2430,7 +2436,7 @@ const owl = readFileSync('./owl.png');
|
|
|
2430
2436
|
const bear = readFileSync('./bear.png');
|
|
2431
2437
|
|
|
2432
2438
|
const { images } = await generateImage({
|
|
2433
|
-
model: openai.image('gpt-image-
|
|
2439
|
+
model: openai.image('gpt-image-2'),
|
|
2434
2440
|
prompt: {
|
|
2435
2441
|
text: 'Combine these animals into a group photo, retaining the original style',
|
|
2436
2442
|
images: [cat, dog, owl, bear],
|
|
@@ -2440,21 +2446,22 @@ const { images } = await generateImage({
|
|
|
2440
2446
|
|
|
2441
2447
|
<Note>
|
|
2442
2448
|
Input images can be provided as `Buffer`, `ArrayBuffer`, `Uint8Array`, or
|
|
2443
|
-
base64-encoded strings. For `gpt-image
|
|
2444
|
-
`webp`, or `jpg` file less than 50MB.
|
|
2449
|
+
base64-encoded strings. For `gpt-image-*` models, each image should be a
|
|
2450
|
+
`png`, `webp`, or `jpg` file less than 50MB.
|
|
2445
2451
|
</Note>
|
|
2446
2452
|
|
|
2447
2453
|
### Model Capabilities
|
|
2448
2454
|
|
|
2449
2455
|
| Model | Sizes |
|
|
2450
2456
|
| ------------------ | ------------------------------- |
|
|
2457
|
+
| `gpt-image-2` | 1024x1024, 1536x1024, 1024x1536 |
|
|
2451
2458
|
| `gpt-image-1.5` | 1024x1024, 1536x1024, 1024x1536 |
|
|
2452
2459
|
| `gpt-image-1-mini` | 1024x1024, 1536x1024, 1024x1536 |
|
|
2453
2460
|
| `gpt-image-1` | 1024x1024, 1536x1024, 1024x1536 |
|
|
2454
2461
|
| `dall-e-3` | 1024x1024, 1792x1024, 1024x1792 |
|
|
2455
2462
|
| `dall-e-2` | 256x256, 512x512, 1024x1024 |
|
|
2456
2463
|
|
|
2457
|
-
You can pass optional `providerOptions` to the image model. These are prone to change by OpenAI and are model dependent. For example, the `gpt-image
|
|
2464
|
+
You can pass optional `providerOptions` to the image model. These are prone to change by OpenAI and are model dependent. For example, the `gpt-image-*` models support the `quality` option:
|
|
2458
2465
|
|
|
2459
2466
|
```ts
|
|
2460
2467
|
import {
|
|
@@ -2464,7 +2471,7 @@ import {
|
|
|
2464
2471
|
import { generateImage } from 'ai';
|
|
2465
2472
|
|
|
2466
2473
|
const { image, providerMetadata } = await generateImage({
|
|
2467
|
-
model: openai.image('gpt-image-
|
|
2474
|
+
model: openai.image('gpt-image-2'),
|
|
2468
2475
|
prompt: 'A salamander at sunrise in a forest pond in the Seychelles.',
|
|
2469
2476
|
providerOptions: {
|
|
2470
2477
|
openai: { quality: 'high' } satisfies OpenAIImageModelGenerationOptions,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/openai",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.79",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@ai-sdk/provider": "
|
|
40
|
-
"@ai-sdk/provider
|
|
39
|
+
"@ai-sdk/provider-utils": "4.0.34",
|
|
40
|
+
"@ai-sdk/provider": "3.0.13"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "20.17.24",
|
|
@@ -1037,11 +1037,13 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1037
1037
|
isShellProviderExecuted,
|
|
1038
1038
|
} = await this.getArgs(options);
|
|
1039
1039
|
|
|
1040
|
+
const url = this.config.url({
|
|
1041
|
+
path: '/responses',
|
|
1042
|
+
modelId: this.modelId,
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1040
1045
|
const { responseHeaders, value: response } = await postJsonToApi({
|
|
1041
|
-
url
|
|
1042
|
-
path: '/responses',
|
|
1043
|
-
modelId: this.modelId,
|
|
1044
|
-
}),
|
|
1046
|
+
url,
|
|
1045
1047
|
headers: combineHeaders(this.config.headers(), options.headers),
|
|
1046
1048
|
body: {
|
|
1047
1049
|
...body,
|
|
@@ -1133,8 +1135,18 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1133
1135
|
|
|
1134
1136
|
// handle failed chunk parsing / validation:
|
|
1135
1137
|
if (!chunk.success) {
|
|
1138
|
+
const error = isOpenAIChatCompletionChunk(chunk.rawValue)
|
|
1139
|
+
? createOpenAIResponsesChatCompletionsMismatchError({
|
|
1140
|
+
value: chunk.rawValue,
|
|
1141
|
+
cause: chunk.error,
|
|
1142
|
+
url,
|
|
1143
|
+
requestBodyValues: body,
|
|
1144
|
+
responseHeaders,
|
|
1145
|
+
})
|
|
1146
|
+
: chunk.error;
|
|
1147
|
+
|
|
1136
1148
|
finishReason = { unified: 'error', raw: undefined };
|
|
1137
|
-
controller.enqueue({ type: 'error', error
|
|
1149
|
+
controller.enqueue({ type: 'error', error });
|
|
1138
1150
|
return;
|
|
1139
1151
|
}
|
|
1140
1152
|
|
|
@@ -2137,6 +2149,50 @@ function isTextDeltaChunk(
|
|
|
2137
2149
|
return chunk.type === 'response.output_text.delta';
|
|
2138
2150
|
}
|
|
2139
2151
|
|
|
2152
|
+
function isOpenAIChatCompletionChunk(value: unknown): boolean {
|
|
2153
|
+
const chunk = asRecord(value);
|
|
2154
|
+
|
|
2155
|
+
return (
|
|
2156
|
+
chunk != null &&
|
|
2157
|
+
Array.isArray(chunk.choices) &&
|
|
2158
|
+
typeof chunk.type !== 'string'
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
function createOpenAIResponsesChatCompletionsMismatchError({
|
|
2163
|
+
value,
|
|
2164
|
+
cause,
|
|
2165
|
+
url,
|
|
2166
|
+
requestBodyValues,
|
|
2167
|
+
responseHeaders,
|
|
2168
|
+
}: {
|
|
2169
|
+
value: unknown;
|
|
2170
|
+
cause: unknown;
|
|
2171
|
+
url: string;
|
|
2172
|
+
requestBodyValues: unknown;
|
|
2173
|
+
responseHeaders?: Record<string, string>;
|
|
2174
|
+
}): APICallError {
|
|
2175
|
+
return new APICallError({
|
|
2176
|
+
message:
|
|
2177
|
+
'Received a Chat Completions stream while using the OpenAI Responses API. ' +
|
|
2178
|
+
"The default OpenAI provider model uses the Responses API. If your custom baseURL targets a Chat Completions-compatible endpoint, use openai.chat('model-id') or createOpenAI(...).chat('model-id') instead. " +
|
|
2179
|
+
'You can also use @ai-sdk/openai-compatible for OpenAI-compatible providers.',
|
|
2180
|
+
url,
|
|
2181
|
+
requestBodyValues,
|
|
2182
|
+
responseHeaders,
|
|
2183
|
+
responseBody: JSON.stringify(value),
|
|
2184
|
+
cause,
|
|
2185
|
+
data: value,
|
|
2186
|
+
isRetryable: false,
|
|
2187
|
+
});
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
2191
|
+
return typeof value === 'object' && value != null
|
|
2192
|
+
? (value as Record<string, unknown>)
|
|
2193
|
+
: undefined;
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2140
2196
|
function isResponseOutputItemDoneChunk(
|
|
2141
2197
|
chunk: OpenAIResponsesChunk,
|
|
2142
2198
|
): chunk is OpenAIResponsesChunk & { type: 'response.output_item.done' } {
|