@n8n/agents 0.26.3 → 0.27.1
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/build.tsbuildinfo +1 -1
- package/dist/runtime/loop/agent-runtime.d.ts +24 -51
- package/dist/runtime/loop/agent-runtime.js +321 -318
- package/dist/runtime/loop/agent-runtime.js.map +1 -1
- package/dist/runtime/loop/checkpoint-data.d.ts +12 -0
- package/dist/runtime/loop/checkpoint-data.js +65 -0
- package/dist/runtime/loop/checkpoint-data.js.map +1 -0
- package/dist/runtime/loop/execution-counter.js +1 -5
- package/dist/runtime/loop/execution-counter.js.map +1 -1
- package/dist/runtime/loop/generate-sink.d.ts +2 -2
- package/dist/runtime/loop/generate-sink.js +3 -5
- package/dist/runtime/loop/generate-sink.js.map +1 -1
- package/dist/runtime/loop/run-output-sink.d.ts +3 -78
- package/dist/runtime/loop/run-output-sink.js +7 -0
- package/dist/runtime/loop/run-output-sink.js.map +1 -1
- package/dist/runtime/loop/runtime-context.d.ts +17 -1
- package/dist/runtime/loop/runtime-context.js +49 -20
- package/dist/runtime/loop/runtime-context.js.map +1 -1
- package/dist/runtime/loop/runtime-helpers.d.ts +1 -1
- package/dist/runtime/loop/stream-sink.d.ts +9 -2
- package/dist/runtime/loop/stream-sink.js +78 -56
- package/dist/runtime/loop/stream-sink.js.map +1 -1
- package/dist/runtime/memory/memory-orchestrator.d.ts +1 -1
- package/dist/runtime/memory/memory-orchestrator.js +8 -8
- package/dist/runtime/memory/memory-orchestrator.js.map +1 -1
- package/dist/runtime/memory/memory-store.d.ts +1 -1
- package/dist/runtime/memory/memory-store.js +7 -2
- package/dist/runtime/memory/memory-store.js.map +1 -1
- package/dist/runtime/memory/tool-result-memory.d.ts +7 -0
- package/dist/runtime/memory/tool-result-memory.js +65 -0
- package/dist/runtime/memory/tool-result-memory.js.map +1 -0
- package/dist/runtime/model/messages.js +20 -9
- package/dist/runtime/model/messages.js.map +1 -1
- package/dist/runtime/model/raw-error.d.ts +1 -1
- package/dist/runtime/state/run-state.d.ts +2 -2
- package/dist/runtime/state/run-state.js +4 -4
- package/dist/runtime/state/run-state.js.map +1 -1
- package/dist/runtime/telemetry/runtime-telemetry.d.ts +1 -1
- package/dist/runtime/tools/delegate-sub-agent-runner.d.ts +13 -0
- package/dist/runtime/tools/delegate-sub-agent-runner.js +361 -0
- package/dist/runtime/tools/delegate-sub-agent-runner.js.map +1 -0
- package/dist/runtime/tools/delegate-sub-agent-tool.d.ts +5 -241
- package/dist/runtime/tools/delegate-sub-agent-tool.js +94 -487
- package/dist/runtime/tools/delegate-sub-agent-tool.js.map +1 -1
- package/dist/runtime/tools/tool-adapter.js +28 -28
- package/dist/runtime/tools/tool-adapter.js.map +1 -1
- package/dist/runtime/tools/tool-call-executor.d.ts +19 -86
- package/dist/runtime/tools/tool-call-executor.js +236 -579
- package/dist/runtime/tools/tool-call-executor.js.map +1 -1
- package/dist/runtime/tools/tool-call-runner.d.ts +25 -0
- package/dist/runtime/tools/tool-call-runner.js +328 -0
- package/dist/runtime/tools/tool-call-runner.js.map +1 -0
- package/dist/runtime/tools/tool-result-guard.d.ts +2 -7
- package/dist/runtime/tools/tool-result-guard.js +13 -70
- package/dist/runtime/tools/tool-result-guard.js.map +1 -1
- package/dist/types/runtime/agent-loop.d.ts +73 -0
- package/dist/types/runtime/agent-loop.js +3 -0
- package/dist/types/runtime/agent-loop.js.map +1 -0
- package/dist/types/runtime/agent-runtime.d.ts +51 -0
- package/dist/types/runtime/agent-runtime.js +3 -0
- package/dist/types/runtime/agent-runtime.js.map +1 -0
- package/dist/types/runtime/delegation.d.ts +234 -0
- package/dist/types/runtime/delegation.js +82 -0
- package/dist/types/runtime/delegation.js.map +1 -0
- package/dist/types/runtime/tool-execution.d.ts +103 -0
- package/dist/types/runtime/tool-execution.js +3 -0
- package/dist/types/runtime/tool-execution.js.map +1 -0
- package/dist/types/sdk/agent-builder.d.ts +1 -1
- package/dist/types/sdk/memory.d.ts +2 -1
- package/package.json +6 -6
|
@@ -1,51 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ToolCallExecutor = void 0;
|
|
4
|
-
const json_schema_1 = require("@n8n/ai-utilities/json-schema");
|
|
5
4
|
const delegate_sub_agent_tool_1 = require("./delegate-sub-agent-tool");
|
|
6
5
|
const sub_agent_task_path_1 = require("./sub-agent-task-path");
|
|
7
|
-
const
|
|
8
|
-
const tool_result_guard_1 = require("./tool-result-guard");
|
|
9
|
-
const untrusted_tool_output_1 = require("./untrusted-tool-output");
|
|
10
|
-
const abort_1 = require("../../sdk/abort");
|
|
11
|
-
const cancellation_1 = require("../../sdk/cancellation");
|
|
12
|
-
const message_1 = require("../../sdk/message");
|
|
13
|
-
const parse_1 = require("../../utils/parse");
|
|
14
|
-
const zod_1 = require("../../utils/zod");
|
|
6
|
+
const tool_call_runner_1 = require("./tool-call-runner");
|
|
15
7
|
const execution_counter_1 = require("../loop/execution-counter");
|
|
16
|
-
const runtime_helpers_1 = require("../loop/runtime-helpers");
|
|
17
8
|
const messages_1 = require("../model/messages");
|
|
18
|
-
function isDeniedApprovalResumeData(value) {
|
|
19
|
-
return value !== null && typeof value === 'object' && Reflect.get(value, 'approved') === false;
|
|
20
|
-
}
|
|
21
|
-
function shouldEmitToolExecutionStart(tool, resumeData) {
|
|
22
|
-
if (!tool.approval)
|
|
23
|
-
return true;
|
|
24
|
-
if (!tool.approval.required && tool.approval.conditional !== true)
|
|
25
|
-
return true;
|
|
26
|
-
if (resumeData === undefined)
|
|
27
|
-
return false;
|
|
28
|
-
return !isDeniedApprovalResumeData(resumeData);
|
|
29
|
-
}
|
|
30
|
-
function getToolResumeJsonSchema(tool, resumeSchemaOverride) {
|
|
31
|
-
const resolvedSchema = resumeSchemaOverride ?? tool.resumeSchema;
|
|
32
|
-
if (!resolvedSchema)
|
|
33
|
-
return undefined;
|
|
34
|
-
return (0, zod_1.isZodSchema)(resolvedSchema) ? (0, json_schema_1.zodSchemaToJsonSchema)(resolvedSchema) : resolvedSchema;
|
|
35
|
-
}
|
|
36
9
|
class ToolCallExecutor {
|
|
37
10
|
constructor(deps) {
|
|
38
11
|
this.deps = deps;
|
|
39
|
-
this.
|
|
12
|
+
this.runner = new tool_call_runner_1.ToolCallRunner(deps);
|
|
40
13
|
}
|
|
41
14
|
get hasOffloadedToolResults() {
|
|
42
|
-
return this.
|
|
43
|
-
}
|
|
44
|
-
get telemetry() {
|
|
45
|
-
return this.deps.telemetry;
|
|
46
|
-
}
|
|
47
|
-
get eventBus() {
|
|
48
|
-
return this.deps.eventBus;
|
|
15
|
+
return this.runner.hasOffloadedToolResults;
|
|
49
16
|
}
|
|
50
17
|
get concurrency() {
|
|
51
18
|
return this.deps.concurrency;
|
|
@@ -83,425 +50,277 @@ class ToolCallExecutor {
|
|
|
83
50
|
return batch;
|
|
84
51
|
}
|
|
85
52
|
async iterateToolCallsConcurrent(ctx) {
|
|
86
|
-
const { toolCalls, toolMap, list, runId, telemetry: resolvedTelemetry, executionCounter, abortSignal, } = ctx;
|
|
87
53
|
const errors = [];
|
|
88
|
-
const runtimeToolCalls =
|
|
89
|
-
for (const toolCall of toolCalls) {
|
|
90
|
-
const normalizedInput = (0, messages_1.normalizeToolInputForModel)(toolCall.input);
|
|
91
|
-
if (!normalizedInput.ok) {
|
|
92
|
-
const error = new Error(normalizedInput.error);
|
|
93
|
-
(0, execution_counter_1.incrementToolCallCount)(executionCounter);
|
|
94
|
-
list.setToolCallError(toolCall.toolCallId, error);
|
|
95
|
-
errors.push({
|
|
96
|
-
toolCallId: toolCall.toolCallId,
|
|
97
|
-
toolName: toolCall.toolName,
|
|
98
|
-
input: normalizedInput.input,
|
|
99
|
-
error,
|
|
100
|
-
});
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
runtimeToolCalls.push({ ...toolCall, input: normalizedInput.input });
|
|
104
|
-
}
|
|
54
|
+
const runtimeToolCalls = this.normalizeToolCalls(ctx.toolCalls, ctx, errors);
|
|
105
55
|
const executableCalls = runtimeToolCalls.filter((tc) => !tc.providerExecuted);
|
|
106
56
|
const providerExecutedCount = runtimeToolCalls.length - executableCalls.length;
|
|
107
57
|
for (let i = 0; i < providerExecutedCount; i++) {
|
|
108
|
-
(0, execution_counter_1.incrementToolCallCount)(executionCounter);
|
|
58
|
+
(0, execution_counter_1.incrementToolCallCount)(ctx.executionCounter);
|
|
109
59
|
}
|
|
110
60
|
const executableCallsById = new Map(executableCalls.map((tc) => [tc.toolCallId, tc]));
|
|
111
61
|
const unexecutedIds = new Set(executableCalls.map((tc) => tc.toolCallId));
|
|
112
|
-
const
|
|
113
|
-
const suspensions = [];
|
|
114
|
-
const pending = {};
|
|
62
|
+
const result = { results: [], suspensions: [], errors, pending: {} };
|
|
115
63
|
for (let batchStart = 0; batchStart < executableCalls.length;) {
|
|
116
64
|
if (ctx.isAborted()) {
|
|
117
|
-
this.
|
|
118
|
-
|
|
119
|
-
const tc = executableCallsById.get(id);
|
|
120
|
-
const modelOutput = '[Skipped: run was aborted]';
|
|
121
|
-
list.setToolCallResult(tc.toolCallId, modelOutput, { canceled: true });
|
|
122
|
-
results.push({
|
|
123
|
-
toolCallId: tc.toolCallId,
|
|
124
|
-
toolName: tc.toolName,
|
|
125
|
-
input: tc.input,
|
|
126
|
-
toolEntry: {
|
|
127
|
-
tool: tc.toolName,
|
|
128
|
-
input: tc.input,
|
|
129
|
-
output: modelOutput,
|
|
130
|
-
transformed: false,
|
|
131
|
-
canceled: true,
|
|
132
|
-
},
|
|
133
|
-
modelOutput,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
return await this.finalizeBatch({ results, suspensions, errors, pending }, ctx);
|
|
65
|
+
this.skipAbortedToolCalls(unexecutedIds, executableCallsById, ctx.list, result.results);
|
|
66
|
+
return await this.finalizeBatch(result, ctx);
|
|
137
67
|
}
|
|
138
|
-
const batch = this.takeNextToolCallBatch(executableCalls, batchStart, toolMap);
|
|
68
|
+
const batch = this.takeNextToolCallBatch(executableCalls, batchStart, ctx.toolMap);
|
|
139
69
|
batchStart += batch.length;
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
toolName: tc.toolName,
|
|
143
|
-
input: tc.input,
|
|
144
|
-
toolMap,
|
|
145
|
-
list,
|
|
146
|
-
runId,
|
|
147
|
-
persistence: ctx.persistence,
|
|
148
|
-
resolvedTelemetry,
|
|
149
|
-
executionCounter,
|
|
150
|
-
abortSignal,
|
|
151
|
-
countToolCall: true,
|
|
152
|
-
})));
|
|
153
|
-
for (const tc of batch) {
|
|
70
|
+
const settled = await this.executeToolCallBatch(batch, ctx);
|
|
71
|
+
for (const tc of batch)
|
|
154
72
|
unexecutedIds.delete(tc.toolCallId);
|
|
155
|
-
|
|
156
|
-
let hasSuspension = false;
|
|
157
|
-
for (let i = 0; i < settledResults.length; i++) {
|
|
158
|
-
const result = settledResults[i];
|
|
159
|
-
const tc = batch[i];
|
|
160
|
-
const toolInput = tc.input;
|
|
161
|
-
if (result.status === 'rejected') {
|
|
162
|
-
list.setToolCallError(tc.toolCallId, result.reason);
|
|
163
|
-
errors.push({
|
|
164
|
-
toolCallId: tc.toolCallId,
|
|
165
|
-
toolName: tc.toolName,
|
|
166
|
-
input: toolInput,
|
|
167
|
-
error: result.reason,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
else if (result.value.outcome === 'suspended') {
|
|
171
|
-
hasSuspension = true;
|
|
172
|
-
suspensions.push({
|
|
173
|
-
toolCallId: tc.toolCallId,
|
|
174
|
-
toolName: tc.toolName,
|
|
175
|
-
input: toolInput,
|
|
176
|
-
payload: result.value.payload,
|
|
177
|
-
resumeSchema: result.value.resumeSchema,
|
|
178
|
-
});
|
|
179
|
-
pending[tc.toolCallId] = {
|
|
180
|
-
suspended: true,
|
|
181
|
-
toolCallId: tc.toolCallId,
|
|
182
|
-
toolName: tc.toolName,
|
|
183
|
-
input: toolInput,
|
|
184
|
-
suspendPayload: result.value.payload,
|
|
185
|
-
resumeSchema: result.value.resumeSchema,
|
|
186
|
-
...(result.value.continuation !== undefined
|
|
187
|
-
? { continuation: result.value.continuation }
|
|
188
|
-
: {}),
|
|
189
|
-
runId,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
else if (result.value.outcome === 'success') {
|
|
193
|
-
results.push({
|
|
194
|
-
toolCallId: tc.toolCallId,
|
|
195
|
-
toolName: tc.toolName,
|
|
196
|
-
input: toolInput,
|
|
197
|
-
toolEntry: result.value.toolEntry,
|
|
198
|
-
modelOutput: result.value.modelOutput,
|
|
199
|
-
customMessage: result.value.customMessage,
|
|
200
|
-
...(result.value.mcpServerName !== undefined
|
|
201
|
-
? { mcpServerName: result.value.mcpServerName }
|
|
202
|
-
: {}),
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
else if (result.value.outcome === 'cancelled') {
|
|
206
|
-
results.push({
|
|
207
|
-
toolCallId: tc.toolCallId,
|
|
208
|
-
toolName: tc.toolName,
|
|
209
|
-
input: toolInput,
|
|
210
|
-
toolEntry: result.value.toolEntry,
|
|
211
|
-
modelOutput: result.value.modelOutput,
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
else if (result.value.outcome === 'error') {
|
|
215
|
-
errors.push({
|
|
216
|
-
toolCallId: tc.toolCallId,
|
|
217
|
-
toolName: tc.toolName,
|
|
218
|
-
input: toolInput,
|
|
219
|
-
error: result.value.error,
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
else if (result.value.outcome === 'noop') {
|
|
223
|
-
}
|
|
224
|
-
}
|
|
73
|
+
const hasSuspension = this.collectBatchResults(batch, settled, result, ctx);
|
|
225
74
|
if (ctx.isAborted()) {
|
|
226
|
-
this.
|
|
227
|
-
|
|
228
|
-
const tc = executableCallsById.get(id);
|
|
229
|
-
const modelOutput = '[Skipped: run was aborted]';
|
|
230
|
-
list.setToolCallResult(tc.toolCallId, modelOutput, { canceled: true });
|
|
231
|
-
results.push({
|
|
232
|
-
toolCallId: tc.toolCallId,
|
|
233
|
-
toolName: tc.toolName,
|
|
234
|
-
input: tc.input,
|
|
235
|
-
toolEntry: {
|
|
236
|
-
tool: tc.toolName,
|
|
237
|
-
input: tc.input,
|
|
238
|
-
output: modelOutput,
|
|
239
|
-
transformed: false,
|
|
240
|
-
canceled: true,
|
|
241
|
-
},
|
|
242
|
-
modelOutput,
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
return await this.finalizeBatch({ results, suspensions, errors, pending }, ctx);
|
|
75
|
+
this.skipAbortedToolCalls(unexecutedIds, executableCallsById, ctx.list, result.results);
|
|
76
|
+
return await this.finalizeBatch(result, ctx);
|
|
246
77
|
}
|
|
247
78
|
if (hasSuspension) {
|
|
248
|
-
|
|
249
|
-
const tc = executableCallsById.get(id);
|
|
250
|
-
pending[tc.toolCallId] = {
|
|
251
|
-
suspended: false,
|
|
252
|
-
toolCallId: tc.toolCallId,
|
|
253
|
-
toolName: tc.toolName,
|
|
254
|
-
input: tc.input,
|
|
255
|
-
};
|
|
256
|
-
}
|
|
79
|
+
this.retainUnexecutedToolCalls(unexecutedIds, executableCallsById, result.pending);
|
|
257
80
|
break;
|
|
258
81
|
}
|
|
259
82
|
}
|
|
260
|
-
return await this.finalizeBatch(
|
|
83
|
+
return await this.finalizeBatch(result, ctx);
|
|
261
84
|
}
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
suspended: true,
|
|
278
|
-
toolCallId: resumedEntry.toolCallId,
|
|
279
|
-
toolName: resumedToolName,
|
|
280
|
-
input: resumedEntry.input,
|
|
281
|
-
suspendPayload: processResult.payload,
|
|
282
|
-
resumeSchema: processResult.resumeSchema,
|
|
283
|
-
...(processResult.continuation !== undefined
|
|
284
|
-
? { continuation: processResult.continuation }
|
|
285
|
-
: {}),
|
|
286
|
-
runId,
|
|
287
|
-
};
|
|
288
|
-
suspensions.push({
|
|
289
|
-
toolCallId: resumedId,
|
|
290
|
-
toolName: resumedToolName,
|
|
291
|
-
input: resumedEntry.input,
|
|
292
|
-
payload: processResult.payload,
|
|
293
|
-
resumeSchema: processResult.resumeSchema,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
else if (processResult.outcome === 'success') {
|
|
297
|
-
results.push({
|
|
298
|
-
toolCallId: resumedEntry.toolCallId,
|
|
299
|
-
toolName: resumedToolName,
|
|
300
|
-
input: resumedEntry.input,
|
|
301
|
-
toolEntry: processResult.toolEntry,
|
|
302
|
-
modelOutput: processResult.modelOutput,
|
|
303
|
-
customMessage: processResult.customMessage,
|
|
304
|
-
...(processResult.mcpServerName !== undefined
|
|
305
|
-
? { mcpServerName: processResult.mcpServerName }
|
|
306
|
-
: {}),
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
else if (processResult.outcome === 'cancelled') {
|
|
310
|
-
results.push({
|
|
311
|
-
toolCallId: resumedEntry.toolCallId,
|
|
312
|
-
toolName: resumedToolName,
|
|
313
|
-
input: resumedEntry.input,
|
|
314
|
-
toolEntry: processResult.toolEntry,
|
|
315
|
-
modelOutput: processResult.modelOutput,
|
|
316
|
-
});
|
|
317
|
-
list.addInput([
|
|
318
|
-
{ role: 'user', content: [{ type: 'text', text: processResult.userMessage }] },
|
|
319
|
-
]);
|
|
320
|
-
for (const id of Object.keys(pendingResume.pendingToolCalls)) {
|
|
321
|
-
if (id !== resumedId) {
|
|
322
|
-
const siblingEntry = pendingResume.pendingToolCalls[id];
|
|
323
|
-
const siblingTool = toolMap.get(siblingEntry.toolName);
|
|
324
|
-
const siblingParams = this.pendingToolCallParams(siblingEntry, ctx, pendingResume.resumeData);
|
|
325
|
-
if (siblingEntry.suspended && siblingTool?.onCancellation) {
|
|
326
|
-
try {
|
|
327
|
-
await this.runCancellationCleanup(siblingParams, siblingTool, processResult.userMessage);
|
|
328
|
-
}
|
|
329
|
-
catch {
|
|
330
|
-
this.retainPendingToolCall(id, siblingEntry, pending, suspensions);
|
|
331
|
-
continue;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
const modelOutput = '[Skipped: a sibling tool call was cancelled]';
|
|
335
|
-
list.setToolCallResult(id, modelOutput, {
|
|
336
|
-
canceled: true,
|
|
337
|
-
});
|
|
338
|
-
results.push({
|
|
339
|
-
toolCallId: siblingEntry.toolCallId,
|
|
340
|
-
toolName: siblingEntry.toolName,
|
|
341
|
-
input: siblingEntry.input,
|
|
342
|
-
toolEntry: {
|
|
343
|
-
tool: siblingEntry.toolName,
|
|
344
|
-
input: siblingEntry.input,
|
|
345
|
-
output: modelOutput,
|
|
346
|
-
transformed: false,
|
|
347
|
-
canceled: true,
|
|
348
|
-
},
|
|
349
|
-
modelOutput,
|
|
350
|
-
});
|
|
351
|
-
}
|
|
85
|
+
normalizeToolCalls(toolCalls, ctx, errors) {
|
|
86
|
+
const calls = [];
|
|
87
|
+
for (const toolCall of toolCalls) {
|
|
88
|
+
const normalizedInput = (0, messages_1.normalizeToolInputForModel)(toolCall.input);
|
|
89
|
+
if (!normalizedInput.ok) {
|
|
90
|
+
const error = new Error(normalizedInput.error);
|
|
91
|
+
(0, execution_counter_1.incrementToolCallCount)(ctx.executionCounter);
|
|
92
|
+
ctx.list.setToolCallError(toolCall.toolCallId, error);
|
|
93
|
+
errors.push({
|
|
94
|
+
toolCallId: toolCall.toolCallId,
|
|
95
|
+
toolName: toolCall.toolName,
|
|
96
|
+
input: normalizedInput.input,
|
|
97
|
+
error,
|
|
98
|
+
});
|
|
99
|
+
continue;
|
|
352
100
|
}
|
|
353
|
-
|
|
101
|
+
calls.push({ ...toolCall, input: normalizedInput.input });
|
|
354
102
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
103
|
+
return calls;
|
|
104
|
+
}
|
|
105
|
+
async executeToolCallBatch(batch, ctx) {
|
|
106
|
+
return await Promise.allSettled(batch.map(async (tc) => await this.runner.processToolCall({
|
|
107
|
+
toolCallId: tc.toolCallId,
|
|
108
|
+
toolName: tc.toolName,
|
|
109
|
+
input: tc.input,
|
|
110
|
+
toolMap: ctx.toolMap,
|
|
111
|
+
list: ctx.list,
|
|
112
|
+
runId: ctx.runId,
|
|
113
|
+
persistence: ctx.persistence,
|
|
114
|
+
resolvedTelemetry: ctx.telemetry,
|
|
115
|
+
executionCounter: ctx.executionCounter,
|
|
116
|
+
abortSignal: ctx.abortSignal,
|
|
117
|
+
countToolCall: true,
|
|
118
|
+
})));
|
|
119
|
+
}
|
|
120
|
+
collectBatchResults(calls, settled, batch, ctx) {
|
|
121
|
+
let hasSuspension = false;
|
|
122
|
+
for (let i = 0; i < settled.length; i++) {
|
|
123
|
+
if (this.collectSettledToolCall(calls[i], settled[i], batch, ctx))
|
|
124
|
+
hasSuspension = true;
|
|
360
125
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
126
|
+
return hasSuspension;
|
|
127
|
+
}
|
|
128
|
+
collectSettledToolCall(call, result, batch, ctx) {
|
|
129
|
+
if (result.status === 'rejected') {
|
|
130
|
+
ctx.list.setToolCallError(call.toolCallId, result.reason);
|
|
131
|
+
batch.errors.push({
|
|
132
|
+
toolCallId: call.toolCallId,
|
|
133
|
+
toolName: call.toolName,
|
|
134
|
+
input: call.input,
|
|
135
|
+
error: result.reason,
|
|
367
136
|
});
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
const outcome = result.value;
|
|
140
|
+
switch (outcome.outcome) {
|
|
141
|
+
case 'suspended':
|
|
142
|
+
batch.suspensions.push(this.buildToolCallSuspension(call, outcome));
|
|
143
|
+
batch.pending[call.toolCallId] = this.buildPendingToolCall(call, outcome, ctx.runId);
|
|
144
|
+
return true;
|
|
145
|
+
case 'success':
|
|
146
|
+
case 'cancelled':
|
|
147
|
+
this.appendCompletedToolCall(call, outcome, batch.results);
|
|
148
|
+
break;
|
|
149
|
+
case 'error':
|
|
150
|
+
batch.errors.push({
|
|
151
|
+
toolCallId: call.toolCallId,
|
|
152
|
+
toolName: call.toolName,
|
|
153
|
+
input: call.input,
|
|
154
|
+
error: outcome.error,
|
|
383
155
|
});
|
|
384
|
-
|
|
156
|
+
break;
|
|
385
157
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
buildToolCallSuspension(call, outcome) {
|
|
161
|
+
return {
|
|
162
|
+
toolCallId: call.toolCallId,
|
|
163
|
+
toolName: call.toolName,
|
|
164
|
+
input: call.input,
|
|
165
|
+
payload: outcome.payload,
|
|
166
|
+
resumeSchema: outcome.resumeSchema,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
buildPendingToolCall(call, outcome, runId) {
|
|
170
|
+
return {
|
|
171
|
+
suspended: true,
|
|
172
|
+
toolCallId: call.toolCallId,
|
|
173
|
+
toolName: call.toolName,
|
|
174
|
+
input: call.input,
|
|
175
|
+
suspendPayload: outcome.payload,
|
|
176
|
+
resumeSchema: outcome.resumeSchema,
|
|
177
|
+
...(outcome.continuation !== undefined ? { continuation: outcome.continuation } : {}),
|
|
178
|
+
runId,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
appendCompletedToolCall(call, outcome, results) {
|
|
182
|
+
const result = {
|
|
183
|
+
toolCallId: call.toolCallId,
|
|
184
|
+
toolName: call.toolName,
|
|
185
|
+
input: call.input,
|
|
186
|
+
toolEntry: outcome.toolEntry,
|
|
187
|
+
modelOutput: outcome.modelOutput,
|
|
188
|
+
};
|
|
189
|
+
if (outcome.outcome === 'success') {
|
|
190
|
+
result.customMessage = outcome.customMessage;
|
|
191
|
+
if (outcome.mcpServerName !== undefined)
|
|
192
|
+
result.mcpServerName = outcome.mcpServerName;
|
|
402
193
|
}
|
|
403
|
-
|
|
194
|
+
results.push(result);
|
|
404
195
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
196
|
+
skipAbortedToolCalls(ids, calls, list, results) {
|
|
197
|
+
this.deps.onCancelled();
|
|
198
|
+
for (const id of ids) {
|
|
199
|
+
const call = calls.get(id);
|
|
200
|
+
const modelOutput = '[Skipped: run was aborted]';
|
|
201
|
+
list.setToolCallResult(call.toolCallId, modelOutput, { canceled: true });
|
|
202
|
+
results.push(this.buildSkippedToolResult(call, modelOutput));
|
|
410
203
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
204
|
+
}
|
|
205
|
+
buildSkippedToolResult(call, modelOutput) {
|
|
206
|
+
return {
|
|
207
|
+
toolCallId: call.toolCallId,
|
|
208
|
+
toolName: call.toolName,
|
|
209
|
+
input: call.input,
|
|
210
|
+
toolEntry: {
|
|
211
|
+
tool: call.toolName,
|
|
212
|
+
input: call.input,
|
|
213
|
+
output: modelOutput,
|
|
214
|
+
transformed: false,
|
|
215
|
+
canceled: true,
|
|
216
|
+
},
|
|
217
|
+
modelOutput,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
retainUnexecutedToolCalls(ids, calls, pending) {
|
|
221
|
+
for (const id of ids) {
|
|
222
|
+
const call = calls.get(id);
|
|
223
|
+
pending[call.toolCallId] = {
|
|
224
|
+
suspended: false,
|
|
225
|
+
toolCallId: call.toolCallId,
|
|
226
|
+
toolName: call.toolName,
|
|
227
|
+
input: call.input,
|
|
228
|
+
};
|
|
414
229
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
230
|
+
}
|
|
231
|
+
async iteratePendingToolCallsConcurrent(ctx) {
|
|
232
|
+
const { pendingResume } = ctx;
|
|
233
|
+
const resumedId = pendingResume.resumeToolCallId;
|
|
234
|
+
const resumedEntry = pendingResume.pendingToolCalls[resumedId];
|
|
235
|
+
if (!resumedEntry)
|
|
236
|
+
throw new Error(`No pending tool call found for toolCallId: ${resumedId}`);
|
|
237
|
+
const batch = { results: [], suspensions: [], errors: [], pending: {} };
|
|
238
|
+
const outcome = await this.runner.processToolCall(this.pendingToolCallParams(resumedEntry, ctx, pendingResume.resumeData));
|
|
239
|
+
if (outcome.outcome === 'cancelled') {
|
|
240
|
+
this.appendCompletedToolCall(resumedEntry, outcome, batch.results);
|
|
241
|
+
ctx.list.addInput([{ role: 'user', content: [{ type: 'text', text: outcome.userMessage }] }]);
|
|
242
|
+
await this.cancelSiblingToolCalls(ctx, batch, outcome.userMessage);
|
|
243
|
+
return await this.finalizeBatch(batch, ctx);
|
|
244
|
+
}
|
|
245
|
+
if (outcome.outcome === 'retryable-error') {
|
|
246
|
+
for (const [id, entry] of Object.entries(pendingResume.pendingToolCalls)) {
|
|
247
|
+
this.retainPendingToolCall(id, entry, batch.pending, batch.suspensions);
|
|
421
248
|
}
|
|
422
|
-
return this.
|
|
423
|
-
}
|
|
424
|
-
if (params.countToolCall ?? true) {
|
|
425
|
-
(0, execution_counter_1.incrementToolCallCount)(params.executionCounter);
|
|
426
|
-
}
|
|
427
|
-
const validation = await this.validateToolInput(params, builtTool);
|
|
428
|
-
if (!validation.ok)
|
|
429
|
-
return validation.outcome;
|
|
430
|
-
const input = validation.input;
|
|
431
|
-
if (shouldEmitToolExecutionStart(builtTool, resumeData)) {
|
|
432
|
-
this.eventBus.emit({
|
|
433
|
-
type: "tool_execution_start",
|
|
434
|
-
toolCallId,
|
|
435
|
-
toolName,
|
|
436
|
-
args: input,
|
|
437
|
-
});
|
|
249
|
+
return await this.finalizeBatch(batch, ctx);
|
|
438
250
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
...
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
if (abortObserved || params.abortSignal?.aborted) {
|
|
461
|
-
await cleanupInterruptedSuspension();
|
|
462
|
-
}
|
|
463
|
-
});
|
|
251
|
+
this.collectResumedToolCall(resumedId, resumedEntry, outcome, batch, ctx.runId);
|
|
252
|
+
await this.executeRemainingToolCalls(ctx, batch);
|
|
253
|
+
return await this.finalizeBatch(batch, ctx);
|
|
254
|
+
}
|
|
255
|
+
collectResumedToolCall(id, entry, outcome, batch, runId) {
|
|
256
|
+
switch (outcome.outcome) {
|
|
257
|
+
case 'suspended':
|
|
258
|
+
batch.pending[id] = this.buildPendingToolCall(entry, outcome, runId);
|
|
259
|
+
batch.suspensions.push(this.buildToolCallSuspension({ ...entry, toolCallId: id }, outcome));
|
|
260
|
+
break;
|
|
261
|
+
case 'success':
|
|
262
|
+
this.appendCompletedToolCall(entry, outcome, batch.results);
|
|
263
|
+
break;
|
|
264
|
+
case 'error':
|
|
265
|
+
batch.errors.push({
|
|
266
|
+
toolCallId: entry.toolCallId,
|
|
267
|
+
toolName: entry.toolName,
|
|
268
|
+
input: entry.input,
|
|
269
|
+
error: outcome.error,
|
|
270
|
+
});
|
|
271
|
+
break;
|
|
464
272
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
273
|
+
}
|
|
274
|
+
async cancelSiblingToolCalls(ctx, batch, userMessage) {
|
|
275
|
+
for (const id of Object.keys(ctx.pendingResume.pendingToolCalls)) {
|
|
276
|
+
if (id === ctx.pendingResume.resumeToolCallId)
|
|
277
|
+
continue;
|
|
278
|
+
const entry = ctx.pendingResume.pendingToolCalls[id];
|
|
279
|
+
const tool = ctx.toolMap.get(entry.toolName);
|
|
280
|
+
const params = this.pendingToolCallParams(entry, ctx, ctx.pendingResume.resumeData);
|
|
281
|
+
if (entry.suspended && tool?.onCancellation) {
|
|
282
|
+
try {
|
|
283
|
+
await this.runner.runCancellationCleanup(params, tool, userMessage);
|
|
470
284
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}
|
|
475
|
-
catch {
|
|
476
|
-
}
|
|
285
|
+
catch {
|
|
286
|
+
this.retainPendingToolCall(id, entry, batch.pending, batch.suspensions);
|
|
287
|
+
continue;
|
|
477
288
|
}
|
|
478
|
-
this.deps.onCancelled();
|
|
479
|
-
return this.buildCancelledOutcome(params, 'Run aborted');
|
|
480
289
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return await this.buildSuspendedOutcome(params, builtTool, toolResult);
|
|
290
|
+
const modelOutput = '[Skipped: a sibling tool call was cancelled]';
|
|
291
|
+
ctx.list.setToolCallResult(id, modelOutput, { canceled: true });
|
|
292
|
+
batch.results.push(this.buildSkippedToolResult(entry, modelOutput));
|
|
485
293
|
}
|
|
486
|
-
return await this.buildSuccessOutcome(params, builtTool, input, toolResult);
|
|
487
294
|
}
|
|
488
|
-
async
|
|
489
|
-
|
|
295
|
+
async executeRemainingToolCalls(ctx, result) {
|
|
296
|
+
const unexecuted = [];
|
|
297
|
+
for (const [id, entry] of Object.entries(ctx.pendingResume.pendingToolCalls)) {
|
|
298
|
+
if (id === ctx.pendingResume.resumeToolCallId)
|
|
299
|
+
continue;
|
|
300
|
+
if (entry.suspended) {
|
|
301
|
+
this.retainPendingToolCall(id, entry, result.pending, result.suspensions);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
unexecuted.push({ toolCallId: id, toolName: entry.toolName, input: entry.input });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (unexecuted.length === 0)
|
|
490
308
|
return;
|
|
491
|
-
await
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
runId:
|
|
496
|
-
persistence:
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
abortSignal:
|
|
500
|
-
|
|
501
|
-
suspendPayload: params.suspendPayload,
|
|
502
|
-
continuation: params.continuation,
|
|
503
|
-
resumeSchema: params.resumeSchema,
|
|
309
|
+
const batch = await this.iterateToolCallsConcurrent({
|
|
310
|
+
toolCalls: unexecuted,
|
|
311
|
+
toolMap: ctx.toolMap,
|
|
312
|
+
list: ctx.list,
|
|
313
|
+
runId: ctx.runId,
|
|
314
|
+
persistence: ctx.persistence,
|
|
315
|
+
telemetry: ctx.telemetry,
|
|
316
|
+
executionCounter: ctx.executionCounter,
|
|
317
|
+
abortSignal: ctx.abortSignal,
|
|
318
|
+
isAborted: ctx.isAborted,
|
|
504
319
|
});
|
|
320
|
+
result.results.push(...batch.results);
|
|
321
|
+
result.suspensions.push(...batch.suspensions);
|
|
322
|
+
result.errors.push(...batch.errors);
|
|
323
|
+
Object.assign(result.pending, batch.pending);
|
|
505
324
|
}
|
|
506
325
|
async cleanupPendingToolCalls(pending, ctx, message = 'Run aborted') {
|
|
507
326
|
for (const entry of Object.values(pending)) {
|
|
@@ -511,7 +330,7 @@ class ToolCallExecutor {
|
|
|
511
330
|
if (!tool?.onCancellation)
|
|
512
331
|
continue;
|
|
513
332
|
try {
|
|
514
|
-
await this.runCancellationCleanup(this.pendingToolCallParams(entry, ctx), tool, message);
|
|
333
|
+
await this.runner.runCancellationCleanup(this.pendingToolCallParams(entry, ctx), tool, message);
|
|
515
334
|
}
|
|
516
335
|
catch {
|
|
517
336
|
}
|
|
@@ -558,168 +377,6 @@ class ToolCallExecutor {
|
|
|
558
377
|
resumeSchema: entry.resumeSchema,
|
|
559
378
|
});
|
|
560
379
|
}
|
|
561
|
-
async toolError(params, error, builtTool) {
|
|
562
|
-
this.eventBus.emit({
|
|
563
|
-
type: "tool_execution_end",
|
|
564
|
-
toolCallId: params.toolCallId,
|
|
565
|
-
toolName: params.toolName,
|
|
566
|
-
result: error,
|
|
567
|
-
isError: true,
|
|
568
|
-
});
|
|
569
|
-
const errorText = (0, runtime_helpers_1.stringifyError)(error);
|
|
570
|
-
const guardedError = await (0, tool_result_guard_1.guardToolErrorForModel)(builtTool?.outputTrust === 'untrusted'
|
|
571
|
-
? (0, untrusted_tool_output_1.protectUntrustedToolError)(errorText, builtTool)
|
|
572
|
-
: errorText, this.deps.tokenCounter, this.getResultStorage(params));
|
|
573
|
-
params.list.setToolCallError(params.toolCallId, guardedError);
|
|
574
|
-
return { outcome: 'error', error };
|
|
575
|
-
}
|
|
576
|
-
findSettledToolCall(list, toolCallId) {
|
|
577
|
-
return list
|
|
578
|
-
.responseDelta()
|
|
579
|
-
.flatMap((m) => ((0, message_1.isLlmMessage)(m) && 'content' in m ? m.content : []))
|
|
580
|
-
.find((c) => c.type === 'tool-call' && c.toolCallId === toolCallId && c.state !== 'pending');
|
|
581
|
-
}
|
|
582
|
-
completeSettledToolCall(params, settledBlock) {
|
|
583
|
-
const settledResult = settledBlock.state === 'resolved' ? settledBlock.output : settledBlock.error;
|
|
584
|
-
this.eventBus.emit({
|
|
585
|
-
type: "tool_execution_end",
|
|
586
|
-
toolCallId: params.toolCallId,
|
|
587
|
-
toolName: params.toolName,
|
|
588
|
-
result: settledResult,
|
|
589
|
-
isError: settledBlock.state === 'rejected',
|
|
590
|
-
});
|
|
591
|
-
return { outcome: 'noop' };
|
|
592
|
-
}
|
|
593
|
-
buildCancelledOutcome(params, userMessage) {
|
|
594
|
-
const { toolCallId, toolName, input, list } = params;
|
|
595
|
-
const modelOutput = `[Tool call cancelled. User said: "${userMessage}"]`;
|
|
596
|
-
this.eventBus.emit({
|
|
597
|
-
type: "tool_execution_end",
|
|
598
|
-
toolCallId,
|
|
599
|
-
toolName,
|
|
600
|
-
result: modelOutput,
|
|
601
|
-
isError: false,
|
|
602
|
-
});
|
|
603
|
-
list.setToolCallResult(toolCallId, modelOutput, { canceled: true });
|
|
604
|
-
return {
|
|
605
|
-
outcome: 'cancelled',
|
|
606
|
-
toolEntry: { tool: toolName, input, output: modelOutput, transformed: false, canceled: true },
|
|
607
|
-
modelOutput,
|
|
608
|
-
userMessage,
|
|
609
|
-
canceled: true,
|
|
610
|
-
};
|
|
611
|
-
}
|
|
612
|
-
async validateToolInput(params, builtTool) {
|
|
613
|
-
if (!builtTool.inputSchema)
|
|
614
|
-
return { ok: true, input: params.input };
|
|
615
|
-
const result = await (0, parse_1.parseWithSchema)(builtTool.inputSchema, params.input);
|
|
616
|
-
if (!result.success) {
|
|
617
|
-
const reason = result.schemaInvalid
|
|
618
|
-
? `Tool ${params.toolName} has an input schema that could not be compiled: ${result.error}`
|
|
619
|
-
: `Invalid tool input: ${result.error}`;
|
|
620
|
-
return { ok: false, outcome: await this.toolError(params, new Error(reason)) };
|
|
621
|
-
}
|
|
622
|
-
return { ok: true, input: result.data };
|
|
623
|
-
}
|
|
624
|
-
async runToolHandler(params, builtTool, input, onSuspend) {
|
|
625
|
-
const { toolCallId, toolName, runId, persistence, resumeData, resolvedTelemetry, executionCounter, abortSignal, suspendPayload, continuation, resumeSchema, } = params;
|
|
626
|
-
return await this.telemetry.withToolSpan(toolCallId, toolName, input, resolvedTelemetry, async () => await (0, abort_1.raceWithAbort)(async () => await (0, tool_adapter_1.executeTool)(input, builtTool, resumeData, resolvedTelemetry, toolCallId, {
|
|
627
|
-
runId,
|
|
628
|
-
persistence,
|
|
629
|
-
...(this.deps.loadSkill ? { loadSkill: this.deps.loadSkill } : {}),
|
|
630
|
-
emitEvent: (event) => this.eventBus.emit(event),
|
|
631
|
-
abortSignal,
|
|
632
|
-
executionCounter,
|
|
633
|
-
suspendPayload,
|
|
634
|
-
continuation,
|
|
635
|
-
resumeSchema,
|
|
636
|
-
onSuspend,
|
|
637
|
-
}), abortSignal));
|
|
638
|
-
}
|
|
639
|
-
async buildSuspendedOutcome(params, builtTool, toolResult) {
|
|
640
|
-
if (builtTool.suspendSchema) {
|
|
641
|
-
const parseResult = await (0, parse_1.parseWithSchema)(builtTool.suspendSchema, toolResult.payload);
|
|
642
|
-
if (!parseResult.success) {
|
|
643
|
-
return await this.toolError(params, new Error(`Invalid suspend payload: ${parseResult.error}`));
|
|
644
|
-
}
|
|
645
|
-
toolResult.payload = parseResult.data;
|
|
646
|
-
}
|
|
647
|
-
const resumeSchema = getToolResumeJsonSchema(builtTool, toolResult.resumeSchema);
|
|
648
|
-
if (!resumeSchema) {
|
|
649
|
-
return await this.toolError(params, new Error(`Tool ${params.toolName} has no resume schema`));
|
|
650
|
-
}
|
|
651
|
-
return {
|
|
652
|
-
outcome: 'suspended',
|
|
653
|
-
payload: toolResult.payload,
|
|
654
|
-
resumeSchema,
|
|
655
|
-
...(toolResult.continuation !== undefined ? { continuation: toolResult.continuation } : {}),
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
async buildSuccessOutcome(params, builtTool, input, toolResult) {
|
|
659
|
-
const { toolCallId, toolName, list } = params;
|
|
660
|
-
let modelResult;
|
|
661
|
-
try {
|
|
662
|
-
modelResult = builtTool.toModelOutput ? builtTool.toModelOutput(toolResult) : toolResult;
|
|
663
|
-
if (builtTool.outputTrust === 'untrusted') {
|
|
664
|
-
modelResult = (0, untrusted_tool_output_1.protectUntrustedToolResult)(modelResult, builtTool);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
catch (error) {
|
|
668
|
-
return await this.toolError(params, error, builtTool);
|
|
669
|
-
}
|
|
670
|
-
const storage = this.getResultStorage(params);
|
|
671
|
-
const guardedResult = await (0, tool_result_guard_1.guardToolResultForModel)(modelResult, this.deps.tokenCounter, storage);
|
|
672
|
-
this.eventBus.emit({
|
|
673
|
-
type: "tool_execution_end",
|
|
674
|
-
toolCallId,
|
|
675
|
-
toolName,
|
|
676
|
-
result: toolResult,
|
|
677
|
-
isError: false,
|
|
678
|
-
});
|
|
679
|
-
list.setToolCallResult(toolCallId, guardedResult.historyOutput);
|
|
680
|
-
let customMessage = await builtTool.toMessage?.(toolResult);
|
|
681
|
-
if (customMessage && builtTool.outputTrust === 'untrusted') {
|
|
682
|
-
customMessage = (0, untrusted_tool_output_1.protectUntrustedToolMessage)(customMessage, builtTool);
|
|
683
|
-
}
|
|
684
|
-
let guardedCustomMessage = customMessage
|
|
685
|
-
? await (0, tool_result_guard_1.guardToolMessageForModel)(customMessage, this.deps.tokenCounter, storage)
|
|
686
|
-
: undefined;
|
|
687
|
-
if (guardedCustomMessage && 'role' in guardedCustomMessage) {
|
|
688
|
-
guardedCustomMessage = {
|
|
689
|
-
...guardedCustomMessage,
|
|
690
|
-
origin: { kind: 'tool', toolName },
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
if (guardedCustomMessage) {
|
|
694
|
-
list.addResponse([guardedCustomMessage]);
|
|
695
|
-
}
|
|
696
|
-
return {
|
|
697
|
-
outcome: 'success',
|
|
698
|
-
toolEntry: {
|
|
699
|
-
tool: toolName,
|
|
700
|
-
input,
|
|
701
|
-
output: toolResult,
|
|
702
|
-
transformed: !!builtTool.toModelOutput,
|
|
703
|
-
},
|
|
704
|
-
modelOutput: guardedResult.wireOutput,
|
|
705
|
-
customMessage: guardedCustomMessage,
|
|
706
|
-
...(builtTool.mcpServerName !== undefined ? { mcpServerName: builtTool.mcpServerName } : {}),
|
|
707
|
-
};
|
|
708
|
-
}
|
|
709
|
-
getResultStorage(params) {
|
|
710
|
-
const filesystem = this.deps.workspaceFilesystem;
|
|
711
|
-
if (!filesystem)
|
|
712
|
-
return undefined;
|
|
713
|
-
return {
|
|
714
|
-
filesystem,
|
|
715
|
-
runId: params.runId,
|
|
716
|
-
toolCallId: params.toolCallId,
|
|
717
|
-
onOffloaded: () => {
|
|
718
|
-
this.offloadedToolResults = true;
|
|
719
|
-
},
|
|
720
|
-
...(params.abortSignal ? { abortSignal: params.abortSignal } : {}),
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
380
|
}
|
|
724
381
|
exports.ToolCallExecutor = ToolCallExecutor;
|
|
725
382
|
//# sourceMappingURL=tool-call-executor.js.map
|