@ai-sdk/openai 4.0.59 → 4.0.60
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 +6 -0
- package/dist/index.d.ts +7 -6
- package/dist/index.js +81 -7
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +15 -9
- package/dist/internal/index.js +80 -6
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +66 -1
- package/package.json +1 -1
- package/src/chat/openai-chat-language-model.ts +29 -1
- package/src/openai-language-model-capabilities.ts +8 -0
- package/src/responses/openai-responses-api.ts +8 -0
- package/src/responses/openai-responses-language-model-options.ts +12 -0
- package/src/responses/openai-responses-language-model.ts +73 -1
package/docs/03-openai.mdx
CHANGED
|
@@ -192,9 +192,23 @@ The following provider options are available:
|
|
|
192
192
|
|
|
193
193
|
<Note>
|
|
194
194
|
Supported reasoning efforts vary by model. GPT-5.6 supports `'none'`, `'low'`,
|
|
195
|
-
`'medium'`, `'high'`, `'xhigh'`, and `'max'`.
|
|
195
|
+
`'medium'`, `'high'`, `'xhigh'`, and `'max'`. GPT-6 and later models support
|
|
196
|
+
`'low'`, `'medium'`, `'high'`, `'xhigh'`, and `'max'`.
|
|
196
197
|
</Note>
|
|
197
198
|
|
|
199
|
+
<Note type="warning">
|
|
200
|
+
GPT-6 and later models do not support `temperature`, `topP`, `logprobs`, or
|
|
201
|
+
the legacy `promptCacheRetention` option. The provider removes these settings
|
|
202
|
+
and returns a warning. Use the Responses API for GPT-6 tool calling.
|
|
203
|
+
</Note>
|
|
204
|
+
|
|
205
|
+
- **reasoningEffortUpdate** _'low' | 'medium' | 'high' | 'xhigh' | 'max'_
|
|
206
|
+
Updates the reasoning effort for GPT-6 and later models starting with the
|
|
207
|
+
current response without changing the request-level effort. Use this with
|
|
208
|
+
`previousResponseId` to preserve the original prompt prefix for caching.
|
|
209
|
+
Configuration updates require standard, single-agent mode and cannot be
|
|
210
|
+
combined with automatic compaction or automatic truncation.
|
|
211
|
+
|
|
198
212
|
- **reasoningMode** _'standard' | 'pro'_
|
|
199
213
|
Controls how much model work GPT-5.6 performs before returning a final answer. `'standard'` is the default. Use `'pro'` for difficult tasks where quality matters more than latency and token usage.
|
|
200
214
|
|
|
@@ -302,6 +316,57 @@ The following OpenAI-specific metadata may be returned:
|
|
|
302
316
|
- **reasoningContext** _(optional)_
|
|
303
317
|
Effective persisted-reasoning context returned by GPT-5.6 (`'current_turn'` or `'all_turns'`).
|
|
304
318
|
|
|
319
|
+
#### Changing Reasoning Effort Mid-Conversation
|
|
320
|
+
|
|
321
|
+
GPT-6 and later models can change reasoning effort between responses without
|
|
322
|
+
changing the request-level `reasoning` setting. The provider sends
|
|
323
|
+
`reasoningEffortUpdate` as an OpenAI `configuration_update` input item before
|
|
324
|
+
the next user message. Keeping the request-level effort unchanged preserves the
|
|
325
|
+
original prompt prefix for prompt caching.
|
|
326
|
+
|
|
327
|
+
```ts highlight="8,26,32"
|
|
328
|
+
import {
|
|
329
|
+
openai,
|
|
330
|
+
type OpenAILanguageModelResponsesOptions,
|
|
331
|
+
type OpenaiResponsesProviderMetadata,
|
|
332
|
+
} from '@ai-sdk/openai';
|
|
333
|
+
import { generateText } from 'ai';
|
|
334
|
+
|
|
335
|
+
const first = await generateText({
|
|
336
|
+
model: openai.responses('gpt-6-astra'),
|
|
337
|
+
reasoning: 'low',
|
|
338
|
+
prompt: 'Draft a database migration plan.',
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const metadata = first.finalStep.providerMetadata as
|
|
342
|
+
| OpenaiResponsesProviderMetadata
|
|
343
|
+
| undefined;
|
|
344
|
+
const previousResponseId = metadata?.openai.responseId;
|
|
345
|
+
|
|
346
|
+
if (!previousResponseId) {
|
|
347
|
+
throw new Error('OpenAI did not return a response ID.');
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const second = await generateText({
|
|
351
|
+
model: openai.responses('gpt-6-astra'),
|
|
352
|
+
reasoning: 'low',
|
|
353
|
+
prompt: 'Analyze the failure modes and propose rollback steps.',
|
|
354
|
+
providerOptions: {
|
|
355
|
+
openai: {
|
|
356
|
+
previousResponseId,
|
|
357
|
+
reasoningEffortUpdate: 'high',
|
|
358
|
+
} satisfies OpenAILanguageModelResponsesOptions,
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
The response metadata continues to report the request-level reasoning effort,
|
|
364
|
+
not the effective effort selected by `reasoningEffortUpdate`. Configuration
|
|
365
|
+
updates are not supported with `reasoningMode: 'pro'`,
|
|
366
|
+
`contextManagement`, or `truncation: 'auto'`. Explicit compaction with
|
|
367
|
+
`compactionTrigger` remains supported; send a new `reasoningEffortUpdate` after
|
|
368
|
+
compaction when the effort should change again.
|
|
369
|
+
|
|
305
370
|
#### Reasoning Output
|
|
306
371
|
|
|
307
372
|
For reasoning models like `gpt-5`, you can enable reasoning summaries to see the model's thought process. Different models support different summarizers—for example, `o4-mini` supports detailed summaries. Set `reasoningSummary: "auto"` to automatically receive the richest level available. When `reasoningEffort` is set to a value other than `'none'`, the OpenAI Responses provider defaults `reasoningSummary` to `'detailed'`; set `reasoningSummary: null` to omit reasoning summaries.
|
package/package.json
CHANGED
|
@@ -118,10 +118,25 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
118
118
|
const modelCapabilities = getOpenAILanguageModelCapabilities(this.modelId);
|
|
119
119
|
|
|
120
120
|
// AI SDK reasoning values map directly to the OpenAI reasoning values.
|
|
121
|
-
|
|
121
|
+
let resolvedReasoningEffort =
|
|
122
122
|
openaiOptions.reasoningEffort ??
|
|
123
123
|
(isCustomReasoning(reasoning) ? reasoning : undefined);
|
|
124
124
|
|
|
125
|
+
if (
|
|
126
|
+
resolvedReasoningEffort != null &&
|
|
127
|
+
modelCapabilities.supportedReasoningEfforts != null &&
|
|
128
|
+
!modelCapabilities.supportedReasoningEfforts.includes(
|
|
129
|
+
resolvedReasoningEffort,
|
|
130
|
+
)
|
|
131
|
+
) {
|
|
132
|
+
warnings.push({
|
|
133
|
+
type: 'unsupported',
|
|
134
|
+
feature: 'reasoningEffort',
|
|
135
|
+
details: `${this.modelId} only supports the following reasoning efforts: ${modelCapabilities.supportedReasoningEfforts.join(', ')}`,
|
|
136
|
+
});
|
|
137
|
+
resolvedReasoningEffort = undefined;
|
|
138
|
+
}
|
|
139
|
+
|
|
125
140
|
const isReasoningModel =
|
|
126
141
|
openaiOptions.forceReasoning ?? modelCapabilities.isReasoningModel;
|
|
127
142
|
|
|
@@ -207,6 +222,19 @@ export class OpenAIChatLanguageModel implements LanguageModelV4 {
|
|
|
207
222
|
messages,
|
|
208
223
|
};
|
|
209
224
|
|
|
225
|
+
if (
|
|
226
|
+
modelCapabilities.supportedReasoningEfforts != null &&
|
|
227
|
+
baseArgs.prompt_cache_retention != null
|
|
228
|
+
) {
|
|
229
|
+
baseArgs.prompt_cache_retention = undefined;
|
|
230
|
+
warnings.push({
|
|
231
|
+
type: 'unsupported',
|
|
232
|
+
feature: 'promptCacheRetention',
|
|
233
|
+
details:
|
|
234
|
+
'promptCacheRetention is not supported by GPT-6 and later models; use promptCacheOptions instead',
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
210
238
|
// remove unsupported settings for reasoning models
|
|
211
239
|
// see https://platform.openai.com/docs/guides/reasoning#limitations
|
|
212
240
|
if (isReasoningModel) {
|
|
@@ -3,6 +3,8 @@ export type OpenAILanguageModelCapabilities = {
|
|
|
3
3
|
systemMessageMode: 'remove' | 'system' | 'developer';
|
|
4
4
|
supportsFlexProcessing: boolean;
|
|
5
5
|
supportsPriorityProcessing: boolean;
|
|
6
|
+
supportsConfigurationUpdate: boolean;
|
|
7
|
+
supportedReasoningEfforts: readonly string[] | undefined;
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Allow temperature, topP, logProbs when reasoningEffort is none.
|
|
@@ -19,6 +21,7 @@ export function getOpenAILanguageModelCapabilities(
|
|
|
19
21
|
gptVersion?.minor == null &&
|
|
20
22
|
(gptVersion?.variant?.startsWith('chat') ?? false);
|
|
21
23
|
const isGptNanoModel = gptVersion?.variant?.startsWith('nano') ?? false;
|
|
24
|
+
const isGpt6OrLaterModel = gptVersion != null && gptVersion.major >= 6;
|
|
22
25
|
|
|
23
26
|
const supportsFlexProcessing =
|
|
24
27
|
(oSeriesVersion != null && oSeriesVersion >= 3) ||
|
|
@@ -41,6 +44,7 @@ export function getOpenAILanguageModelCapabilities(
|
|
|
41
44
|
// https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility
|
|
42
45
|
// GPT-5.1 and later model families support temperature, topP, logProbs when reasoningEffort is none.
|
|
43
46
|
const supportsNonReasoningParameters =
|
|
47
|
+
!isGpt6OrLaterModel &&
|
|
44
48
|
gptVersion != null &&
|
|
45
49
|
(gptVersion.major > 5 ||
|
|
46
50
|
(gptVersion.major === 5 && (gptVersion.minor ?? 0) >= 1));
|
|
@@ -50,6 +54,10 @@ export function getOpenAILanguageModelCapabilities(
|
|
|
50
54
|
return {
|
|
51
55
|
supportsFlexProcessing,
|
|
52
56
|
supportsPriorityProcessing,
|
|
57
|
+
supportsConfigurationUpdate: isGpt6OrLaterModel,
|
|
58
|
+
supportedReasoningEfforts: isGpt6OrLaterModel
|
|
59
|
+
? ['low', 'medium', 'high', 'xhigh', 'max']
|
|
60
|
+
: undefined,
|
|
53
61
|
isReasoningModel,
|
|
54
62
|
systemMessageMode,
|
|
55
63
|
supportsNonReasoningParameters,
|
|
@@ -180,6 +180,7 @@ export type OpenAIResponsesInputItem =
|
|
|
180
180
|
| OpenAIResponsesReasoning
|
|
181
181
|
| OpenAIResponsesItemReference
|
|
182
182
|
| OpenAIResponsesCompactionItem
|
|
183
|
+
| OpenAIResponsesConfigurationUpdate
|
|
183
184
|
| OpenAIResponsesCompactionTrigger;
|
|
184
185
|
|
|
185
186
|
export type OpenAIResponsesIncludeValue =
|
|
@@ -468,6 +469,13 @@ export type OpenAIResponsesCompactionItem = {
|
|
|
468
469
|
encrypted_content: string;
|
|
469
470
|
};
|
|
470
471
|
|
|
472
|
+
export type OpenAIResponsesConfigurationUpdate = {
|
|
473
|
+
type: 'configuration_update';
|
|
474
|
+
reasoning: {
|
|
475
|
+
effort: 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
476
|
+
};
|
|
477
|
+
};
|
|
478
|
+
|
|
471
479
|
export type OpenAIResponsesCompactionTrigger = {
|
|
472
480
|
type: 'compaction_trigger';
|
|
473
481
|
};
|
|
@@ -264,6 +264,18 @@ export const openaiLanguageModelResponsesOptionsSchema = lazySchema(() =>
|
|
|
264
264
|
*/
|
|
265
265
|
reasoningEffort: z.string().nullish(),
|
|
266
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Updates the reasoning effort for GPT-6 and later models starting with this response
|
|
269
|
+
* without changing the request-level reasoning effort. This preserves the
|
|
270
|
+
* request prefix for prompt caching.
|
|
271
|
+
*
|
|
272
|
+
* Only supported by GPT-6 and later models in standard, single-agent mode. Cannot be
|
|
273
|
+
* combined with automatic compaction or automatic truncation.
|
|
274
|
+
*/
|
|
275
|
+
reasoningEffortUpdate: z
|
|
276
|
+
.enum(['low', 'medium', 'high', 'xhigh', 'max'])
|
|
277
|
+
.optional(),
|
|
278
|
+
|
|
267
279
|
/**
|
|
268
280
|
* Controls how much model work GPT-5.6 performs before returning a final answer.
|
|
269
281
|
* `standard` is the default. `pro` increases quality, latency, and token usage.
|
|
@@ -296,9 +296,25 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
296
296
|
});
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
-
|
|
299
|
+
let resolvedReasoningEffort =
|
|
300
300
|
openaiOptions?.reasoningEffort ??
|
|
301
301
|
(isCustomReasoning(reasoning) ? reasoning : undefined);
|
|
302
|
+
|
|
303
|
+
if (
|
|
304
|
+
resolvedReasoningEffort != null &&
|
|
305
|
+
modelCapabilities.supportedReasoningEfforts != null &&
|
|
306
|
+
!modelCapabilities.supportedReasoningEfforts.includes(
|
|
307
|
+
resolvedReasoningEffort,
|
|
308
|
+
)
|
|
309
|
+
) {
|
|
310
|
+
warnings.push({
|
|
311
|
+
type: 'unsupported',
|
|
312
|
+
feature: 'reasoningEffort',
|
|
313
|
+
details: `${this.modelId} only supports the following reasoning efforts: ${modelCapabilities.supportedReasoningEfforts.join(', ')}`,
|
|
314
|
+
});
|
|
315
|
+
resolvedReasoningEffort = undefined;
|
|
316
|
+
}
|
|
317
|
+
|
|
302
318
|
const resolvedReasoningSummary =
|
|
303
319
|
openaiOptions?.reasoningSummary !== undefined
|
|
304
320
|
? openaiOptions.reasoningSummary
|
|
@@ -384,6 +400,29 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
384
400
|
|
|
385
401
|
warnings.push(...inputWarnings);
|
|
386
402
|
|
|
403
|
+
const reasoningEffortUpdate = openaiOptions?.reasoningEffortUpdate;
|
|
404
|
+
const configurationUpdateIsSupported =
|
|
405
|
+
reasoningEffortUpdate == null ||
|
|
406
|
+
(modelCapabilities.supportsConfigurationUpdate &&
|
|
407
|
+
openaiOptions?.reasoningMode !== 'pro' &&
|
|
408
|
+
openaiOptions?.contextManagement == null &&
|
|
409
|
+
openaiOptions?.truncation !== 'auto');
|
|
410
|
+
|
|
411
|
+
if (reasoningEffortUpdate != null && !configurationUpdateIsSupported) {
|
|
412
|
+
warnings.push({
|
|
413
|
+
type: 'unsupported',
|
|
414
|
+
feature: 'reasoningEffortUpdate',
|
|
415
|
+
details: !modelCapabilities.supportsConfigurationUpdate
|
|
416
|
+
? 'reasoningEffortUpdate is only supported by GPT-6 and later models'
|
|
417
|
+
: 'reasoningEffortUpdate requires standard reasoning mode without automatic compaction or automatic truncation',
|
|
418
|
+
});
|
|
419
|
+
} else if (reasoningEffortUpdate != null) {
|
|
420
|
+
input.unshift({
|
|
421
|
+
type: 'configuration_update',
|
|
422
|
+
reasoning: { effort: reasoningEffortUpdate },
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
387
426
|
// A compaction trigger is a request control, not conversation history.
|
|
388
427
|
// OpenAI requires it to be the final input item, so append it only after
|
|
389
428
|
// the complete prompt has been converted.
|
|
@@ -526,6 +565,19 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
526
565
|
}),
|
|
527
566
|
};
|
|
528
567
|
|
|
568
|
+
if (
|
|
569
|
+
modelCapabilities.supportsConfigurationUpdate &&
|
|
570
|
+
baseArgs.prompt_cache_retention != null
|
|
571
|
+
) {
|
|
572
|
+
baseArgs.prompt_cache_retention = undefined;
|
|
573
|
+
warnings.push({
|
|
574
|
+
type: 'unsupported',
|
|
575
|
+
feature: 'promptCacheRetention',
|
|
576
|
+
details:
|
|
577
|
+
'promptCacheRetention is not supported by GPT-6 and later models; use promptCacheOptions instead',
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
|
|
529
581
|
// remove unsupported settings for reasoning models
|
|
530
582
|
// see https://platform.openai.com/docs/guides/reasoning#limitations
|
|
531
583
|
if (isReasoningModel) {
|
|
@@ -554,6 +606,26 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
554
606
|
details: 'topP is not supported for reasoning models',
|
|
555
607
|
});
|
|
556
608
|
}
|
|
609
|
+
|
|
610
|
+
if (
|
|
611
|
+
modelCapabilities.supportedReasoningEfforts != null &&
|
|
612
|
+
(baseArgs.top_logprobs != null ||
|
|
613
|
+
baseArgs.include?.includes('message.output_text.logprobs'))
|
|
614
|
+
) {
|
|
615
|
+
baseArgs.top_logprobs = undefined;
|
|
616
|
+
const filteredInclude = baseArgs.include?.filter(
|
|
617
|
+
value => value !== 'message.output_text.logprobs',
|
|
618
|
+
);
|
|
619
|
+
baseArgs.include =
|
|
620
|
+
filteredInclude != null && filteredInclude.length > 0
|
|
621
|
+
? filteredInclude
|
|
622
|
+
: undefined;
|
|
623
|
+
warnings.push({
|
|
624
|
+
type: 'unsupported',
|
|
625
|
+
feature: 'logprobs',
|
|
626
|
+
details: 'logprobs is not supported for reasoning models',
|
|
627
|
+
});
|
|
628
|
+
}
|
|
557
629
|
}
|
|
558
630
|
} else {
|
|
559
631
|
if (openaiOptions?.reasoningEffort != null) {
|