@openai/agents-core 0.5.4 → 0.6.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/computer.d.ts +10 -2
- package/dist/events.d.ts +1 -1
- package/dist/events.js.map +1 -1
- package/dist/events.mjs.map +1 -1
- package/dist/extensions/handoffFilters.d.ts +4 -3
- package/dist/extensions/handoffFilters.js +8 -3
- package/dist/extensions/handoffFilters.js.map +1 -1
- package/dist/extensions/handoffFilters.mjs +9 -4
- package/dist/extensions/handoffFilters.mjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/items.d.ts +1158 -32
- package/dist/items.js +56 -2
- package/dist/items.js.map +1 -1
- package/dist/items.mjs +53 -1
- package/dist/items.mjs.map +1 -1
- package/dist/metadata.js +3 -3
- package/dist/metadata.mjs +3 -3
- package/dist/model.d.ts +14 -2
- package/dist/run.js +2 -2
- package/dist/run.js.map +1 -1
- package/dist/run.mjs +3 -3
- package/dist/run.mjs.map +1 -1
- package/dist/runContext.js +116 -67
- package/dist/runContext.js.map +1 -1
- package/dist/runContext.mjs +116 -67
- package/dist/runContext.mjs.map +1 -1
- package/dist/runState.d.ts +493 -17
- package/dist/runState.js +303 -12
- package/dist/runState.js.map +1 -1
- package/dist/runState.mjs +304 -13
- package/dist/runState.mjs.map +1 -1
- package/dist/runner/modelOutputs.d.ts +5 -1
- package/dist/runner/modelOutputs.js +552 -12
- package/dist/runner/modelOutputs.js.map +1 -1
- package/dist/runner/modelOutputs.mjs +552 -13
- package/dist/runner/modelOutputs.mjs.map +1 -1
- package/dist/runner/modelPreparation.js +5 -2
- package/dist/runner/modelPreparation.js.map +1 -1
- package/dist/runner/modelPreparation.mjs +5 -2
- package/dist/runner/modelPreparation.mjs.map +1 -1
- package/dist/runner/sessionPersistence.js +17 -3
- package/dist/runner/sessionPersistence.js.map +1 -1
- package/dist/runner/sessionPersistence.mjs +17 -3
- package/dist/runner/sessionPersistence.mjs.map +1 -1
- package/dist/runner/streaming.js +8 -0
- package/dist/runner/streaming.js.map +1 -1
- package/dist/runner/streaming.mjs +9 -1
- package/dist/runner/streaming.mjs.map +1 -1
- package/dist/runner/toolExecution.js +102 -67
- package/dist/runner/toolExecution.js.map +1 -1
- package/dist/runner/toolExecution.mjs +102 -67
- package/dist/runner/toolExecution.mjs.map +1 -1
- package/dist/runner/toolSearch.d.ts +23 -0
- package/dist/runner/toolSearch.js +426 -0
- package/dist/runner/toolSearch.js.map +1 -0
- package/dist/runner/toolSearch.mjs +416 -0
- package/dist/runner/toolSearch.mjs.map +1 -0
- package/dist/runner/turnResolution.js +2 -1
- package/dist/runner/turnResolution.js.map +1 -1
- package/dist/runner/turnResolution.mjs +2 -1
- package/dist/runner/turnResolution.mjs.map +1 -1
- package/dist/tool.d.ts +50 -0
- package/dist/tool.js +79 -0
- package/dist/tool.js.map +1 -1
- package/dist/tool.mjs +74 -0
- package/dist/tool.mjs.map +1 -1
- package/dist/toolIdentity.d.ts +23 -0
- package/dist/toolIdentity.js +105 -0
- package/dist/toolIdentity.js.map +1 -0
- package/dist/toolIdentity.mjs +89 -0
- package/dist/toolIdentity.mjs.map +1 -0
- package/dist/tooling.d.ts +24 -0
- package/dist/tooling.js +110 -0
- package/dist/tooling.js.map +1 -0
- package/dist/tooling.mjs +97 -0
- package/dist/tooling.mjs.map +1 -0
- package/dist/types/aliases.d.ts +3 -3
- package/dist/types/protocol.d.ts +417 -12
- package/dist/types/protocol.js +59 -4
- package/dist/types/protocol.js.map +1 -1
- package/dist/types/protocol.mjs +57 -2
- package/dist/types/protocol.mjs.map +1 -1
- package/dist/types/providerData.d.ts +2 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +15 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +2 -0
- package/dist/utils/index.mjs.map +1 -1
- package/dist/utils/serialize.js +37 -6
- package/dist/utils/serialize.js.map +1 -1
- package/dist/utils/serialize.mjs +37 -6
- package/dist/utils/serialize.mjs.map +1 -1
- package/dist/utils/toolSearch.d.ts +1 -0
- package/dist/utils/toolSearch.js +13 -0
- package/dist/utils/toolSearch.js.map +1 -0
- package/dist/utils/toolSearch.mjs +2 -0
- package/dist/utils/toolSearch.mjs.map +1 -0
- package/package.json +2 -2
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.processModelResponse = processModelResponse;
|
|
4
|
+
exports.processModelResponseAsync = processModelResponseAsync;
|
|
4
5
|
const errors_1 = require("../errors.js");
|
|
5
6
|
const items_1 = require("../items.js");
|
|
7
|
+
const tool_1 = require("../tool.js");
|
|
6
8
|
const context_1 = require("../tracing/context.js");
|
|
9
|
+
const toolIdentity_1 = require("../toolIdentity.js");
|
|
10
|
+
const utils_1 = require("../utils/index.js");
|
|
11
|
+
const toolSearch_1 = require("./toolSearch.js");
|
|
7
12
|
function ensureToolAvailable(tool, message, data) {
|
|
8
13
|
if (!tool) {
|
|
9
14
|
(0, context_1.addErrorToCurrentSpan)({
|
|
@@ -21,17 +26,36 @@ function handleToolCallAction({ output, tool, agent, errorMessage, errorData, it
|
|
|
21
26
|
actions.push(buildAction(resolvedTool));
|
|
22
27
|
}
|
|
23
28
|
function resolveFunctionOrHandoff(toolCall, handoffMap, functionMap, agent) {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
const resolvedToolName = (0, toolIdentity_1.resolveFunctionToolCallName)(toolCall, functionMap) ?? toolCall.name;
|
|
30
|
+
const namespace = (0, toolIdentity_1.getToolCallNamespace)(toolCall);
|
|
31
|
+
if (!namespace && typeof resolvedToolName === 'string') {
|
|
32
|
+
const functionTool = functionMap.get(resolvedToolName);
|
|
33
|
+
const handoff = handoffMap.get(toolCall.name);
|
|
34
|
+
if (functionTool && handoff && resolvedToolName.includes('.')) {
|
|
35
|
+
const message = `Ambiguous dotted tool call ${resolvedToolName} in agent ${agent.name}: it matches both a namespaced function tool and a handoff. Rename one of them or emit the function call with explicit namespace metadata.`;
|
|
36
|
+
(0, context_1.addErrorToCurrentSpan)({
|
|
37
|
+
message,
|
|
38
|
+
data: {
|
|
39
|
+
tool_name: resolvedToolName,
|
|
40
|
+
agent_name: agent.name,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
throw new errors_1.ModelBehaviorError(message);
|
|
44
|
+
}
|
|
45
|
+
if (functionTool && resolvedToolName.includes('.')) {
|
|
46
|
+
return { type: 'function', tool: functionTool };
|
|
47
|
+
}
|
|
48
|
+
if (handoff) {
|
|
49
|
+
return { type: 'handoff', handoff };
|
|
50
|
+
}
|
|
27
51
|
}
|
|
28
|
-
const functionTool = functionMap.get(
|
|
52
|
+
const functionTool = functionMap.get(resolvedToolName);
|
|
29
53
|
if (!functionTool) {
|
|
30
|
-
const message = `Tool ${
|
|
54
|
+
const message = `Tool ${resolvedToolName} not found in agent ${agent.name}.`;
|
|
31
55
|
(0, context_1.addErrorToCurrentSpan)({
|
|
32
56
|
message,
|
|
33
57
|
data: {
|
|
34
|
-
tool_name:
|
|
58
|
+
tool_name: resolvedToolName,
|
|
35
59
|
agent_name: agent.name,
|
|
36
60
|
},
|
|
37
61
|
});
|
|
@@ -39,6 +63,271 @@ function resolveFunctionOrHandoff(toolCall, handoffMap, functionMap, agent) {
|
|
|
39
63
|
}
|
|
40
64
|
return { type: 'function', tool: functionTool };
|
|
41
65
|
}
|
|
66
|
+
function normalizeFunctionToolCallForStorage(toolCall, tool) {
|
|
67
|
+
const namespace = (0, toolIdentity_1.getToolCallNamespace)(toolCall);
|
|
68
|
+
const explicitNamespace = (0, toolIdentity_1.getFunctionToolNamespace)(tool);
|
|
69
|
+
const qualifiedToolName = (0, toolIdentity_1.getFunctionToolQualifiedName)(tool);
|
|
70
|
+
if (namespace ||
|
|
71
|
+
!explicitNamespace ||
|
|
72
|
+
!qualifiedToolName ||
|
|
73
|
+
toolCall.name !== qualifiedToolName) {
|
|
74
|
+
return toolCall;
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
...toolCall,
|
|
78
|
+
name: tool.name,
|
|
79
|
+
namespace: explicitNamespace,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function getRawAgentInputItem(item) {
|
|
83
|
+
if (item &&
|
|
84
|
+
typeof item === 'object' &&
|
|
85
|
+
'rawItem' in item &&
|
|
86
|
+
item.rawItem &&
|
|
87
|
+
typeof item.rawItem === 'object') {
|
|
88
|
+
return item.rawItem;
|
|
89
|
+
}
|
|
90
|
+
return item;
|
|
91
|
+
}
|
|
92
|
+
function refreshLoadedDeferredToolNames(state) {
|
|
93
|
+
state.loadedToolNames.clear();
|
|
94
|
+
for (const toolSearchOutput of state.keyedToolSearchOutputsByKey.values()) {
|
|
95
|
+
(0, toolSearch_1.addLoadedToolNamesFromToolSearchOutput)(toolSearchOutput, state.loadedToolNames);
|
|
96
|
+
}
|
|
97
|
+
for (const toolSearchOutput of state.anonymousToolSearchOutputs) {
|
|
98
|
+
(0, toolSearch_1.addLoadedToolNamesFromToolSearchOutput)(toolSearchOutput, state.loadedToolNames);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function recordLoadedToolSearchOutput(state, toolSearchOutput) {
|
|
102
|
+
const replacementKey = (0, utils_1.getToolSearchOutputReplacementKey)(toolSearchOutput);
|
|
103
|
+
if (replacementKey) {
|
|
104
|
+
state.keyedToolSearchOutputsByKey.set(replacementKey, toolSearchOutput);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
state.anonymousToolSearchOutputs.push(toolSearchOutput);
|
|
108
|
+
}
|
|
109
|
+
refreshLoadedDeferredToolNames(state);
|
|
110
|
+
}
|
|
111
|
+
function collectLoadedDeferredToolStateFromHistory(items, agent) {
|
|
112
|
+
const state = {
|
|
113
|
+
anonymousToolSearchOutputs: [],
|
|
114
|
+
keyedToolSearchOutputsByKey: new Map(),
|
|
115
|
+
loadedToolNames: new Set(),
|
|
116
|
+
};
|
|
117
|
+
for (const item of items) {
|
|
118
|
+
if (item instanceof items_1.RunToolSearchOutputItem &&
|
|
119
|
+
item.agent.name !== agent.name) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const rawItem = getRawAgentInputItem(item);
|
|
123
|
+
if (rawItem?.type !== 'tool_search_output') {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const replacementKey = (0, utils_1.getToolSearchOutputReplacementKey)(rawItem);
|
|
127
|
+
if (replacementKey) {
|
|
128
|
+
state.keyedToolSearchOutputsByKey.set(replacementKey, rawItem);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
state.anonymousToolSearchOutputs.push(rawItem);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
refreshLoadedDeferredToolNames(state);
|
|
135
|
+
return state;
|
|
136
|
+
}
|
|
137
|
+
function seedHostedMcpToolsFromLoadedDeferredToolState(state, mcpToolMap, preserveExistingServerLabels) {
|
|
138
|
+
for (const toolSearchOutput of state.keyedToolSearchOutputsByKey.values()) {
|
|
139
|
+
(0, toolSearch_1.addHostedMcpToolsFromToolSearchOutput)(toolSearchOutput, mcpToolMap, {
|
|
140
|
+
preserveExistingServerLabels,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
for (const toolSearchOutput of state.anonymousToolSearchOutputs) {
|
|
144
|
+
(0, toolSearch_1.addHostedMcpToolsFromToolSearchOutput)(toolSearchOutput, mcpToolMap, {
|
|
145
|
+
preserveExistingServerLabels,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function buildFunctionToolMap(tools) {
|
|
150
|
+
return new Map(tools
|
|
151
|
+
.filter((t) => t.type === 'function')
|
|
152
|
+
.map((t) => [(0, toolIdentity_1.getFunctionToolQualifiedName)(t) ?? t.name, t]));
|
|
153
|
+
}
|
|
154
|
+
function registerRuntimeToolSearchTools(args) {
|
|
155
|
+
const { availableTools, functionMap, mcpToolMap, replaceableRuntimeToolKeys, runtimeTools, } = args;
|
|
156
|
+
const availableToolsByKey = new Map();
|
|
157
|
+
for (const tool of availableTools) {
|
|
158
|
+
const key = (0, tool_1.getToolSearchRuntimeToolKey)(tool);
|
|
159
|
+
if (key) {
|
|
160
|
+
availableToolsByKey.set(key, tool);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const novelTools = [];
|
|
164
|
+
for (const runtimeTool of runtimeTools) {
|
|
165
|
+
const runtimeToolKey = (0, tool_1.getToolSearchRuntimeToolKey)(runtimeTool);
|
|
166
|
+
if (!runtimeToolKey) {
|
|
167
|
+
throw new errors_1.ModelBehaviorError('Client tool_search execute() returned an unsupported tool type.');
|
|
168
|
+
}
|
|
169
|
+
const existingTool = availableToolsByKey.get(runtimeToolKey);
|
|
170
|
+
if (existingTool && existingTool !== runtimeTool) {
|
|
171
|
+
if (!replaceableRuntimeToolKeys?.has(runtimeToolKey)) {
|
|
172
|
+
throw new errors_1.ModelBehaviorError(`Client tool_search execute() returned tool "${runtimeToolKey}" that conflicts with an existing available tool.`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else if (existingTool === runtimeTool) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
availableToolsByKey.set(runtimeToolKey, runtimeTool);
|
|
179
|
+
novelTools.push(runtimeTool);
|
|
180
|
+
if (runtimeTool.type === 'function') {
|
|
181
|
+
functionMap.set((0, toolIdentity_1.getFunctionToolQualifiedName)(runtimeTool) ?? runtimeTool.name, runtimeTool);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (runtimeTool.type === 'hosted_tool' &&
|
|
185
|
+
runtimeTool.providerData?.type === 'mcp') {
|
|
186
|
+
mcpToolMap.set(runtimeTool.providerData.server_label, runtimeTool);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
throw new errors_1.ModelBehaviorError('Client tool_search execute() returned an unsupported tool type.');
|
|
190
|
+
}
|
|
191
|
+
return novelTools;
|
|
192
|
+
}
|
|
193
|
+
function buildGeneratedClientToolSearchOutputMap(modelResponse, tools, hasClientToolSearchTool) {
|
|
194
|
+
const clientToolSearchCalls = [];
|
|
195
|
+
const pendingClientToolSearchMatchKeys = [];
|
|
196
|
+
const resolvedToolSearchCallIds = new Set();
|
|
197
|
+
for (const output of modelResponse.output) {
|
|
198
|
+
if (output.type === 'tool_search_call') {
|
|
199
|
+
const toolSearchExecution = (0, utils_1.getToolSearchExecution)(output);
|
|
200
|
+
if (toolSearchExecution === 'client' ||
|
|
201
|
+
(typeof toolSearchExecution === 'undefined' && hasClientToolSearchTool)) {
|
|
202
|
+
clientToolSearchCalls.push(output);
|
|
203
|
+
const matchKey = (0, utils_1.getToolSearchMatchKey)(output);
|
|
204
|
+
if (matchKey) {
|
|
205
|
+
pendingClientToolSearchMatchKeys.push(matchKey);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (output.type !== 'tool_search_output') {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const explicitCallId = (0, utils_1.getToolSearchProviderCallId)(output);
|
|
214
|
+
const toolSearchExecution = (0, utils_1.getToolSearchExecution)(output);
|
|
215
|
+
if (explicitCallId) {
|
|
216
|
+
resolvedToolSearchCallIds.add(explicitCallId);
|
|
217
|
+
const pendingIndex = pendingClientToolSearchMatchKeys.indexOf(explicitCallId);
|
|
218
|
+
if (pendingIndex >= 0) {
|
|
219
|
+
pendingClientToolSearchMatchKeys.splice(pendingIndex, 1);
|
|
220
|
+
}
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (toolSearchExecution !== 'server') {
|
|
224
|
+
const pendingMatchKey = pendingClientToolSearchMatchKeys.shift();
|
|
225
|
+
if (pendingMatchKey) {
|
|
226
|
+
resolvedToolSearchCallIds.add(pendingMatchKey);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const generatedOutputs = new Map();
|
|
231
|
+
for (const toolSearchCall of clientToolSearchCalls) {
|
|
232
|
+
const matchKey = (0, utils_1.getToolSearchMatchKey)(toolSearchCall);
|
|
233
|
+
if (matchKey && resolvedToolSearchCallIds.has(matchKey)) {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
generatedOutputs.set(toolSearchCall, (0, toolSearch_1.createBuiltInClientToolSearchOutput)(toolSearchCall, tools));
|
|
237
|
+
}
|
|
238
|
+
return generatedOutputs;
|
|
239
|
+
}
|
|
240
|
+
async function buildGeneratedClientToolSearchOutputMapAsync(args) {
|
|
241
|
+
const { agent, modelResponse, runContext, tools } = args;
|
|
242
|
+
const clientToolSearchTool = (0, toolSearch_1.getClientToolSearchHelper)(tools);
|
|
243
|
+
const hasClientToolSearchTool = typeof clientToolSearchTool !== 'undefined';
|
|
244
|
+
const executionTools = [...tools];
|
|
245
|
+
const clientToolSearchCalls = [];
|
|
246
|
+
const pendingClientToolSearchMatchKeys = [];
|
|
247
|
+
const resolvedToolSearchCallIds = new Set();
|
|
248
|
+
for (const output of modelResponse.output) {
|
|
249
|
+
if (output.type === 'tool_search_call') {
|
|
250
|
+
const toolSearchExecution = (0, utils_1.getToolSearchExecution)(output);
|
|
251
|
+
if (toolSearchExecution === 'client' ||
|
|
252
|
+
(typeof toolSearchExecution === 'undefined' && hasClientToolSearchTool)) {
|
|
253
|
+
clientToolSearchCalls.push(output);
|
|
254
|
+
const matchKey = (0, utils_1.getToolSearchMatchKey)(output);
|
|
255
|
+
if (matchKey) {
|
|
256
|
+
pendingClientToolSearchMatchKeys.push(matchKey);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (output.type !== 'tool_search_output') {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
const explicitCallId = (0, utils_1.getToolSearchProviderCallId)(output);
|
|
265
|
+
const toolSearchExecution = (0, utils_1.getToolSearchExecution)(output);
|
|
266
|
+
if (explicitCallId) {
|
|
267
|
+
resolvedToolSearchCallIds.add(explicitCallId);
|
|
268
|
+
const pendingIndex = pendingClientToolSearchMatchKeys.indexOf(explicitCallId);
|
|
269
|
+
if (pendingIndex >= 0) {
|
|
270
|
+
pendingClientToolSearchMatchKeys.splice(pendingIndex, 1);
|
|
271
|
+
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (toolSearchExecution !== 'server') {
|
|
275
|
+
const pendingMatchKey = pendingClientToolSearchMatchKeys.shift();
|
|
276
|
+
if (pendingMatchKey) {
|
|
277
|
+
resolvedToolSearchCallIds.add(pendingMatchKey);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const generatedOutputs = new Map();
|
|
282
|
+
for (const toolSearchCall of clientToolSearchCalls) {
|
|
283
|
+
const matchKey = (0, utils_1.getToolSearchMatchKey)(toolSearchCall);
|
|
284
|
+
if (matchKey && resolvedToolSearchCallIds.has(matchKey)) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
if (clientToolSearchTool &&
|
|
288
|
+
(0, tool_1.getClientToolSearchExecutor)(clientToolSearchTool)) {
|
|
289
|
+
const generatedOutput = await (0, toolSearch_1.executeCustomClientToolSearch)({
|
|
290
|
+
agent,
|
|
291
|
+
runContext,
|
|
292
|
+
toolSearchCall,
|
|
293
|
+
toolSearchTool: clientToolSearchTool,
|
|
294
|
+
tools: executionTools,
|
|
295
|
+
});
|
|
296
|
+
generatedOutputs.set(toolSearchCall, generatedOutput);
|
|
297
|
+
executionTools.push(...generatedOutput.runtimeTools);
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
generatedOutputs.set(toolSearchCall, {
|
|
301
|
+
output: (0, toolSearch_1.createBuiltInClientToolSearchOutput)(toolSearchCall, executionTools),
|
|
302
|
+
runtimeTools: [],
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
return generatedOutputs;
|
|
306
|
+
}
|
|
307
|
+
function ensureDeferredFunctionToolLoaded(toolCall, tool, loadedToolNames, agent) {
|
|
308
|
+
if (tool.deferLoading !== true) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const explicitNamespace = (0, toolIdentity_1.getFunctionToolNamespace)(tool);
|
|
312
|
+
const qualifiedName = (0, toolIdentity_1.getFunctionToolQualifiedName)(tool);
|
|
313
|
+
const isLoaded = (qualifiedName ? loadedToolNames.has(qualifiedName) : false) ||
|
|
314
|
+
((!explicitNamespace || explicitNamespace === tool.name) &&
|
|
315
|
+
loadedToolNames.has(tool.name));
|
|
316
|
+
if (isLoaded) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const toolName = qualifiedName ?? tool.name;
|
|
320
|
+
const message = `Model produced deferred function call ${toolName} before it was loaded via tool_search.`;
|
|
321
|
+
(0, context_1.addErrorToCurrentSpan)({
|
|
322
|
+
message,
|
|
323
|
+
data: {
|
|
324
|
+
agent_name: agent.name,
|
|
325
|
+
tool_name: toolName,
|
|
326
|
+
tool_call_id: toolCall.callId,
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
throw new errors_1.ModelBehaviorError(message);
|
|
330
|
+
}
|
|
42
331
|
function parseShellCallStatus(status) {
|
|
43
332
|
if (status === 'in_progress' ||
|
|
44
333
|
status === 'completed' ||
|
|
@@ -64,7 +353,7 @@ function hasPendingShellOutputStatus(output) {
|
|
|
64
353
|
* Walks a raw model response and classifies each item so the runner can schedule follow-up work.
|
|
65
354
|
* Returns both the serializable RunItems (for history/streaming) and the actionable tool metadata.
|
|
66
355
|
*/
|
|
67
|
-
function processModelResponse(modelResponse, agent, tools, handoffs) {
|
|
356
|
+
function processModelResponse(modelResponse, agent, tools, handoffs, priorItems = []) {
|
|
68
357
|
const items = [];
|
|
69
358
|
const runHandoffs = [];
|
|
70
359
|
const runFunctions = [];
|
|
@@ -78,7 +367,7 @@ function processModelResponse(modelResponse, agent, tools, handoffs) {
|
|
|
78
367
|
// Resolve tools upfront so we can look up the concrete handler in O(1) while iterating outputs.
|
|
79
368
|
const functionMap = new Map(tools
|
|
80
369
|
.filter((t) => t.type === 'function')
|
|
81
|
-
.map((t) => [t.name, t]));
|
|
370
|
+
.map((t) => [(0, toolIdentity_1.getFunctionToolQualifiedName)(t) ?? t.name, t]));
|
|
82
371
|
const computerTool = tools.find((t) => t.type === 'computer');
|
|
83
372
|
const shellTool = tools.find((t) => t.type === 'shell');
|
|
84
373
|
const applyPatchTool = tools.find((t) => t.type === 'apply_patch');
|
|
@@ -86,12 +375,40 @@ function processModelResponse(modelResponse, agent, tools, handoffs) {
|
|
|
86
375
|
.filter((t) => t.type === 'hosted_tool' && t.providerData?.type === 'mcp')
|
|
87
376
|
.map((t) => t)
|
|
88
377
|
.map((t) => [t.providerData.server_label, t]));
|
|
378
|
+
const originalMcpServerLabels = new Set(mcpToolMap.keys());
|
|
379
|
+
const hasClientToolSearchTool = tools.some((tool) => tool.type === 'hosted_tool' &&
|
|
380
|
+
tool.providerData?.type === 'tool_search' &&
|
|
381
|
+
tool.providerData.execution === 'client');
|
|
382
|
+
const loadedDeferredToolState = collectLoadedDeferredToolStateFromHistory(priorItems, agent);
|
|
383
|
+
seedHostedMcpToolsFromLoadedDeferredToolState(loadedDeferredToolState, mcpToolMap, originalMcpServerLabels);
|
|
384
|
+
const generatedClientToolSearchOutputsByCall = buildGeneratedClientToolSearchOutputMap(modelResponse, tools, hasClientToolSearchTool);
|
|
385
|
+
let hasGeneratedClientToolSearchOutputs = false;
|
|
89
386
|
for (const output of modelResponse.output) {
|
|
90
387
|
if (output.type === 'message') {
|
|
91
388
|
if (output.role === 'assistant') {
|
|
92
389
|
items.push(new items_1.RunMessageOutputItem(output, agent));
|
|
93
390
|
}
|
|
94
391
|
}
|
|
392
|
+
else if (output.type === 'tool_search_call') {
|
|
393
|
+
items.push(new items_1.RunToolSearchCallItem(output, agent));
|
|
394
|
+
toolsUsed.push('tool_search');
|
|
395
|
+
const generatedOutput = generatedClientToolSearchOutputsByCall.get(output);
|
|
396
|
+
if (generatedOutput) {
|
|
397
|
+
items.push(new items_1.RunToolSearchOutputItem(generatedOutput, agent));
|
|
398
|
+
recordLoadedToolSearchOutput(loadedDeferredToolState, generatedOutput);
|
|
399
|
+
(0, toolSearch_1.addHostedMcpToolsFromToolSearchOutput)(generatedOutput, mcpToolMap, {
|
|
400
|
+
preserveExistingServerLabels: originalMcpServerLabels,
|
|
401
|
+
});
|
|
402
|
+
hasGeneratedClientToolSearchOutputs = true;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
else if (output.type === 'tool_search_output') {
|
|
406
|
+
items.push(new items_1.RunToolSearchOutputItem(output, agent));
|
|
407
|
+
recordLoadedToolSearchOutput(loadedDeferredToolState, output);
|
|
408
|
+
(0, toolSearch_1.addHostedMcpToolsFromToolSearchOutput)(output, mcpToolMap, {
|
|
409
|
+
preserveExistingServerLabels: originalMcpServerLabels,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
95
412
|
else if (output.type === 'hosted_tool_call') {
|
|
96
413
|
items.push(new items_1.RunToolCallItem(output, agent));
|
|
97
414
|
const toolName = output.name;
|
|
@@ -204,9 +521,9 @@ function processModelResponse(modelResponse, agent, tools, handoffs) {
|
|
|
204
521
|
if (output.type !== 'function_call') {
|
|
205
522
|
continue;
|
|
206
523
|
}
|
|
207
|
-
toolsUsed.push(output.name);
|
|
208
524
|
const resolved = resolveFunctionOrHandoff(output, handoffMap, functionMap, agent);
|
|
209
525
|
if (resolved.type === 'handoff') {
|
|
526
|
+
toolsUsed.push(output.name);
|
|
210
527
|
items.push(new items_1.RunHandoffCallItem(output, agent));
|
|
211
528
|
runHandoffs.push({
|
|
212
529
|
toolCall: output,
|
|
@@ -214,9 +531,12 @@ function processModelResponse(modelResponse, agent, tools, handoffs) {
|
|
|
214
531
|
});
|
|
215
532
|
}
|
|
216
533
|
else {
|
|
217
|
-
|
|
534
|
+
ensureDeferredFunctionToolLoaded(output, resolved.tool, loadedDeferredToolState.loadedToolNames, agent);
|
|
535
|
+
const normalizedToolCall = normalizeFunctionToolCallForStorage(output, resolved.tool);
|
|
536
|
+
toolsUsed.push((0, toolIdentity_1.getFunctionToolQualifiedName)(resolved.tool) ?? resolved.tool.name);
|
|
537
|
+
items.push(new items_1.RunToolCallItem(normalizedToolCall, agent));
|
|
218
538
|
runFunctions.push({
|
|
219
|
-
toolCall:
|
|
539
|
+
toolCall: normalizedToolCall,
|
|
220
540
|
tool: resolved.tool,
|
|
221
541
|
});
|
|
222
542
|
}
|
|
@@ -237,7 +557,227 @@ function processModelResponse(modelResponse, agent, tools, handoffs) {
|
|
|
237
557
|
runComputerActions.length > 0 ||
|
|
238
558
|
runShellActions.length > 0 ||
|
|
239
559
|
hasHostedShellCall ||
|
|
240
|
-
runApplyPatchActions.length > 0
|
|
560
|
+
runApplyPatchActions.length > 0 ||
|
|
561
|
+
hasGeneratedClientToolSearchOutputs);
|
|
562
|
+
},
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
async function processModelResponseAsync(modelResponse, agent, tools, handoffs, state, priorItems = []) {
|
|
566
|
+
const clientToolSearchTool = (0, toolSearch_1.getClientToolSearchHelper)(tools);
|
|
567
|
+
const hasCustomClientToolSearchExecutor = Boolean(clientToolSearchTool && (0, tool_1.getClientToolSearchExecutor)(clientToolSearchTool));
|
|
568
|
+
const hasRelevantClientToolSearchCall = modelResponse.output.some((output) => output.type === 'tool_search_call' &&
|
|
569
|
+
((0, utils_1.getToolSearchExecution)(output) === 'client' ||
|
|
570
|
+
(typeof (0, utils_1.getToolSearchExecution)(output) === 'undefined' &&
|
|
571
|
+
typeof clientToolSearchTool !== 'undefined')));
|
|
572
|
+
if (!hasCustomClientToolSearchExecutor || !hasRelevantClientToolSearchCall) {
|
|
573
|
+
return processModelResponse(modelResponse, agent, tools, handoffs, priorItems);
|
|
574
|
+
}
|
|
575
|
+
const items = [];
|
|
576
|
+
const runHandoffs = [];
|
|
577
|
+
const runFunctions = [];
|
|
578
|
+
const runComputerActions = [];
|
|
579
|
+
const runShellActions = [];
|
|
580
|
+
let hasHostedShellCall = false;
|
|
581
|
+
const runApplyPatchActions = [];
|
|
582
|
+
const runMCPApprovalRequests = [];
|
|
583
|
+
const toolsUsed = [];
|
|
584
|
+
const handoffMap = new Map(handoffs.map((h) => [h.toolName, h]));
|
|
585
|
+
const functionMap = buildFunctionToolMap(tools);
|
|
586
|
+
const computerTool = tools.find((t) => t.type === 'computer');
|
|
587
|
+
const shellTool = tools.find((t) => t.type === 'shell');
|
|
588
|
+
const applyPatchTool = tools.find((t) => t.type === 'apply_patch');
|
|
589
|
+
const mcpToolMap = new Map(tools
|
|
590
|
+
.filter((t) => t.type === 'hosted_tool' && t.providerData?.type === 'mcp')
|
|
591
|
+
.map((t) => t)
|
|
592
|
+
.map((t) => [t.providerData.server_label, t]));
|
|
593
|
+
const originalMcpServerLabels = new Set(mcpToolMap.keys());
|
|
594
|
+
const replaceableRuntimeToolKeys = new Set(state
|
|
595
|
+
.getToolSearchRuntimeTools(agent)
|
|
596
|
+
.map((tool) => (0, tool_1.getToolSearchRuntimeToolKey)(tool))
|
|
597
|
+
.filter((key) => typeof key === 'string'));
|
|
598
|
+
const loadedDeferredToolState = collectLoadedDeferredToolStateFromHistory(priorItems, agent);
|
|
599
|
+
seedHostedMcpToolsFromLoadedDeferredToolState(loadedDeferredToolState, mcpToolMap, originalMcpServerLabels);
|
|
600
|
+
const generatedClientToolSearchOutputsByCall = await buildGeneratedClientToolSearchOutputMapAsync({
|
|
601
|
+
agent,
|
|
602
|
+
modelResponse,
|
|
603
|
+
runContext: state._context,
|
|
604
|
+
tools,
|
|
605
|
+
});
|
|
606
|
+
let hasGeneratedClientToolSearchOutputs = false;
|
|
607
|
+
const availableTools = [...tools];
|
|
608
|
+
for (const output of modelResponse.output) {
|
|
609
|
+
if (output.type === 'message') {
|
|
610
|
+
if (output.role === 'assistant') {
|
|
611
|
+
items.push(new items_1.RunMessageOutputItem(output, agent));
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
else if (output.type === 'tool_search_call') {
|
|
615
|
+
items.push(new items_1.RunToolSearchCallItem(output, agent));
|
|
616
|
+
toolsUsed.push('tool_search');
|
|
617
|
+
const generatedOutput = generatedClientToolSearchOutputsByCall.get(output);
|
|
618
|
+
if (generatedOutput) {
|
|
619
|
+
items.push(new items_1.RunToolSearchOutputItem(generatedOutput.output, agent));
|
|
620
|
+
recordLoadedToolSearchOutput(loadedDeferredToolState, generatedOutput.output);
|
|
621
|
+
(0, toolSearch_1.addHostedMcpToolsFromToolSearchOutput)(generatedOutput.output, mcpToolMap, {
|
|
622
|
+
preserveExistingServerLabels: originalMcpServerLabels,
|
|
623
|
+
});
|
|
624
|
+
const novelRuntimeTools = registerRuntimeToolSearchTools({
|
|
625
|
+
availableTools,
|
|
626
|
+
functionMap,
|
|
627
|
+
mcpToolMap,
|
|
628
|
+
replaceableRuntimeToolKeys,
|
|
629
|
+
runtimeTools: generatedOutput.runtimeTools,
|
|
630
|
+
});
|
|
631
|
+
state.recordToolSearchRuntimeTools(agent, generatedOutput.output, novelRuntimeTools);
|
|
632
|
+
hasGeneratedClientToolSearchOutputs = true;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
else if (output.type === 'tool_search_output') {
|
|
636
|
+
items.push(new items_1.RunToolSearchOutputItem(output, agent));
|
|
637
|
+
recordLoadedToolSearchOutput(loadedDeferredToolState, output);
|
|
638
|
+
(0, toolSearch_1.addHostedMcpToolsFromToolSearchOutput)(output, mcpToolMap, {
|
|
639
|
+
preserveExistingServerLabels: originalMcpServerLabels,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
else if (output.type === 'hosted_tool_call') {
|
|
643
|
+
items.push(new items_1.RunToolCallItem(output, agent));
|
|
644
|
+
const toolName = output.name;
|
|
645
|
+
toolsUsed.push(toolName);
|
|
646
|
+
if (output.providerData?.type === 'mcp_approval_request' ||
|
|
647
|
+
output.name === 'mcp_approval_request') {
|
|
648
|
+
const providerData = output.providerData;
|
|
649
|
+
const mcpServerLabel = providerData.server_label;
|
|
650
|
+
const mcpServerTool = mcpToolMap.get(mcpServerLabel);
|
|
651
|
+
if (typeof mcpServerTool === 'undefined') {
|
|
652
|
+
const message = `MCP server (${mcpServerLabel}) not found in Agent (${agent.name})`;
|
|
653
|
+
(0, context_1.addErrorToCurrentSpan)({
|
|
654
|
+
message,
|
|
655
|
+
data: { mcp_server_label: mcpServerLabel },
|
|
656
|
+
});
|
|
657
|
+
throw new errors_1.ModelBehaviorError(message);
|
|
658
|
+
}
|
|
659
|
+
const approvalItem = new items_1.RunToolApprovalItem({
|
|
660
|
+
type: 'hosted_tool_call',
|
|
661
|
+
name: providerData.name,
|
|
662
|
+
id: providerData.id,
|
|
663
|
+
status: 'in_progress',
|
|
664
|
+
providerData,
|
|
665
|
+
}, agent);
|
|
666
|
+
runMCPApprovalRequests.push({
|
|
667
|
+
requestItem: approvalItem,
|
|
668
|
+
mcpTool: mcpServerTool,
|
|
669
|
+
});
|
|
670
|
+
if (!mcpServerTool.providerData.on_approval) {
|
|
671
|
+
items.push(approvalItem);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
else if (output.type === 'reasoning') {
|
|
676
|
+
items.push(new items_1.RunReasoningItem(output, agent));
|
|
677
|
+
}
|
|
678
|
+
else if (output.type === 'computer_call') {
|
|
679
|
+
handleToolCallAction({
|
|
680
|
+
output,
|
|
681
|
+
tool: computerTool,
|
|
682
|
+
agent,
|
|
683
|
+
errorMessage: 'Model produced computer action without a computer tool.',
|
|
684
|
+
errorData: { agent_name: agent.name },
|
|
685
|
+
items,
|
|
686
|
+
toolsUsed,
|
|
687
|
+
actions: runComputerActions,
|
|
688
|
+
buildAction: (resolvedTool) => ({
|
|
689
|
+
toolCall: output,
|
|
690
|
+
computer: resolvedTool,
|
|
691
|
+
}),
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
else if (output.type === 'shell_call') {
|
|
695
|
+
const resolvedShellTool = ensureToolAvailable(shellTool, 'Model produced shell action without a shell tool.', { agent_name: agent.name });
|
|
696
|
+
items.push(new items_1.RunToolCallItem(output, agent));
|
|
697
|
+
toolsUsed.push(resolvedShellTool.name);
|
|
698
|
+
const shellEnvironmentType = resolvedShellTool.environment?.type ?? 'local';
|
|
699
|
+
if (shellEnvironmentType !== 'local') {
|
|
700
|
+
if (isShellCallPendingStatus(output.status)) {
|
|
701
|
+
hasHostedShellCall = true;
|
|
702
|
+
}
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
if (!resolvedShellTool.shell) {
|
|
706
|
+
const message = 'Model produced local shell action without a local shell implementation.';
|
|
707
|
+
(0, context_1.addErrorToCurrentSpan)({
|
|
708
|
+
message,
|
|
709
|
+
data: { agent_name: agent.name },
|
|
710
|
+
});
|
|
711
|
+
throw new errors_1.ModelBehaviorError(message);
|
|
712
|
+
}
|
|
713
|
+
runShellActions.push({
|
|
714
|
+
toolCall: output,
|
|
715
|
+
shell: resolvedShellTool,
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
else if (output.type === 'shell_call_output') {
|
|
719
|
+
items.push(new items_1.RunToolCallOutputItem(output, agent, output.output));
|
|
720
|
+
if (hasPendingShellOutputStatus(output)) {
|
|
721
|
+
hasHostedShellCall = true;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
else if (output.type === 'apply_patch_call') {
|
|
725
|
+
handleToolCallAction({
|
|
726
|
+
output,
|
|
727
|
+
tool: applyPatchTool,
|
|
728
|
+
agent,
|
|
729
|
+
errorMessage: 'Model produced apply_patch action without an apply_patch tool.',
|
|
730
|
+
errorData: { agent_name: agent.name },
|
|
731
|
+
items,
|
|
732
|
+
toolsUsed,
|
|
733
|
+
actions: runApplyPatchActions,
|
|
734
|
+
buildAction: (resolvedTool) => ({
|
|
735
|
+
toolCall: output,
|
|
736
|
+
applyPatch: resolvedTool,
|
|
737
|
+
}),
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
if (output.type !== 'function_call') {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
const resolved = resolveFunctionOrHandoff(output, handoffMap, functionMap, agent);
|
|
744
|
+
if (resolved.type === 'handoff') {
|
|
745
|
+
toolsUsed.push(output.name);
|
|
746
|
+
items.push(new items_1.RunHandoffCallItem(output, agent));
|
|
747
|
+
runHandoffs.push({
|
|
748
|
+
toolCall: output,
|
|
749
|
+
handoff: resolved.handoff,
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
else {
|
|
753
|
+
ensureDeferredFunctionToolLoaded(output, resolved.tool, loadedDeferredToolState.loadedToolNames, agent);
|
|
754
|
+
const normalizedToolCall = normalizeFunctionToolCallForStorage(output, resolved.tool);
|
|
755
|
+
toolsUsed.push((0, toolIdentity_1.getFunctionToolQualifiedName)(resolved.tool) ?? resolved.tool.name);
|
|
756
|
+
items.push(new items_1.RunToolCallItem(normalizedToolCall, agent));
|
|
757
|
+
runFunctions.push({
|
|
758
|
+
toolCall: normalizedToolCall,
|
|
759
|
+
tool: resolved.tool,
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
return {
|
|
764
|
+
newItems: items,
|
|
765
|
+
handoffs: runHandoffs,
|
|
766
|
+
functions: runFunctions,
|
|
767
|
+
computerActions: runComputerActions,
|
|
768
|
+
shellActions: runShellActions,
|
|
769
|
+
applyPatchActions: runApplyPatchActions,
|
|
770
|
+
mcpApprovalRequests: runMCPApprovalRequests,
|
|
771
|
+
toolsUsed,
|
|
772
|
+
hasToolsOrApprovalsToRun() {
|
|
773
|
+
return (runHandoffs.length > 0 ||
|
|
774
|
+
runFunctions.length > 0 ||
|
|
775
|
+
runMCPApprovalRequests.length > 0 ||
|
|
776
|
+
runComputerActions.length > 0 ||
|
|
777
|
+
runShellActions.length > 0 ||
|
|
778
|
+
hasHostedShellCall ||
|
|
779
|
+
runApplyPatchActions.length > 0 ||
|
|
780
|
+
hasGeneratedClientToolSearchOutputs);
|
|
241
781
|
},
|
|
242
782
|
};
|
|
243
783
|
}
|