@ai-sdk/openai 4.0.0-beta.2 → 4.0.0-beta.21
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 +234 -22
- package/README.md +2 -0
- package/dist/index.d.mts +134 -35
- package/dist/index.d.ts +134 -35
- package/dist/index.js +1700 -1139
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1697 -1117
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +107 -41
- package/dist/internal/index.d.ts +107 -41
- package/dist/internal/index.js +1380 -939
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +1371 -917
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-openai.mdx +274 -9
- package/package.json +3 -5
- package/src/chat/convert-openai-chat-usage.ts +2 -2
- package/src/chat/convert-to-openai-chat-messages.ts +26 -15
- package/src/chat/map-openai-finish-reason.ts +2 -2
- package/src/chat/openai-chat-language-model.ts +32 -24
- package/src/chat/openai-chat-options.ts +5 -0
- package/src/chat/openai-chat-prepare-tools.ts +6 -6
- package/src/completion/convert-openai-completion-usage.ts +2 -2
- package/src/completion/convert-to-openai-completion-prompt.ts +2 -2
- package/src/completion/map-openai-finish-reason.ts +2 -2
- package/src/completion/openai-completion-language-model.ts +20 -20
- package/src/embedding/openai-embedding-model.ts +5 -5
- package/src/files/openai-files-api.ts +17 -0
- package/src/files/openai-files-options.ts +18 -0
- package/src/files/openai-files.ts +102 -0
- package/src/image/openai-image-model.ts +9 -9
- package/src/index.ts +2 -0
- package/src/openai-config.ts +5 -5
- package/src/openai-language-model-capabilities.ts +3 -2
- package/src/openai-provider.ts +39 -21
- package/src/openai-tools.ts +12 -1
- package/src/responses/convert-openai-responses-usage.ts +2 -2
- package/src/responses/convert-to-openai-responses-input.ts +188 -14
- package/src/responses/map-openai-responses-finish-reason.ts +2 -2
- package/src/responses/openai-responses-api.ts +136 -2
- package/src/responses/openai-responses-language-model.ts +233 -37
- package/src/responses/openai-responses-options.ts +24 -2
- package/src/responses/openai-responses-prepare-tools.ts +34 -9
- package/src/responses/openai-responses-provider-metadata.ts +10 -0
- package/src/speech/openai-speech-model.ts +7 -7
- package/src/tool/custom.ts +0 -6
- package/src/tool/tool-search.ts +98 -0
- package/src/transcription/openai-transcription-model.ts +8 -8
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APICallError,
|
|
3
3
|
JSONValue,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
LanguageModelV4,
|
|
5
|
+
LanguageModelV4Prompt,
|
|
6
|
+
LanguageModelV4CallOptions,
|
|
7
|
+
LanguageModelV4Content,
|
|
8
|
+
LanguageModelV4FinishReason,
|
|
9
|
+
LanguageModelV4GenerateResult,
|
|
10
|
+
LanguageModelV4ProviderTool,
|
|
11
|
+
LanguageModelV4StreamPart,
|
|
12
|
+
LanguageModelV4StreamResult,
|
|
13
|
+
LanguageModelV4ToolApprovalRequest,
|
|
14
|
+
SharedV4ProviderMetadata,
|
|
15
|
+
SharedV4Warning,
|
|
16
16
|
} from '@ai-sdk/provider';
|
|
17
17
|
import {
|
|
18
18
|
combineHeaders,
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
createToolNameMapping,
|
|
22
22
|
generateId,
|
|
23
23
|
InferSchema,
|
|
24
|
+
isCustomReasoning,
|
|
24
25
|
parseProviderOptions,
|
|
25
26
|
ParseResult,
|
|
26
27
|
postJsonToApi,
|
|
@@ -38,6 +39,10 @@ import { imageGenerationOutputSchema } from '../tool/image-generation';
|
|
|
38
39
|
import { localShellInputSchema } from '../tool/local-shell';
|
|
39
40
|
import { mcpOutputSchema } from '../tool/mcp';
|
|
40
41
|
import { shellInputSchema, shellOutputSchema } from '../tool/shell';
|
|
42
|
+
import {
|
|
43
|
+
toolSearchInputSchema,
|
|
44
|
+
toolSearchOutputSchema,
|
|
45
|
+
} from '../tool/tool-search';
|
|
41
46
|
import { webSearchOutputSchema } from '../tool/web-search';
|
|
42
47
|
import {
|
|
43
48
|
convertOpenAIResponsesUsage,
|
|
@@ -63,6 +68,7 @@ import {
|
|
|
63
68
|
} from './openai-responses-options';
|
|
64
69
|
import { prepareResponsesTools } from './openai-responses-prepare-tools';
|
|
65
70
|
import {
|
|
71
|
+
ResponsesCompactionProviderMetadata,
|
|
66
72
|
ResponsesProviderMetadata,
|
|
67
73
|
ResponsesReasoningProviderMetadata,
|
|
68
74
|
ResponsesSourceDocumentProviderMetadata,
|
|
@@ -77,7 +83,7 @@ import {
|
|
|
77
83
|
* so that tool results reference the correct tool call.
|
|
78
84
|
*/
|
|
79
85
|
function extractApprovalRequestIdToToolCallIdMapping(
|
|
80
|
-
prompt:
|
|
86
|
+
prompt: LanguageModelV4Prompt,
|
|
81
87
|
): Record<string, string> {
|
|
82
88
|
const mapping: Record<string, string> = {};
|
|
83
89
|
for (const message of prompt) {
|
|
@@ -94,8 +100,8 @@ function extractApprovalRequestIdToToolCallIdMapping(
|
|
|
94
100
|
return mapping;
|
|
95
101
|
}
|
|
96
102
|
|
|
97
|
-
export class OpenAIResponsesLanguageModel implements
|
|
98
|
-
readonly specificationVersion = '
|
|
103
|
+
export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
104
|
+
readonly specificationVersion = 'v4';
|
|
99
105
|
|
|
100
106
|
readonly modelId: OpenAIResponsesModelId;
|
|
101
107
|
|
|
@@ -125,12 +131,13 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
125
131
|
frequencyPenalty,
|
|
126
132
|
seed,
|
|
127
133
|
prompt,
|
|
134
|
+
reasoning,
|
|
128
135
|
providerOptions,
|
|
129
136
|
tools,
|
|
130
137
|
toolChoice,
|
|
131
138
|
responseFormat,
|
|
132
|
-
}:
|
|
133
|
-
const warnings:
|
|
139
|
+
}: LanguageModelV4CallOptions) {
|
|
140
|
+
const warnings: SharedV4Warning[] = [];
|
|
134
141
|
const modelCapabilities = getOpenAILanguageModelCapabilities(this.modelId);
|
|
135
142
|
|
|
136
143
|
if (topK != null) {
|
|
@@ -170,6 +177,10 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
170
177
|
});
|
|
171
178
|
}
|
|
172
179
|
|
|
180
|
+
const resolvedReasoningEffort =
|
|
181
|
+
openaiOptions?.reasoningEffort ??
|
|
182
|
+
(isCustomReasoning(reasoning) ? reasoning : undefined);
|
|
183
|
+
|
|
173
184
|
const isReasoningModel =
|
|
174
185
|
openaiOptions?.forceReasoning ?? modelCapabilities.isReasoningModel;
|
|
175
186
|
|
|
@@ -193,11 +204,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
193
204
|
'openai.web_search_preview': 'web_search_preview',
|
|
194
205
|
'openai.mcp': 'mcp',
|
|
195
206
|
'openai.apply_patch': 'apply_patch',
|
|
207
|
+
'openai.tool_search': 'tool_search',
|
|
196
208
|
},
|
|
197
|
-
resolveProviderToolName: tool =>
|
|
198
|
-
tool.id === 'openai.custom'
|
|
199
|
-
? (tool.args as { name?: string }).name
|
|
200
|
-
: undefined,
|
|
201
209
|
});
|
|
202
210
|
|
|
203
211
|
const customProviderToolNames = new Set<string>();
|
|
@@ -273,7 +281,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
273
281
|
tool.type === 'provider' &&
|
|
274
282
|
(tool.id === 'openai.web_search' ||
|
|
275
283
|
tool.id === 'openai.web_search_preview'),
|
|
276
|
-
) as
|
|
284
|
+
) as LanguageModelV4ProviderTool | undefined
|
|
277
285
|
)?.name;
|
|
278
286
|
|
|
279
287
|
if (webSearchToolName) {
|
|
@@ -336,13 +344,21 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
336
344
|
top_logprobs: topLogprobs,
|
|
337
345
|
truncation: openaiOptions?.truncation,
|
|
338
346
|
|
|
347
|
+
// context management (server-side compaction):
|
|
348
|
+
...(openaiOptions?.contextManagement && {
|
|
349
|
+
context_management: openaiOptions.contextManagement.map(cm => ({
|
|
350
|
+
type: cm.type,
|
|
351
|
+
compact_threshold: cm.compactThreshold,
|
|
352
|
+
})),
|
|
353
|
+
}),
|
|
354
|
+
|
|
339
355
|
// model-specific settings:
|
|
340
356
|
...(isReasoningModel &&
|
|
341
|
-
(
|
|
357
|
+
(resolvedReasoningEffort != null ||
|
|
342
358
|
openaiOptions?.reasoningSummary != null) && {
|
|
343
359
|
reasoning: {
|
|
344
|
-
...(
|
|
345
|
-
effort:
|
|
360
|
+
...(resolvedReasoningEffort != null && {
|
|
361
|
+
effort: resolvedReasoningEffort,
|
|
346
362
|
}),
|
|
347
363
|
...(openaiOptions?.reasoningSummary != null && {
|
|
348
364
|
summary: openaiOptions.reasoningSummary,
|
|
@@ -358,7 +374,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
358
374
|
// https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility
|
|
359
375
|
if (
|
|
360
376
|
!(
|
|
361
|
-
|
|
377
|
+
resolvedReasoningEffort === 'none' &&
|
|
362
378
|
modelCapabilities.supportsNonReasoningParameters
|
|
363
379
|
)
|
|
364
380
|
) {
|
|
@@ -454,8 +470,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
454
470
|
}
|
|
455
471
|
|
|
456
472
|
async doGenerate(
|
|
457
|
-
options:
|
|
458
|
-
): Promise<
|
|
473
|
+
options: LanguageModelV4CallOptions,
|
|
474
|
+
): Promise<LanguageModelV4GenerateResult> {
|
|
459
475
|
const {
|
|
460
476
|
args: body,
|
|
461
477
|
warnings,
|
|
@@ -500,11 +516,12 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
500
516
|
});
|
|
501
517
|
}
|
|
502
518
|
|
|
503
|
-
const content: Array<
|
|
519
|
+
const content: Array<LanguageModelV4Content> = [];
|
|
504
520
|
const logprobs: Array<OpenAIResponsesLogprobs> = [];
|
|
505
521
|
|
|
506
522
|
// flag that checks if there have been client-side tool calls (not executed by openai)
|
|
507
523
|
let hasFunctionCall = false;
|
|
524
|
+
const hostedToolSearchCallIds: string[] = [];
|
|
508
525
|
|
|
509
526
|
// map response content to content array (defined when there is no error)
|
|
510
527
|
for (const part of response.output!) {
|
|
@@ -551,6 +568,54 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
551
568
|
break;
|
|
552
569
|
}
|
|
553
570
|
|
|
571
|
+
case 'tool_search_call': {
|
|
572
|
+
const toolCallId = part.call_id ?? part.id;
|
|
573
|
+
const isHosted = part.execution === 'server';
|
|
574
|
+
|
|
575
|
+
if (isHosted) {
|
|
576
|
+
hostedToolSearchCallIds.push(toolCallId);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
content.push({
|
|
580
|
+
type: 'tool-call',
|
|
581
|
+
toolCallId,
|
|
582
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
583
|
+
input: JSON.stringify({
|
|
584
|
+
arguments: part.arguments,
|
|
585
|
+
call_id: part.call_id,
|
|
586
|
+
} satisfies InferSchema<typeof toolSearchInputSchema>),
|
|
587
|
+
...(isHosted ? { providerExecuted: true } : {}),
|
|
588
|
+
providerMetadata: {
|
|
589
|
+
[providerOptionsName]: {
|
|
590
|
+
itemId: part.id,
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
case 'tool_search_output': {
|
|
599
|
+
const toolCallId =
|
|
600
|
+
part.call_id ?? hostedToolSearchCallIds.shift() ?? part.id;
|
|
601
|
+
|
|
602
|
+
content.push({
|
|
603
|
+
type: 'tool-result',
|
|
604
|
+
toolCallId,
|
|
605
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
606
|
+
result: {
|
|
607
|
+
tools: part.tools,
|
|
608
|
+
} satisfies InferSchema<typeof toolSearchOutputSchema>,
|
|
609
|
+
providerMetadata: {
|
|
610
|
+
[providerOptionsName]: {
|
|
611
|
+
itemId: part.id,
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
|
|
554
619
|
case 'local_shell_call': {
|
|
555
620
|
content.push({
|
|
556
621
|
type: 'tool-call',
|
|
@@ -621,7 +686,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
621
686
|
logprobs.push(contentPart.logprobs);
|
|
622
687
|
}
|
|
623
688
|
|
|
624
|
-
const providerMetadata:
|
|
689
|
+
const providerMetadata: SharedV4ProviderMetadata[string] = {
|
|
625
690
|
itemId: part.id,
|
|
626
691
|
...(part.phase != null && { phase: part.phase }),
|
|
627
692
|
...(contentPart.annotations.length > 0 && {
|
|
@@ -833,7 +898,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
833
898
|
type: 'tool-approval-request',
|
|
834
899
|
approvalId: approvalRequestId,
|
|
835
900
|
toolCallId: dummyToolCallId,
|
|
836
|
-
} satisfies
|
|
901
|
+
} satisfies LanguageModelV4ToolApprovalRequest);
|
|
837
902
|
break;
|
|
838
903
|
}
|
|
839
904
|
|
|
@@ -927,10 +992,25 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
927
992
|
|
|
928
993
|
break;
|
|
929
994
|
}
|
|
995
|
+
|
|
996
|
+
case 'compaction': {
|
|
997
|
+
content.push({
|
|
998
|
+
type: 'custom',
|
|
999
|
+
kind: 'openai.compaction',
|
|
1000
|
+
providerMetadata: {
|
|
1001
|
+
[providerOptionsName]: {
|
|
1002
|
+
type: 'compaction',
|
|
1003
|
+
itemId: part.id,
|
|
1004
|
+
encryptedContent: part.encrypted_content,
|
|
1005
|
+
} satisfies ResponsesCompactionProviderMetadata,
|
|
1006
|
+
},
|
|
1007
|
+
});
|
|
1008
|
+
break;
|
|
1009
|
+
}
|
|
930
1010
|
}
|
|
931
1011
|
}
|
|
932
1012
|
|
|
933
|
-
const providerMetadata:
|
|
1013
|
+
const providerMetadata: SharedV4ProviderMetadata = {
|
|
934
1014
|
[providerOptionsName]: {
|
|
935
1015
|
responseId: response.id,
|
|
936
1016
|
...(logprobs.length > 0 ? { logprobs } : {}),
|
|
@@ -966,8 +1046,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
966
1046
|
}
|
|
967
1047
|
|
|
968
1048
|
async doStream(
|
|
969
|
-
options:
|
|
970
|
-
): Promise<
|
|
1049
|
+
options: LanguageModelV4CallOptions,
|
|
1050
|
+
): Promise<LanguageModelV4StreamResult> {
|
|
971
1051
|
const {
|
|
972
1052
|
args: body,
|
|
973
1053
|
warnings,
|
|
@@ -1006,7 +1086,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1006
1086
|
string
|
|
1007
1087
|
>();
|
|
1008
1088
|
|
|
1009
|
-
let finishReason:
|
|
1089
|
+
let finishReason: LanguageModelV4FinishReason = {
|
|
1010
1090
|
unified: 'other',
|
|
1011
1091
|
raw: undefined,
|
|
1012
1092
|
};
|
|
@@ -1026,6 +1106,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1026
1106
|
hasDiff: boolean;
|
|
1027
1107
|
endEmitted: boolean;
|
|
1028
1108
|
};
|
|
1109
|
+
toolSearchExecution?: 'server' | 'client';
|
|
1029
1110
|
}
|
|
1030
1111
|
| undefined
|
|
1031
1112
|
> = {};
|
|
@@ -1054,12 +1135,13 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1054
1135
|
> = {};
|
|
1055
1136
|
|
|
1056
1137
|
let serviceTier: string | undefined;
|
|
1138
|
+
const hostedToolSearchCallIds: string[] = [];
|
|
1057
1139
|
|
|
1058
1140
|
return {
|
|
1059
1141
|
stream: response.pipeThrough(
|
|
1060
1142
|
new TransformStream<
|
|
1061
1143
|
ParseResult<OpenAIResponsesChunk>,
|
|
1062
|
-
|
|
1144
|
+
LanguageModelV4StreamPart
|
|
1063
1145
|
>({
|
|
1064
1146
|
start(controller) {
|
|
1065
1147
|
controller.enqueue({ type: 'stream-start', warnings });
|
|
@@ -1188,6 +1270,28 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1188
1270
|
input: '{}',
|
|
1189
1271
|
providerExecuted: true,
|
|
1190
1272
|
});
|
|
1273
|
+
} else if (value.item.type === 'tool_search_call') {
|
|
1274
|
+
const toolCallId = value.item.id;
|
|
1275
|
+
const toolName =
|
|
1276
|
+
toolNameMapping.toCustomToolName('tool_search');
|
|
1277
|
+
const isHosted = value.item.execution === 'server';
|
|
1278
|
+
|
|
1279
|
+
ongoingToolCalls[value.output_index] = {
|
|
1280
|
+
toolName,
|
|
1281
|
+
toolCallId,
|
|
1282
|
+
toolSearchExecution: value.item.execution ?? 'server',
|
|
1283
|
+
};
|
|
1284
|
+
|
|
1285
|
+
if (isHosted) {
|
|
1286
|
+
controller.enqueue({
|
|
1287
|
+
type: 'tool-input-start',
|
|
1288
|
+
id: toolCallId,
|
|
1289
|
+
toolName,
|
|
1290
|
+
providerExecuted: true,
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
} else if (value.item.type === 'tool_search_output') {
|
|
1294
|
+
// handled on output_item.done so we can pair it with the call
|
|
1191
1295
|
} else if (
|
|
1192
1296
|
value.item.type === 'mcp_call' ||
|
|
1193
1297
|
value.item.type === 'mcp_list_tools' ||
|
|
@@ -1418,6 +1522,67 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1418
1522
|
result: value.item.result,
|
|
1419
1523
|
} satisfies InferSchema<typeof imageGenerationOutputSchema>,
|
|
1420
1524
|
});
|
|
1525
|
+
} else if (value.item.type === 'tool_search_call') {
|
|
1526
|
+
const toolCall = ongoingToolCalls[value.output_index];
|
|
1527
|
+
const isHosted = value.item.execution === 'server';
|
|
1528
|
+
|
|
1529
|
+
if (toolCall != null) {
|
|
1530
|
+
const toolCallId = isHosted
|
|
1531
|
+
? toolCall.toolCallId
|
|
1532
|
+
: (value.item.call_id ?? value.item.id);
|
|
1533
|
+
|
|
1534
|
+
if (isHosted) {
|
|
1535
|
+
hostedToolSearchCallIds.push(toolCallId);
|
|
1536
|
+
} else {
|
|
1537
|
+
controller.enqueue({
|
|
1538
|
+
type: 'tool-input-start',
|
|
1539
|
+
id: toolCallId,
|
|
1540
|
+
toolName: toolCall.toolName,
|
|
1541
|
+
});
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
controller.enqueue({
|
|
1545
|
+
type: 'tool-input-end',
|
|
1546
|
+
id: toolCallId,
|
|
1547
|
+
});
|
|
1548
|
+
|
|
1549
|
+
controller.enqueue({
|
|
1550
|
+
type: 'tool-call',
|
|
1551
|
+
toolCallId,
|
|
1552
|
+
toolName: toolCall.toolName,
|
|
1553
|
+
input: JSON.stringify({
|
|
1554
|
+
arguments: value.item.arguments,
|
|
1555
|
+
call_id: isHosted ? null : toolCallId,
|
|
1556
|
+
} satisfies InferSchema<typeof toolSearchInputSchema>),
|
|
1557
|
+
...(isHosted ? { providerExecuted: true } : {}),
|
|
1558
|
+
providerMetadata: {
|
|
1559
|
+
[providerOptionsName]: {
|
|
1560
|
+
itemId: value.item.id,
|
|
1561
|
+
},
|
|
1562
|
+
},
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
ongoingToolCalls[value.output_index] = undefined;
|
|
1567
|
+
} else if (value.item.type === 'tool_search_output') {
|
|
1568
|
+
const toolCallId =
|
|
1569
|
+
value.item.call_id ??
|
|
1570
|
+
hostedToolSearchCallIds.shift() ??
|
|
1571
|
+
value.item.id;
|
|
1572
|
+
|
|
1573
|
+
controller.enqueue({
|
|
1574
|
+
type: 'tool-result',
|
|
1575
|
+
toolCallId,
|
|
1576
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
1577
|
+
result: {
|
|
1578
|
+
tools: value.item.tools,
|
|
1579
|
+
} satisfies InferSchema<typeof toolSearchOutputSchema>,
|
|
1580
|
+
providerMetadata: {
|
|
1581
|
+
[providerOptionsName]: {
|
|
1582
|
+
itemId: value.item.id,
|
|
1583
|
+
},
|
|
1584
|
+
},
|
|
1585
|
+
});
|
|
1421
1586
|
} else if (value.item.type === 'mcp_call') {
|
|
1422
1587
|
ongoingToolCalls[value.output_index] = undefined;
|
|
1423
1588
|
|
|
@@ -1647,6 +1812,18 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1647
1812
|
}
|
|
1648
1813
|
|
|
1649
1814
|
delete activeReasoning[value.item.id];
|
|
1815
|
+
} else if (value.item.type === 'compaction') {
|
|
1816
|
+
controller.enqueue({
|
|
1817
|
+
type: 'custom',
|
|
1818
|
+
kind: 'openai.compaction',
|
|
1819
|
+
providerMetadata: {
|
|
1820
|
+
[providerOptionsName]: {
|
|
1821
|
+
type: 'compaction',
|
|
1822
|
+
itemId: value.item.id,
|
|
1823
|
+
encryptedContent: value.item.encrypted_content,
|
|
1824
|
+
} satisfies ResponsesCompactionProviderMetadata,
|
|
1825
|
+
},
|
|
1826
|
+
});
|
|
1650
1827
|
}
|
|
1651
1828
|
} else if (isResponseFunctionCallArgumentsDeltaChunk(value)) {
|
|
1652
1829
|
const toolCall = ongoingToolCalls[value.output_index];
|
|
@@ -1867,6 +2044,19 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1867
2044
|
if (typeof value.response.service_tier === 'string') {
|
|
1868
2045
|
serviceTier = value.response.service_tier;
|
|
1869
2046
|
}
|
|
2047
|
+
} else if (isResponseFailedChunk(value)) {
|
|
2048
|
+
const incompleteReason =
|
|
2049
|
+
value.response.incomplete_details?.reason;
|
|
2050
|
+
finishReason = {
|
|
2051
|
+
unified: incompleteReason
|
|
2052
|
+
? mapOpenAIResponseFinishReason({
|
|
2053
|
+
finishReason: incompleteReason,
|
|
2054
|
+
hasFunctionCall,
|
|
2055
|
+
})
|
|
2056
|
+
: 'error',
|
|
2057
|
+
raw: incompleteReason ?? 'error',
|
|
2058
|
+
};
|
|
2059
|
+
usage = value.response.usage ?? undefined;
|
|
1870
2060
|
} else if (isResponseAnnotationAddedChunk(value)) {
|
|
1871
2061
|
ongoingAnnotations.push(value.annotation);
|
|
1872
2062
|
if (value.annotation.type === 'url_citation') {
|
|
@@ -1941,7 +2131,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1941
2131
|
},
|
|
1942
2132
|
|
|
1943
2133
|
flush(controller) {
|
|
1944
|
-
const providerMetadata:
|
|
2134
|
+
const providerMetadata: SharedV4ProviderMetadata = {
|
|
1945
2135
|
[providerOptionsName]: {
|
|
1946
2136
|
responseId: responseId,
|
|
1947
2137
|
...(logprobs.length > 0 ? { logprobs } : {}),
|
|
@@ -1986,6 +2176,12 @@ function isResponseFinishedChunk(
|
|
|
1986
2176
|
);
|
|
1987
2177
|
}
|
|
1988
2178
|
|
|
2179
|
+
function isResponseFailedChunk(
|
|
2180
|
+
chunk: OpenAIResponsesChunk,
|
|
2181
|
+
): chunk is OpenAIResponsesChunk & { type: 'response.failed' } {
|
|
2182
|
+
return chunk.type === 'response.failed';
|
|
2183
|
+
}
|
|
2184
|
+
|
|
1989
2185
|
function isResponseCreatedChunk(
|
|
1990
2186
|
chunk: OpenAIResponsesChunk,
|
|
1991
2187
|
): chunk is OpenAIResponsesChunk & { type: 'response.created' } {
|
|
@@ -37,11 +37,16 @@ export const openaiResponsesReasoningModelIds = [
|
|
|
37
37
|
'gpt-5.2-chat-latest',
|
|
38
38
|
'gpt-5.2-pro',
|
|
39
39
|
'gpt-5.2-codex',
|
|
40
|
+
'gpt-5.3-chat-latest',
|
|
41
|
+
'gpt-5.3-codex',
|
|
40
42
|
'gpt-5.4',
|
|
41
43
|
'gpt-5.4-2026-03-05',
|
|
44
|
+
'gpt-5.4-mini',
|
|
45
|
+
'gpt-5.4-mini-2026-03-17',
|
|
46
|
+
'gpt-5.4-nano',
|
|
47
|
+
'gpt-5.4-nano-2026-03-17',
|
|
42
48
|
'gpt-5.4-pro',
|
|
43
49
|
'gpt-5.4-pro-2026-03-05',
|
|
44
|
-
'gpt-5.3-codex',
|
|
45
50
|
] as const;
|
|
46
51
|
|
|
47
52
|
export const openaiResponsesModelIds = [
|
|
@@ -98,11 +103,16 @@ export type OpenAIResponsesModelId =
|
|
|
98
103
|
| 'gpt-5.2-pro'
|
|
99
104
|
| 'gpt-5.2-pro-2025-12-11'
|
|
100
105
|
| 'gpt-5.2-codex'
|
|
106
|
+
| 'gpt-5.3-chat-latest'
|
|
107
|
+
| 'gpt-5.3-codex'
|
|
101
108
|
| 'gpt-5.4'
|
|
102
109
|
| 'gpt-5.4-2026-03-05'
|
|
110
|
+
| 'gpt-5.4-mini'
|
|
111
|
+
| 'gpt-5.4-mini-2026-03-17'
|
|
112
|
+
| 'gpt-5.4-nano'
|
|
113
|
+
| 'gpt-5.4-nano-2026-03-17'
|
|
103
114
|
| 'gpt-5.4-pro'
|
|
104
115
|
| 'gpt-5.4-pro-2026-03-05'
|
|
105
|
-
| 'gpt-5.3-codex'
|
|
106
116
|
| 'gpt-5-2025-08-07'
|
|
107
117
|
| 'gpt-5-chat-latest'
|
|
108
118
|
| 'gpt-5-codex'
|
|
@@ -298,6 +308,18 @@ export const openaiLanguageModelResponsesOptionsSchema = lazySchema(() =>
|
|
|
298
308
|
* and defaults `systemMessageMode` to `developer` unless overridden.
|
|
299
309
|
*/
|
|
300
310
|
forceReasoning: z.boolean().optional(),
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Enable server-side context management (compaction).
|
|
314
|
+
*/
|
|
315
|
+
contextManagement: z
|
|
316
|
+
.array(
|
|
317
|
+
z.object({
|
|
318
|
+
type: z.literal('compaction'),
|
|
319
|
+
compactThreshold: z.number(),
|
|
320
|
+
}),
|
|
321
|
+
)
|
|
322
|
+
.nullish(),
|
|
301
323
|
}),
|
|
302
324
|
),
|
|
303
325
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
LanguageModelV4CallOptions,
|
|
3
|
+
SharedV4Warning,
|
|
4
4
|
UnsupportedFunctionalityError,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import { ToolNameMapping, validateTypes } from '@ai-sdk/provider-utils';
|
|
@@ -10,6 +10,7 @@ import { imageGenerationArgsSchema } from '../tool/image-generation';
|
|
|
10
10
|
import { customArgsSchema } from '../tool/custom';
|
|
11
11
|
import { mcpArgsSchema } from '../tool/mcp';
|
|
12
12
|
import { shellArgsSchema } from '../tool/shell';
|
|
13
|
+
import { toolSearchArgsSchema } from '../tool/tool-search';
|
|
13
14
|
import { webSearchArgsSchema } from '../tool/web-search';
|
|
14
15
|
import { webSearchPreviewArgsSchema } from '../tool/web-search-preview';
|
|
15
16
|
import { OpenAIResponsesTool } from './openai-responses-api';
|
|
@@ -20,8 +21,8 @@ export async function prepareResponsesTools({
|
|
|
20
21
|
toolNameMapping,
|
|
21
22
|
customProviderToolNames,
|
|
22
23
|
}: {
|
|
23
|
-
tools:
|
|
24
|
-
toolChoice:
|
|
24
|
+
tools: LanguageModelV4CallOptions['tools'];
|
|
25
|
+
toolChoice: LanguageModelV4CallOptions['toolChoice'] | undefined;
|
|
25
26
|
toolNameMapping?: ToolNameMapping;
|
|
26
27
|
customProviderToolNames?: Set<string>;
|
|
27
28
|
}): Promise<{
|
|
@@ -39,12 +40,12 @@ export async function prepareResponsesTools({
|
|
|
39
40
|
| { type: 'mcp' }
|
|
40
41
|
| { type: 'image_generation' }
|
|
41
42
|
| { type: 'apply_patch' };
|
|
42
|
-
toolWarnings:
|
|
43
|
+
toolWarnings: SharedV4Warning[];
|
|
43
44
|
}> {
|
|
44
45
|
// when the tools array is empty, change it to undefined to prevent errors:
|
|
45
46
|
tools = tools?.length ? tools : undefined;
|
|
46
47
|
|
|
47
|
-
const toolWarnings:
|
|
48
|
+
const toolWarnings: SharedV4Warning[] = [];
|
|
48
49
|
|
|
49
50
|
if (tools == null) {
|
|
50
51
|
return { tools: undefined, toolChoice: undefined, toolWarnings };
|
|
@@ -56,15 +57,22 @@ export async function prepareResponsesTools({
|
|
|
56
57
|
|
|
57
58
|
for (const tool of tools) {
|
|
58
59
|
switch (tool.type) {
|
|
59
|
-
case 'function':
|
|
60
|
+
case 'function': {
|
|
61
|
+
const openaiOptions = tool.providerOptions?.openai as
|
|
62
|
+
| { deferLoading?: boolean }
|
|
63
|
+
| undefined;
|
|
64
|
+
const deferLoading = openaiOptions?.deferLoading;
|
|
65
|
+
|
|
60
66
|
openaiTools.push({
|
|
61
67
|
type: 'function',
|
|
62
68
|
name: tool.name,
|
|
63
69
|
description: tool.description,
|
|
64
70
|
parameters: tool.inputSchema,
|
|
65
71
|
...(tool.strict != null ? { strict: tool.strict } : {}),
|
|
72
|
+
...(deferLoading != null ? { defer_loading: deferLoading } : {}),
|
|
66
73
|
});
|
|
67
74
|
break;
|
|
75
|
+
}
|
|
68
76
|
case 'provider': {
|
|
69
77
|
switch (tool.id) {
|
|
70
78
|
case 'openai.file_search': {
|
|
@@ -241,11 +249,28 @@ export async function prepareResponsesTools({
|
|
|
241
249
|
|
|
242
250
|
openaiTools.push({
|
|
243
251
|
type: 'custom',
|
|
244
|
-
name:
|
|
252
|
+
name: tool.name,
|
|
245
253
|
description: args.description,
|
|
246
254
|
format: args.format,
|
|
247
255
|
});
|
|
248
|
-
resolvedCustomProviderToolNames.add(
|
|
256
|
+
resolvedCustomProviderToolNames.add(tool.name);
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
case 'openai.tool_search': {
|
|
260
|
+
const args = await validateTypes({
|
|
261
|
+
value: tool.args,
|
|
262
|
+
schema: toolSearchArgsSchema,
|
|
263
|
+
});
|
|
264
|
+
openaiTools.push({
|
|
265
|
+
type: 'tool_search',
|
|
266
|
+
...(args.execution != null ? { execution: args.execution } : {}),
|
|
267
|
+
...(args.description != null
|
|
268
|
+
? { description: args.description }
|
|
269
|
+
: {}),
|
|
270
|
+
...(args.parameters != null
|
|
271
|
+
? { parameters: args.parameters }
|
|
272
|
+
: {}),
|
|
273
|
+
});
|
|
249
274
|
break;
|
|
250
275
|
}
|
|
251
276
|
}
|
|
@@ -30,6 +30,16 @@ export type OpenaiResponsesProviderMetadata = {
|
|
|
30
30
|
openai: ResponsesProviderMetadata;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
export type ResponsesCompactionProviderMetadata = {
|
|
34
|
+
type: 'compaction';
|
|
35
|
+
itemId: string;
|
|
36
|
+
encryptedContent?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type OpenaiResponsesCompactionProviderMetadata = {
|
|
40
|
+
openai: ResponsesCompactionProviderMetadata;
|
|
41
|
+
};
|
|
42
|
+
|
|
33
43
|
export type ResponsesTextProviderMetadata = {
|
|
34
44
|
itemId: string;
|
|
35
45
|
phase?: 'commentary' | 'final_answer' | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SpeechModelV4, SharedV4Warning } from '@ai-sdk/provider';
|
|
2
2
|
import {
|
|
3
3
|
combineHeaders,
|
|
4
4
|
createBinaryResponseHandler,
|
|
@@ -19,8 +19,8 @@ interface OpenAISpeechModelConfig extends OpenAIConfig {
|
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export class OpenAISpeechModel implements
|
|
23
|
-
readonly specificationVersion = '
|
|
22
|
+
export class OpenAISpeechModel implements SpeechModelV4 {
|
|
23
|
+
readonly specificationVersion = 'v4';
|
|
24
24
|
|
|
25
25
|
get provider(): string {
|
|
26
26
|
return this.config.provider;
|
|
@@ -39,8 +39,8 @@ export class OpenAISpeechModel implements SpeechModelV3 {
|
|
|
39
39
|
instructions,
|
|
40
40
|
language,
|
|
41
41
|
providerOptions,
|
|
42
|
-
}: Parameters<
|
|
43
|
-
const warnings:
|
|
42
|
+
}: Parameters<SpeechModelV4['doGenerate']>[0]) {
|
|
43
|
+
const warnings: SharedV4Warning[] = [];
|
|
44
44
|
|
|
45
45
|
// Parse provider options
|
|
46
46
|
const openAIOptions = await parseProviderOptions({
|
|
@@ -98,8 +98,8 @@ export class OpenAISpeechModel implements SpeechModelV3 {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
async doGenerate(
|
|
101
|
-
options: Parameters<
|
|
102
|
-
): Promise<Awaited<ReturnType<
|
|
101
|
+
options: Parameters<SpeechModelV4['doGenerate']>[0],
|
|
102
|
+
): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>> {
|
|
103
103
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
104
104
|
const { requestBody, warnings } = await this.getArgs(options);
|
|
105
105
|
|