@ai-sdk/openai 4.0.0-beta.1 → 4.0.0-beta.11
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 +145 -0
- package/dist/index.d.mts +69 -22
- package/dist/index.d.ts +69 -22
- package/dist/index.js +1169 -873
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1123 -822
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +56 -28
- package/dist/internal/index.d.ts +56 -28
- package/dist/internal/index.js +1198 -912
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +1180 -889
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-openai.mdx +142 -3
- package/package.json +3 -3
- package/src/chat/convert-openai-chat-usage.ts +2 -2
- package/src/chat/convert-to-openai-chat-messages.ts +5 -5
- package/src/chat/map-openai-finish-reason.ts +2 -2
- package/src/chat/openai-chat-language-model.ts +22 -22
- package/src/chat/openai-chat-options.ts +1 -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/image/openai-image-model.ts +9 -9
- package/src/openai-language-model-capabilities.ts +1 -0
- package/src/openai-provider.ts +21 -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 +116 -12
- package/src/responses/map-openai-responses-finish-reason.ts +2 -2
- package/src/responses/openai-responses-api.ts +87 -1
- package/src/responses/openai-responses-language-model.ts +168 -33
- package/src/responses/openai-responses-options.ts +4 -2
- package/src/responses/openai-responses-prepare-tools.ts +34 -9
- 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,
|
|
@@ -38,6 +38,10 @@ import { imageGenerationOutputSchema } from '../tool/image-generation';
|
|
|
38
38
|
import { localShellInputSchema } from '../tool/local-shell';
|
|
39
39
|
import { mcpOutputSchema } from '../tool/mcp';
|
|
40
40
|
import { shellInputSchema, shellOutputSchema } from '../tool/shell';
|
|
41
|
+
import {
|
|
42
|
+
toolSearchInputSchema,
|
|
43
|
+
toolSearchOutputSchema,
|
|
44
|
+
} from '../tool/tool-search';
|
|
41
45
|
import { webSearchOutputSchema } from '../tool/web-search';
|
|
42
46
|
import {
|
|
43
47
|
convertOpenAIResponsesUsage,
|
|
@@ -77,7 +81,7 @@ import {
|
|
|
77
81
|
* so that tool results reference the correct tool call.
|
|
78
82
|
*/
|
|
79
83
|
function extractApprovalRequestIdToToolCallIdMapping(
|
|
80
|
-
prompt:
|
|
84
|
+
prompt: LanguageModelV4Prompt,
|
|
81
85
|
): Record<string, string> {
|
|
82
86
|
const mapping: Record<string, string> = {};
|
|
83
87
|
for (const message of prompt) {
|
|
@@ -94,8 +98,8 @@ function extractApprovalRequestIdToToolCallIdMapping(
|
|
|
94
98
|
return mapping;
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
export class OpenAIResponsesLanguageModel implements
|
|
98
|
-
readonly specificationVersion = '
|
|
101
|
+
export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
102
|
+
readonly specificationVersion = 'v4';
|
|
99
103
|
|
|
100
104
|
readonly modelId: OpenAIResponsesModelId;
|
|
101
105
|
|
|
@@ -129,8 +133,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
129
133
|
tools,
|
|
130
134
|
toolChoice,
|
|
131
135
|
responseFormat,
|
|
132
|
-
}:
|
|
133
|
-
const warnings:
|
|
136
|
+
}: LanguageModelV4CallOptions) {
|
|
137
|
+
const warnings: SharedV4Warning[] = [];
|
|
134
138
|
const modelCapabilities = getOpenAILanguageModelCapabilities(this.modelId);
|
|
135
139
|
|
|
136
140
|
if (topK != null) {
|
|
@@ -193,11 +197,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
193
197
|
'openai.web_search_preview': 'web_search_preview',
|
|
194
198
|
'openai.mcp': 'mcp',
|
|
195
199
|
'openai.apply_patch': 'apply_patch',
|
|
200
|
+
'openai.tool_search': 'tool_search',
|
|
196
201
|
},
|
|
197
|
-
resolveProviderToolName: tool =>
|
|
198
|
-
tool.id === 'openai.custom'
|
|
199
|
-
? (tool.args as { name?: string }).name
|
|
200
|
-
: undefined,
|
|
201
202
|
});
|
|
202
203
|
|
|
203
204
|
const customProviderToolNames = new Set<string>();
|
|
@@ -273,7 +274,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
273
274
|
tool.type === 'provider' &&
|
|
274
275
|
(tool.id === 'openai.web_search' ||
|
|
275
276
|
tool.id === 'openai.web_search_preview'),
|
|
276
|
-
) as
|
|
277
|
+
) as LanguageModelV4ProviderTool | undefined
|
|
277
278
|
)?.name;
|
|
278
279
|
|
|
279
280
|
if (webSearchToolName) {
|
|
@@ -454,8 +455,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
454
455
|
}
|
|
455
456
|
|
|
456
457
|
async doGenerate(
|
|
457
|
-
options:
|
|
458
|
-
): Promise<
|
|
458
|
+
options: LanguageModelV4CallOptions,
|
|
459
|
+
): Promise<LanguageModelV4GenerateResult> {
|
|
459
460
|
const {
|
|
460
461
|
args: body,
|
|
461
462
|
warnings,
|
|
@@ -500,11 +501,12 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
500
501
|
});
|
|
501
502
|
}
|
|
502
503
|
|
|
503
|
-
const content: Array<
|
|
504
|
+
const content: Array<LanguageModelV4Content> = [];
|
|
504
505
|
const logprobs: Array<OpenAIResponsesLogprobs> = [];
|
|
505
506
|
|
|
506
507
|
// flag that checks if there have been client-side tool calls (not executed by openai)
|
|
507
508
|
let hasFunctionCall = false;
|
|
509
|
+
const hostedToolSearchCallIds: string[] = [];
|
|
508
510
|
|
|
509
511
|
// map response content to content array (defined when there is no error)
|
|
510
512
|
for (const part of response.output!) {
|
|
@@ -551,6 +553,54 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
551
553
|
break;
|
|
552
554
|
}
|
|
553
555
|
|
|
556
|
+
case 'tool_search_call': {
|
|
557
|
+
const toolCallId = part.call_id ?? part.id;
|
|
558
|
+
const isHosted = part.execution === 'server';
|
|
559
|
+
|
|
560
|
+
if (isHosted) {
|
|
561
|
+
hostedToolSearchCallIds.push(toolCallId);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
content.push({
|
|
565
|
+
type: 'tool-call',
|
|
566
|
+
toolCallId,
|
|
567
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
568
|
+
input: JSON.stringify({
|
|
569
|
+
arguments: part.arguments,
|
|
570
|
+
call_id: part.call_id,
|
|
571
|
+
} satisfies InferSchema<typeof toolSearchInputSchema>),
|
|
572
|
+
...(isHosted ? { providerExecuted: true } : {}),
|
|
573
|
+
providerMetadata: {
|
|
574
|
+
[providerOptionsName]: {
|
|
575
|
+
itemId: part.id,
|
|
576
|
+
},
|
|
577
|
+
},
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
case 'tool_search_output': {
|
|
584
|
+
const toolCallId =
|
|
585
|
+
part.call_id ?? hostedToolSearchCallIds.shift() ?? part.id;
|
|
586
|
+
|
|
587
|
+
content.push({
|
|
588
|
+
type: 'tool-result',
|
|
589
|
+
toolCallId,
|
|
590
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
591
|
+
result: {
|
|
592
|
+
tools: part.tools,
|
|
593
|
+
} satisfies InferSchema<typeof toolSearchOutputSchema>,
|
|
594
|
+
providerMetadata: {
|
|
595
|
+
[providerOptionsName]: {
|
|
596
|
+
itemId: part.id,
|
|
597
|
+
},
|
|
598
|
+
},
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
break;
|
|
602
|
+
}
|
|
603
|
+
|
|
554
604
|
case 'local_shell_call': {
|
|
555
605
|
content.push({
|
|
556
606
|
type: 'tool-call',
|
|
@@ -621,7 +671,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
621
671
|
logprobs.push(contentPart.logprobs);
|
|
622
672
|
}
|
|
623
673
|
|
|
624
|
-
const providerMetadata:
|
|
674
|
+
const providerMetadata: SharedV4ProviderMetadata[string] = {
|
|
625
675
|
itemId: part.id,
|
|
626
676
|
...(part.phase != null && { phase: part.phase }),
|
|
627
677
|
...(contentPart.annotations.length > 0 && {
|
|
@@ -833,7 +883,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
833
883
|
type: 'tool-approval-request',
|
|
834
884
|
approvalId: approvalRequestId,
|
|
835
885
|
toolCallId: dummyToolCallId,
|
|
836
|
-
} satisfies
|
|
886
|
+
} satisfies LanguageModelV4ToolApprovalRequest);
|
|
837
887
|
break;
|
|
838
888
|
}
|
|
839
889
|
|
|
@@ -930,7 +980,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
930
980
|
}
|
|
931
981
|
}
|
|
932
982
|
|
|
933
|
-
const providerMetadata:
|
|
983
|
+
const providerMetadata: SharedV4ProviderMetadata = {
|
|
934
984
|
[providerOptionsName]: {
|
|
935
985
|
responseId: response.id,
|
|
936
986
|
...(logprobs.length > 0 ? { logprobs } : {}),
|
|
@@ -966,8 +1016,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
966
1016
|
}
|
|
967
1017
|
|
|
968
1018
|
async doStream(
|
|
969
|
-
options:
|
|
970
|
-
): Promise<
|
|
1019
|
+
options: LanguageModelV4CallOptions,
|
|
1020
|
+
): Promise<LanguageModelV4StreamResult> {
|
|
971
1021
|
const {
|
|
972
1022
|
args: body,
|
|
973
1023
|
warnings,
|
|
@@ -1006,7 +1056,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1006
1056
|
string
|
|
1007
1057
|
>();
|
|
1008
1058
|
|
|
1009
|
-
let finishReason:
|
|
1059
|
+
let finishReason: LanguageModelV4FinishReason = {
|
|
1010
1060
|
unified: 'other',
|
|
1011
1061
|
raw: undefined,
|
|
1012
1062
|
};
|
|
@@ -1026,6 +1076,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1026
1076
|
hasDiff: boolean;
|
|
1027
1077
|
endEmitted: boolean;
|
|
1028
1078
|
};
|
|
1079
|
+
toolSearchExecution?: 'server' | 'client';
|
|
1029
1080
|
}
|
|
1030
1081
|
| undefined
|
|
1031
1082
|
> = {};
|
|
@@ -1054,12 +1105,13 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1054
1105
|
> = {};
|
|
1055
1106
|
|
|
1056
1107
|
let serviceTier: string | undefined;
|
|
1108
|
+
const hostedToolSearchCallIds: string[] = [];
|
|
1057
1109
|
|
|
1058
1110
|
return {
|
|
1059
1111
|
stream: response.pipeThrough(
|
|
1060
1112
|
new TransformStream<
|
|
1061
1113
|
ParseResult<OpenAIResponsesChunk>,
|
|
1062
|
-
|
|
1114
|
+
LanguageModelV4StreamPart
|
|
1063
1115
|
>({
|
|
1064
1116
|
start(controller) {
|
|
1065
1117
|
controller.enqueue({ type: 'stream-start', warnings });
|
|
@@ -1188,6 +1240,28 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1188
1240
|
input: '{}',
|
|
1189
1241
|
providerExecuted: true,
|
|
1190
1242
|
});
|
|
1243
|
+
} else if (value.item.type === 'tool_search_call') {
|
|
1244
|
+
const toolCallId = value.item.id;
|
|
1245
|
+
const toolName =
|
|
1246
|
+
toolNameMapping.toCustomToolName('tool_search');
|
|
1247
|
+
const isHosted = value.item.execution === 'server';
|
|
1248
|
+
|
|
1249
|
+
ongoingToolCalls[value.output_index] = {
|
|
1250
|
+
toolName,
|
|
1251
|
+
toolCallId,
|
|
1252
|
+
toolSearchExecution: value.item.execution ?? 'server',
|
|
1253
|
+
};
|
|
1254
|
+
|
|
1255
|
+
if (isHosted) {
|
|
1256
|
+
controller.enqueue({
|
|
1257
|
+
type: 'tool-input-start',
|
|
1258
|
+
id: toolCallId,
|
|
1259
|
+
toolName,
|
|
1260
|
+
providerExecuted: true,
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
} else if (value.item.type === 'tool_search_output') {
|
|
1264
|
+
// handled on output_item.done so we can pair it with the call
|
|
1191
1265
|
} else if (
|
|
1192
1266
|
value.item.type === 'mcp_call' ||
|
|
1193
1267
|
value.item.type === 'mcp_list_tools' ||
|
|
@@ -1418,6 +1492,67 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1418
1492
|
result: value.item.result,
|
|
1419
1493
|
} satisfies InferSchema<typeof imageGenerationOutputSchema>,
|
|
1420
1494
|
});
|
|
1495
|
+
} else if (value.item.type === 'tool_search_call') {
|
|
1496
|
+
const toolCall = ongoingToolCalls[value.output_index];
|
|
1497
|
+
const isHosted = value.item.execution === 'server';
|
|
1498
|
+
|
|
1499
|
+
if (toolCall != null) {
|
|
1500
|
+
const toolCallId = isHosted
|
|
1501
|
+
? toolCall.toolCallId
|
|
1502
|
+
: (value.item.call_id ?? value.item.id);
|
|
1503
|
+
|
|
1504
|
+
if (isHosted) {
|
|
1505
|
+
hostedToolSearchCallIds.push(toolCallId);
|
|
1506
|
+
} else {
|
|
1507
|
+
controller.enqueue({
|
|
1508
|
+
type: 'tool-input-start',
|
|
1509
|
+
id: toolCallId,
|
|
1510
|
+
toolName: toolCall.toolName,
|
|
1511
|
+
});
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
controller.enqueue({
|
|
1515
|
+
type: 'tool-input-end',
|
|
1516
|
+
id: toolCallId,
|
|
1517
|
+
});
|
|
1518
|
+
|
|
1519
|
+
controller.enqueue({
|
|
1520
|
+
type: 'tool-call',
|
|
1521
|
+
toolCallId,
|
|
1522
|
+
toolName: toolCall.toolName,
|
|
1523
|
+
input: JSON.stringify({
|
|
1524
|
+
arguments: value.item.arguments,
|
|
1525
|
+
call_id: isHosted ? null : toolCallId,
|
|
1526
|
+
} satisfies InferSchema<typeof toolSearchInputSchema>),
|
|
1527
|
+
...(isHosted ? { providerExecuted: true } : {}),
|
|
1528
|
+
providerMetadata: {
|
|
1529
|
+
[providerOptionsName]: {
|
|
1530
|
+
itemId: value.item.id,
|
|
1531
|
+
},
|
|
1532
|
+
},
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
ongoingToolCalls[value.output_index] = undefined;
|
|
1537
|
+
} else if (value.item.type === 'tool_search_output') {
|
|
1538
|
+
const toolCallId =
|
|
1539
|
+
value.item.call_id ??
|
|
1540
|
+
hostedToolSearchCallIds.shift() ??
|
|
1541
|
+
value.item.id;
|
|
1542
|
+
|
|
1543
|
+
controller.enqueue({
|
|
1544
|
+
type: 'tool-result',
|
|
1545
|
+
toolCallId,
|
|
1546
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
1547
|
+
result: {
|
|
1548
|
+
tools: value.item.tools,
|
|
1549
|
+
} satisfies InferSchema<typeof toolSearchOutputSchema>,
|
|
1550
|
+
providerMetadata: {
|
|
1551
|
+
[providerOptionsName]: {
|
|
1552
|
+
itemId: value.item.id,
|
|
1553
|
+
},
|
|
1554
|
+
},
|
|
1555
|
+
});
|
|
1421
1556
|
} else if (value.item.type === 'mcp_call') {
|
|
1422
1557
|
ongoingToolCalls[value.output_index] = undefined;
|
|
1423
1558
|
|
|
@@ -1941,7 +2076,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1941
2076
|
},
|
|
1942
2077
|
|
|
1943
2078
|
flush(controller) {
|
|
1944
|
-
const providerMetadata:
|
|
2079
|
+
const providerMetadata: SharedV4ProviderMetadata = {
|
|
1945
2080
|
[providerOptionsName]: {
|
|
1946
2081
|
responseId: responseId,
|
|
1947
2082
|
...(logprobs.length > 0 ? { logprobs } : {}),
|
|
@@ -37,11 +37,12 @@ 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',
|
|
42
44
|
'gpt-5.4-pro',
|
|
43
45
|
'gpt-5.4-pro-2026-03-05',
|
|
44
|
-
'gpt-5.3-codex',
|
|
45
46
|
] as const;
|
|
46
47
|
|
|
47
48
|
export const openaiResponsesModelIds = [
|
|
@@ -98,11 +99,12 @@ export type OpenAIResponsesModelId =
|
|
|
98
99
|
| 'gpt-5.2-pro'
|
|
99
100
|
| 'gpt-5.2-pro-2025-12-11'
|
|
100
101
|
| 'gpt-5.2-codex'
|
|
102
|
+
| 'gpt-5.3-chat-latest'
|
|
103
|
+
| 'gpt-5.3-codex'
|
|
101
104
|
| 'gpt-5.4'
|
|
102
105
|
| 'gpt-5.4-2026-03-05'
|
|
103
106
|
| 'gpt-5.4-pro'
|
|
104
107
|
| 'gpt-5.4-pro-2026-03-05'
|
|
105
|
-
| 'gpt-5.3-codex'
|
|
106
108
|
| 'gpt-5-2025-08-07'
|
|
107
109
|
| 'gpt-5-chat-latest'
|
|
108
110
|
| 'gpt-5-codex'
|
|
@@ -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
|
}
|
|
@@ -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
|
|
package/src/tool/custom.ts
CHANGED
|
@@ -8,7 +8,6 @@ import { z } from 'zod/v4';
|
|
|
8
8
|
export const customArgsSchema = lazySchema(() =>
|
|
9
9
|
zodSchema(
|
|
10
10
|
z.object({
|
|
11
|
-
name: z.string(),
|
|
12
11
|
description: z.string().optional(),
|
|
13
12
|
format: z
|
|
14
13
|
.union([
|
|
@@ -31,11 +30,6 @@ const customInputSchema = lazySchema(() => zodSchema(z.string()));
|
|
|
31
30
|
export const customToolFactory = createProviderToolFactory<
|
|
32
31
|
string,
|
|
33
32
|
{
|
|
34
|
-
/**
|
|
35
|
-
* The name of the custom tool, used to identify it in the API.
|
|
36
|
-
*/
|
|
37
|
-
name: string;
|
|
38
|
-
|
|
39
33
|
/**
|
|
40
34
|
* An optional description of what the tool does.
|
|
41
35
|
*/
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { JSONObject } from '@ai-sdk/provider';
|
|
2
|
+
import {
|
|
3
|
+
createProviderToolFactoryWithOutputSchema,
|
|
4
|
+
FlexibleSchema,
|
|
5
|
+
lazySchema,
|
|
6
|
+
zodSchema,
|
|
7
|
+
} from '@ai-sdk/provider-utils';
|
|
8
|
+
import { z } from 'zod/v4';
|
|
9
|
+
|
|
10
|
+
export const toolSearchArgsSchema = lazySchema(() =>
|
|
11
|
+
zodSchema(
|
|
12
|
+
z.object({
|
|
13
|
+
execution: z.enum(['server', 'client']).optional(),
|
|
14
|
+
description: z.string().optional(),
|
|
15
|
+
parameters: z.record(z.string(), z.unknown()).optional(),
|
|
16
|
+
}),
|
|
17
|
+
),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const toolSearchInputSchema = lazySchema(() =>
|
|
21
|
+
zodSchema(
|
|
22
|
+
z.object({
|
|
23
|
+
arguments: z.unknown().optional(),
|
|
24
|
+
call_id: z.string().nullish(),
|
|
25
|
+
}),
|
|
26
|
+
),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export const toolSearchOutputSchema: FlexibleSchema<{
|
|
30
|
+
tools: Array<JSONObject>;
|
|
31
|
+
}> = lazySchema(() =>
|
|
32
|
+
zodSchema(
|
|
33
|
+
z.object({
|
|
34
|
+
tools: z.array(z.record(z.string(), z.unknown())),
|
|
35
|
+
}),
|
|
36
|
+
),
|
|
37
|
+
) as FlexibleSchema<{ tools: Array<JSONObject> }>;
|
|
38
|
+
|
|
39
|
+
const toolSearchToolFactory = createProviderToolFactoryWithOutputSchema<
|
|
40
|
+
{
|
|
41
|
+
/**
|
|
42
|
+
* The arguments from the tool_search_call.
|
|
43
|
+
* This is preserved for multi-turn conversation reconstruction.
|
|
44
|
+
*/
|
|
45
|
+
arguments?: unknown;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The call ID from the tool_search_call.
|
|
49
|
+
* Present for client-executed tool search; null for hosted.
|
|
50
|
+
*/
|
|
51
|
+
call_id?: string | null;
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
/**
|
|
55
|
+
* The tools that were loaded by the tool search.
|
|
56
|
+
* These are the deferred tools that the model requested to load.
|
|
57
|
+
* Each tool is represented as a JSON object with properties depending on its type.
|
|
58
|
+
*
|
|
59
|
+
* Common properties include:
|
|
60
|
+
* - `type`: The type of the tool (e.g., 'function', 'web_search', etc.)
|
|
61
|
+
* - `name`: The name of the tool (for function tools)
|
|
62
|
+
* - `description`: A description of the tool
|
|
63
|
+
* - `deferLoading`: Whether this tool was deferred (had defer_loading: true)
|
|
64
|
+
* - `parameters`: The JSON Schema for the function parameters (for function tools)
|
|
65
|
+
* - `strict`: Whether to enable strict schema adherence (for function tools)
|
|
66
|
+
*/
|
|
67
|
+
tools: Array<JSONObject>;
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
/**
|
|
71
|
+
* Whether the tool search is executed by the server (hosted) or client.
|
|
72
|
+
* - `'server'` (default): OpenAI performs the search across deferred tools.
|
|
73
|
+
* - `'client'`: The model emits a `tool_search_call` and your `execute`
|
|
74
|
+
* function performs the lookup, returning the tools to load.
|
|
75
|
+
*/
|
|
76
|
+
execution?: 'server' | 'client';
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* A description of the tool search capability.
|
|
80
|
+
* Only used for client-executed tool search.
|
|
81
|
+
*/
|
|
82
|
+
description?: string;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* JSON Schema for the search arguments your application expects.
|
|
86
|
+
* Only used for client-executed tool search.
|
|
87
|
+
*/
|
|
88
|
+
parameters?: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
>({
|
|
91
|
+
id: 'openai.tool_search',
|
|
92
|
+
inputSchema: toolSearchInputSchema,
|
|
93
|
+
outputSchema: toolSearchOutputSchema,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export const toolSearch = (
|
|
97
|
+
args: Parameters<typeof toolSearchToolFactory>[0] = {},
|
|
98
|
+
) => toolSearchToolFactory(args);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
TranscriptionModelV4,
|
|
3
|
+
TranscriptionModelV4CallOptions,
|
|
4
|
+
SharedV4Warning,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import {
|
|
7
7
|
combineHeaders,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
} from './openai-transcription-options';
|
|
22
22
|
|
|
23
23
|
export type OpenAITranscriptionCallOptions = Omit<
|
|
24
|
-
|
|
24
|
+
TranscriptionModelV4CallOptions,
|
|
25
25
|
'providerOptions'
|
|
26
26
|
> & {
|
|
27
27
|
providerOptions?: {
|
|
@@ -96,8 +96,8 @@ const languageMap = {
|
|
|
96
96
|
welsh: 'cy',
|
|
97
97
|
};
|
|
98
98
|
|
|
99
|
-
export class OpenAITranscriptionModel implements
|
|
100
|
-
readonly specificationVersion = '
|
|
99
|
+
export class OpenAITranscriptionModel implements TranscriptionModelV4 {
|
|
100
|
+
readonly specificationVersion = 'v4';
|
|
101
101
|
|
|
102
102
|
get provider(): string {
|
|
103
103
|
return this.config.provider;
|
|
@@ -113,7 +113,7 @@ export class OpenAITranscriptionModel implements TranscriptionModelV3 {
|
|
|
113
113
|
mediaType,
|
|
114
114
|
providerOptions,
|
|
115
115
|
}: OpenAITranscriptionCallOptions) {
|
|
116
|
-
const warnings:
|
|
116
|
+
const warnings: SharedV4Warning[] = [];
|
|
117
117
|
|
|
118
118
|
// Parse provider options
|
|
119
119
|
const openAIOptions = await parseProviderOptions({
|
|
@@ -176,7 +176,7 @@ export class OpenAITranscriptionModel implements TranscriptionModelV3 {
|
|
|
176
176
|
|
|
177
177
|
async doGenerate(
|
|
178
178
|
options: OpenAITranscriptionCallOptions,
|
|
179
|
-
): Promise<Awaited<ReturnType<
|
|
179
|
+
): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>> {
|
|
180
180
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
181
181
|
const { formData, warnings } = await this.getArgs(options);
|
|
182
182
|
|