@ai-sdk/openai 4.0.0-beta.7 → 4.0.0-beta.74
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 +636 -24
- package/README.md +2 -0
- package/dist/index.d.ts +240 -44
- package/dist/index.js +3345 -1683
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +390 -36
- package/dist/internal/index.js +2707 -1706
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +413 -39
- package/package.json +16 -17
- package/src/chat/convert-openai-chat-usage.ts +1 -1
- package/src/chat/convert-to-openai-chat-messages.ts +96 -68
- package/src/chat/map-openai-finish-reason.ts +1 -1
- package/src/chat/openai-chat-api.ts +6 -2
- package/src/chat/{openai-chat-options.ts → openai-chat-language-model-options.ts} +11 -1
- package/src/chat/openai-chat-language-model.ts +82 -148
- package/src/chat/openai-chat-prepare-tools.ts +3 -3
- package/src/completion/convert-openai-completion-usage.ts +1 -1
- package/src/completion/convert-to-openai-completion-prompt.ts +1 -2
- package/src/completion/map-openai-finish-reason.ts +1 -1
- package/src/completion/openai-completion-api.ts +5 -2
- package/src/completion/{openai-completion-options.ts → openai-completion-language-model-options.ts} +5 -1
- package/src/completion/openai-completion-language-model.ts +53 -17
- package/src/embedding/{openai-embedding-options.ts → openai-embedding-model-options.ts} +5 -1
- package/src/embedding/openai-embedding-model.ts +22 -5
- package/src/files/openai-files-api.ts +17 -0
- package/src/files/openai-files-options.ts +22 -0
- package/src/files/openai-files.ts +100 -0
- package/src/image/openai-image-model-options.ts +123 -0
- package/src/image/openai-image-model.ts +62 -83
- package/src/index.ts +15 -6
- package/src/internal/index.ts +7 -6
- package/src/openai-config.ts +7 -7
- package/src/openai-language-model-capabilities.ts +5 -4
- package/src/openai-provider.ts +80 -9
- package/src/openai-stream-error.ts +181 -0
- package/src/openai-tools.ts +12 -1
- package/src/realtime/index.ts +2 -0
- package/src/realtime/openai-realtime-event-mapper.ts +436 -0
- package/src/realtime/openai-realtime-model-options.ts +3 -0
- package/src/realtime/openai-realtime-model.ts +111 -0
- package/src/responses/convert-openai-responses-usage.ts +1 -1
- package/src/responses/convert-to-openai-responses-input.ts +345 -90
- package/src/responses/map-openai-responses-finish-reason.ts +1 -1
- package/src/responses/openai-responses-api.ts +186 -17
- package/src/responses/{openai-responses-options.ts → openai-responses-language-model-options.ts} +55 -1
- package/src/responses/openai-responses-language-model.ts +330 -52
- package/src/responses/openai-responses-prepare-tools.ts +129 -18
- package/src/responses/openai-responses-provider-metadata.ts +12 -2
- package/src/skills/openai-skills-api.ts +31 -0
- package/src/skills/openai-skills.ts +83 -0
- package/src/speech/{openai-speech-options.ts → openai-speech-model-options.ts} +5 -1
- package/src/speech/openai-speech-model.ts +23 -7
- package/src/tool/apply-patch.ts +33 -32
- package/src/tool/code-interpreter.ts +40 -41
- package/src/tool/custom.ts +2 -8
- package/src/tool/file-search.ts +3 -3
- package/src/tool/image-generation.ts +2 -2
- package/src/tool/local-shell.ts +2 -2
- package/src/tool/mcp.ts +3 -3
- package/src/tool/shell.ts +9 -4
- package/src/tool/tool-search.ts +98 -0
- package/src/tool/web-search-preview.ts +2 -2
- package/src/tool/web-search.ts +10 -2
- package/src/transcription/{openai-transcription-options.ts → openai-transcription-model-options.ts} +5 -1
- package/src/transcription/openai-transcription-model.ts +35 -13
- package/dist/index.d.mts +0 -1107
- package/dist/index.mjs +0 -6509
- package/dist/index.mjs.map +0 -1
- package/dist/internal/index.d.mts +0 -1137
- package/dist/internal/index.mjs +0 -6322
- package/dist/internal/index.mjs.map +0 -1
- package/src/image/openai-image-options.ts +0 -31
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APICallError,
|
|
3
|
-
JSONValue,
|
|
4
|
-
LanguageModelV4,
|
|
5
|
-
LanguageModelV4Prompt,
|
|
6
|
-
LanguageModelV4CallOptions,
|
|
7
|
-
LanguageModelV4Content,
|
|
8
|
-
LanguageModelV4FinishReason,
|
|
9
|
-
LanguageModelV4GenerateResult,
|
|
10
|
-
LanguageModelV4ProviderTool,
|
|
11
|
-
LanguageModelV4StreamPart,
|
|
12
|
-
LanguageModelV4StreamResult,
|
|
13
|
-
LanguageModelV4ToolApprovalRequest,
|
|
14
|
-
SharedV4ProviderMetadata,
|
|
15
|
-
SharedV4Warning,
|
|
3
|
+
type JSONValue,
|
|
4
|
+
type LanguageModelV4,
|
|
5
|
+
type LanguageModelV4Prompt,
|
|
6
|
+
type LanguageModelV4CallOptions,
|
|
7
|
+
type LanguageModelV4Content,
|
|
8
|
+
type LanguageModelV4FinishReason,
|
|
9
|
+
type LanguageModelV4GenerateResult,
|
|
10
|
+
type LanguageModelV4ProviderTool,
|
|
11
|
+
type LanguageModelV4StreamPart,
|
|
12
|
+
type LanguageModelV4StreamResult,
|
|
13
|
+
type LanguageModelV4ToolApprovalRequest,
|
|
14
|
+
type SharedV4ProviderMetadata,
|
|
15
|
+
type SharedV4Warning,
|
|
16
16
|
} from '@ai-sdk/provider';
|
|
17
17
|
import {
|
|
18
18
|
combineHeaders,
|
|
@@ -20,49 +20,59 @@ import {
|
|
|
20
20
|
createJsonResponseHandler,
|
|
21
21
|
createToolNameMapping,
|
|
22
22
|
generateId,
|
|
23
|
-
|
|
23
|
+
isCustomReasoning,
|
|
24
24
|
parseProviderOptions,
|
|
25
|
-
ParseResult,
|
|
26
25
|
postJsonToApi,
|
|
26
|
+
serializeModelOptions,
|
|
27
|
+
WORKFLOW_DESERIALIZE,
|
|
28
|
+
WORKFLOW_SERIALIZE,
|
|
29
|
+
type InferSchema,
|
|
30
|
+
type ParseResult,
|
|
27
31
|
} from '@ai-sdk/provider-utils';
|
|
28
|
-
import { OpenAIConfig } from '../openai-config';
|
|
32
|
+
import type { OpenAIConfig } from '../openai-config';
|
|
29
33
|
import { openaiFailedResponseHandler } from '../openai-error';
|
|
30
34
|
import { getOpenAILanguageModelCapabilities } from '../openai-language-model-capabilities';
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
35
|
+
import { throwIfOpenAIStreamErrorBeforeOutput } from '../openai-stream-error';
|
|
36
|
+
import type { applyPatchInputSchema } from '../tool/apply-patch';
|
|
37
|
+
import type {
|
|
33
38
|
codeInterpreterInputSchema,
|
|
34
39
|
codeInterpreterOutputSchema,
|
|
35
40
|
} from '../tool/code-interpreter';
|
|
36
|
-
import { fileSearchOutputSchema } from '../tool/file-search';
|
|
37
|
-
import { imageGenerationOutputSchema } from '../tool/image-generation';
|
|
38
|
-
import { localShellInputSchema } from '../tool/local-shell';
|
|
39
|
-
import { mcpOutputSchema } from '../tool/mcp';
|
|
40
|
-
import { shellInputSchema, shellOutputSchema } from '../tool/shell';
|
|
41
|
-
import {
|
|
41
|
+
import type { fileSearchOutputSchema } from '../tool/file-search';
|
|
42
|
+
import type { imageGenerationOutputSchema } from '../tool/image-generation';
|
|
43
|
+
import type { localShellInputSchema } from '../tool/local-shell';
|
|
44
|
+
import type { mcpOutputSchema } from '../tool/mcp';
|
|
45
|
+
import type { shellInputSchema, shellOutputSchema } from '../tool/shell';
|
|
46
|
+
import type {
|
|
47
|
+
toolSearchInputSchema,
|
|
48
|
+
toolSearchOutputSchema,
|
|
49
|
+
} from '../tool/tool-search';
|
|
50
|
+
import type { webSearchOutputSchema } from '../tool/web-search';
|
|
42
51
|
import {
|
|
43
52
|
convertOpenAIResponsesUsage,
|
|
44
|
-
OpenAIResponsesUsage,
|
|
53
|
+
type OpenAIResponsesUsage,
|
|
45
54
|
} from './convert-openai-responses-usage';
|
|
46
55
|
import { convertToOpenAIResponsesInput } from './convert-to-openai-responses-input';
|
|
47
56
|
import { mapOpenAIResponseFinishReason } from './map-openai-responses-finish-reason';
|
|
48
57
|
import {
|
|
49
|
-
OpenAIResponsesChunk,
|
|
50
58
|
openaiResponsesChunkSchema,
|
|
51
|
-
OpenAIResponsesIncludeOptions,
|
|
52
|
-
OpenAIResponsesIncludeValue,
|
|
53
|
-
OpenAIResponsesLogprobs,
|
|
54
59
|
openaiResponsesResponseSchema,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
type OpenAIResponsesChunk,
|
|
61
|
+
type OpenAIResponsesIncludeOptions,
|
|
62
|
+
type OpenAIResponsesIncludeValue,
|
|
63
|
+
type OpenAIResponsesLogprobs,
|
|
64
|
+
type OpenAIResponsesWebSearchAction,
|
|
65
|
+
type OpenAIResponsesApplyPatchOperationDiffDeltaChunk,
|
|
66
|
+
type OpenAIResponsesApplyPatchOperationDiffDoneChunk,
|
|
58
67
|
} from './openai-responses-api';
|
|
59
68
|
import {
|
|
60
|
-
OpenAIResponsesModelId,
|
|
61
69
|
openaiLanguageModelResponsesOptionsSchema,
|
|
62
70
|
TOP_LOGPROBS_MAX,
|
|
63
|
-
|
|
71
|
+
type OpenAIResponsesModelId,
|
|
72
|
+
} from './openai-responses-language-model-options';
|
|
64
73
|
import { prepareResponsesTools } from './openai-responses-prepare-tools';
|
|
65
|
-
import {
|
|
74
|
+
import type {
|
|
75
|
+
ResponsesCompactionProviderMetadata,
|
|
66
76
|
ResponsesProviderMetadata,
|
|
67
77
|
ResponsesReasoningProviderMetadata,
|
|
68
78
|
ResponsesSourceDocumentProviderMetadata,
|
|
@@ -101,6 +111,20 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
101
111
|
|
|
102
112
|
private readonly config: OpenAIConfig;
|
|
103
113
|
|
|
114
|
+
static [WORKFLOW_SERIALIZE](model: OpenAIResponsesLanguageModel) {
|
|
115
|
+
return serializeModelOptions({
|
|
116
|
+
modelId: model.modelId,
|
|
117
|
+
config: model.config,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
122
|
+
modelId: OpenAIResponsesModelId;
|
|
123
|
+
config: OpenAIConfig;
|
|
124
|
+
}) {
|
|
125
|
+
return new OpenAIResponsesLanguageModel(options.modelId, options.config);
|
|
126
|
+
}
|
|
127
|
+
|
|
104
128
|
constructor(modelId: OpenAIResponsesModelId, config: OpenAIConfig) {
|
|
105
129
|
this.modelId = modelId;
|
|
106
130
|
this.config = config;
|
|
@@ -125,6 +149,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
125
149
|
frequencyPenalty,
|
|
126
150
|
seed,
|
|
127
151
|
prompt,
|
|
152
|
+
reasoning,
|
|
128
153
|
providerOptions,
|
|
129
154
|
tools,
|
|
130
155
|
toolChoice,
|
|
@@ -170,6 +195,10 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
170
195
|
});
|
|
171
196
|
}
|
|
172
197
|
|
|
198
|
+
const resolvedReasoningEffort =
|
|
199
|
+
openaiOptions?.reasoningEffort ??
|
|
200
|
+
(isCustomReasoning(reasoning) ? reasoning : undefined);
|
|
201
|
+
|
|
173
202
|
const isReasoningModel =
|
|
174
203
|
openaiOptions?.forceReasoning ?? modelCapabilities.isReasoningModel;
|
|
175
204
|
|
|
@@ -193,11 +222,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
193
222
|
'openai.web_search_preview': 'web_search_preview',
|
|
194
223
|
'openai.mcp': 'mcp',
|
|
195
224
|
'openai.apply_patch': 'apply_patch',
|
|
225
|
+
'openai.tool_search': 'tool_search',
|
|
196
226
|
},
|
|
197
|
-
resolveProviderToolName: tool =>
|
|
198
|
-
tool.id === 'openai.custom'
|
|
199
|
-
? (tool.args as { name?: string }).name
|
|
200
|
-
: undefined,
|
|
201
227
|
});
|
|
202
228
|
|
|
203
229
|
const customProviderToolNames = new Set<string>();
|
|
@@ -208,6 +234,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
208
234
|
} = await prepareResponsesTools({
|
|
209
235
|
tools,
|
|
210
236
|
toolChoice,
|
|
237
|
+
allowedTools: openaiOptions?.allowedTools ?? undefined,
|
|
211
238
|
toolNameMapping,
|
|
212
239
|
customProviderToolNames,
|
|
213
240
|
});
|
|
@@ -223,8 +250,11 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
223
250
|
: modelCapabilities.systemMessageMode),
|
|
224
251
|
providerOptionsName,
|
|
225
252
|
fileIdPrefixes: this.config.fileIdPrefixes,
|
|
253
|
+
passThroughUnsupportedFiles:
|
|
254
|
+
openaiOptions?.passThroughUnsupportedFiles ?? false,
|
|
226
255
|
store: openaiOptions?.store ?? true,
|
|
227
256
|
hasConversation: openaiOptions?.conversation != null,
|
|
257
|
+
hasPreviousResponseId: openaiOptions?.previousResponseId != null,
|
|
228
258
|
hasLocalShellTool: hasOpenAITool('openai.local_shell'),
|
|
229
259
|
hasShellTool: hasOpenAITool('openai.shell'),
|
|
230
260
|
hasApplyPatchTool: hasOpenAITool('openai.apply_patch'),
|
|
@@ -336,13 +366,21 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
336
366
|
top_logprobs: topLogprobs,
|
|
337
367
|
truncation: openaiOptions?.truncation,
|
|
338
368
|
|
|
369
|
+
// context management (server-side compaction):
|
|
370
|
+
...(openaiOptions?.contextManagement && {
|
|
371
|
+
context_management: openaiOptions.contextManagement.map(cm => ({
|
|
372
|
+
type: cm.type,
|
|
373
|
+
compact_threshold: cm.compactThreshold,
|
|
374
|
+
})),
|
|
375
|
+
}),
|
|
376
|
+
|
|
339
377
|
// model-specific settings:
|
|
340
378
|
...(isReasoningModel &&
|
|
341
|
-
(
|
|
379
|
+
(resolvedReasoningEffort != null ||
|
|
342
380
|
openaiOptions?.reasoningSummary != null) && {
|
|
343
381
|
reasoning: {
|
|
344
|
-
...(
|
|
345
|
-
effort:
|
|
382
|
+
...(resolvedReasoningEffort != null && {
|
|
383
|
+
effort: resolvedReasoningEffort,
|
|
346
384
|
}),
|
|
347
385
|
...(openaiOptions?.reasoningSummary != null && {
|
|
348
386
|
summary: openaiOptions.reasoningSummary,
|
|
@@ -358,7 +396,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
358
396
|
// https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility
|
|
359
397
|
if (
|
|
360
398
|
!(
|
|
361
|
-
|
|
399
|
+
resolvedReasoningEffort === 'none' &&
|
|
362
400
|
modelCapabilities.supportsNonReasoningParameters
|
|
363
401
|
)
|
|
364
402
|
) {
|
|
@@ -478,7 +516,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
478
516
|
rawValue: rawResponse,
|
|
479
517
|
} = await postJsonToApi({
|
|
480
518
|
url,
|
|
481
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
519
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
482
520
|
body,
|
|
483
521
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
484
522
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -505,6 +543,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
505
543
|
|
|
506
544
|
// flag that checks if there have been client-side tool calls (not executed by openai)
|
|
507
545
|
let hasFunctionCall = false;
|
|
546
|
+
const hostedToolSearchCallIds: string[] = [];
|
|
508
547
|
|
|
509
548
|
// map response content to content array (defined when there is no error)
|
|
510
549
|
for (const part of response.output!) {
|
|
@@ -551,6 +590,54 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
551
590
|
break;
|
|
552
591
|
}
|
|
553
592
|
|
|
593
|
+
case 'tool_search_call': {
|
|
594
|
+
const toolCallId = part.call_id ?? part.id;
|
|
595
|
+
const isHosted = part.execution === 'server';
|
|
596
|
+
|
|
597
|
+
if (isHosted) {
|
|
598
|
+
hostedToolSearchCallIds.push(toolCallId);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
content.push({
|
|
602
|
+
type: 'tool-call',
|
|
603
|
+
toolCallId,
|
|
604
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
605
|
+
input: JSON.stringify({
|
|
606
|
+
arguments: part.arguments,
|
|
607
|
+
call_id: part.call_id,
|
|
608
|
+
} satisfies InferSchema<typeof toolSearchInputSchema>),
|
|
609
|
+
...(isHosted ? { providerExecuted: true } : {}),
|
|
610
|
+
providerMetadata: {
|
|
611
|
+
[providerOptionsName]: {
|
|
612
|
+
itemId: part.id,
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
case 'tool_search_output': {
|
|
621
|
+
const toolCallId =
|
|
622
|
+
part.call_id ?? hostedToolSearchCallIds.shift() ?? part.id;
|
|
623
|
+
|
|
624
|
+
content.push({
|
|
625
|
+
type: 'tool-result',
|
|
626
|
+
toolCallId,
|
|
627
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
628
|
+
result: {
|
|
629
|
+
tools: part.tools,
|
|
630
|
+
} satisfies InferSchema<typeof toolSearchOutputSchema>,
|
|
631
|
+
providerMetadata: {
|
|
632
|
+
[providerOptionsName]: {
|
|
633
|
+
itemId: part.id,
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
break;
|
|
639
|
+
}
|
|
640
|
+
|
|
554
641
|
case 'local_shell_call': {
|
|
555
642
|
content.push({
|
|
556
643
|
type: 'tool-call',
|
|
@@ -721,6 +808,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
721
808
|
providerMetadata: {
|
|
722
809
|
[providerOptionsName]: {
|
|
723
810
|
itemId: part.id,
|
|
811
|
+
...(part.namespace != null && { namespace: part.namespace }),
|
|
724
812
|
},
|
|
725
813
|
},
|
|
726
814
|
});
|
|
@@ -927,6 +1015,21 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
927
1015
|
|
|
928
1016
|
break;
|
|
929
1017
|
}
|
|
1018
|
+
|
|
1019
|
+
case 'compaction': {
|
|
1020
|
+
content.push({
|
|
1021
|
+
type: 'custom',
|
|
1022
|
+
kind: 'openai.compaction',
|
|
1023
|
+
providerMetadata: {
|
|
1024
|
+
[providerOptionsName]: {
|
|
1025
|
+
type: 'compaction',
|
|
1026
|
+
itemId: part.id,
|
|
1027
|
+
encryptedContent: part.encrypted_content,
|
|
1028
|
+
} satisfies ResponsesCompactionProviderMetadata,
|
|
1029
|
+
},
|
|
1030
|
+
});
|
|
1031
|
+
break;
|
|
1032
|
+
}
|
|
930
1033
|
}
|
|
931
1034
|
}
|
|
932
1035
|
|
|
@@ -978,12 +1081,14 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
978
1081
|
isShellProviderExecuted,
|
|
979
1082
|
} = await this.getArgs(options);
|
|
980
1083
|
|
|
1084
|
+
const url = this.config.url({
|
|
1085
|
+
path: '/responses',
|
|
1086
|
+
modelId: this.modelId,
|
|
1087
|
+
});
|
|
1088
|
+
|
|
981
1089
|
const { responseHeaders, value: response } = await postJsonToApi({
|
|
982
|
-
url
|
|
983
|
-
|
|
984
|
-
modelId: this.modelId,
|
|
985
|
-
}),
|
|
986
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
1090
|
+
url,
|
|
1091
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
987
1092
|
body: {
|
|
988
1093
|
...body,
|
|
989
1094
|
stream: true,
|
|
@@ -996,6 +1101,19 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
996
1101
|
fetch: this.config.fetch,
|
|
997
1102
|
});
|
|
998
1103
|
|
|
1104
|
+
const checkedResponse = await throwIfOpenAIStreamErrorBeforeOutput({
|
|
1105
|
+
stream: response,
|
|
1106
|
+
getError: chunk =>
|
|
1107
|
+
isErrorChunk(chunk) ||
|
|
1108
|
+
(isResponseFailedChunk(chunk) && chunk.response.error != null)
|
|
1109
|
+
? chunk
|
|
1110
|
+
: undefined,
|
|
1111
|
+
isOutputChunk: isResponseOutputChunk,
|
|
1112
|
+
url,
|
|
1113
|
+
requestBodyValues: body,
|
|
1114
|
+
responseHeaders,
|
|
1115
|
+
});
|
|
1116
|
+
|
|
999
1117
|
const self = this;
|
|
1000
1118
|
|
|
1001
1119
|
const approvalRequestIdToDummyToolCallIdFromPrompt =
|
|
@@ -1026,6 +1144,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1026
1144
|
hasDiff: boolean;
|
|
1027
1145
|
endEmitted: boolean;
|
|
1028
1146
|
};
|
|
1147
|
+
toolSearchExecution?: 'server' | 'client';
|
|
1029
1148
|
}
|
|
1030
1149
|
| undefined
|
|
1031
1150
|
> = {};
|
|
@@ -1054,9 +1173,11 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1054
1173
|
> = {};
|
|
1055
1174
|
|
|
1056
1175
|
let serviceTier: string | undefined;
|
|
1176
|
+
const hostedToolSearchCallIds: string[] = [];
|
|
1177
|
+
let encounteredStreamError = false;
|
|
1057
1178
|
|
|
1058
|
-
|
|
1059
|
-
stream:
|
|
1179
|
+
const result = {
|
|
1180
|
+
stream: checkedResponse.pipeThrough(
|
|
1060
1181
|
new TransformStream<
|
|
1061
1182
|
ParseResult<OpenAIResponsesChunk>,
|
|
1062
1183
|
LanguageModelV4StreamPart
|
|
@@ -1188,6 +1309,28 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1188
1309
|
input: '{}',
|
|
1189
1310
|
providerExecuted: true,
|
|
1190
1311
|
});
|
|
1312
|
+
} else if (value.item.type === 'tool_search_call') {
|
|
1313
|
+
const toolCallId = value.item.id;
|
|
1314
|
+
const toolName =
|
|
1315
|
+
toolNameMapping.toCustomToolName('tool_search');
|
|
1316
|
+
const isHosted = value.item.execution === 'server';
|
|
1317
|
+
|
|
1318
|
+
ongoingToolCalls[value.output_index] = {
|
|
1319
|
+
toolName,
|
|
1320
|
+
toolCallId,
|
|
1321
|
+
toolSearchExecution: value.item.execution ?? 'server',
|
|
1322
|
+
};
|
|
1323
|
+
|
|
1324
|
+
if (isHosted) {
|
|
1325
|
+
controller.enqueue({
|
|
1326
|
+
type: 'tool-input-start',
|
|
1327
|
+
id: toolCallId,
|
|
1328
|
+
toolName,
|
|
1329
|
+
providerExecuted: true,
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
} else if (value.item.type === 'tool_search_output') {
|
|
1333
|
+
// handled on output_item.done so we can pair it with the call
|
|
1191
1334
|
} else if (
|
|
1192
1335
|
value.item.type === 'mcp_call' ||
|
|
1193
1336
|
value.item.type === 'mcp_list_tools' ||
|
|
@@ -1305,6 +1448,13 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1305
1448
|
controller.enqueue({
|
|
1306
1449
|
type: 'tool-input-end',
|
|
1307
1450
|
id: value.item.call_id,
|
|
1451
|
+
...(value.item.namespace != null && {
|
|
1452
|
+
providerMetadata: {
|
|
1453
|
+
[providerOptionsName]: {
|
|
1454
|
+
namespace: value.item.namespace,
|
|
1455
|
+
},
|
|
1456
|
+
},
|
|
1457
|
+
}),
|
|
1308
1458
|
});
|
|
1309
1459
|
|
|
1310
1460
|
controller.enqueue({
|
|
@@ -1315,6 +1465,9 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1315
1465
|
providerMetadata: {
|
|
1316
1466
|
[providerOptionsName]: {
|
|
1317
1467
|
itemId: value.item.id,
|
|
1468
|
+
...(value.item.namespace != null && {
|
|
1469
|
+
namespace: value.item.namespace,
|
|
1470
|
+
}),
|
|
1318
1471
|
},
|
|
1319
1472
|
},
|
|
1320
1473
|
});
|
|
@@ -1418,6 +1571,67 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1418
1571
|
result: value.item.result,
|
|
1419
1572
|
} satisfies InferSchema<typeof imageGenerationOutputSchema>,
|
|
1420
1573
|
});
|
|
1574
|
+
} else if (value.item.type === 'tool_search_call') {
|
|
1575
|
+
const toolCall = ongoingToolCalls[value.output_index];
|
|
1576
|
+
const isHosted = value.item.execution === 'server';
|
|
1577
|
+
|
|
1578
|
+
if (toolCall != null) {
|
|
1579
|
+
const toolCallId = isHosted
|
|
1580
|
+
? toolCall.toolCallId
|
|
1581
|
+
: (value.item.call_id ?? value.item.id);
|
|
1582
|
+
|
|
1583
|
+
if (isHosted) {
|
|
1584
|
+
hostedToolSearchCallIds.push(toolCallId);
|
|
1585
|
+
} else {
|
|
1586
|
+
controller.enqueue({
|
|
1587
|
+
type: 'tool-input-start',
|
|
1588
|
+
id: toolCallId,
|
|
1589
|
+
toolName: toolCall.toolName,
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
controller.enqueue({
|
|
1594
|
+
type: 'tool-input-end',
|
|
1595
|
+
id: toolCallId,
|
|
1596
|
+
});
|
|
1597
|
+
|
|
1598
|
+
controller.enqueue({
|
|
1599
|
+
type: 'tool-call',
|
|
1600
|
+
toolCallId,
|
|
1601
|
+
toolName: toolCall.toolName,
|
|
1602
|
+
input: JSON.stringify({
|
|
1603
|
+
arguments: value.item.arguments,
|
|
1604
|
+
call_id: isHosted ? null : toolCallId,
|
|
1605
|
+
} satisfies InferSchema<typeof toolSearchInputSchema>),
|
|
1606
|
+
...(isHosted ? { providerExecuted: true } : {}),
|
|
1607
|
+
providerMetadata: {
|
|
1608
|
+
[providerOptionsName]: {
|
|
1609
|
+
itemId: value.item.id,
|
|
1610
|
+
},
|
|
1611
|
+
},
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
ongoingToolCalls[value.output_index] = undefined;
|
|
1616
|
+
} else if (value.item.type === 'tool_search_output') {
|
|
1617
|
+
const toolCallId =
|
|
1618
|
+
value.item.call_id ??
|
|
1619
|
+
hostedToolSearchCallIds.shift() ??
|
|
1620
|
+
value.item.id;
|
|
1621
|
+
|
|
1622
|
+
controller.enqueue({
|
|
1623
|
+
type: 'tool-result',
|
|
1624
|
+
toolCallId,
|
|
1625
|
+
toolName: toolNameMapping.toCustomToolName('tool_search'),
|
|
1626
|
+
result: {
|
|
1627
|
+
tools: value.item.tools,
|
|
1628
|
+
} satisfies InferSchema<typeof toolSearchOutputSchema>,
|
|
1629
|
+
providerMetadata: {
|
|
1630
|
+
[providerOptionsName]: {
|
|
1631
|
+
itemId: value.item.id,
|
|
1632
|
+
},
|
|
1633
|
+
},
|
|
1634
|
+
});
|
|
1421
1635
|
} else if (value.item.type === 'mcp_call') {
|
|
1422
1636
|
ongoingToolCalls[value.output_index] = undefined;
|
|
1423
1637
|
|
|
@@ -1647,6 +1861,18 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1647
1861
|
}
|
|
1648
1862
|
|
|
1649
1863
|
delete activeReasoning[value.item.id];
|
|
1864
|
+
} else if (value.item.type === 'compaction') {
|
|
1865
|
+
controller.enqueue({
|
|
1866
|
+
type: 'custom',
|
|
1867
|
+
kind: 'openai.compaction',
|
|
1868
|
+
providerMetadata: {
|
|
1869
|
+
[providerOptionsName]: {
|
|
1870
|
+
type: 'compaction',
|
|
1871
|
+
itemId: value.item.id,
|
|
1872
|
+
encryptedContent: value.item.encrypted_content,
|
|
1873
|
+
} satisfies ResponsesCompactionProviderMetadata,
|
|
1874
|
+
},
|
|
1875
|
+
});
|
|
1650
1876
|
}
|
|
1651
1877
|
} else if (isResponseFunctionCallArgumentsDeltaChunk(value)) {
|
|
1652
1878
|
const toolCall = ongoingToolCalls[value.output_index];
|
|
@@ -1867,6 +2093,35 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1867
2093
|
if (typeof value.response.service_tier === 'string') {
|
|
1868
2094
|
serviceTier = value.response.service_tier;
|
|
1869
2095
|
}
|
|
2096
|
+
} else if (isResponseFailedChunk(value)) {
|
|
2097
|
+
const incompleteReason =
|
|
2098
|
+
value.response.incomplete_details?.reason;
|
|
2099
|
+
finishReason = {
|
|
2100
|
+
unified: incompleteReason
|
|
2101
|
+
? mapOpenAIResponseFinishReason({
|
|
2102
|
+
finishReason: incompleteReason,
|
|
2103
|
+
hasFunctionCall,
|
|
2104
|
+
})
|
|
2105
|
+
: 'error',
|
|
2106
|
+
raw: incompleteReason ?? 'error',
|
|
2107
|
+
};
|
|
2108
|
+
usage = value.response.usage ?? undefined;
|
|
2109
|
+
|
|
2110
|
+
if (!encounteredStreamError && value.response.error != null) {
|
|
2111
|
+
encounteredStreamError = true;
|
|
2112
|
+
controller.enqueue({
|
|
2113
|
+
type: 'error',
|
|
2114
|
+
error: {
|
|
2115
|
+
type: 'response.failed',
|
|
2116
|
+
sequence_number: value.sequence_number,
|
|
2117
|
+
response: {
|
|
2118
|
+
error: value.response.error,
|
|
2119
|
+
incomplete_details: value.response.incomplete_details,
|
|
2120
|
+
service_tier: value.response.service_tier,
|
|
2121
|
+
},
|
|
2122
|
+
},
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
1870
2125
|
} else if (isResponseAnnotationAddedChunk(value)) {
|
|
1871
2126
|
ongoingAnnotations.push(value.annotation);
|
|
1872
2127
|
if (value.annotation.type === 'url_citation') {
|
|
@@ -1936,6 +2191,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1936
2191
|
});
|
|
1937
2192
|
}
|
|
1938
2193
|
} else if (isErrorChunk(value)) {
|
|
2194
|
+
encounteredStreamError = true;
|
|
2195
|
+
finishReason = { unified: 'error', raw: 'error' };
|
|
1939
2196
|
controller.enqueue({ type: 'error', error: value });
|
|
1940
2197
|
}
|
|
1941
2198
|
},
|
|
@@ -1961,6 +2218,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1961
2218
|
request: { body },
|
|
1962
2219
|
response: { headers: responseHeaders },
|
|
1963
2220
|
};
|
|
2221
|
+
|
|
2222
|
+
return result;
|
|
1964
2223
|
}
|
|
1965
2224
|
}
|
|
1966
2225
|
|
|
@@ -1986,6 +2245,12 @@ function isResponseFinishedChunk(
|
|
|
1986
2245
|
);
|
|
1987
2246
|
}
|
|
1988
2247
|
|
|
2248
|
+
function isResponseFailedChunk(
|
|
2249
|
+
chunk: OpenAIResponsesChunk,
|
|
2250
|
+
): chunk is OpenAIResponsesChunk & { type: 'response.failed' } {
|
|
2251
|
+
return chunk.type === 'response.failed';
|
|
2252
|
+
}
|
|
2253
|
+
|
|
1989
2254
|
function isResponseCreatedChunk(
|
|
1990
2255
|
chunk: OpenAIResponsesChunk,
|
|
1991
2256
|
): chunk is OpenAIResponsesChunk & { type: 'response.created' } {
|
|
@@ -2064,6 +2329,15 @@ function isErrorChunk(
|
|
|
2064
2329
|
return chunk.type === 'error';
|
|
2065
2330
|
}
|
|
2066
2331
|
|
|
2332
|
+
function isResponseOutputChunk(chunk: OpenAIResponsesChunk): boolean {
|
|
2333
|
+
return !(
|
|
2334
|
+
chunk.type === 'response.created' ||
|
|
2335
|
+
chunk.type === 'response.failed' ||
|
|
2336
|
+
chunk.type === 'error' ||
|
|
2337
|
+
chunk.type === 'unknown_chunk'
|
|
2338
|
+
);
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2067
2341
|
function mapWebSearchOutput(
|
|
2068
2342
|
action: OpenAIResponsesWebSearchAction | null | undefined,
|
|
2069
2343
|
): InferSchema<typeof webSearchOutputSchema> {
|
|
@@ -2074,7 +2348,11 @@ function mapWebSearchOutput(
|
|
|
2074
2348
|
switch (action.type) {
|
|
2075
2349
|
case 'search':
|
|
2076
2350
|
return {
|
|
2077
|
-
action: {
|
|
2351
|
+
action: {
|
|
2352
|
+
type: 'search',
|
|
2353
|
+
query: action.query ?? undefined,
|
|
2354
|
+
...(action.queries != null && { queries: action.queries }),
|
|
2355
|
+
},
|
|
2078
2356
|
// include sources when provided by the Responses API (behind include flag)
|
|
2079
2357
|
...(action.sources != null && { sources: action.sources }),
|
|
2080
2358
|
};
|