@ai-sdk/openai 3.0.77 → 3.0.78

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.
@@ -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-1` model supports powerful image editing capabilities. Pass input images via `prompt.images` to transform, combine, or edit existing images.
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-1'),
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-1'),
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-1` supports up to 16 input images:
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-1'),
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-1`, each image should be a `png`,
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-1` model supports the `quality` option:
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-1.5'),
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.77",
3
+ "version": "3.0.78",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -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: this.config.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: chunk.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' } {