@openai/agents-openai 0.5.4 → 0.7.0
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/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/metadata.js +3 -3
- package/dist/metadata.mjs +3 -3
- package/dist/openaiChatCompletionsConverter.d.ts +1 -0
- package/dist/openaiChatCompletionsConverter.js +122 -16
- package/dist/openaiChatCompletionsConverter.js.map +1 -1
- package/dist/openaiChatCompletionsConverter.mjs +121 -16
- package/dist/openaiChatCompletionsConverter.mjs.map +1 -1
- package/dist/openaiChatCompletionsModel.d.ts +2 -1
- package/dist/openaiChatCompletionsModel.js +20 -3
- package/dist/openaiChatCompletionsModel.js.map +1 -1
- package/dist/openaiChatCompletionsModel.mjs +22 -5
- package/dist/openaiChatCompletionsModel.mjs.map +1 -1
- package/dist/openaiResponsesModel.d.ts +19 -5
- package/dist/openaiResponsesModel.js +724 -74
- package/dist/openaiResponsesModel.js.map +1 -1
- package/dist/openaiResponsesModel.mjs +726 -76
- package/dist/openaiResponsesModel.mjs.map +1 -1
- package/dist/retryAdvice.d.ts +2 -0
- package/dist/retryAdvice.js +98 -0
- package/dist/retryAdvice.js.map +1 -0
- package/dist/retryAdvice.mjs +95 -0
- package/dist/retryAdvice.mjs.map +1 -0
- package/dist/tools.d.ts +22 -1
- package/dist/tools.js +38 -0
- package/dist/tools.js.map +1 -1
- package/dist/tools.mjs +37 -0
- package/dist/tools.mjs.map +1 -1
- package/dist/types/providerData.d.ts +4 -0
- package/dist/utils/providerData.d.ts +26 -2
- package/dist/utils/providerData.js +60 -8
- package/dist/utils/providerData.js.map +1 -1
- package/dist/utils/providerData.mjs +57 -8
- package/dist/utils/providerData.mjs.map +1 -1
- package/package.json +3 -3
|
@@ -11,6 +11,7 @@ exports.convertToOutputItem = convertToOutputItem;
|
|
|
11
11
|
const agents_core_1 = require("@openai/agents-core");
|
|
12
12
|
const openai_1 = __importDefault(require("openai"));
|
|
13
13
|
const logger_1 = __importDefault(require("./logger.js"));
|
|
14
|
+
const retryAdvice_1 = require("./retryAdvice.js");
|
|
14
15
|
const zod_1 = require("zod");
|
|
15
16
|
const defaults_1 = require("./defaults.js");
|
|
16
17
|
const responsesWebSocketConnection_1 = require("./responsesWebSocketConnection.js");
|
|
@@ -18,6 +19,106 @@ const responsesTransportUtils_1 = require("./responsesTransportUtils.js");
|
|
|
18
19
|
const tools_1 = require("./tools.js");
|
|
19
20
|
const providerData_1 = require("./utils/providerData.js");
|
|
20
21
|
const utils_1 = require("@openai/agents-core/utils");
|
|
22
|
+
/**
|
|
23
|
+
* Tool search outputs are replayed through agents-core protocol items, which use camelCase
|
|
24
|
+
* field names, while the Responses API wire shape uses snake_case. Keep this codec even with
|
|
25
|
+
* first-class upstream types because the local protocol still normalizes these payloads.
|
|
26
|
+
*/
|
|
27
|
+
function toOpenAIToolSearchOutputToolPayload(tool, _withinNamespace = false) {
|
|
28
|
+
if (!tool || typeof tool !== 'object' || Array.isArray(tool)) {
|
|
29
|
+
return tool;
|
|
30
|
+
}
|
|
31
|
+
if (tool.type === 'tool_reference' && typeof tool.functionName === 'string') {
|
|
32
|
+
return {
|
|
33
|
+
type: 'tool_reference',
|
|
34
|
+
function_name: tool.functionName,
|
|
35
|
+
...(typeof tool.namespace === 'string'
|
|
36
|
+
? { namespace: tool.namespace }
|
|
37
|
+
: {}),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (tool.type === 'namespace' && Array.isArray(tool.tools)) {
|
|
41
|
+
return {
|
|
42
|
+
...tool,
|
|
43
|
+
tools: tool.tools.map((entry) => toOpenAIToolSearchOutputToolPayload(entry, true)),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (tool.type === 'function') {
|
|
47
|
+
const { deferLoading, ...rest } = tool;
|
|
48
|
+
return {
|
|
49
|
+
...rest,
|
|
50
|
+
...(typeof deferLoading === 'boolean'
|
|
51
|
+
? { defer_loading: deferLoading }
|
|
52
|
+
: {}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return tool;
|
|
56
|
+
}
|
|
57
|
+
function fromOpenAIToolSearchOutputToolPayload(tool, _withinNamespace = false) {
|
|
58
|
+
if (!tool || typeof tool !== 'object' || Array.isArray(tool)) {
|
|
59
|
+
return tool;
|
|
60
|
+
}
|
|
61
|
+
if (tool.type === 'tool_reference' &&
|
|
62
|
+
typeof tool.function_name === 'string') {
|
|
63
|
+
return {
|
|
64
|
+
type: 'tool_reference',
|
|
65
|
+
functionName: tool.function_name,
|
|
66
|
+
...(typeof tool.namespace === 'string'
|
|
67
|
+
? { namespace: tool.namespace }
|
|
68
|
+
: {}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (tool.type === 'namespace' && Array.isArray(tool.tools)) {
|
|
72
|
+
return {
|
|
73
|
+
...tool,
|
|
74
|
+
tools: tool.tools.map((entry) => fromOpenAIToolSearchOutputToolPayload(entry, true)),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
if (tool.type === 'function') {
|
|
78
|
+
const { defer_loading, ...rest } = tool;
|
|
79
|
+
return {
|
|
80
|
+
...rest,
|
|
81
|
+
...(typeof defer_loading === 'boolean'
|
|
82
|
+
? { deferLoading: defer_loading }
|
|
83
|
+
: {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return tool;
|
|
87
|
+
}
|
|
88
|
+
function isNeverSentWebSocketError(error) {
|
|
89
|
+
if ((0, responsesWebSocketConnection_1.isWebSocketNotOpenError)(error)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
const errorCause = error instanceof Error
|
|
93
|
+
? error.cause
|
|
94
|
+
: undefined;
|
|
95
|
+
if (error instanceof responsesWebSocketConnection_1.ResponsesWebSocketInternalError &&
|
|
96
|
+
error.code === 'connection_closed_before_opening') {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
if (errorCause instanceof responsesWebSocketConnection_1.ResponsesWebSocketInternalError &&
|
|
100
|
+
errorCause.code === 'connection_closed_before_opening') {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
function isAmbiguousWebSocketReplayError(error) {
|
|
106
|
+
if (error instanceof responsesWebSocketConnection_1.ResponsesWebSocketInternalError &&
|
|
107
|
+
error.code === 'connection_closed_before_terminal_response_event') {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
const errorCause = error instanceof Error
|
|
111
|
+
? error.cause
|
|
112
|
+
: undefined;
|
|
113
|
+
return (errorCause instanceof responsesWebSocketConnection_1.ResponsesWebSocketInternalError &&
|
|
114
|
+
errorCause.code === 'connection_closed_before_terminal_response_event');
|
|
115
|
+
}
|
|
116
|
+
function hasSerializedComputerDisplayMetadata(tool) {
|
|
117
|
+
return (typeof tool.environment === 'string' &&
|
|
118
|
+
Array.isArray(tool.dimensions) &&
|
|
119
|
+
tool.dimensions.length === 2 &&
|
|
120
|
+
tool.dimensions.every((value) => typeof value === 'number'));
|
|
121
|
+
}
|
|
21
122
|
const HostedToolChoice = zod_1.z.enum([
|
|
22
123
|
'file_search',
|
|
23
124
|
'web_search',
|
|
@@ -26,12 +127,16 @@ const HostedToolChoice = zod_1.z.enum([
|
|
|
26
127
|
'image_generation',
|
|
27
128
|
'mcp',
|
|
28
129
|
// Specialized local tools
|
|
29
|
-
'computer_use_preview',
|
|
30
130
|
'shell',
|
|
31
131
|
'apply_patch',
|
|
32
132
|
]);
|
|
33
133
|
const DefaultToolChoice = zod_1.z.enum(['auto', 'required', 'none']);
|
|
34
|
-
|
|
134
|
+
const BuiltinComputerToolChoice = zod_1.z.enum([
|
|
135
|
+
'computer',
|
|
136
|
+
'computer_use',
|
|
137
|
+
'computer_use_preview',
|
|
138
|
+
]);
|
|
139
|
+
function getToolChoice(toolChoice, options) {
|
|
35
140
|
if (typeof toolChoice === 'undefined') {
|
|
36
141
|
return undefined;
|
|
37
142
|
}
|
|
@@ -39,12 +144,202 @@ function getToolChoice(toolChoice) {
|
|
|
39
144
|
if (resultDefaultCheck.success) {
|
|
40
145
|
return resultDefaultCheck.data;
|
|
41
146
|
}
|
|
147
|
+
const builtinComputerToolChoice = BuiltinComputerToolChoice.safeParse(toolChoice);
|
|
148
|
+
if (builtinComputerToolChoice.success) {
|
|
149
|
+
if (hasBuiltinComputerTool(options?.tools) ||
|
|
150
|
+
options?.allowPromptSuppliedComputerTool === true) {
|
|
151
|
+
return getBuiltinComputerToolChoice(builtinComputerToolChoice.data, {
|
|
152
|
+
model: options?.model,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (builtinComputerToolChoice.data === 'computer_use_preview') {
|
|
156
|
+
return { type: 'computer_use_preview' };
|
|
157
|
+
}
|
|
158
|
+
return { type: 'function', name: builtinComputerToolChoice.data };
|
|
159
|
+
}
|
|
42
160
|
const result = HostedToolChoice.safeParse(toolChoice);
|
|
43
161
|
if (result.success) {
|
|
44
162
|
return { type: result.data };
|
|
45
163
|
}
|
|
46
164
|
return { type: 'function', name: toolChoice };
|
|
47
165
|
}
|
|
166
|
+
function normalizeToolSearchStatus(status) {
|
|
167
|
+
return status === 'in_progress' ||
|
|
168
|
+
status === 'completed' ||
|
|
169
|
+
status === 'incomplete'
|
|
170
|
+
? status
|
|
171
|
+
: null;
|
|
172
|
+
}
|
|
173
|
+
function hasBuiltinComputerTool(tools) {
|
|
174
|
+
return (tools ?? []).some((tool) => tool.type === 'computer' ||
|
|
175
|
+
tool.type === 'computer_use' ||
|
|
176
|
+
tool.type === 'computer_use_preview');
|
|
177
|
+
}
|
|
178
|
+
function isPreviewComputerModel(model) {
|
|
179
|
+
return typeof model === 'string' && model.startsWith('computer-use-preview');
|
|
180
|
+
}
|
|
181
|
+
function shouldUsePreviewComputerTool(options) {
|
|
182
|
+
if (isPreviewComputerModel(options?.model)) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
if (typeof options?.model === 'string') {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
if (options?.toolChoice === 'computer' ||
|
|
189
|
+
options?.toolChoice === 'computer_use') {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
function getBuiltinComputerToolChoice(toolChoice, options) {
|
|
195
|
+
if (shouldUsePreviewComputerTool({
|
|
196
|
+
model: options?.model,
|
|
197
|
+
toolChoice,
|
|
198
|
+
})) {
|
|
199
|
+
return { type: 'computer_use_preview' };
|
|
200
|
+
}
|
|
201
|
+
if (toolChoice === 'computer_use') {
|
|
202
|
+
return { type: 'computer_use' };
|
|
203
|
+
}
|
|
204
|
+
return { type: 'computer' };
|
|
205
|
+
}
|
|
206
|
+
function isBuiltinComputerToolType(type) {
|
|
207
|
+
return (type === 'computer' ||
|
|
208
|
+
type === 'computer_use' ||
|
|
209
|
+
type === 'computer_use_preview');
|
|
210
|
+
}
|
|
211
|
+
function isCompatibleBuiltinComputerToolChoice(toolChoiceType, toolType) {
|
|
212
|
+
if (!isBuiltinComputerToolType(toolChoiceType)) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
if (toolChoiceType === 'computer_use_preview') {
|
|
216
|
+
return toolType === 'computer_use_preview';
|
|
217
|
+
}
|
|
218
|
+
return toolType === 'computer';
|
|
219
|
+
}
|
|
220
|
+
function isToolChoiceAvailable(toolChoice, tools) {
|
|
221
|
+
if (toolChoice === 'auto' || toolChoice === 'none') {
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
if (toolChoice === 'required') {
|
|
225
|
+
return tools.length > 0;
|
|
226
|
+
}
|
|
227
|
+
if (toolChoice.type === 'function') {
|
|
228
|
+
return hasFunctionToolChoiceName(toolChoice.name, tools);
|
|
229
|
+
}
|
|
230
|
+
return tools.some((tool) => isCompatibleBuiltinComputerToolChoice(toolChoice.type, tool.type)
|
|
231
|
+
? true
|
|
232
|
+
: tool.type === toolChoice.type);
|
|
233
|
+
}
|
|
234
|
+
function hasFunctionToolChoiceName(toolChoiceName, tools, namespacePrefix) {
|
|
235
|
+
return (findFunctionToolChoice(toolChoiceName, tools, namespacePrefix) !== undefined);
|
|
236
|
+
}
|
|
237
|
+
function findFunctionToolChoice(toolChoiceName, tools, namespacePrefix) {
|
|
238
|
+
for (const tool of tools) {
|
|
239
|
+
if (isNamedFunctionTool(tool)) {
|
|
240
|
+
const qualifiedName = namespacePrefix
|
|
241
|
+
? `${namespacePrefix}.${tool.name}`
|
|
242
|
+
: tool.name;
|
|
243
|
+
if (toolChoiceName === qualifiedName) {
|
|
244
|
+
return tool;
|
|
245
|
+
}
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (isNamespaceTool(tool)) {
|
|
249
|
+
const nestedNamespace = namespacePrefix
|
|
250
|
+
? `${namespacePrefix}.${tool.name}`
|
|
251
|
+
: tool.name;
|
|
252
|
+
const matchedTool = findFunctionToolChoice(toolChoiceName, tool.tools, nestedNamespace);
|
|
253
|
+
if (matchedTool) {
|
|
254
|
+
return matchedTool;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
function collectAvailableToolChoiceNames(tools, namespacePrefix) {
|
|
261
|
+
const availableToolChoices = [];
|
|
262
|
+
for (const tool of tools) {
|
|
263
|
+
if (isNamedFunctionTool(tool)) {
|
|
264
|
+
availableToolChoices.push(namespacePrefix ? `${namespacePrefix}.${tool.name}` : tool.name);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (isNamespaceTool(tool)) {
|
|
268
|
+
const nestedNamespace = namespacePrefix
|
|
269
|
+
? `${namespacePrefix}.${tool.name}`
|
|
270
|
+
: tool.name;
|
|
271
|
+
availableToolChoices.push(...collectAvailableToolChoiceNames(tool.tools, nestedNamespace));
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
availableToolChoices.push(tool.type);
|
|
275
|
+
}
|
|
276
|
+
return availableToolChoices;
|
|
277
|
+
}
|
|
278
|
+
function isNamedFunctionTool(tool) {
|
|
279
|
+
return (tool.type === 'function' &&
|
|
280
|
+
typeof tool.name === 'string');
|
|
281
|
+
}
|
|
282
|
+
function isNamespaceTool(tool) {
|
|
283
|
+
const candidate = tool;
|
|
284
|
+
return (tool.type === 'namespace' &&
|
|
285
|
+
typeof candidate.name === 'string' &&
|
|
286
|
+
Array.isArray(candidate.tools));
|
|
287
|
+
}
|
|
288
|
+
function getExtraBodyToolsForToolChoiceValidation(extraBody) {
|
|
289
|
+
if (!extraBody || !Array.isArray(extraBody.tools)) {
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
return extraBody.tools;
|
|
293
|
+
}
|
|
294
|
+
function assertSupportedToolChoice(toolChoice, tools, options) {
|
|
295
|
+
const allowPromptSuppliedTools = options?.allowPromptSuppliedTools === true;
|
|
296
|
+
if (!toolChoice ||
|
|
297
|
+
toolChoice === 'auto' ||
|
|
298
|
+
toolChoice === 'required' ||
|
|
299
|
+
toolChoice === 'none' ||
|
|
300
|
+
toolChoice.type !== 'function') {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const matchedFunctionTool = findFunctionToolChoice(toolChoice.name, tools);
|
|
304
|
+
if (!matchedFunctionTool &&
|
|
305
|
+
allowPromptSuppliedTools &&
|
|
306
|
+
toolChoice.name !== 'tool_search') {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (matchedFunctionTool
|
|
310
|
+
?.defer_loading === true) {
|
|
311
|
+
throw new agents_core_1.UserError(`modelSettings.toolChoice="${toolChoice.name}" cannot force a deferred function tool in Responses. Use "auto" so tool_search can load it.`);
|
|
312
|
+
}
|
|
313
|
+
if (toolChoice.name === 'tool_search' &&
|
|
314
|
+
!hasFunctionToolChoiceName(toolChoice.name, tools)) {
|
|
315
|
+
throw new agents_core_1.UserError('modelSettings.toolChoice="tool_search" is only supported for a custom function named "tool_search". Responses does not support forcing the built-in tool_search tool. Use "auto" instead.');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function getCompatibleToolChoice(toolChoice, tools, options) {
|
|
319
|
+
const allowPromptSuppliedTools = options?.allowPromptSuppliedTools === true;
|
|
320
|
+
if (typeof toolChoice === 'undefined') {
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
if (isToolChoiceAvailable(toolChoice, tools) || allowPromptSuppliedTools) {
|
|
324
|
+
return toolChoice;
|
|
325
|
+
}
|
|
326
|
+
const availableToolChoices = [
|
|
327
|
+
...new Set(collectAvailableToolChoiceNames(tools)),
|
|
328
|
+
];
|
|
329
|
+
const availableToolChoicesMessage = availableToolChoices.length > 0
|
|
330
|
+
? ` Available tools: ${availableToolChoices.join(', ')}.`
|
|
331
|
+
: ' No tools are available in the outgoing Responses request.';
|
|
332
|
+
if (toolChoice === 'required') {
|
|
333
|
+
throw new agents_core_1.UserError(`modelSettings.toolChoice="required" requires at least one available tool in the outgoing Responses request.${availableToolChoicesMessage}`);
|
|
334
|
+
}
|
|
335
|
+
if (toolChoice === 'auto' || toolChoice === 'none') {
|
|
336
|
+
throw new Error(`Unexpected unavailable tool choice: ${JSON.stringify(toolChoice)}`);
|
|
337
|
+
}
|
|
338
|
+
if (toolChoice.type === 'function') {
|
|
339
|
+
throw new agents_core_1.UserError(`modelSettings.toolChoice="${toolChoice.name}" does not match any available tool in the outgoing Responses request.${availableToolChoicesMessage}`);
|
|
340
|
+
}
|
|
341
|
+
throw new agents_core_1.UserError(`modelSettings.toolChoice="${toolChoice.type}" is unavailable in the outgoing Responses request.${availableToolChoicesMessage}`);
|
|
342
|
+
}
|
|
48
343
|
function getResponseFormat(outputType, otherProperties) {
|
|
49
344
|
if (outputType === 'text') {
|
|
50
345
|
return otherProperties;
|
|
@@ -98,12 +393,13 @@ function convertLegacyToolOutputContent(output) {
|
|
|
98
393
|
const legacyImageUrl = output.imageUrl;
|
|
99
394
|
const legacyFileId = output.fileId;
|
|
100
395
|
const dataValue = output.data;
|
|
396
|
+
const topLevelInlineMediaType = getImageInlineMediaType(output);
|
|
101
397
|
if (typeof output.image === 'string' && output.image.length > 0) {
|
|
102
398
|
structured.image = output.image;
|
|
103
399
|
}
|
|
104
400
|
else if (isRecord(output.image)) {
|
|
105
401
|
const imageObj = output.image;
|
|
106
|
-
const inlineMediaType = getImageInlineMediaType(imageObj);
|
|
402
|
+
const inlineMediaType = getImageInlineMediaType(imageObj) ?? topLevelInlineMediaType;
|
|
107
403
|
if (typeof imageObj.url === 'string' && imageObj.url.length > 0) {
|
|
108
404
|
structured.image = imageObj.url;
|
|
109
405
|
}
|
|
@@ -143,7 +439,7 @@ function convertLegacyToolOutputContent(output) {
|
|
|
143
439
|
base64Data = (0, utils_1.encodeUint8ArrayToBase64)(dataValue);
|
|
144
440
|
}
|
|
145
441
|
if (base64Data) {
|
|
146
|
-
structured.image = base64Data;
|
|
442
|
+
structured.image = formatInlineData(base64Data, topLevelInlineMediaType);
|
|
147
443
|
}
|
|
148
444
|
}
|
|
149
445
|
if (output.providerData) {
|
|
@@ -388,9 +684,16 @@ function getImageInlineMediaType(source) {
|
|
|
388
684
|
if (typeof source.mediaType === 'string' && source.mediaType.length > 0) {
|
|
389
685
|
return source.mediaType;
|
|
390
686
|
}
|
|
687
|
+
if (typeof source.mimeType === 'string' &&
|
|
688
|
+
source.mimeType.length > 0) {
|
|
689
|
+
return source.mimeType;
|
|
690
|
+
}
|
|
391
691
|
return undefined;
|
|
392
692
|
}
|
|
393
693
|
function formatInlineData(data, mediaType) {
|
|
694
|
+
if (typeof data === 'string' && data.startsWith('data:')) {
|
|
695
|
+
return data;
|
|
696
|
+
}
|
|
394
697
|
const base64 = typeof data === 'string' ? data : (0, utils_1.encodeUint8ArrayToBase64)(data);
|
|
395
698
|
return mediaType ? `data:${mediaType};base64,${base64}` : base64;
|
|
396
699
|
}
|
|
@@ -507,11 +810,70 @@ function toOpenAIShellEnvironment(environment) {
|
|
|
507
810
|
}
|
|
508
811
|
throw new agents_core_1.UserError(`Unsupported shell environment type: ${String(environment.type)}`);
|
|
509
812
|
}
|
|
510
|
-
function getTools(tools, handoffs) {
|
|
813
|
+
function getTools(tools, handoffs, options) {
|
|
511
814
|
const openaiTools = [];
|
|
512
815
|
const include = [];
|
|
816
|
+
const namespaceStateByName = new Map();
|
|
817
|
+
let hasDeferredSearchableTool = false;
|
|
818
|
+
let hasToolSearch = false;
|
|
819
|
+
const usePreviewComputerTool = shouldUsePreviewComputerTool({
|
|
820
|
+
model: options?.model,
|
|
821
|
+
toolChoice: options?.toolChoice,
|
|
822
|
+
});
|
|
513
823
|
for (const tool of tools) {
|
|
514
|
-
|
|
824
|
+
if (tool.type === 'function') {
|
|
825
|
+
const isDeferredFunction = tool.deferLoading === true;
|
|
826
|
+
hasDeferredSearchableTool ||= isDeferredFunction;
|
|
827
|
+
const namespaceName = typeof tool.namespace === 'string' ? tool.namespace.trim() : '';
|
|
828
|
+
if (namespaceName.length > 0) {
|
|
829
|
+
const namespaceDescription = typeof tool.namespaceDescription === 'string'
|
|
830
|
+
? tool.namespaceDescription.trim()
|
|
831
|
+
: '';
|
|
832
|
+
if (namespaceDescription.length === 0) {
|
|
833
|
+
throw new agents_core_1.UserError(`All tools in namespace "${namespaceName}" must provide a non-empty description.`);
|
|
834
|
+
}
|
|
835
|
+
let namespaceState = namespaceStateByName.get(namespaceName);
|
|
836
|
+
if (!namespaceState) {
|
|
837
|
+
namespaceState = {
|
|
838
|
+
index: openaiTools.length,
|
|
839
|
+
description: namespaceDescription,
|
|
840
|
+
functionNames: new Set(),
|
|
841
|
+
tools: [],
|
|
842
|
+
};
|
|
843
|
+
namespaceStateByName.set(namespaceName, namespaceState);
|
|
844
|
+
openaiTools.push({});
|
|
845
|
+
}
|
|
846
|
+
else if (namespaceState.description !== namespaceDescription) {
|
|
847
|
+
throw new agents_core_1.UserError(`All tools in namespace "${namespaceName}" must share the same description.`);
|
|
848
|
+
}
|
|
849
|
+
const { tool: openaiTool, include: openaiIncludes } = converTool(tool, {
|
|
850
|
+
usePreviewComputerTool,
|
|
851
|
+
});
|
|
852
|
+
if (namespaceState.functionNames.has(tool.name)) {
|
|
853
|
+
throw new agents_core_1.UserError(`Namespace "${namespaceName}" cannot contain duplicate function tool name "${tool.name}".`);
|
|
854
|
+
}
|
|
855
|
+
namespaceState.functionNames.add(tool.name);
|
|
856
|
+
namespaceState.tools.push(openaiTool);
|
|
857
|
+
if (openaiIncludes && openaiIncludes.length > 0) {
|
|
858
|
+
for (const item of openaiIncludes) {
|
|
859
|
+
include.push(item);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
continue;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
if (tool.type === 'hosted_tool' &&
|
|
866
|
+
tool.providerData?.type === 'tool_search') {
|
|
867
|
+
hasToolSearch = true;
|
|
868
|
+
}
|
|
869
|
+
if (tool.type === 'hosted_tool' &&
|
|
870
|
+
tool.providerData?.type === 'mcp' &&
|
|
871
|
+
tool.providerData.defer_loading === true) {
|
|
872
|
+
hasDeferredSearchableTool = true;
|
|
873
|
+
}
|
|
874
|
+
const { tool: openaiTool, include: openaiIncludes } = converTool(tool, {
|
|
875
|
+
usePreviewComputerTool,
|
|
876
|
+
});
|
|
515
877
|
openaiTools.push(openaiTool);
|
|
516
878
|
if (openaiIncludes && openaiIncludes.length > 0) {
|
|
517
879
|
for (const item of openaiIncludes) {
|
|
@@ -519,31 +881,57 @@ function getTools(tools, handoffs) {
|
|
|
519
881
|
}
|
|
520
882
|
}
|
|
521
883
|
}
|
|
884
|
+
if (hasDeferredSearchableTool && !hasToolSearch) {
|
|
885
|
+
throw new agents_core_1.UserError('Deferred function tools and hosted MCP tools with deferLoading: true require toolSearchTool() in the same request.');
|
|
886
|
+
}
|
|
887
|
+
for (const [namespaceName, namespaceState,] of namespaceStateByName.entries()) {
|
|
888
|
+
openaiTools[namespaceState.index] = {
|
|
889
|
+
type: 'namespace',
|
|
890
|
+
name: namespaceName,
|
|
891
|
+
description: namespaceState.description,
|
|
892
|
+
tools: namespaceState.tools,
|
|
893
|
+
};
|
|
894
|
+
}
|
|
522
895
|
return {
|
|
523
896
|
tools: [...openaiTools, ...handoffs.map(getHandoffTool)],
|
|
524
897
|
include,
|
|
525
898
|
};
|
|
526
899
|
}
|
|
527
|
-
function converTool(tool) {
|
|
900
|
+
function converTool(tool, options) {
|
|
528
901
|
if (tool.type === 'function') {
|
|
902
|
+
const openaiTool = {
|
|
903
|
+
type: 'function',
|
|
904
|
+
name: tool.name,
|
|
905
|
+
description: tool.description,
|
|
906
|
+
parameters: tool.parameters,
|
|
907
|
+
strict: tool.strict,
|
|
908
|
+
};
|
|
909
|
+
if (tool.deferLoading) {
|
|
910
|
+
openaiTool.defer_loading = true;
|
|
911
|
+
}
|
|
529
912
|
return {
|
|
530
|
-
tool:
|
|
531
|
-
type: 'function',
|
|
532
|
-
name: tool.name,
|
|
533
|
-
description: tool.description,
|
|
534
|
-
parameters: tool.parameters,
|
|
535
|
-
strict: tool.strict,
|
|
536
|
-
},
|
|
913
|
+
tool: openaiTool,
|
|
537
914
|
include: undefined,
|
|
538
915
|
};
|
|
539
916
|
}
|
|
540
917
|
else if (tool.type === 'computer') {
|
|
918
|
+
if (options?.usePreviewComputerTool) {
|
|
919
|
+
if (!hasSerializedComputerDisplayMetadata(tool)) {
|
|
920
|
+
throw new agents_core_1.UserError('Preview computer tools require environment and dimensions. Provide them on your Computer implementation or target a GA computer model such as gpt-5.4.');
|
|
921
|
+
}
|
|
922
|
+
return {
|
|
923
|
+
tool: {
|
|
924
|
+
type: 'computer_use_preview',
|
|
925
|
+
environment: tool.environment,
|
|
926
|
+
display_width: tool.dimensions[0],
|
|
927
|
+
display_height: tool.dimensions[1],
|
|
928
|
+
},
|
|
929
|
+
include: undefined,
|
|
930
|
+
};
|
|
931
|
+
}
|
|
541
932
|
return {
|
|
542
933
|
tool: {
|
|
543
|
-
type: '
|
|
544
|
-
environment: tool.environment,
|
|
545
|
-
display_width: tool.dimensions[0],
|
|
546
|
-
display_height: tool.dimensions[1],
|
|
934
|
+
type: 'computer',
|
|
547
935
|
},
|
|
548
936
|
include: undefined,
|
|
549
937
|
};
|
|
@@ -614,6 +1002,17 @@ function converTool(tool) {
|
|
|
614
1002
|
include: undefined,
|
|
615
1003
|
};
|
|
616
1004
|
}
|
|
1005
|
+
else if (tool.providerData?.type === 'tool_search') {
|
|
1006
|
+
return {
|
|
1007
|
+
tool: {
|
|
1008
|
+
type: 'tool_search',
|
|
1009
|
+
execution: tool.providerData.execution,
|
|
1010
|
+
description: tool.providerData.description,
|
|
1011
|
+
parameters: tool.providerData.parameters,
|
|
1012
|
+
},
|
|
1013
|
+
include: undefined,
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
617
1016
|
else if (tool.providerData?.type === 'image_generation') {
|
|
618
1017
|
return {
|
|
619
1018
|
tool: {
|
|
@@ -633,17 +1032,22 @@ function converTool(tool) {
|
|
|
633
1032
|
};
|
|
634
1033
|
}
|
|
635
1034
|
else if (tool.providerData?.type === 'mcp') {
|
|
1035
|
+
const openaiTool = {
|
|
1036
|
+
type: 'mcp',
|
|
1037
|
+
server_label: tool.providerData.server_label,
|
|
1038
|
+
server_url: tool.providerData.server_url,
|
|
1039
|
+
connector_id: tool.providerData.connector_id,
|
|
1040
|
+
authorization: tool.providerData.authorization,
|
|
1041
|
+
allowed_tools: tool.providerData.allowed_tools,
|
|
1042
|
+
headers: tool.providerData.headers,
|
|
1043
|
+
require_approval: convertMCPRequireApproval(tool.providerData.require_approval),
|
|
1044
|
+
server_description: tool.providerData.server_description,
|
|
1045
|
+
};
|
|
1046
|
+
if (tool.providerData.defer_loading === true) {
|
|
1047
|
+
openaiTool.defer_loading = true;
|
|
1048
|
+
}
|
|
636
1049
|
return {
|
|
637
|
-
tool:
|
|
638
|
-
type: 'mcp',
|
|
639
|
-
server_label: tool.providerData.server_label,
|
|
640
|
-
server_url: tool.providerData.server_url,
|
|
641
|
-
connector_id: tool.providerData.connector_id,
|
|
642
|
-
authorization: tool.providerData.authorization,
|
|
643
|
-
allowed_tools: tool.providerData.allowed_tools,
|
|
644
|
-
headers: tool.providerData.headers,
|
|
645
|
-
require_approval: convertMCPRequireApproval(tool.providerData.require_approval),
|
|
646
|
-
},
|
|
1050
|
+
tool: openaiTool,
|
|
647
1051
|
include: undefined,
|
|
648
1052
|
};
|
|
649
1053
|
}
|
|
@@ -682,7 +1086,10 @@ function getInputMessageContent(entry) {
|
|
|
682
1086
|
return {
|
|
683
1087
|
type: 'input_text',
|
|
684
1088
|
text: entry.text,
|
|
685
|
-
...(0, providerData_1.
|
|
1089
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(entry.providerData, [
|
|
1090
|
+
'type',
|
|
1091
|
+
'text',
|
|
1092
|
+
]),
|
|
686
1093
|
};
|
|
687
1094
|
}
|
|
688
1095
|
else if (entry.type === 'input_image') {
|
|
@@ -704,7 +1111,12 @@ function getInputMessageContent(entry) {
|
|
|
704
1111
|
}
|
|
705
1112
|
return {
|
|
706
1113
|
...imageEntry,
|
|
707
|
-
...(0, providerData_1.
|
|
1114
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(entry.providerData, [
|
|
1115
|
+
'type',
|
|
1116
|
+
'detail',
|
|
1117
|
+
'image_url',
|
|
1118
|
+
'file_id',
|
|
1119
|
+
]),
|
|
708
1120
|
};
|
|
709
1121
|
}
|
|
710
1122
|
else if (entry.type === 'input_file') {
|
|
@@ -749,25 +1161,54 @@ function getInputMessageContent(entry) {
|
|
|
749
1161
|
}
|
|
750
1162
|
return {
|
|
751
1163
|
...fileEntry,
|
|
752
|
-
...(0, providerData_1.
|
|
1164
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(entry.providerData, [
|
|
1165
|
+
'type',
|
|
1166
|
+
'file_data',
|
|
1167
|
+
'file_url',
|
|
1168
|
+
'file_id',
|
|
1169
|
+
'filename',
|
|
1170
|
+
]),
|
|
753
1171
|
};
|
|
754
1172
|
}
|
|
755
1173
|
throw new agents_core_1.UserError(`Unsupported input content type: ${JSON.stringify(entry)}`);
|
|
756
1174
|
}
|
|
1175
|
+
function getProviderDataField(providerData, keys) {
|
|
1176
|
+
if (!providerData ||
|
|
1177
|
+
typeof providerData !== 'object' ||
|
|
1178
|
+
Array.isArray(providerData)) {
|
|
1179
|
+
return undefined;
|
|
1180
|
+
}
|
|
1181
|
+
const record = providerData;
|
|
1182
|
+
for (const key of keys) {
|
|
1183
|
+
if (typeof record[key] !== 'undefined') {
|
|
1184
|
+
return record[key];
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
return undefined;
|
|
1188
|
+
}
|
|
757
1189
|
function getOutputMessageContent(entry) {
|
|
758
1190
|
if (entry.type === 'output_text') {
|
|
1191
|
+
const annotations = getProviderDataField(entry.providerData, ['annotations']);
|
|
1192
|
+
const normalizedAnnotations = Array.isArray(annotations) ? annotations : [];
|
|
759
1193
|
return {
|
|
760
1194
|
type: 'output_text',
|
|
761
1195
|
text: entry.text,
|
|
762
|
-
annotations:
|
|
763
|
-
...(0, providerData_1.
|
|
1196
|
+
annotations: normalizedAnnotations,
|
|
1197
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(entry.providerData, [
|
|
1198
|
+
'type',
|
|
1199
|
+
'text',
|
|
1200
|
+
'annotations',
|
|
1201
|
+
]),
|
|
764
1202
|
};
|
|
765
1203
|
}
|
|
766
1204
|
if (entry.type === 'refusal') {
|
|
767
1205
|
return {
|
|
768
1206
|
type: 'refusal',
|
|
769
1207
|
refusal: entry.refusal,
|
|
770
|
-
...(0, providerData_1.
|
|
1208
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(entry.providerData, [
|
|
1209
|
+
'type',
|
|
1210
|
+
'refusal',
|
|
1211
|
+
]),
|
|
771
1212
|
};
|
|
772
1213
|
}
|
|
773
1214
|
throw new agents_core_1.UserError(`Unsupported output content type: ${JSON.stringify(entry)}`);
|
|
@@ -778,7 +1219,11 @@ function getMessageItem(item) {
|
|
|
778
1219
|
id: item.id,
|
|
779
1220
|
role: 'system',
|
|
780
1221
|
content: item.content,
|
|
781
|
-
...(0, providerData_1.
|
|
1222
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1223
|
+
'id',
|
|
1224
|
+
'role',
|
|
1225
|
+
'content',
|
|
1226
|
+
]),
|
|
782
1227
|
};
|
|
783
1228
|
}
|
|
784
1229
|
if (item.role === 'user') {
|
|
@@ -787,14 +1232,22 @@ function getMessageItem(item) {
|
|
|
787
1232
|
id: item.id,
|
|
788
1233
|
role: 'user',
|
|
789
1234
|
content: item.content,
|
|
790
|
-
...(0, providerData_1.
|
|
1235
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1236
|
+
'id',
|
|
1237
|
+
'role',
|
|
1238
|
+
'content',
|
|
1239
|
+
]),
|
|
791
1240
|
};
|
|
792
1241
|
}
|
|
793
1242
|
return {
|
|
794
1243
|
id: item.id,
|
|
795
1244
|
role: 'user',
|
|
796
1245
|
content: item.content.map(getInputMessageContent),
|
|
797
|
-
...(0, providerData_1.
|
|
1246
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1247
|
+
'id',
|
|
1248
|
+
'role',
|
|
1249
|
+
'content',
|
|
1250
|
+
]),
|
|
798
1251
|
};
|
|
799
1252
|
}
|
|
800
1253
|
if (item.role === 'assistant') {
|
|
@@ -804,7 +1257,13 @@ function getMessageItem(item) {
|
|
|
804
1257
|
role: 'assistant',
|
|
805
1258
|
content: item.content.map(getOutputMessageContent),
|
|
806
1259
|
status: item.status,
|
|
807
|
-
...(0, providerData_1.
|
|
1260
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1261
|
+
'type',
|
|
1262
|
+
'id',
|
|
1263
|
+
'role',
|
|
1264
|
+
'content',
|
|
1265
|
+
'status',
|
|
1266
|
+
]),
|
|
808
1267
|
};
|
|
809
1268
|
return assistantMessage;
|
|
810
1269
|
}
|
|
@@ -851,6 +1310,52 @@ function getInputItems(input) {
|
|
|
851
1310
|
if (isMessageItem(item)) {
|
|
852
1311
|
return getMessageItem(item);
|
|
853
1312
|
}
|
|
1313
|
+
if (item.type === 'tool_search_call') {
|
|
1314
|
+
const status = normalizeToolSearchStatus(item.status);
|
|
1315
|
+
const callId = (0, utils_1.getToolSearchProviderCallId)(item);
|
|
1316
|
+
const execution = (0, utils_1.getToolSearchExecution)(item);
|
|
1317
|
+
const toolSearchCall = {
|
|
1318
|
+
type: 'tool_search_call',
|
|
1319
|
+
id: item.id,
|
|
1320
|
+
...(status !== null ? { status } : {}),
|
|
1321
|
+
arguments: item.arguments,
|
|
1322
|
+
...(callId ? { call_id: callId } : {}),
|
|
1323
|
+
...(execution ? { execution } : {}),
|
|
1324
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1325
|
+
'type',
|
|
1326
|
+
'id',
|
|
1327
|
+
'status',
|
|
1328
|
+
'arguments',
|
|
1329
|
+
'call_id',
|
|
1330
|
+
'callId',
|
|
1331
|
+
'execution',
|
|
1332
|
+
]),
|
|
1333
|
+
};
|
|
1334
|
+
return toolSearchCall;
|
|
1335
|
+
}
|
|
1336
|
+
if (item.type === 'tool_search_output') {
|
|
1337
|
+
const status = normalizeToolSearchStatus(item.status);
|
|
1338
|
+
const callId = (0, utils_1.getToolSearchProviderCallId)(item);
|
|
1339
|
+
const execution = (0, utils_1.getToolSearchExecution)(item);
|
|
1340
|
+
const toolSearchOutput = {
|
|
1341
|
+
type: 'tool_search_output',
|
|
1342
|
+
id: item.id,
|
|
1343
|
+
...(status !== null ? { status } : {}),
|
|
1344
|
+
tools: item.tools.map((tool) => toOpenAIToolSearchOutputToolPayload(tool)),
|
|
1345
|
+
...(callId ? { call_id: callId } : {}),
|
|
1346
|
+
...(execution ? { execution } : {}),
|
|
1347
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1348
|
+
'type',
|
|
1349
|
+
'id',
|
|
1350
|
+
'status',
|
|
1351
|
+
'tools',
|
|
1352
|
+
'call_id',
|
|
1353
|
+
'callId',
|
|
1354
|
+
'execution',
|
|
1355
|
+
]),
|
|
1356
|
+
};
|
|
1357
|
+
return toolSearchOutput;
|
|
1358
|
+
}
|
|
854
1359
|
if (item.type === 'function_call') {
|
|
855
1360
|
const entry = {
|
|
856
1361
|
id: item.id,
|
|
@@ -859,7 +1364,18 @@ function getInputItems(input) {
|
|
|
859
1364
|
call_id: item.callId,
|
|
860
1365
|
arguments: item.arguments,
|
|
861
1366
|
status: item.status,
|
|
862
|
-
...(
|
|
1367
|
+
...(typeof item.namespace === 'string'
|
|
1368
|
+
? { namespace: item.namespace }
|
|
1369
|
+
: {}),
|
|
1370
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1371
|
+
'id',
|
|
1372
|
+
'type',
|
|
1373
|
+
'name',
|
|
1374
|
+
'call_id',
|
|
1375
|
+
'arguments',
|
|
1376
|
+
'status',
|
|
1377
|
+
'namespace',
|
|
1378
|
+
]),
|
|
863
1379
|
};
|
|
864
1380
|
return entry;
|
|
865
1381
|
}
|
|
@@ -871,45 +1387,98 @@ function getInputItems(input) {
|
|
|
871
1387
|
call_id: item.callId,
|
|
872
1388
|
output: normalizedOutput,
|
|
873
1389
|
status: item.status,
|
|
874
|
-
...(0, providerData_1.
|
|
1390
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1391
|
+
'type',
|
|
1392
|
+
'id',
|
|
1393
|
+
'call_id',
|
|
1394
|
+
'output',
|
|
1395
|
+
'status',
|
|
1396
|
+
'namespace',
|
|
1397
|
+
]),
|
|
875
1398
|
};
|
|
876
1399
|
return entry;
|
|
877
1400
|
}
|
|
878
1401
|
if (item.type === 'reasoning') {
|
|
1402
|
+
const encryptedContent = getProviderDataField(item.providerData, [
|
|
1403
|
+
'encryptedContent',
|
|
1404
|
+
'encrypted_content',
|
|
1405
|
+
]);
|
|
879
1406
|
const entry = {
|
|
880
1407
|
id: item.id,
|
|
881
1408
|
type: 'reasoning',
|
|
882
1409
|
summary: item.content.map((content) => ({
|
|
883
1410
|
type: 'summary_text',
|
|
884
1411
|
text: content.text,
|
|
885
|
-
...(0, providerData_1.
|
|
1412
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(content.providerData, ['type', 'text']),
|
|
886
1413
|
})),
|
|
887
|
-
|
|
888
|
-
|
|
1414
|
+
...(typeof encryptedContent === 'string'
|
|
1415
|
+
? { encrypted_content: encryptedContent }
|
|
1416
|
+
: {}),
|
|
1417
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1418
|
+
'id',
|
|
1419
|
+
'type',
|
|
1420
|
+
'summary',
|
|
1421
|
+
'encrypted_content',
|
|
1422
|
+
]),
|
|
889
1423
|
};
|
|
890
1424
|
return entry;
|
|
891
1425
|
}
|
|
892
1426
|
if (item.type === 'computer_call') {
|
|
1427
|
+
const pendingSafetyChecks = getProviderDataField(item.providerData, ['pendingSafetyChecks', 'pending_safety_checks']);
|
|
1428
|
+
const normalizedPendingSafetyChecks = Array.isArray(pendingSafetyChecks) ? pendingSafetyChecks : [];
|
|
1429
|
+
const batchedActions = Array.isArray(item.actions)
|
|
1430
|
+
? (item
|
|
1431
|
+
.actions ?? [])
|
|
1432
|
+
: [];
|
|
1433
|
+
const actionPayload = batchedActions.length > 0
|
|
1434
|
+
? {
|
|
1435
|
+
action: item.action ?? batchedActions[0],
|
|
1436
|
+
actions: batchedActions,
|
|
1437
|
+
}
|
|
1438
|
+
: item.action
|
|
1439
|
+
? { action: item.action }
|
|
1440
|
+
: {};
|
|
893
1441
|
const entry = {
|
|
894
1442
|
type: 'computer_call',
|
|
895
1443
|
call_id: item.callId,
|
|
896
1444
|
id: item.id,
|
|
897
|
-
action: item.action,
|
|
898
1445
|
status: item.status,
|
|
899
|
-
pending_safety_checks:
|
|
900
|
-
...
|
|
1446
|
+
pending_safety_checks: normalizedPendingSafetyChecks,
|
|
1447
|
+
...actionPayload,
|
|
1448
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1449
|
+
'type',
|
|
1450
|
+
'call_id',
|
|
1451
|
+
'id',
|
|
1452
|
+
'action',
|
|
1453
|
+
'actions',
|
|
1454
|
+
'status',
|
|
1455
|
+
'pending_safety_checks',
|
|
1456
|
+
]),
|
|
901
1457
|
};
|
|
902
1458
|
return entry;
|
|
903
1459
|
}
|
|
904
1460
|
if (item.type === 'computer_call_result') {
|
|
1461
|
+
const acknowledgedSafetyChecks = getProviderDataField(item.providerData, [
|
|
1462
|
+
'acknowledgedSafetyChecks',
|
|
1463
|
+
'acknowledged_safety_checks',
|
|
1464
|
+
]);
|
|
905
1465
|
const entry = {
|
|
906
1466
|
type: 'computer_call_output',
|
|
907
1467
|
id: item.id,
|
|
908
1468
|
call_id: item.callId,
|
|
909
1469
|
output: buildResponseOutput(item),
|
|
910
1470
|
status: item.providerData?.status,
|
|
911
|
-
acknowledged_safety_checks:
|
|
912
|
-
|
|
1471
|
+
acknowledged_safety_checks: Array.isArray(acknowledgedSafetyChecks)
|
|
1472
|
+
? acknowledgedSafetyChecks
|
|
1473
|
+
: [],
|
|
1474
|
+
...(0, providerData_1.getSnakeCasedProviderDataWithoutReservedKeys)(item.providerData, [
|
|
1475
|
+
'type',
|
|
1476
|
+
'id',
|
|
1477
|
+
'call_id',
|
|
1478
|
+
'output',
|
|
1479
|
+
'status',
|
|
1480
|
+
'acknowledged_safety_checks',
|
|
1481
|
+
]),
|
|
913
1482
|
};
|
|
914
1483
|
return entry;
|
|
915
1484
|
}
|
|
@@ -1162,6 +1731,30 @@ function convertToOutputItem(items) {
|
|
|
1162
1731
|
providerData,
|
|
1163
1732
|
};
|
|
1164
1733
|
}
|
|
1734
|
+
else if (item.type === 'tool_search_call') {
|
|
1735
|
+
const { id, type: _type, status, arguments: args, ...providerData } = item;
|
|
1736
|
+
const output = {
|
|
1737
|
+
type: 'tool_search_call',
|
|
1738
|
+
id,
|
|
1739
|
+
status,
|
|
1740
|
+
arguments: args,
|
|
1741
|
+
providerData,
|
|
1742
|
+
};
|
|
1743
|
+
return output;
|
|
1744
|
+
}
|
|
1745
|
+
else if (item.type === 'tool_search_output') {
|
|
1746
|
+
const { id, type: _type, status, tools, ...providerData } = item;
|
|
1747
|
+
const output = {
|
|
1748
|
+
type: 'tool_search_output',
|
|
1749
|
+
id,
|
|
1750
|
+
status,
|
|
1751
|
+
tools: Array.isArray(tools)
|
|
1752
|
+
? tools.map((tool) => fromOpenAIToolSearchOutputToolPayload(tool))
|
|
1753
|
+
: [],
|
|
1754
|
+
providerData,
|
|
1755
|
+
};
|
|
1756
|
+
return output;
|
|
1757
|
+
}
|
|
1165
1758
|
else if (item.type === 'file_search_call' ||
|
|
1166
1759
|
item.type === 'web_search_call' ||
|
|
1167
1760
|
item.type === 'image_generation_call' ||
|
|
@@ -1184,12 +1777,14 @@ function convertToOutputItem(items) {
|
|
|
1184
1777
|
return output;
|
|
1185
1778
|
}
|
|
1186
1779
|
else if (item.type === 'function_call') {
|
|
1187
|
-
const
|
|
1780
|
+
const functionCall = item;
|
|
1781
|
+
const { call_id, name, namespace, status, arguments: args, ...providerData } = functionCall;
|
|
1188
1782
|
const output = {
|
|
1189
1783
|
type: 'function_call',
|
|
1190
|
-
id:
|
|
1784
|
+
id: functionCall.id,
|
|
1191
1785
|
callId: call_id,
|
|
1192
1786
|
name,
|
|
1787
|
+
...(typeof namespace === 'string' ? { namespace } : {}),
|
|
1193
1788
|
status,
|
|
1194
1789
|
arguments: args,
|
|
1195
1790
|
providerData,
|
|
@@ -1197,12 +1792,13 @@ function convertToOutputItem(items) {
|
|
|
1197
1792
|
return output;
|
|
1198
1793
|
}
|
|
1199
1794
|
else if (item.type === 'function_call_output') {
|
|
1200
|
-
const { call_id, status, output: rawOutput, name: toolName, function_name: functionName, ...providerData } = item;
|
|
1795
|
+
const { call_id, status, output: rawOutput, name: toolName, function_name: functionName, namespace, ...providerData } = item;
|
|
1201
1796
|
const output = {
|
|
1202
1797
|
type: 'function_call_result',
|
|
1203
1798
|
id: item.id,
|
|
1204
1799
|
callId: call_id,
|
|
1205
1800
|
name: toolName ?? functionName ?? call_id,
|
|
1801
|
+
...(typeof namespace === 'string' ? { namespace } : {}),
|
|
1206
1802
|
status: status ?? 'completed',
|
|
1207
1803
|
output: convertFunctionCallOutputToProtocol(rawOutput),
|
|
1208
1804
|
providerData,
|
|
@@ -1210,13 +1806,18 @@ function convertToOutputItem(items) {
|
|
|
1210
1806
|
return output;
|
|
1211
1807
|
}
|
|
1212
1808
|
else if (item.type === 'computer_call') {
|
|
1213
|
-
const { call_id, status, action, ...providerData } = item;
|
|
1809
|
+
const { call_id, status, action, actions, ...providerData } = item;
|
|
1810
|
+
const normalizedActions = Array.isArray(actions) && actions.length > 0 ? actions : undefined;
|
|
1811
|
+
if (!normalizedActions && !action) {
|
|
1812
|
+
throw new agents_core_1.UserError(`Unsupported computer call item without an action or actions: ${JSON.stringify(item)}`);
|
|
1813
|
+
}
|
|
1214
1814
|
const output = {
|
|
1215
1815
|
type: 'computer_call',
|
|
1216
1816
|
id: item.id,
|
|
1217
1817
|
callId: call_id,
|
|
1218
1818
|
status,
|
|
1219
|
-
action,
|
|
1819
|
+
action: action ?? normalizedActions?.[0],
|
|
1820
|
+
...(normalizedActions ? { actions: normalizedActions } : {}),
|
|
1220
1821
|
providerData,
|
|
1221
1822
|
};
|
|
1222
1823
|
return output;
|
|
@@ -1460,15 +2061,22 @@ class OpenAIResponsesModel {
|
|
|
1460
2061
|
this._client = client;
|
|
1461
2062
|
this._model = model;
|
|
1462
2063
|
}
|
|
2064
|
+
getRetryAdvice(args) {
|
|
2065
|
+
return (0, retryAdvice_1.getOpenAIRetryAdvice)(args);
|
|
2066
|
+
}
|
|
1463
2067
|
async _fetchResponse(request, stream) {
|
|
1464
2068
|
const builtRequest = this._buildResponsesCreateRequest(request, stream);
|
|
1465
|
-
const
|
|
2069
|
+
const requestOptions = {
|
|
1466
2070
|
headers: builtRequest.sdkRequestHeaders,
|
|
1467
2071
|
signal: builtRequest.signal,
|
|
1468
2072
|
...(builtRequest.transportExtraQuery
|
|
1469
2073
|
? { query: builtRequest.transportExtraQuery }
|
|
1470
2074
|
: {}),
|
|
1471
|
-
}
|
|
2075
|
+
};
|
|
2076
|
+
if (request._internal?.runnerManagedRetry === true) {
|
|
2077
|
+
requestOptions.maxRetries = 0;
|
|
2078
|
+
}
|
|
2079
|
+
const responsePromise = this._client.responses.create(builtRequest.requestData, requestOptions);
|
|
1472
2080
|
let response;
|
|
1473
2081
|
if (stream) {
|
|
1474
2082
|
const withResponse = responsePromise
|
|
@@ -1495,9 +2103,30 @@ class OpenAIResponsesModel {
|
|
|
1495
2103
|
}
|
|
1496
2104
|
_buildResponsesCreateRequest(request, stream) {
|
|
1497
2105
|
const input = getInputItems(request.input);
|
|
1498
|
-
const
|
|
1499
|
-
|
|
2106
|
+
const prompt = getPrompt(request.prompt);
|
|
2107
|
+
// When a prompt template already declares a model, skip sending the agent's default model.
|
|
2108
|
+
// If the caller explicitly requests an override, include the resolved model name in the request.
|
|
2109
|
+
const shouldSendModel = !request.prompt || request.overridePromptModel === true;
|
|
2110
|
+
const effectiveRequestModel = shouldSendModel ? this._model : undefined;
|
|
1500
2111
|
const { providerData: providerDataWithoutTransport, overrides: transportOverrides, } = (0, responsesTransportUtils_1.splitResponsesTransportOverrides)(request.modelSettings.providerData);
|
|
2112
|
+
const { tools, include } = getTools(request.tools, request.handoffs, {
|
|
2113
|
+
model: effectiveRequestModel,
|
|
2114
|
+
toolChoice: request.modelSettings.toolChoice,
|
|
2115
|
+
});
|
|
2116
|
+
const toolChoiceValidationTools = [
|
|
2117
|
+
...tools,
|
|
2118
|
+
...getExtraBodyToolsForToolChoiceValidation(transportOverrides.extraBody),
|
|
2119
|
+
];
|
|
2120
|
+
const allowPromptSuppliedTools = Boolean(request.prompt) &&
|
|
2121
|
+
!(request.toolsExplicitlyProvided === true && tools.length === 0);
|
|
2122
|
+
const toolChoice = getToolChoice(request.modelSettings.toolChoice, {
|
|
2123
|
+
tools: toolChoiceValidationTools,
|
|
2124
|
+
model: effectiveRequestModel,
|
|
2125
|
+
allowPromptSuppliedComputerTool: allowPromptSuppliedTools,
|
|
2126
|
+
});
|
|
2127
|
+
assertSupportedToolChoice(toolChoice, toolChoiceValidationTools, {
|
|
2128
|
+
allowPromptSuppliedTools,
|
|
2129
|
+
});
|
|
1501
2130
|
const { text, ...restOfProviderData } = providerDataWithoutTransport;
|
|
1502
2131
|
if (request.modelSettings.reasoning) {
|
|
1503
2132
|
// Merge top-level reasoning settings with provider data.
|
|
@@ -1512,25 +2141,19 @@ class OpenAIResponsesModel {
|
|
|
1512
2141
|
mergedText = { ...request.modelSettings.text, ...text };
|
|
1513
2142
|
}
|
|
1514
2143
|
const responseFormat = getResponseFormat(request.outputType, mergedText);
|
|
1515
|
-
const prompt = getPrompt(request.prompt);
|
|
1516
2144
|
let parallelToolCalls = undefined;
|
|
1517
2145
|
if (typeof request.modelSettings.parallelToolCalls === 'boolean') {
|
|
1518
|
-
if (request.modelSettings.parallelToolCalls && tools.length === 0) {
|
|
1519
|
-
throw new Error('Parallel tool calls are not supported without tools');
|
|
1520
|
-
}
|
|
1521
2146
|
parallelToolCalls = request.modelSettings.parallelToolCalls;
|
|
1522
2147
|
}
|
|
1523
|
-
// When a prompt template already declares a model, skip sending the agent's default model.
|
|
1524
|
-
// If the caller explicitly requests an override, include the resolved model name in the request.
|
|
1525
|
-
const shouldSendModel = !request.prompt || request.overridePromptModel === true;
|
|
1526
2148
|
const shouldSendTools = tools.length > 0 ||
|
|
1527
2149
|
request.toolsExplicitlyProvided === true ||
|
|
1528
2150
|
!request.prompt;
|
|
1529
|
-
const
|
|
1530
|
-
|
|
1531
|
-
|
|
2151
|
+
const compatibleToolChoice = getCompatibleToolChoice(toolChoice, toolChoiceValidationTools, {
|
|
2152
|
+
allowPromptSuppliedTools,
|
|
2153
|
+
});
|
|
2154
|
+
const shouldOmitToolChoice = typeof compatibleToolChoice === 'undefined';
|
|
1532
2155
|
let requestData = {
|
|
1533
|
-
...(
|
|
2156
|
+
...(effectiveRequestModel ? { model: effectiveRequestModel } : {}),
|
|
1534
2157
|
instructions: normalizeInstructions(request.systemInstructions),
|
|
1535
2158
|
input,
|
|
1536
2159
|
include,
|
|
@@ -1547,7 +2170,7 @@ class OpenAIResponsesModel {
|
|
|
1547
2170
|
truncation: request.modelSettings.truncation,
|
|
1548
2171
|
max_output_tokens: request.modelSettings.maxTokens,
|
|
1549
2172
|
...(!shouldOmitToolChoice
|
|
1550
|
-
? { tool_choice:
|
|
2173
|
+
? { tool_choice: compatibleToolChoice }
|
|
1551
2174
|
: {}),
|
|
1552
2175
|
parallel_tool_calls: parallelToolCalls,
|
|
1553
2176
|
stream,
|
|
@@ -1739,6 +2362,23 @@ class OpenAIResponsesWSModel extends OpenAIResponsesModel {
|
|
|
1739
2362
|
this.#websocketBaseURL = options.websocketBaseURL;
|
|
1740
2363
|
this.#reuseConnection = options.reuseConnection ?? true;
|
|
1741
2364
|
}
|
|
2365
|
+
getRetryAdvice(args) {
|
|
2366
|
+
if (isNeverSentWebSocketError(args.error)) {
|
|
2367
|
+
return {
|
|
2368
|
+
suggested: true,
|
|
2369
|
+
replaySafety: 'safe',
|
|
2370
|
+
reason: args.error instanceof Error ? args.error.message : undefined,
|
|
2371
|
+
};
|
|
2372
|
+
}
|
|
2373
|
+
if (isAmbiguousWebSocketReplayError(args.error)) {
|
|
2374
|
+
return {
|
|
2375
|
+
suggested: false,
|
|
2376
|
+
replaySafety: 'unsafe',
|
|
2377
|
+
reason: args.error instanceof Error ? args.error.message : undefined,
|
|
2378
|
+
};
|
|
2379
|
+
}
|
|
2380
|
+
return super.getRetryAdvice(args);
|
|
2381
|
+
}
|
|
1742
2382
|
async _fetchResponse(request, stream) {
|
|
1743
2383
|
// The websocket transport always uses streamed Responses events, then callers either
|
|
1744
2384
|
// consume the stream directly or collapse it into the final terminal response.
|
|
@@ -1747,12 +2387,22 @@ class OpenAIResponsesWSModel extends OpenAIResponsesModel {
|
|
|
1747
2387
|
return this.#iterWebSocketResponseEvents(builtRequest);
|
|
1748
2388
|
}
|
|
1749
2389
|
let finalResponse;
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
2390
|
+
let receivedAnyEvent = false;
|
|
2391
|
+
try {
|
|
2392
|
+
for await (const event of this.#iterWebSocketResponseEvents(builtRequest)) {
|
|
2393
|
+
receivedAnyEvent = true;
|
|
2394
|
+
const eventType = event.type;
|
|
2395
|
+
if (isTerminalResponsesStreamEventType(eventType)) {
|
|
2396
|
+
finalResponse = event
|
|
2397
|
+
.response;
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
catch (error) {
|
|
2402
|
+
if (receivedAnyEvent && error instanceof Error) {
|
|
2403
|
+
error.unsafeToReplay = true;
|
|
1755
2404
|
}
|
|
2405
|
+
throw error;
|
|
1756
2406
|
}
|
|
1757
2407
|
if (!finalResponse) {
|
|
1758
2408
|
throw new Error('Responses websocket stream ended without a terminal response event.');
|