@ai-sdk/openai 4.0.105 → 4.0.107
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 +26 -0
- package/dist/index.d.ts +51 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +611 -202
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +6 -4
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +565 -164
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +127 -5
- package/package.json +3 -3
- package/src/chat/convert-to-openai-chat-messages.ts +22 -3
- package/src/chat/openai-chat-language-model.ts +27 -20
- package/src/completion/openai-completion-language-model.ts +11 -3
- package/src/embedding/openai-embedding-model.ts +2 -1
- package/src/files/openai-files.ts +10 -8
- package/src/image/openai-image-model-options.ts +10 -20
- package/src/image/openai-image-model.ts +10 -21
- package/src/live/openai-realtime-model-live.ts +15 -16
- package/src/openai-batch.ts +22 -6
- package/src/openai-config.ts +2 -1
- package/src/openai-decision-model.ts +2 -1
- package/src/openai-model-catalog.ts +935 -0
- package/src/openai-provider.ts +18 -13
- package/src/realtime/openai-realtime-factory.ts +6 -6
- package/src/realtime/openai-realtime-model.ts +7 -3
- package/src/resolve-openai-reasoning-effort.ts +45 -0
- package/src/responses/convert-to-openai-responses-input.ts +29 -11
- package/src/responses/openai-responses-language-model.ts +28 -22
- package/src/skills/openai-skills.ts +4 -2
- package/src/speech/openai-speech-model.ts +5 -1
- package/src/speech-translation/openai-speech-translation-model.ts +5 -1
- package/src/transcription/openai-transcription-model-options.ts +12 -0
- package/src/transcription/openai-transcription-model.ts +29 -56
- package/src/openai-language-model-capabilities.ts +0 -196
package/docs/03-openai.mdx
CHANGED
|
@@ -99,11 +99,14 @@ You can use the following optional settings to customize the OpenAI provider ins
|
|
|
99
99
|
chat models with `openai.chat('model-id')` instead, or use the
|
|
100
100
|
[OpenAI-compatible provider](/providers/openai-compatible-providers).
|
|
101
101
|
|
|
102
|
-
- **apiKey**
|
|
102
|
+
- **apiKey** _string | PromiseLike<string> | (() => string | PromiseLike<string>)_
|
|
103
103
|
|
|
104
104
|
API key that is being sent using the `Authorization` header.
|
|
105
105
|
It defaults to the `OPENAI_API_KEY` environment variable.
|
|
106
106
|
|
|
107
|
+
A function is called before each request and may return a promise. Use it to
|
|
108
|
+
supply refreshed credentials; a promise value resolves to the same key each time.
|
|
109
|
+
|
|
107
110
|
- **name** _string_
|
|
108
111
|
|
|
109
112
|
The provider name. You can set this when using OpenAI compatible providers
|
|
@@ -3065,6 +3068,8 @@ The following optional provider options are available for OpenAI completion mode
|
|
|
3065
3068
|
|
|
3066
3069
|
### Model Capabilities
|
|
3067
3070
|
|
|
3071
|
+
{/* model-capabilities:openai-language:start */}
|
|
3072
|
+
|
|
3068
3073
|
| Model | Image Input | Audio Input | Object Generation | Tool Usage |
|
|
3069
3074
|
| --------------------- | ----------- | ----------- | ----------------- | ---------- |
|
|
3070
3075
|
| `gpt-6-astra` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
@@ -3101,6 +3106,8 @@ The following optional provider options are available for OpenAI completion mode
|
|
|
3101
3106
|
| `gpt-4o` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
3102
3107
|
| `gpt-4o-mini` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
3103
3108
|
|
|
3109
|
+
{/* model-capabilities:openai-language:end */}
|
|
3110
|
+
|
|
3104
3111
|
<Note>
|
|
3105
3112
|
The table above lists popular models. Please see the [OpenAI
|
|
3106
3113
|
docs](https://platform.openai.com/docs/models) for a full list of available
|
|
@@ -3108,6 +3115,53 @@ The following optional provider options are available for OpenAI completion mode
|
|
|
3108
3115
|
provider model ID as a string if needed.
|
|
3109
3116
|
</Note>
|
|
3110
3117
|
|
|
3118
|
+
#### Request Capabilities
|
|
3119
|
+
|
|
3120
|
+
Reasoning and sampling support depend on the selected model and request options.
|
|
3121
|
+
Conditional cells describe when a parameter is supported. "Not declared" means
|
|
3122
|
+
the catalog does not enumerate reasoning efforts; it does not mean every effort
|
|
3123
|
+
is supported.
|
|
3124
|
+
|
|
3125
|
+
{/* model-capabilities:openai-language-request:start */}
|
|
3126
|
+
|
|
3127
|
+
| Model | Reasoning | Reasoning Efforts | Temperature | Top P |
|
|
3128
|
+
| --------------------- | --------- | ----------------------------------------------- | ------------------------------------------------ | ------------------------------------------------ |
|
|
3129
|
+
| `gpt-6-astra` | <Check /> | `low`, `medium`, `high`, `xhigh`, `max` | <Cross /> | <Cross /> |
|
|
3130
|
+
| `gpt-6.1-sol` | <Check /> | `low`, `medium`, `high`, `xhigh`, `max` | <Cross /> | <Cross /> |
|
|
3131
|
+
| `gpt-6.1-terra` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh`, `max` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3132
|
+
| `gpt-6-luna` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh`, `max` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3133
|
+
| `gpt-6-sol` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh`, `max` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3134
|
+
| `gpt-5.6` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh`, `max` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3135
|
+
| `gpt-5.6-luna` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh`, `max` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3136
|
+
| `gpt-5.6-sol` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh`, `max` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3137
|
+
| `gpt-5.6-terra` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh`, `max` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3138
|
+
| `gpt-5.5` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3139
|
+
| `gpt-5.4-pro` | <Check /> | Not declared | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3140
|
+
| `gpt-5.4` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3141
|
+
| `gpt-5.4-mini` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3142
|
+
| `gpt-5.4-nano` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3143
|
+
| `gpt-5.3-chat-latest` | <Check /> | Not declared | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3144
|
+
| `gpt-5.2-pro` | <Check /> | Not declared | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3145
|
+
| `gpt-5.2-chat-latest` | <Check /> | Not declared | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3146
|
+
| `gpt-5.2` | <Check /> | `none`, `low`, `medium`, `high`, `xhigh` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3147
|
+
| `gpt-5.1-codex-mini` | <Check /> | Not declared | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3148
|
+
| `gpt-5.1-codex` | <Check /> | Not declared | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3149
|
+
| `gpt-5.1-chat-latest` | <Check /> | Not declared | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3150
|
+
| `gpt-5.1` | <Check /> | `none`, `low`, `medium`, `high` | Conditional: Only when reasoning effort is none. | Conditional: Only when reasoning effort is none. |
|
|
3151
|
+
| `gpt-5-pro` | <Check /> | Not declared | <Cross /> | <Cross /> |
|
|
3152
|
+
| `gpt-5` | <Check /> | `minimal`, `low`, `medium`, `high` | <Cross /> | <Cross /> |
|
|
3153
|
+
| `gpt-5-mini` | <Check /> | `minimal`, `low`, `medium`, `high` | <Cross /> | <Cross /> |
|
|
3154
|
+
| `gpt-5-nano` | <Check /> | `minimal`, `low`, `medium`, `high` | <Cross /> | <Cross /> |
|
|
3155
|
+
| `gpt-5-codex` | <Check /> | Not declared | <Cross /> | <Cross /> |
|
|
3156
|
+
| `gpt-5-chat-latest` | <Cross /> | Not declared | <Check /> | <Check /> |
|
|
3157
|
+
| `gpt-4.1` | <Cross /> | Not declared | <Check /> | <Check /> |
|
|
3158
|
+
| `gpt-4.1-mini` | <Cross /> | Not declared | <Check /> | <Check /> |
|
|
3159
|
+
| `gpt-4.1-nano` | <Cross /> | Not declared | <Check /> | <Check /> |
|
|
3160
|
+
| `gpt-4o` | <Cross /> | Not declared | <Check /> | <Check /> |
|
|
3161
|
+
| `gpt-4o-mini` | <Cross /> | Not declared | <Check /> | <Check /> |
|
|
3162
|
+
|
|
3163
|
+
{/* model-capabilities:openai-language-request:end */}
|
|
3164
|
+
|
|
3111
3165
|
## Realtime Models
|
|
3112
3166
|
|
|
3113
3167
|
<Note type="warning">Realtime is an experimental feature.</Note>
|
|
@@ -3136,8 +3190,9 @@ Live supports **browser WSS sessions through an application-owned relay with cli
|
|
|
3136
3190
|
delegation**, using `experimental_useRealtime` for the browser runtime, and optional
|
|
3137
3191
|
browser-direct WebRTC. Your application owns the agent and tool execution; Live
|
|
3138
3192
|
delegations do not invoke `onToolCall`. For a low-level server adapter, obtain server-only connection
|
|
3139
|
-
settings with `liveModel.getServerWebSocketConfig()` and serialize commands with
|
|
3140
|
-
`liveModel.serializeClientEvent()`.
|
|
3193
|
+
settings with `await liveModel.getServerWebSocketConfig()` and serialize commands with
|
|
3194
|
+
`liveModel.serializeClientEvent()`. Connection settings resolve asynchronously when
|
|
3195
|
+
using an asynchronous API key supplier. Create one parser per connection with
|
|
3141
3196
|
`liveModel.createServerEventParser()` and pass incoming JSON to the returned
|
|
3142
3197
|
function. It returns arrays of normalized events and retains each original event
|
|
3143
3198
|
in `raw`.
|
|
@@ -3227,6 +3282,17 @@ relays. Continuous conversation semantics do not imply browser support for every
|
|
|
3227
3282
|
provider codec or transport. The [Realtime guide](/docs/ai-sdk-core/realtime) covers
|
|
3228
3283
|
legacy token-based, turn-based sessions.
|
|
3229
3284
|
|
|
3285
|
+
### Model Capabilities
|
|
3286
|
+
|
|
3287
|
+
{/* model-capabilities:openai-realtime:start */}
|
|
3288
|
+
|
|
3289
|
+
| Model | Conversation | Transports |
|
|
3290
|
+
| -------------- | ------------ | ----------------- |
|
|
3291
|
+
| `gpt-live-1` | continuous | websocket, webrtc |
|
|
3292
|
+
| `gpt-realtime` | turn-based | websocket |
|
|
3293
|
+
|
|
3294
|
+
{/* model-capabilities:openai-realtime:end */}
|
|
3295
|
+
|
|
3230
3296
|
## Embedding Models
|
|
3231
3297
|
|
|
3232
3298
|
You can create models that call the [OpenAI embeddings API](https://platform.openai.com/docs/api-reference/embeddings)
|
|
@@ -3269,12 +3335,16 @@ The following optional provider options are available for OpenAI embedding model
|
|
|
3269
3335
|
|
|
3270
3336
|
### Model Capabilities
|
|
3271
3337
|
|
|
3338
|
+
{/* model-capabilities:openai-embedding:start */}
|
|
3339
|
+
|
|
3272
3340
|
| Model | Default Dimensions | Custom Dimensions |
|
|
3273
3341
|
| ------------------------ | ------------------ | ----------------- |
|
|
3274
3342
|
| `text-embedding-3-large` | 3072 | <Check /> |
|
|
3275
3343
|
| `text-embedding-3-small` | 1536 | <Check /> |
|
|
3276
3344
|
| `text-embedding-ada-002` | 1536 | <Cross /> |
|
|
3277
3345
|
|
|
3346
|
+
{/* model-capabilities:openai-embedding:end */}
|
|
3347
|
+
|
|
3278
3348
|
## Image Models
|
|
3279
3349
|
|
|
3280
3350
|
You can create models that call the [OpenAI image generation API](https://platform.openai.com/docs/api-reference/images)
|
|
@@ -3379,6 +3449,8 @@ const { images } = await generateImage({
|
|
|
3379
3449
|
|
|
3380
3450
|
### Model Capabilities
|
|
3381
3451
|
|
|
3452
|
+
{/* model-capabilities:openai-image:start */}
|
|
3453
|
+
|
|
3382
3454
|
| Model | Sizes |
|
|
3383
3455
|
| ------------------------ | -------------------------------------- |
|
|
3384
3456
|
| `gpt-image-2.5-flare` | Standard presets and custom dimensions |
|
|
@@ -3390,6 +3462,8 @@ const { images } = await generateImage({
|
|
|
3390
3462
|
| `dall-e-3` | 1024x1024, 1792x1024, 1024x1792 |
|
|
3391
3463
|
| `dall-e-2` | 256x256, 512x512, 1024x1024 |
|
|
3392
3464
|
|
|
3465
|
+
{/* model-capabilities:openai-image:end */}
|
|
3466
|
+
|
|
3393
3467
|
Use `gpt-image-2.5-flare` for fast, general-purpose image generation and
|
|
3394
3468
|
`gpt-image-2.5-sunburst` when editing precision and instruction following are
|
|
3395
3469
|
the priority. Both models accept custom `WIDTHxHEIGHT` sizes whose dimensions
|
|
@@ -3469,6 +3543,32 @@ const result = await transcribe({
|
|
|
3469
3543
|
});
|
|
3470
3544
|
```
|
|
3471
3545
|
|
|
3546
|
+
For `gpt-transcribe`, use `languages` for expected languages and `keywords` for
|
|
3547
|
+
names, acronyms, and domain vocabulary. These hints are sent as repeated
|
|
3548
|
+
`languages[]` and `keywords[]` multipart fields:
|
|
3549
|
+
|
|
3550
|
+
```ts
|
|
3551
|
+
import { transcribe } from 'ai';
|
|
3552
|
+
import { openai, type OpenAITranscriptionModelOptions } from '@ai-sdk/openai';
|
|
3553
|
+
|
|
3554
|
+
const result = await transcribe({
|
|
3555
|
+
model: openai.transcription('gpt-transcribe'),
|
|
3556
|
+
audio: new Uint8Array([1, 2, 3, 4]),
|
|
3557
|
+
providerOptions: {
|
|
3558
|
+
openai: {
|
|
3559
|
+
languages: ['en', 'fr'],
|
|
3560
|
+
keywords: ['premium plan', 'AC-42'],
|
|
3561
|
+
prompt: 'A customer support call.',
|
|
3562
|
+
} satisfies OpenAITranscriptionModelOptions,
|
|
3563
|
+
},
|
|
3564
|
+
});
|
|
3565
|
+
```
|
|
3566
|
+
|
|
3567
|
+
Use `languages` instead of `language` with `gpt-transcribe`; do not send both.
|
|
3568
|
+
The API validates model support and language codes. These two options currently
|
|
3569
|
+
apply to REST transcription; the provider reports unsupported-option warnings
|
|
3570
|
+
if they are supplied to `experimental_streamTranscribe`.
|
|
3571
|
+
|
|
3472
3572
|
To get word-level timestamps, specify the granularity:
|
|
3473
3573
|
|
|
3474
3574
|
```ts highlight="8-9"
|
|
@@ -3518,6 +3618,16 @@ The following provider options are available:
|
|
|
3518
3618
|
For streaming with `gpt-transcribe` and `gpt-live-transcribe`, it is sent as a single-entry `languages` list.
|
|
3519
3619
|
Optional.
|
|
3520
3620
|
|
|
3621
|
+
- **languages** _string[]_
|
|
3622
|
+
Expected languages for REST transcription, such as `['en', 'fr']` for `gpt-transcribe`.
|
|
3623
|
+
Use this instead of `language`; do not send both. The API validates model support.
|
|
3624
|
+
Optional.
|
|
3625
|
+
|
|
3626
|
+
- **keywords** _string[]_
|
|
3627
|
+
Vocabulary hints for REST transcription, such as product names, acronyms, or technical terms.
|
|
3628
|
+
Supported by `gpt-transcribe`; the API validates support for other models.
|
|
3629
|
+
Optional.
|
|
3630
|
+
|
|
3521
3631
|
- **prompt** _string_
|
|
3522
3632
|
An optional text to guide the model's style or continue a previous audio segment. The prompt should match the audio language.
|
|
3523
3633
|
Optional.
|
|
@@ -3547,6 +3657,8 @@ The following provider options are available:
|
|
|
3547
3657
|
|
|
3548
3658
|
### Model Capabilities
|
|
3549
3659
|
|
|
3660
|
+
{/* model-capabilities:openai-transcription:start */}
|
|
3661
|
+
|
|
3550
3662
|
| Model | Transcription | Streaming | Duration | Segments | Language |
|
|
3551
3663
|
| --------------------------- | ------------- | --------- | --------- | --------- | --------- |
|
|
3552
3664
|
| `whisper-1` | <Check /> | <Cross /> | <Check /> | <Check /> | <Check /> |
|
|
@@ -3557,6 +3669,8 @@ The following provider options are available:
|
|
|
3557
3669
|
| `gpt-live-transcribe` | <Cross /> | <Check /> | <Cross /> | <Cross /> | <Cross /> |
|
|
3558
3670
|
| `gpt-realtime-whisper` | <Cross /> | <Check /> | <Cross /> | <Cross /> | <Cross /> |
|
|
3559
3671
|
|
|
3672
|
+
{/* model-capabilities:openai-transcription:end */}
|
|
3673
|
+
|
|
3560
3674
|
## Translation Models
|
|
3561
3675
|
|
|
3562
3676
|
<Note type="warning">Speech translation is an experimental feature.</Note>
|
|
@@ -3597,10 +3711,14 @@ Unsupported source and output settings surface as call warnings.
|
|
|
3597
3711
|
|
|
3598
3712
|
### Model Capabilities
|
|
3599
3713
|
|
|
3714
|
+
{/* model-capabilities:openai-speech-translation:start */}
|
|
3715
|
+
|
|
3600
3716
|
| Model | Translated Audio | Translated Text | Source Transcript |
|
|
3601
3717
|
| ------------------------ | ---------------- | --------------- | ----------------- |
|
|
3602
3718
|
| `gpt-realtime-translate` | <Check /> | <Check /> | <Check /> |
|
|
3603
3719
|
|
|
3720
|
+
{/* model-capabilities:openai-speech-translation:end */}
|
|
3721
|
+
|
|
3604
3722
|
## Speech Models
|
|
3605
3723
|
|
|
3606
3724
|
You can create models that call the [OpenAI speech API](https://platform.openai.com/docs/api-reference/audio/speech)
|
|
@@ -3656,12 +3774,16 @@ const result = await generateSpeech({
|
|
|
3656
3774
|
|
|
3657
3775
|
### Model Capabilities
|
|
3658
3776
|
|
|
3777
|
+
{/* model-capabilities:openai-speech:start */}
|
|
3778
|
+
|
|
3659
3779
|
| Model | Instructions |
|
|
3660
3780
|
| ----------------- | ------------ |
|
|
3661
|
-
| `tts-1` | <
|
|
3662
|
-
| `tts-1-hd` | <
|
|
3781
|
+
| `tts-1` | <Cross /> |
|
|
3782
|
+
| `tts-1-hd` | <Cross /> |
|
|
3663
3783
|
| `gpt-4o-mini-tts` | <Check /> |
|
|
3664
3784
|
|
|
3785
|
+
{/* model-capabilities:openai-speech:end */}
|
|
3786
|
+
|
|
3665
3787
|
## Decision Models
|
|
3666
3788
|
|
|
3667
3789
|
Create an experimental decision model with `openai.decisionModel(modelId)`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/openai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.107",
|
|
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.
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
38
|
+
"@ai-sdk/provider": "4.0.35",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.73"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ai-sdk/test-server": "2.0.4",
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
} from '@ai-sdk/provider';
|
|
7
7
|
import type { OpenAIChatPrompt } from './openai-chat-prompt';
|
|
8
8
|
import {
|
|
9
|
+
secureJsonParse,
|
|
10
|
+
stringifyWithBigIntAndCycles,
|
|
9
11
|
convertToBase64,
|
|
10
12
|
getTopLevelMediaType,
|
|
11
13
|
resolveFullMediaType,
|
|
@@ -13,7 +15,22 @@ import {
|
|
|
13
15
|
} from '@ai-sdk/provider-utils';
|
|
14
16
|
|
|
15
17
|
function serializeToolCallArguments(input: unknown): string {
|
|
16
|
-
|
|
18
|
+
if (typeof input === 'string') {
|
|
19
|
+
try {
|
|
20
|
+
const parsed = secureJsonParse(input);
|
|
21
|
+
if (
|
|
22
|
+
typeof parsed !== 'object' ||
|
|
23
|
+
parsed === null ||
|
|
24
|
+
Array.isArray(parsed)
|
|
25
|
+
) {
|
|
26
|
+
return '{}';
|
|
27
|
+
}
|
|
28
|
+
return input;
|
|
29
|
+
} catch {
|
|
30
|
+
return '{}';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return stringifyWithBigIntAndCycles(
|
|
17
34
|
typeof input === 'object' && input !== null && !Array.isArray(input)
|
|
18
35
|
? input
|
|
19
36
|
: {},
|
|
@@ -326,14 +343,16 @@ export function convertToOpenAIChatMessages({
|
|
|
326
343
|
break;
|
|
327
344
|
case 'error-text':
|
|
328
345
|
case 'error-json':
|
|
329
|
-
contentValue =
|
|
346
|
+
contentValue = stringifyWithBigIntAndCycles({
|
|
347
|
+
error: output.value,
|
|
348
|
+
});
|
|
330
349
|
break;
|
|
331
350
|
case 'execution-denied':
|
|
332
351
|
contentValue = output.reason ?? 'Tool call execution denied.';
|
|
333
352
|
break;
|
|
334
353
|
case 'content':
|
|
335
354
|
case 'json':
|
|
336
|
-
contentValue =
|
|
355
|
+
contentValue = stringifyWithBigIntAndCycles(output.value);
|
|
337
356
|
break;
|
|
338
357
|
}
|
|
339
358
|
|
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
type SharedV4Warning,
|
|
12
12
|
} from '@ai-sdk/provider';
|
|
13
13
|
import {
|
|
14
|
+
type Resolvable,
|
|
15
|
+
resolve,
|
|
14
16
|
StreamingToolCallTracker,
|
|
15
17
|
combineHeaders,
|
|
16
18
|
createEventSourceResponseHandler,
|
|
@@ -26,14 +28,12 @@ import {
|
|
|
26
28
|
type ParseResult,
|
|
27
29
|
} from '@ai-sdk/provider-utils';
|
|
28
30
|
import { openaiFailedResponseHandler } from '../openai-error';
|
|
29
|
-
import {
|
|
30
|
-
getOpenAILanguageModelCapabilities,
|
|
31
|
-
resolveOpenAIReasoningEffort,
|
|
32
|
-
} from '../openai-language-model-capabilities';
|
|
31
|
+
import { getOpenAILanguageModelEntry } from '../openai-model-catalog';
|
|
33
32
|
import {
|
|
34
33
|
createOpenAIProviderStreamError,
|
|
35
34
|
throwIfOpenAIStreamErrorBeforeOutput,
|
|
36
35
|
} from '../openai-stream-error';
|
|
36
|
+
import { resolveOpenAIReasoningEffort } from '../resolve-openai-reasoning-effort';
|
|
37
37
|
import {
|
|
38
38
|
convertOpenAIChatUsage,
|
|
39
39
|
type OpenAIChatUsage,
|
|
@@ -57,7 +57,7 @@ type OpenAIChatConfig = {
|
|
|
57
57
|
provider: string;
|
|
58
58
|
/** Model ID sent to the API. Defaults to the model's reported ID. */
|
|
59
59
|
requestModelId?: string;
|
|
60
|
-
headers?:
|
|
60
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
61
61
|
url: (options: { modelId: string; path: string }) => string;
|
|
62
62
|
fetch?: FetchFunction;
|
|
63
63
|
};
|
|
@@ -122,12 +122,15 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
122
122
|
schema: openaiLanguageModelChatOptions,
|
|
123
123
|
})) ?? {};
|
|
124
124
|
|
|
125
|
-
const
|
|
125
|
+
const {
|
|
126
|
+
capabilities: { language: modelCapabilities },
|
|
127
|
+
requestConfig: { language: modelRequestConfig },
|
|
128
|
+
} = getOpenAILanguageModelEntry(this.modelId);
|
|
126
129
|
|
|
127
130
|
// Some models reject function tools unless reasoning is disabled, even
|
|
128
131
|
// when no reasoning effort is sent, so reasoning is set to 'none'.
|
|
129
132
|
const requiresNoReasoningEffort =
|
|
130
|
-
!modelCapabilities.
|
|
133
|
+
!modelCapabilities.endpoints.chat.functionToolsWithReasoning &&
|
|
131
134
|
openaiOptions.reasoningEffort == null &&
|
|
132
135
|
(tools?.some(tool => tool.type === 'function') ?? false);
|
|
133
136
|
|
|
@@ -150,14 +153,15 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
150
153
|
reasoning,
|
|
151
154
|
// Only the Responses API supports `max`.
|
|
152
155
|
supportedReasoningEfforts:
|
|
153
|
-
modelCapabilities.
|
|
156
|
+
modelCapabilities.reasoning.efforts?.filter(
|
|
154
157
|
effort => effort !== 'max',
|
|
155
158
|
),
|
|
156
159
|
warnings,
|
|
157
160
|
});
|
|
158
161
|
|
|
159
162
|
const isReasoningModel =
|
|
160
|
-
openaiOptions.forceReasoning ??
|
|
163
|
+
openaiOptions.forceReasoning ??
|
|
164
|
+
modelCapabilities.reasoning.support === true;
|
|
161
165
|
|
|
162
166
|
if (topK != null) {
|
|
163
167
|
warnings.push({ type: 'unsupported', feature: 'topK' });
|
|
@@ -181,7 +185,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
181
185
|
openaiOptions.systemMessageMode ??
|
|
182
186
|
(isReasoningModel
|
|
183
187
|
? 'developer'
|
|
184
|
-
:
|
|
188
|
+
: modelRequestConfig.systemMessageMode),
|
|
185
189
|
},
|
|
186
190
|
);
|
|
187
191
|
|
|
@@ -261,7 +265,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
261
265
|
};
|
|
262
266
|
|
|
263
267
|
if (
|
|
264
|
-
modelCapabilities.
|
|
268
|
+
!modelCapabilities.promptCache.retention &&
|
|
265
269
|
baseArgs.prompt_cache_retention != null
|
|
266
270
|
) {
|
|
267
271
|
baseArgs.prompt_cache_retention = undefined;
|
|
@@ -280,7 +284,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
280
284
|
// https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility
|
|
281
285
|
if (
|
|
282
286
|
resolvedReasoningEffort !== 'none' ||
|
|
283
|
-
|
|
287
|
+
modelCapabilities.reasoning.sampling !== 'reasoning-effort-none'
|
|
284
288
|
) {
|
|
285
289
|
if (baseArgs.temperature != null) {
|
|
286
290
|
baseArgs.temperature = undefined;
|
|
@@ -346,10 +350,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
346
350
|
}
|
|
347
351
|
baseArgs.max_tokens = undefined;
|
|
348
352
|
}
|
|
349
|
-
} else if (
|
|
350
|
-
this.modelId.startsWith('gpt-4o-search-preview') ||
|
|
351
|
-
this.modelId.startsWith('gpt-4o-mini-search-preview')
|
|
352
|
-
) {
|
|
353
|
+
} else if (!modelCapabilities.endpoints.chat.temperatureWithoutReasoning) {
|
|
353
354
|
if (baseArgs.temperature != null) {
|
|
354
355
|
baseArgs.temperature = undefined;
|
|
355
356
|
warnings.push({
|
|
@@ -364,7 +365,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
364
365
|
// Validate flex processing support
|
|
365
366
|
if (
|
|
366
367
|
openaiOptions.serviceTier === 'flex' &&
|
|
367
|
-
!modelCapabilities.
|
|
368
|
+
!modelCapabilities.serviceTiers.flex
|
|
368
369
|
) {
|
|
369
370
|
warnings.push({
|
|
370
371
|
type: 'unsupported',
|
|
@@ -379,7 +380,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
379
380
|
if (
|
|
380
381
|
(openaiOptions.serviceTier === 'priority' ||
|
|
381
382
|
openaiOptions.serviceTier === 'fast') &&
|
|
382
|
-
!modelCapabilities.
|
|
383
|
+
!modelCapabilities.serviceTiers.priority
|
|
383
384
|
) {
|
|
384
385
|
warnings.push({
|
|
385
386
|
type: 'unsupported',
|
|
@@ -423,7 +424,10 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
423
424
|
path: '/chat/completions',
|
|
424
425
|
modelId: this.config.requestModelId ?? this.modelId,
|
|
425
426
|
}),
|
|
426
|
-
headers: combineHeaders(
|
|
427
|
+
headers: combineHeaders(
|
|
428
|
+
await resolve(this.config.headers),
|
|
429
|
+
options.headers,
|
|
430
|
+
),
|
|
427
431
|
body,
|
|
428
432
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
429
433
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -526,7 +530,10 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
526
530
|
|
|
527
531
|
const { responseHeaders, value: response } = await postJsonToApi({
|
|
528
532
|
url,
|
|
529
|
-
headers: combineHeaders(
|
|
533
|
+
headers: combineHeaders(
|
|
534
|
+
await resolve(this.config.headers),
|
|
535
|
+
options.headers,
|
|
536
|
+
),
|
|
530
537
|
body,
|
|
531
538
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
532
539
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
@@ -9,6 +9,8 @@ import type {
|
|
|
9
9
|
SharedV4Warning,
|
|
10
10
|
} from '@ai-sdk/provider';
|
|
11
11
|
import {
|
|
12
|
+
type Resolvable,
|
|
13
|
+
resolve,
|
|
12
14
|
combineHeaders,
|
|
13
15
|
createEventSourceResponseHandler,
|
|
14
16
|
createJsonResponseHandler,
|
|
@@ -45,7 +47,7 @@ type OpenAICompletionConfig = {
|
|
|
45
47
|
provider: string;
|
|
46
48
|
/** Model ID sent to the API. Defaults to the model's reported ID. */
|
|
47
49
|
requestModelId?: string;
|
|
48
|
-
headers?:
|
|
50
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
49
51
|
url: (options: { modelId: string; path: string }) => string;
|
|
50
52
|
fetch?: FetchFunction;
|
|
51
53
|
};
|
|
@@ -196,7 +198,10 @@ export class OpenAICompletionLanguageModel implements LanguageModelV4 {
|
|
|
196
198
|
path: '/completions',
|
|
197
199
|
modelId: this.config.requestModelId ?? this.modelId,
|
|
198
200
|
}),
|
|
199
|
-
headers: combineHeaders(
|
|
201
|
+
headers: combineHeaders(
|
|
202
|
+
await resolve(this.config.headers),
|
|
203
|
+
options.headers,
|
|
204
|
+
),
|
|
200
205
|
body: args,
|
|
201
206
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
202
207
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -253,7 +258,10 @@ export class OpenAICompletionLanguageModel implements LanguageModelV4 {
|
|
|
253
258
|
|
|
254
259
|
const { responseHeaders, value: response } = await postJsonToApi({
|
|
255
260
|
url,
|
|
256
|
-
headers: combineHeaders(
|
|
261
|
+
headers: combineHeaders(
|
|
262
|
+
await resolve(this.config.headers),
|
|
263
|
+
options.headers,
|
|
264
|
+
),
|
|
257
265
|
body,
|
|
258
266
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
259
267
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
type EmbeddingModelV4,
|
|
4
4
|
} from '@ai-sdk/provider';
|
|
5
5
|
import {
|
|
6
|
+
resolve,
|
|
6
7
|
combineHeaders,
|
|
7
8
|
createJsonResponseHandler,
|
|
8
9
|
EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL,
|
|
@@ -87,7 +88,7 @@ export class OpenAIEmbeddingModel implements EmbeddingModelV4 {
|
|
|
87
88
|
path: '/embeddings',
|
|
88
89
|
modelId: this.modelId,
|
|
89
90
|
}),
|
|
90
|
-
headers: combineHeaders(this.config.headers
|
|
91
|
+
headers: combineHeaders(await resolve(this.config.headers), headers),
|
|
91
92
|
body: {
|
|
92
93
|
model: this.modelId,
|
|
93
94
|
input: values,
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
type SharedV4ProviderReference,
|
|
13
13
|
} from '@ai-sdk/provider';
|
|
14
14
|
import {
|
|
15
|
+
type Resolvable,
|
|
16
|
+
resolve,
|
|
15
17
|
combineHeaders,
|
|
16
18
|
convertInlineFileDataToUint8Array,
|
|
17
19
|
createBinaryStreamResponseHandler,
|
|
@@ -39,7 +41,7 @@ import {
|
|
|
39
41
|
interface OpenAIFilesConfig {
|
|
40
42
|
provider: string;
|
|
41
43
|
baseURL: string;
|
|
42
|
-
headers:
|
|
44
|
+
headers: Resolvable<Record<string, string | undefined>>;
|
|
43
45
|
fetch?: FetchFunction;
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -65,10 +67,10 @@ export class OpenAIFiles implements FilesV4 {
|
|
|
65
67
|
return fileId;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
private getHeaders(
|
|
70
|
+
private async getHeaders(
|
|
69
71
|
headers: Record<string, string | undefined> | undefined,
|
|
70
|
-
): Record<string, string | undefined
|
|
71
|
-
return combineHeaders(this.config.headers
|
|
72
|
+
): Promise<Record<string, string | undefined>> {
|
|
73
|
+
return combineHeaders(await resolve(this.config.headers), headers);
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
async uploadFile({
|
|
@@ -95,7 +97,7 @@ export class OpenAIFiles implements FilesV4 {
|
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
const purpose = openaiOptions?.purpose ?? 'assistants';
|
|
98
|
-
const requestHeaders = this.getHeaders(headers);
|
|
100
|
+
const requestHeaders = await this.getHeaders(headers);
|
|
99
101
|
const url = `${this.config.baseURL}/files`;
|
|
100
102
|
|
|
101
103
|
let response: OpenAIFilesResponse;
|
|
@@ -200,7 +202,7 @@ export class OpenAIFiles implements FilesV4 {
|
|
|
200
202
|
|
|
201
203
|
const { value: response } = await getFromApi({
|
|
202
204
|
url: `${this.config.baseURL}/files/${encodePathSegment(fileId)}`,
|
|
203
|
-
headers: this.getHeaders(headers),
|
|
205
|
+
headers: await this.getHeaders(headers),
|
|
204
206
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
205
207
|
successfulResponseHandler: createJsonResponseHandler(
|
|
206
208
|
openaiFilesResponseSchema,
|
|
@@ -236,7 +238,7 @@ export class OpenAIFiles implements FilesV4 {
|
|
|
236
238
|
|
|
237
239
|
const { value: content, responseHeaders } = await getFromApi({
|
|
238
240
|
url: `${this.config.baseURL}/files/${encodePathSegment(fileId)}/content`,
|
|
239
|
-
headers: this.getHeaders(headers),
|
|
241
|
+
headers: await this.getHeaders(headers),
|
|
240
242
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
241
243
|
successfulResponseHandler: createBinaryStreamResponseHandler(),
|
|
242
244
|
abortSignal,
|
|
@@ -263,7 +265,7 @@ export class OpenAIFiles implements FilesV4 {
|
|
|
263
265
|
|
|
264
266
|
const { value: response } = await deleteFromApi({
|
|
265
267
|
url: `${this.config.baseURL}/files/${encodePathSegment(fileId)}`,
|
|
266
|
-
headers: this.getHeaders(headers),
|
|
268
|
+
headers: await this.getHeaders(headers),
|
|
267
269
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
268
270
|
successfulResponseHandler: createJsonResponseHandler(
|
|
269
271
|
openaiFileDeleteResponseSchema,
|
|
@@ -4,6 +4,10 @@ import {
|
|
|
4
4
|
type InferSchema,
|
|
5
5
|
} from '@ai-sdk/provider-utils';
|
|
6
6
|
import { z } from 'zod/v4';
|
|
7
|
+
import {
|
|
8
|
+
getOpenAIImageModelEntry,
|
|
9
|
+
openaiImageModelMaxImagesPerCall,
|
|
10
|
+
} from '../openai-model-catalog';
|
|
7
11
|
|
|
8
12
|
export type OpenAIImageModelId =
|
|
9
13
|
| 'dall-e-3'
|
|
@@ -19,33 +23,19 @@ export type OpenAIImageModelId =
|
|
|
19
23
|
| 'chatgpt-image-latest'
|
|
20
24
|
| (string & {});
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
'dall-e-3': 1,
|
|
25
|
-
'dall-e-2': 10,
|
|
26
|
-
'gpt-image-1': 10,
|
|
27
|
-
'gpt-image-1-mini': 10,
|
|
28
|
-
'gpt-image-1.5': 10,
|
|
29
|
-
'gpt-image-2': 10,
|
|
30
|
-
'gpt-image-2.5-flare': 10,
|
|
31
|
-
'gpt-image-2.5-flare-2026-09-08': 10,
|
|
32
|
-
'gpt-image-2.5-sunburst': 10,
|
|
33
|
-
'gpt-image-2.5-sunburst-2026-09-08': 10,
|
|
34
|
-
'chatgpt-image-latest': 10,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const defaultResponseFormatPrefixes = ['chatgpt-image-', 'gpt-image-'];
|
|
26
|
+
export const modelMaxImagesPerCall: Record<OpenAIImageModelId, number> =
|
|
27
|
+
openaiImageModelMaxImagesPerCall;
|
|
38
28
|
|
|
39
29
|
export function hasDefaultResponseFormat(modelId: string): boolean {
|
|
40
|
-
return
|
|
41
|
-
modelId.
|
|
30
|
+
return (
|
|
31
|
+
getOpenAIImageModelEntry(modelId).requestConfig.image.responseFormat ===
|
|
32
|
+
'provider-default'
|
|
42
33
|
);
|
|
43
34
|
}
|
|
44
35
|
|
|
45
36
|
export function getMaxImagesPerCall(modelId: OpenAIImageModelId): number {
|
|
46
37
|
return (
|
|
47
|
-
|
|
48
|
-
(modelId.startsWith('gpt-image-') ? 10 : 1)
|
|
38
|
+
getOpenAIImageModelEntry(modelId).capabilities.image.maxImagesPerCall ?? 1
|
|
49
39
|
);
|
|
50
40
|
}
|
|
51
41
|
|