@ai-sdk/openai 4.0.59 → 4.0.61
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 +20 -0
- package/dist/index.d.ts +47 -11
- package/dist/index.js +278 -138
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +45 -11
- package/dist/internal/index.js +188 -51
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +138 -10
- package/package.json +3 -3
- package/src/chat/openai-chat-language-model.ts +29 -1
- package/src/index.ts +1 -0
- package/src/{openai-responses-batch.ts → openai-batch.ts} +71 -87
- package/src/openai-language-model-capabilities.ts +10 -0
- package/src/openai-provider.ts +27 -6
- package/src/openai-tools.ts +1 -0
- package/src/responses/convert-to-openai-responses-input.ts +13 -0
- package/src/responses/openai-responses-api.ts +18 -0
- package/src/responses/openai-responses-language-model-options.ts +12 -0
- package/src/responses/openai-responses-language-model.ts +137 -29
- package/src/responses/openai-responses-prepare-tools.ts +47 -0
- package/src/responses/openai-responses-provider-metadata.ts +16 -0
- package/src/tool/custom.ts +7 -0
package/src/openai-provider.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
Experimental_BatchV4 as BatchV4,
|
|
2
3
|
EmbeddingModelV4,
|
|
3
|
-
Experimental_BatchLanguageModelV4 as BatchLanguageModelV4,
|
|
4
4
|
FilesV4,
|
|
5
5
|
ImageModelV4,
|
|
6
6
|
LanguageModelV4,
|
|
@@ -31,7 +31,8 @@ import type { OpenAIEmbeddingModelId } from './embedding/openai-embedding-model-
|
|
|
31
31
|
import { OpenAIImageModel } from './image/openai-image-model';
|
|
32
32
|
import type { OpenAIImageModelId } from './image/openai-image-model-options';
|
|
33
33
|
import { openaiTools } from './openai-tools';
|
|
34
|
-
import {
|
|
34
|
+
import { OpenAIBatch } from './openai-batch';
|
|
35
|
+
import { OpenAIResponsesLanguageModel } from './responses/openai-responses-language-model';
|
|
35
36
|
import { OpenAIRealtimeModel } from './realtime/openai-realtime-model';
|
|
36
37
|
import type { OpenAIResponsesModelId } from './responses/openai-responses-language-model-options';
|
|
37
38
|
import { OpenAISpeechModel } from './speech/openai-speech-model';
|
|
@@ -44,12 +45,12 @@ import { OpenAISkills } from './skills/openai-skills';
|
|
|
44
45
|
import { VERSION } from './version';
|
|
45
46
|
|
|
46
47
|
export interface OpenAIProvider extends ProviderV4 {
|
|
47
|
-
(modelId: OpenAIResponsesModelId):
|
|
48
|
+
(modelId: OpenAIResponsesModelId): LanguageModelV4;
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
51
|
* Creates an OpenAI model for text generation.
|
|
51
52
|
*/
|
|
52
|
-
languageModel(modelId: OpenAIResponsesModelId):
|
|
53
|
+
languageModel(modelId: OpenAIResponsesModelId): LanguageModelV4;
|
|
53
54
|
|
|
54
55
|
/**
|
|
55
56
|
* Creates an OpenAI chat model for text generation.
|
|
@@ -59,7 +60,7 @@ export interface OpenAIProvider extends ProviderV4 {
|
|
|
59
60
|
/**
|
|
60
61
|
* Creates an OpenAI responses API model for text generation.
|
|
61
62
|
*/
|
|
62
|
-
responses(modelId: OpenAIResponsesModelId):
|
|
63
|
+
responses(modelId: OpenAIResponsesModelId): LanguageModelV4;
|
|
63
64
|
|
|
64
65
|
/**
|
|
65
66
|
* Creates an OpenAI completion model for text generation.
|
|
@@ -136,6 +137,11 @@ export interface OpenAIProvider extends ProviderV4 {
|
|
|
136
137
|
*/
|
|
137
138
|
skills(): SkillsV4;
|
|
138
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Returns a BatchV4 interface for processing batches with OpenAI.
|
|
142
|
+
*/
|
|
143
|
+
experimental_batch(): BatchV4<{ text: OpenAIResponsesModelId }>;
|
|
144
|
+
|
|
139
145
|
/**
|
|
140
146
|
* OpenAI-specific tools.
|
|
141
147
|
*/
|
|
@@ -306,7 +312,7 @@ export function createOpenAI(
|
|
|
306
312
|
};
|
|
307
313
|
|
|
308
314
|
const createResponsesModel = (modelId: OpenAIResponsesModelId) => {
|
|
309
|
-
return new
|
|
315
|
+
return new OpenAIResponsesLanguageModel(modelId, {
|
|
310
316
|
provider: `${providerName}.responses`,
|
|
311
317
|
baseURL,
|
|
312
318
|
url: ({ path }) => `${baseURL}${path}`,
|
|
@@ -317,6 +323,20 @@ export function createOpenAI(
|
|
|
317
323
|
});
|
|
318
324
|
};
|
|
319
325
|
|
|
326
|
+
const createBatch = () =>
|
|
327
|
+
new OpenAIBatch({
|
|
328
|
+
provider: `${providerName}.batch`,
|
|
329
|
+
config: {
|
|
330
|
+
provider: `${providerName}.responses`,
|
|
331
|
+
baseURL,
|
|
332
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
333
|
+
headers: getHeaders,
|
|
334
|
+
fetch: options.fetch,
|
|
335
|
+
// Soft-deprecated. TODO: remove in v8
|
|
336
|
+
fileIdPrefixes: ['file-'],
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
|
|
320
340
|
const createRealtimeModel = (modelId: string) =>
|
|
321
341
|
new OpenAIRealtimeModel(modelId, {
|
|
322
342
|
provider: `${providerName}.realtime`,
|
|
@@ -371,6 +391,7 @@ export function createOpenAI(
|
|
|
371
391
|
provider.speechModel = createSpeechModel;
|
|
372
392
|
provider.files = createFiles;
|
|
373
393
|
provider.skills = createSkills;
|
|
394
|
+
provider.experimental_batch = createBatch;
|
|
374
395
|
|
|
375
396
|
provider.experimental_realtime = experimentalRealtimeFactory;
|
|
376
397
|
|
package/src/openai-tools.ts
CHANGED
|
@@ -28,6 +28,7 @@ export const openaiTools = {
|
|
|
28
28
|
* `input` field is a string matching the specified grammar.
|
|
29
29
|
*
|
|
30
30
|
* @param description - An optional description of the tool.
|
|
31
|
+
* @param async - Whether the model can continue without waiting for the tool result.
|
|
31
32
|
* @param format - The output format constraint (grammar type, syntax, and definition).
|
|
32
33
|
*/
|
|
33
34
|
customTool,
|
|
@@ -677,6 +677,17 @@ export async function convertToOpenAIResponsesInput({
|
|
|
677
677
|
).providerMetadata?.[providerOptionsName]?.namespace) as
|
|
678
678
|
| string
|
|
679
679
|
| undefined;
|
|
680
|
+
const isAsync = (part.providerOptions?.[providerOptionsName]
|
|
681
|
+
?.async ??
|
|
682
|
+
(
|
|
683
|
+
part as {
|
|
684
|
+
providerMetadata?: {
|
|
685
|
+
[providerOptionsName]?: { async?: boolean };
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
).providerMetadata?.[providerOptionsName]?.async) as
|
|
689
|
+
| boolean
|
|
690
|
+
| undefined;
|
|
680
691
|
const caller = part.providerOptions?.[providerOptionsName]
|
|
681
692
|
?.caller as
|
|
682
693
|
| { type: 'direct' }
|
|
@@ -904,6 +915,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
904
915
|
typeof part.input === 'string'
|
|
905
916
|
? part.input
|
|
906
917
|
: JSON.stringify(part.input),
|
|
918
|
+
...(isAsync != null && { async: isAsync }),
|
|
907
919
|
id,
|
|
908
920
|
});
|
|
909
921
|
break;
|
|
@@ -914,6 +926,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
914
926
|
call_id: part.toolCallId,
|
|
915
927
|
name: resolvedToolName,
|
|
916
928
|
arguments: serializeToolCallArguments(part.input),
|
|
929
|
+
...(isAsync != null && { async: isAsync }),
|
|
917
930
|
...(namespace != null && { namespace }),
|
|
918
931
|
...(caller != null && {
|
|
919
932
|
caller: mapToolCaller(caller),
|
|
@@ -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 =
|
|
@@ -272,6 +273,7 @@ export type OpenAIResponsesFunctionCall = {
|
|
|
272
273
|
call_id: string;
|
|
273
274
|
name: string;
|
|
274
275
|
arguments: string;
|
|
276
|
+
async?: boolean;
|
|
275
277
|
id?: string;
|
|
276
278
|
namespace?: string;
|
|
277
279
|
caller?: OpenAIResponsesToolCaller;
|
|
@@ -334,6 +336,7 @@ export type OpenAIResponsesCustomToolCall = {
|
|
|
334
336
|
call_id: string;
|
|
335
337
|
name: string;
|
|
336
338
|
input: string;
|
|
339
|
+
async?: boolean;
|
|
337
340
|
};
|
|
338
341
|
|
|
339
342
|
export type OpenAIResponsesCustomToolCallOutput = {
|
|
@@ -468,6 +471,13 @@ export type OpenAIResponsesCompactionItem = {
|
|
|
468
471
|
encrypted_content: string;
|
|
469
472
|
};
|
|
470
473
|
|
|
474
|
+
export type OpenAIResponsesConfigurationUpdate = {
|
|
475
|
+
type: 'configuration_update';
|
|
476
|
+
reasoning: {
|
|
477
|
+
effort: 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
478
|
+
};
|
|
479
|
+
};
|
|
480
|
+
|
|
471
481
|
export type OpenAIResponsesCompactionTrigger = {
|
|
472
482
|
type: 'compaction_trigger';
|
|
473
483
|
};
|
|
@@ -515,6 +525,7 @@ export type OpenAIResponsesFunctionTool = {
|
|
|
515
525
|
name: string;
|
|
516
526
|
description: string | undefined;
|
|
517
527
|
parameters: JSONSchema7;
|
|
528
|
+
async?: boolean;
|
|
518
529
|
strict?: boolean;
|
|
519
530
|
defer_loading?: boolean;
|
|
520
531
|
allowed_callers?: Array<'direct' | 'programmatic'>;
|
|
@@ -655,6 +666,7 @@ export type OpenAIResponsesTool =
|
|
|
655
666
|
type: 'custom';
|
|
656
667
|
name: string;
|
|
657
668
|
description?: string;
|
|
669
|
+
async?: boolean;
|
|
658
670
|
format?:
|
|
659
671
|
| {
|
|
660
672
|
type: 'grammar';
|
|
@@ -936,6 +948,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
936
948
|
call_id: z.string(),
|
|
937
949
|
name: z.string(),
|
|
938
950
|
arguments: z.string(),
|
|
951
|
+
async: z.boolean().nullish(),
|
|
939
952
|
namespace: z.string().nullish(),
|
|
940
953
|
caller: openaiResponsesToolCallerSchema.nullish(),
|
|
941
954
|
}),
|
|
@@ -1013,6 +1026,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
1013
1026
|
call_id: z.string(),
|
|
1014
1027
|
name: z.string(),
|
|
1015
1028
|
input: z.string(),
|
|
1029
|
+
async: z.boolean().nullish(),
|
|
1016
1030
|
}),
|
|
1017
1031
|
z.object({
|
|
1018
1032
|
type: z.literal('shell_call'),
|
|
@@ -1085,6 +1099,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
1085
1099
|
call_id: z.string(),
|
|
1086
1100
|
name: z.string(),
|
|
1087
1101
|
arguments: z.string(),
|
|
1102
|
+
async: z.boolean().nullish(),
|
|
1088
1103
|
status: z.enum(['in_progress', 'completed', 'incomplete']),
|
|
1089
1104
|
namespace: z.string().nullish(),
|
|
1090
1105
|
caller: openaiResponsesToolCallerSchema.nullish(),
|
|
@@ -1097,6 +1112,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
1097
1112
|
call_id: z.string(),
|
|
1098
1113
|
name: z.string(),
|
|
1099
1114
|
input: z.string(),
|
|
1115
|
+
async: z.boolean().nullish(),
|
|
1100
1116
|
status: z.literal('completed'),
|
|
1101
1117
|
}),
|
|
1102
1118
|
z.object({
|
|
@@ -1585,6 +1601,7 @@ export const openaiResponsesResponseSchema = lazySchema(() =>
|
|
|
1585
1601
|
name: z.string(),
|
|
1586
1602
|
arguments: z.string(),
|
|
1587
1603
|
id: z.string(),
|
|
1604
|
+
async: z.boolean().nullish(),
|
|
1588
1605
|
namespace: z.string().nullish(),
|
|
1589
1606
|
caller: openaiResponsesToolCallerSchema.nullish(),
|
|
1590
1607
|
}),
|
|
@@ -1596,6 +1613,7 @@ export const openaiResponsesResponseSchema = lazySchema(() =>
|
|
|
1596
1613
|
name: z.string(),
|
|
1597
1614
|
input: z.string(),
|
|
1598
1615
|
id: z.string(),
|
|
1616
|
+
async: z.boolean().nullish(),
|
|
1599
1617
|
}),
|
|
1600
1618
|
openaiResponsesComputerCallSchema,
|
|
1601
1619
|
z.object({
|
|
@@ -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.
|
|
@@ -94,6 +94,7 @@ import type {
|
|
|
94
94
|
ResponsesReasoningProviderMetadata,
|
|
95
95
|
ResponsesSourceDocumentProviderMetadata,
|
|
96
96
|
ResponsesTextProviderMetadata,
|
|
97
|
+
ResponsesToolCallProviderMetadata,
|
|
97
98
|
} from './openai-responses-provider-metadata';
|
|
98
99
|
|
|
99
100
|
/**
|
|
@@ -202,6 +203,11 @@ function mapComputerCallInput({
|
|
|
202
203
|
};
|
|
203
204
|
}
|
|
204
205
|
|
|
206
|
+
export const openaiResponsesSupportedUrls: Record<string, RegExp[]> = {
|
|
207
|
+
'image/*': [/^https?:\/\/.*$/],
|
|
208
|
+
'application/pdf': [/^https?:\/\/.*$/],
|
|
209
|
+
};
|
|
210
|
+
|
|
205
211
|
export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
206
212
|
readonly specificationVersion = 'v4';
|
|
207
213
|
|
|
@@ -231,33 +237,38 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
231
237
|
this.config = config;
|
|
232
238
|
}
|
|
233
239
|
|
|
234
|
-
readonly supportedUrls
|
|
235
|
-
'image/*': [/^https?:\/\/.*$/],
|
|
236
|
-
'application/pdf': [/^https?:\/\/.*$/],
|
|
237
|
-
};
|
|
240
|
+
readonly supportedUrls = openaiResponsesSupportedUrls;
|
|
238
241
|
|
|
239
242
|
get provider(): string {
|
|
240
243
|
return this.config.provider;
|
|
241
244
|
}
|
|
242
245
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
246
|
+
static async prepareRequest({
|
|
247
|
+
modelId,
|
|
248
|
+
config,
|
|
249
|
+
options: {
|
|
250
|
+
maxOutputTokens,
|
|
251
|
+
temperature,
|
|
252
|
+
stopSequences,
|
|
253
|
+
topP,
|
|
254
|
+
topK,
|
|
255
|
+
presencePenalty,
|
|
256
|
+
frequencyPenalty,
|
|
257
|
+
seed,
|
|
258
|
+
prompt,
|
|
259
|
+
reasoning,
|
|
260
|
+
providerOptions,
|
|
261
|
+
tools,
|
|
262
|
+
toolChoice,
|
|
263
|
+
responseFormat,
|
|
264
|
+
},
|
|
265
|
+
}: {
|
|
266
|
+
modelId: OpenAIResponsesModelId;
|
|
267
|
+
config: OpenAIConfig;
|
|
268
|
+
options: LanguageModelV4CallOptions;
|
|
269
|
+
}) {
|
|
259
270
|
const warnings: SharedV4Warning[] = [];
|
|
260
|
-
const modelCapabilities = getOpenAILanguageModelCapabilities(
|
|
271
|
+
const modelCapabilities = getOpenAILanguageModelCapabilities(modelId);
|
|
261
272
|
|
|
262
273
|
if (topK != null) {
|
|
263
274
|
warnings.push({ type: 'unsupported', feature: 'topK' });
|
|
@@ -279,7 +290,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
279
290
|
warnings.push({ type: 'unsupported', feature: 'stopSequences' });
|
|
280
291
|
}
|
|
281
292
|
|
|
282
|
-
const providerOptionsName =
|
|
293
|
+
const providerOptionsName = config.provider.includes('azure')
|
|
283
294
|
? 'azure'
|
|
284
295
|
: 'openai';
|
|
285
296
|
let openaiOptions = await parseProviderOptions({
|
|
@@ -296,9 +307,25 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
296
307
|
});
|
|
297
308
|
}
|
|
298
309
|
|
|
299
|
-
|
|
310
|
+
let resolvedReasoningEffort =
|
|
300
311
|
openaiOptions?.reasoningEffort ??
|
|
301
312
|
(isCustomReasoning(reasoning) ? reasoning : undefined);
|
|
313
|
+
|
|
314
|
+
if (
|
|
315
|
+
resolvedReasoningEffort != null &&
|
|
316
|
+
modelCapabilities.supportedReasoningEfforts != null &&
|
|
317
|
+
!modelCapabilities.supportedReasoningEfforts.includes(
|
|
318
|
+
resolvedReasoningEffort,
|
|
319
|
+
)
|
|
320
|
+
) {
|
|
321
|
+
warnings.push({
|
|
322
|
+
type: 'unsupported',
|
|
323
|
+
feature: 'reasoningEffort',
|
|
324
|
+
details: `${modelId} only supports the following reasoning efforts: ${modelCapabilities.supportedReasoningEfforts.join(', ')}`,
|
|
325
|
+
});
|
|
326
|
+
resolvedReasoningEffort = undefined;
|
|
327
|
+
}
|
|
328
|
+
|
|
302
329
|
const resolvedReasoningSummary =
|
|
303
330
|
openaiOptions?.reasoningSummary !== undefined
|
|
304
331
|
? openaiOptions.reasoningSummary
|
|
@@ -351,6 +378,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
351
378
|
toolNameMapping,
|
|
352
379
|
customProviderToolNames,
|
|
353
380
|
outputSchemaToolNames,
|
|
381
|
+
supportsAsyncToolCalling: modelCapabilities.supportsAsyncToolCalling,
|
|
354
382
|
});
|
|
355
383
|
|
|
356
384
|
const { input, warnings: inputWarnings } =
|
|
@@ -363,7 +391,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
363
391
|
? 'developer'
|
|
364
392
|
: modelCapabilities.systemMessageMode),
|
|
365
393
|
providerOptionsName,
|
|
366
|
-
fileIdPrefixes:
|
|
394
|
+
fileIdPrefixes: config.fileIdPrefixes,
|
|
367
395
|
passThroughUnsupportedFiles:
|
|
368
396
|
openaiOptions?.passThroughUnsupportedFiles ?? false,
|
|
369
397
|
store: openaiOptions?.store ?? true,
|
|
@@ -384,6 +412,29 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
384
412
|
|
|
385
413
|
warnings.push(...inputWarnings);
|
|
386
414
|
|
|
415
|
+
const reasoningEffortUpdate = openaiOptions?.reasoningEffortUpdate;
|
|
416
|
+
const configurationUpdateIsSupported =
|
|
417
|
+
reasoningEffortUpdate == null ||
|
|
418
|
+
(modelCapabilities.supportsConfigurationUpdate &&
|
|
419
|
+
openaiOptions?.reasoningMode !== 'pro' &&
|
|
420
|
+
openaiOptions?.contextManagement == null &&
|
|
421
|
+
openaiOptions?.truncation !== 'auto');
|
|
422
|
+
|
|
423
|
+
if (reasoningEffortUpdate != null && !configurationUpdateIsSupported) {
|
|
424
|
+
warnings.push({
|
|
425
|
+
type: 'unsupported',
|
|
426
|
+
feature: 'reasoningEffortUpdate',
|
|
427
|
+
details: !modelCapabilities.supportsConfigurationUpdate
|
|
428
|
+
? 'reasoningEffortUpdate is only supported by GPT-6 and later models'
|
|
429
|
+
: 'reasoningEffortUpdate requires standard reasoning mode without automatic compaction or automatic truncation',
|
|
430
|
+
});
|
|
431
|
+
} else if (reasoningEffortUpdate != null) {
|
|
432
|
+
input.unshift({
|
|
433
|
+
type: 'configuration_update',
|
|
434
|
+
reasoning: { effort: reasoningEffortUpdate },
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
387
438
|
// A compaction trigger is a request control, not conversation history.
|
|
388
439
|
// OpenAI requires it to be the final input item, so append it only after
|
|
389
440
|
// the complete prompt has been converted.
|
|
@@ -451,7 +502,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
451
502
|
}
|
|
452
503
|
|
|
453
504
|
const baseArgs = {
|
|
454
|
-
model:
|
|
505
|
+
model: modelId,
|
|
455
506
|
input,
|
|
456
507
|
temperature,
|
|
457
508
|
top_p: topP,
|
|
@@ -526,6 +577,19 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
526
577
|
}),
|
|
527
578
|
};
|
|
528
579
|
|
|
580
|
+
if (
|
|
581
|
+
modelCapabilities.supportsConfigurationUpdate &&
|
|
582
|
+
baseArgs.prompt_cache_retention != null
|
|
583
|
+
) {
|
|
584
|
+
baseArgs.prompt_cache_retention = undefined;
|
|
585
|
+
warnings.push({
|
|
586
|
+
type: 'unsupported',
|
|
587
|
+
feature: 'promptCacheRetention',
|
|
588
|
+
details:
|
|
589
|
+
'promptCacheRetention is not supported by GPT-6 and later models; use promptCacheOptions instead',
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
|
|
529
593
|
// remove unsupported settings for reasoning models
|
|
530
594
|
// see https://platform.openai.com/docs/guides/reasoning#limitations
|
|
531
595
|
if (isReasoningModel) {
|
|
@@ -554,6 +618,26 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
554
618
|
details: 'topP is not supported for reasoning models',
|
|
555
619
|
});
|
|
556
620
|
}
|
|
621
|
+
|
|
622
|
+
if (
|
|
623
|
+
modelCapabilities.supportedReasoningEfforts != null &&
|
|
624
|
+
(baseArgs.top_logprobs != null ||
|
|
625
|
+
baseArgs.include?.includes('message.output_text.logprobs'))
|
|
626
|
+
) {
|
|
627
|
+
baseArgs.top_logprobs = undefined;
|
|
628
|
+
const filteredInclude = baseArgs.include?.filter(
|
|
629
|
+
value => value !== 'message.output_text.logprobs',
|
|
630
|
+
);
|
|
631
|
+
baseArgs.include =
|
|
632
|
+
filteredInclude != null && filteredInclude.length > 0
|
|
633
|
+
? filteredInclude
|
|
634
|
+
: undefined;
|
|
635
|
+
warnings.push({
|
|
636
|
+
type: 'unsupported',
|
|
637
|
+
feature: 'logprobs',
|
|
638
|
+
details: 'logprobs is not supported for reasoning models',
|
|
639
|
+
});
|
|
640
|
+
}
|
|
557
641
|
}
|
|
558
642
|
} else {
|
|
559
643
|
if (openaiOptions?.reasoningEffort != null) {
|
|
@@ -645,6 +729,14 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
645
729
|
};
|
|
646
730
|
}
|
|
647
731
|
|
|
732
|
+
private getArgs(options: LanguageModelV4CallOptions) {
|
|
733
|
+
return OpenAIResponsesLanguageModel.prepareRequest({
|
|
734
|
+
modelId: this.modelId,
|
|
735
|
+
config: this.config,
|
|
736
|
+
options,
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
|
|
648
740
|
async doGenerate(
|
|
649
741
|
options: LanguageModelV4CallOptions,
|
|
650
742
|
): Promise<LanguageModelV4GenerateResult> {
|
|
@@ -997,6 +1089,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
997
1089
|
providerMetadata: {
|
|
998
1090
|
[providerOptionsName]: {
|
|
999
1091
|
itemId: part.id,
|
|
1092
|
+
...(part.async != null && { async: part.async }),
|
|
1000
1093
|
...(part.namespace != null && { namespace: part.namespace }),
|
|
1001
1094
|
...(part.caller != null && {
|
|
1002
1095
|
caller:
|
|
@@ -1007,7 +1100,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1007
1100
|
}
|
|
1008
1101
|
: part.caller,
|
|
1009
1102
|
}),
|
|
1010
|
-
},
|
|
1103
|
+
} satisfies ResponsesToolCallProviderMetadata,
|
|
1011
1104
|
},
|
|
1012
1105
|
});
|
|
1013
1106
|
break;
|
|
@@ -1066,7 +1159,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1066
1159
|
providerMetadata: {
|
|
1067
1160
|
[providerOptionsName]: {
|
|
1068
1161
|
itemId: part.id,
|
|
1069
|
-
|
|
1162
|
+
...(part.async != null && { async: part.async }),
|
|
1163
|
+
} satisfies ResponsesToolCallProviderMetadata,
|
|
1070
1164
|
},
|
|
1071
1165
|
});
|
|
1072
1166
|
break;
|
|
@@ -1413,6 +1507,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1413
1507
|
toolSearchExecution?: 'server' | 'client';
|
|
1414
1508
|
suppressInputStreaming?: boolean;
|
|
1415
1509
|
bufferedInputDeltas?: string[];
|
|
1510
|
+
async?: boolean | null;
|
|
1416
1511
|
}
|
|
1417
1512
|
| undefined
|
|
1418
1513
|
> = {};
|
|
@@ -1506,6 +1601,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1506
1601
|
toolCallId: value.item.call_id,
|
|
1507
1602
|
suppressInputStreaming,
|
|
1508
1603
|
bufferedInputDeltas: suppressInputStreaming ? [] : undefined,
|
|
1604
|
+
async: value.item.async,
|
|
1509
1605
|
};
|
|
1510
1606
|
|
|
1511
1607
|
if (!suppressInputStreaming) {
|
|
@@ -1522,6 +1618,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1522
1618
|
ongoingToolCalls[value.output_index] = {
|
|
1523
1619
|
toolName,
|
|
1524
1620
|
toolCallId: value.item.call_id,
|
|
1621
|
+
async: value.item.async,
|
|
1525
1622
|
};
|
|
1526
1623
|
|
|
1527
1624
|
controller.enqueue({
|
|
@@ -1812,6 +1909,11 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1812
1909
|
providerMetadata: {
|
|
1813
1910
|
[providerOptionsName]: {
|
|
1814
1911
|
itemId: item.id,
|
|
1912
|
+
...(item.async != null
|
|
1913
|
+
? { async: item.async }
|
|
1914
|
+
: ongoingToolCall?.async != null
|
|
1915
|
+
? { async: ongoingToolCall.async }
|
|
1916
|
+
: {}),
|
|
1815
1917
|
...(item.namespace != null && {
|
|
1816
1918
|
namespace: item.namespace,
|
|
1817
1919
|
}),
|
|
@@ -1824,7 +1926,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1824
1926
|
}
|
|
1825
1927
|
: item.caller,
|
|
1826
1928
|
}),
|
|
1827
|
-
},
|
|
1929
|
+
} satisfies ResponsesToolCallProviderMetadata,
|
|
1828
1930
|
},
|
|
1829
1931
|
});
|
|
1830
1932
|
};
|
|
@@ -1907,6 +2009,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1907
2009
|
},
|
|
1908
2010
|
});
|
|
1909
2011
|
} else if (value.item.type === 'custom_tool_call') {
|
|
2012
|
+
const ongoingToolCall = ongoingToolCalls[value.output_index];
|
|
1910
2013
|
ongoingToolCalls[value.output_index] = undefined;
|
|
1911
2014
|
hasFunctionCall = true;
|
|
1912
2015
|
const toolName = toolNameMapping.toCustomToolName(
|
|
@@ -1926,7 +2029,12 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1926
2029
|
providerMetadata: {
|
|
1927
2030
|
[providerOptionsName]: {
|
|
1928
2031
|
itemId: value.item.id,
|
|
1929
|
-
|
|
2032
|
+
...(value.item.async != null
|
|
2033
|
+
? { async: value.item.async }
|
|
2034
|
+
: ongoingToolCall?.async != null
|
|
2035
|
+
? { async: ongoingToolCall.async }
|
|
2036
|
+
: {}),
|
|
2037
|
+
} satisfies ResponsesToolCallProviderMetadata,
|
|
1930
2038
|
},
|
|
1931
2039
|
});
|
|
1932
2040
|
} else if (value.item.type === 'web_search_call') {
|
|
@@ -33,6 +33,11 @@ type AllowedToolResolution =
|
|
|
33
33
|
|
|
34
34
|
export type OpenAIToolOptions = {
|
|
35
35
|
allowedCallers?: Array<'direct' | 'programmatic'>;
|
|
36
|
+
/**
|
|
37
|
+
* Whether the model can continue generating after calling this tool without
|
|
38
|
+
* waiting for its result.
|
|
39
|
+
*/
|
|
40
|
+
async?: boolean;
|
|
36
41
|
deferLoading?: boolean;
|
|
37
42
|
outputSchema?: JSONObject;
|
|
38
43
|
namespace?: {
|
|
@@ -48,6 +53,7 @@ export async function prepareResponsesTools({
|
|
|
48
53
|
toolNameMapping,
|
|
49
54
|
customProviderToolNames,
|
|
50
55
|
outputSchemaToolNames,
|
|
56
|
+
supportsAsyncToolCalling = true,
|
|
51
57
|
}: {
|
|
52
58
|
tools: LanguageModelV4CallOptions['tools'];
|
|
53
59
|
toolChoice: LanguageModelV4CallOptions['toolChoice'] | undefined;
|
|
@@ -58,6 +64,7 @@ export async function prepareResponsesTools({
|
|
|
58
64
|
toolNameMapping?: ToolNameMapping;
|
|
59
65
|
customProviderToolNames?: Set<string>;
|
|
60
66
|
outputSchemaToolNames?: Set<string>;
|
|
67
|
+
supportsAsyncToolCalling?: boolean;
|
|
61
68
|
}): Promise<{
|
|
62
69
|
tools?: Array<OpenAIResponsesTool>;
|
|
63
70
|
toolChoice?:
|
|
@@ -140,6 +147,12 @@ export async function prepareResponsesTools({
|
|
|
140
147
|
const openaiFunctionTool = prepareFunctionTool({
|
|
141
148
|
tool,
|
|
142
149
|
options: openaiOptions,
|
|
150
|
+
async: resolveAsyncToolOption({
|
|
151
|
+
value: openaiOptions?.async,
|
|
152
|
+
supportsAsyncToolCalling,
|
|
153
|
+
toolName: tool.name,
|
|
154
|
+
toolWarnings,
|
|
155
|
+
}),
|
|
143
156
|
});
|
|
144
157
|
const namespace = openaiOptions?.namespace;
|
|
145
158
|
|
|
@@ -378,6 +391,14 @@ export async function prepareResponsesTools({
|
|
|
378
391
|
type: 'custom',
|
|
379
392
|
name: tool.name,
|
|
380
393
|
description: args.description,
|
|
394
|
+
...(resolveAsyncToolOption({
|
|
395
|
+
value: args.async,
|
|
396
|
+
supportsAsyncToolCalling,
|
|
397
|
+
toolName: tool.name,
|
|
398
|
+
toolWarnings,
|
|
399
|
+
}) != null
|
|
400
|
+
? { async: args.async }
|
|
401
|
+
: {}),
|
|
381
402
|
format: args.format,
|
|
382
403
|
});
|
|
383
404
|
resolvedCustomProviderToolNames.add(tool.name);
|
|
@@ -606,9 +627,11 @@ function toAllowedToolResolution(
|
|
|
606
627
|
function prepareFunctionTool({
|
|
607
628
|
tool,
|
|
608
629
|
options,
|
|
630
|
+
async,
|
|
609
631
|
}: {
|
|
610
632
|
tool: LanguageModelV4FunctionTool;
|
|
611
633
|
options: OpenAIToolOptions | undefined;
|
|
634
|
+
async: boolean | undefined;
|
|
612
635
|
}): OpenAIResponsesFunctionTool {
|
|
613
636
|
const deferLoading = options?.deferLoading;
|
|
614
637
|
|
|
@@ -617,6 +640,7 @@ function prepareFunctionTool({
|
|
|
617
640
|
name: tool.name,
|
|
618
641
|
description: tool.description,
|
|
619
642
|
parameters: tool.inputSchema,
|
|
643
|
+
...(async != null ? { async } : {}),
|
|
620
644
|
...(tool.strict != null ? { strict: tool.strict } : {}),
|
|
621
645
|
...(deferLoading != null ? { defer_loading: deferLoading } : {}),
|
|
622
646
|
...(options?.allowedCallers != null
|
|
@@ -628,6 +652,29 @@ function prepareFunctionTool({
|
|
|
628
652
|
};
|
|
629
653
|
}
|
|
630
654
|
|
|
655
|
+
function resolveAsyncToolOption({
|
|
656
|
+
value,
|
|
657
|
+
supportsAsyncToolCalling,
|
|
658
|
+
toolName,
|
|
659
|
+
toolWarnings,
|
|
660
|
+
}: {
|
|
661
|
+
value: boolean | undefined;
|
|
662
|
+
supportsAsyncToolCalling: boolean;
|
|
663
|
+
toolName: string;
|
|
664
|
+
toolWarnings: SharedV4Warning[];
|
|
665
|
+
}): boolean | undefined {
|
|
666
|
+
if (value !== true || supportsAsyncToolCalling) {
|
|
667
|
+
return value;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
toolWarnings.push({
|
|
671
|
+
type: 'unsupported',
|
|
672
|
+
feature: `async tool calling for "${toolName}"`,
|
|
673
|
+
details: 'Async tool calling is only supported by GPT-6 and later models.',
|
|
674
|
+
});
|
|
675
|
+
return undefined;
|
|
676
|
+
}
|
|
677
|
+
|
|
631
678
|
function mapShellEnvironment(environment: {
|
|
632
679
|
type?: string;
|
|
633
680
|
[key: string]: unknown;
|