@n8n/agents 0.10.0 → 0.11.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/build.tsbuildinfo +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +27 -5
- package/dist/index.js.map +1 -1
- package/dist/runtime/agent-runtime.d.ts +14 -6
- package/dist/runtime/agent-runtime.js +320 -243
- package/dist/runtime/agent-runtime.js.map +1 -1
- package/dist/runtime/delegate-sub-agent-tool.d.ts +87 -0
- package/dist/runtime/delegate-sub-agent-tool.js +362 -0
- package/dist/runtime/delegate-sub-agent-tool.js.map +1 -0
- package/dist/runtime/event-bus.d.ts +8 -0
- package/dist/runtime/event-bus.js +48 -0
- package/dist/runtime/event-bus.js.map +1 -1
- package/dist/runtime/mcp-connection.d.ts +1 -2
- package/dist/runtime/mcp-connection.js +1 -4
- package/dist/runtime/mcp-connection.js.map +1 -1
- package/dist/runtime/message-list.d.ts +9 -3
- package/dist/runtime/message-list.js +16 -5
- package/dist/runtime/message-list.js.map +1 -1
- package/dist/runtime/messages.js +10 -2
- package/dist/runtime/messages.js.map +1 -1
- package/dist/runtime/model-factory.js +12 -0
- package/dist/runtime/model-factory.js.map +1 -1
- package/dist/runtime/provider-credentials.d.ts +13 -0
- package/dist/runtime/provider-credentials.js +1 -0
- package/dist/runtime/provider-credentials.js.map +1 -1
- package/dist/runtime/runtime-helpers.d.ts +1 -2
- package/dist/runtime/runtime-helpers.js +0 -8
- package/dist/runtime/runtime-helpers.js.map +1 -1
- package/dist/runtime/sdk-owned-tool.d.ts +4 -0
- package/dist/runtime/sdk-owned-tool.js +19 -0
- package/dist/runtime/sdk-owned-tool.js.map +1 -0
- package/dist/runtime/stream.js +8 -0
- package/dist/runtime/stream.js.map +1 -1
- package/dist/runtime/sub-agent-task-path.d.ts +10 -0
- package/dist/runtime/sub-agent-task-path.js +39 -0
- package/dist/runtime/sub-agent-task-path.js.map +1 -0
- package/dist/runtime/title-generation.js +3 -5
- package/dist/runtime/title-generation.js.map +1 -1
- package/dist/runtime/tool-adapter.d.ts +0 -9
- package/dist/runtime/tool-adapter.js +12 -21
- package/dist/runtime/tool-adapter.js.map +1 -1
- package/dist/runtime/write-todos-tool.d.ts +3 -0
- package/dist/runtime/write-todos-tool.js +95 -0
- package/dist/runtime/write-todos-tool.js.map +1 -0
- package/dist/sdk/agent.d.ts +19 -12
- package/dist/sdk/agent.js +318 -91
- package/dist/sdk/agent.js.map +1 -1
- package/dist/sdk/cancellation.d.ts +7 -0
- package/dist/sdk/cancellation.js +16 -0
- package/dist/sdk/cancellation.js.map +1 -0
- package/dist/sdk/catalog.js +20 -4
- package/dist/sdk/catalog.js.map +1 -1
- package/dist/sdk/mcp-client.d.ts +1 -1
- package/dist/sdk/mcp-client.js +2 -2
- package/dist/sdk/mcp-client.js.map +1 -1
- package/dist/sdk/memory.d.ts +1 -3
- package/dist/sdk/memory.js +0 -14
- package/dist/sdk/memory.js.map +1 -1
- package/dist/sdk/provider-capabilities.js +1 -0
- package/dist/sdk/provider-capabilities.js.map +1 -1
- package/dist/sdk/tool.d.ts +3 -0
- package/dist/sdk/tool.js +42 -10
- package/dist/sdk/tool.js.map +1 -1
- package/dist/storage/base-memory.d.ts +0 -31
- package/dist/storage/base-memory.js +0 -9
- package/dist/storage/base-memory.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/runtime/event.d.ts +31 -1
- package/dist/types/runtime/event.js +2 -0
- package/dist/types/runtime/event.js.map +1 -1
- package/dist/types/sdk/agent-builder.d.ts +0 -1
- package/dist/types/sdk/agent.d.ts +20 -15
- package/dist/types/sdk/memory.d.ts +0 -42
- package/dist/types/sdk/message.d.ts +1 -0
- package/dist/types/sdk/tool.d.ts +19 -1
- package/dist/utils/json-schema.d.ts +3 -0
- package/dist/utils/json-schema.js +72 -0
- package/dist/utils/json-schema.js.map +1 -0
- package/dist/workspace/filesystem/daytona-filesystem.d.ts +25 -0
- package/dist/workspace/filesystem/daytona-filesystem.js +130 -0
- package/dist/workspace/filesystem/daytona-filesystem.js.map +1 -0
- package/dist/workspace/filesystem/n8n-sandbox-filesystem.d.ts +25 -0
- package/dist/workspace/filesystem/n8n-sandbox-filesystem.js +126 -0
- package/dist/workspace/filesystem/n8n-sandbox-filesystem.js.map +1 -0
- package/dist/workspace/sandbox/base-sandbox.d.ts +1 -0
- package/dist/workspace/sandbox/base-sandbox.js +5 -0
- package/dist/workspace/sandbox/base-sandbox.js.map +1 -1
- package/dist/workspace/sandbox/create-workspace.d.ts +4 -0
- package/dist/workspace/sandbox/create-workspace.js +58 -0
- package/dist/workspace/sandbox/create-workspace.js.map +1 -0
- package/dist/workspace/sandbox/daytona-auth-manager.d.ts +26 -0
- package/dist/workspace/sandbox/daytona-auth-manager.js +84 -0
- package/dist/workspace/sandbox/daytona-auth-manager.js.map +1 -0
- package/dist/workspace/sandbox/daytona-sandbox.d.ts +72 -0
- package/dist/workspace/sandbox/daytona-sandbox.js +357 -0
- package/dist/workspace/sandbox/daytona-sandbox.js.map +1 -0
- package/dist/workspace/sandbox/index.d.ts +7 -0
- package/dist/workspace/sandbox/index.js +22 -0
- package/dist/workspace/sandbox/index.js.map +1 -0
- package/dist/workspace/sandbox/lazy-daytona.d.ts +2 -0
- package/dist/workspace/sandbox/lazy-daytona.js +12 -0
- package/dist/workspace/sandbox/lazy-daytona.js.map +1 -0
- package/dist/workspace/sandbox/logger.d.ts +12 -0
- package/dist/workspace/sandbox/logger.js +3 -0
- package/dist/workspace/sandbox/logger.js.map +1 -0
- package/dist/workspace/sandbox/n8n-sandbox-sandbox.d.ts +35 -0
- package/dist/workspace/sandbox/n8n-sandbox-sandbox.js +138 -0
- package/dist/workspace/sandbox/n8n-sandbox-sandbox.js.map +1 -0
- package/dist/workspace/sandbox/provider.d.ts +4 -0
- package/dist/workspace/sandbox/provider.js +14 -0
- package/dist/workspace/sandbox/provider.js.map +1 -0
- package/dist/workspace/sandbox/run-in-sandbox.d.ts +26 -0
- package/dist/workspace/sandbox/run-in-sandbox.js +19 -0
- package/dist/workspace/sandbox/run-in-sandbox.js.map +1 -0
- package/dist/workspace/sandbox/types.d.ts +41 -0
- package/dist/workspace/sandbox/types.js +3 -0
- package/dist/workspace/sandbox/types.js.map +1 -0
- package/dist/workspace/sandbox/workspace-root.d.ts +16 -0
- package/dist/workspace/sandbox/workspace-root.js +69 -0
- package/dist/workspace/sandbox/workspace-root.js.map +1 -0
- package/dist/workspace/tools/batch-str-replace-file.js +2 -2
- package/dist/workspace/tools/batch-str-replace-file.js.map +1 -1
- package/dist/workspace/tools/str-replace-file.js +2 -2
- package/dist/workspace/tools/str-replace-file.js.map +1 -1
- package/package.json +29 -17
- package/dist/sdk/network.d.ts +0 -20
- package/dist/sdk/network.js +0 -46
- package/dist/sdk/network.js.map +0 -1
|
@@ -6,6 +6,7 @@ const catalog_1 = require("../sdk/catalog");
|
|
|
6
6
|
const message_1 = require("../sdk/message");
|
|
7
7
|
const background_task_tracker_1 = require("./background-task-tracker");
|
|
8
8
|
const deferred_tool_manager_1 = require("./deferred-tool-manager");
|
|
9
|
+
const delegate_sub_agent_tool_1 = require("./delegate-sub-agent-tool");
|
|
9
10
|
const episodic_memory_1 = require("./episodic-memory");
|
|
10
11
|
const event_bus_1 = require("./event-bus");
|
|
11
12
|
const execution_counter_1 = require("./execution-counter");
|
|
@@ -26,9 +27,12 @@ const runtime_helpers_1 = require("./runtime-helpers");
|
|
|
26
27
|
const scoped_memory_task_runner_1 = require("./scoped-memory-task-runner");
|
|
27
28
|
const stream_1 = require("./stream");
|
|
28
29
|
const strip_orphaned_tool_messages_1 = require("./strip-orphaned-tool-messages");
|
|
30
|
+
const sub_agent_task_path_1 = require("./sub-agent-task-path");
|
|
29
31
|
const title_generation_1 = require("./title-generation");
|
|
30
32
|
const tool_adapter_1 = require("./tool-adapter");
|
|
33
|
+
const cancellation_1 = require("../sdk/cancellation");
|
|
31
34
|
const telemetry_1 = require("../sdk/telemetry");
|
|
35
|
+
const json_schema_1 = require("../utils/json-schema");
|
|
32
36
|
const parse_1 = require("../utils/parse");
|
|
33
37
|
const zod_1 = require("../utils/zod");
|
|
34
38
|
function isActiveSpanTracer(value) {
|
|
@@ -56,9 +60,7 @@ function summarizeToolForTelemetry(tool) {
|
|
|
56
60
|
description: tool.description,
|
|
57
61
|
type: tool.mcpTool ? 'mcp' : 'local',
|
|
58
62
|
...(tool.mcpServerName ? { mcp_server: tool.mcpServerName } : {}),
|
|
59
|
-
...(tool.suspendSchema || tool.resumeSchema || tool.
|
|
60
|
-
? { approval: true }
|
|
61
|
-
: {}),
|
|
63
|
+
...(tool.suspendSchema || tool.resumeSchema || tool.approval ? { approval: true } : {}),
|
|
62
64
|
...(tool.inputSchema ? { input_schema: getToolInputSchema(tool) } : {}),
|
|
63
65
|
};
|
|
64
66
|
}
|
|
@@ -72,6 +74,23 @@ function summarizeProviderToolForTelemetry(tool) {
|
|
|
72
74
|
...(tool.inputSchema ? { input_schema: getToolInputSchema(tool) } : {}),
|
|
73
75
|
};
|
|
74
76
|
}
|
|
77
|
+
function isDeniedApprovalResumeData(value) {
|
|
78
|
+
return value !== null && typeof value === 'object' && Reflect.get(value, 'approved') === false;
|
|
79
|
+
}
|
|
80
|
+
function shouldEmitToolExecutionStart(tool, resumeData) {
|
|
81
|
+
if (!tool.approval)
|
|
82
|
+
return true;
|
|
83
|
+
if (!tool.approval.required && tool.approval.conditional !== true)
|
|
84
|
+
return true;
|
|
85
|
+
if (resumeData === undefined)
|
|
86
|
+
return false;
|
|
87
|
+
return !isDeniedApprovalResumeData(resumeData);
|
|
88
|
+
}
|
|
89
|
+
function getToolResumeJsonSchema(tool) {
|
|
90
|
+
if (!tool.resumeSchema)
|
|
91
|
+
return undefined;
|
|
92
|
+
return (0, zod_1.isZodSchema)(tool.resumeSchema) ? (0, zod_to_json_schema_1.zodToJsonSchema)(tool.resumeSchema) : tool.resumeSchema;
|
|
93
|
+
}
|
|
75
94
|
function buildAgentRootInputAttributes(config) {
|
|
76
95
|
const localTools = (config.tools ?? []).map(summarizeToolForTelemetry);
|
|
77
96
|
const providerTools = (config.providerTools ?? []).map(summarizeProviderToolForTelemetry);
|
|
@@ -115,11 +134,13 @@ class AgentRuntime {
|
|
|
115
134
|
this.backgroundTasks = new background_task_tracker_1.BackgroundTaskTracker();
|
|
116
135
|
this.episodicMemoryTasksByResource = new Map();
|
|
117
136
|
this.config = config;
|
|
137
|
+
this.runId = config.runId ?? (0, run_state_1.generateRunId)();
|
|
118
138
|
if (config.deferredTools && config.deferredTools.length > 0) {
|
|
119
139
|
this.deferredToolManager = new deferred_tool_manager_1.DeferredToolManager(config.deferredTools, config.toolSearch);
|
|
120
140
|
}
|
|
121
|
-
this.runState = new run_state_1.RunStateManager(config.checkpointStorage);
|
|
141
|
+
this.runState = config.runState ?? new run_state_1.RunStateManager(config.checkpointStorage);
|
|
122
142
|
this.eventBus = config.eventBus ?? new event_bus_1.AgentEventBus();
|
|
143
|
+
this.modelCost = config.modelCost;
|
|
123
144
|
this.currentState = {
|
|
124
145
|
persistence: undefined,
|
|
125
146
|
status: 'idle',
|
|
@@ -131,6 +152,7 @@ class AgentRuntime {
|
|
|
131
152
|
this.config.telemetry = telemetry;
|
|
132
153
|
}
|
|
133
154
|
async dispose() {
|
|
155
|
+
this.eventBus.dispose();
|
|
134
156
|
await this.backgroundTasks.flush();
|
|
135
157
|
}
|
|
136
158
|
getState() {
|
|
@@ -140,44 +162,59 @@ class AgentRuntime {
|
|
|
140
162
|
this.eventBus.abort();
|
|
141
163
|
}
|
|
142
164
|
async generate(input, options) {
|
|
143
|
-
const
|
|
165
|
+
const abortScope = this.eventBus.createAbortScope(options?.abortSignal);
|
|
144
166
|
let list = undefined;
|
|
145
167
|
try {
|
|
146
168
|
const initializedList = await this.initRun(input, options);
|
|
147
169
|
list = initializedList;
|
|
148
|
-
const rawResult = await this.withTelemetryRootSpan('generate', options, runId, async () => await this.runGenerateLoop({ list: initializedList, options,
|
|
149
|
-
return this.finalizeGenerate(rawResult, list
|
|
170
|
+
const rawResult = await this.withTelemetryRootSpan('generate', options, this.runId, async () => await this.runGenerateLoop({ list: initializedList, options, abortScope }));
|
|
171
|
+
return this.finalizeGenerate(rawResult, list);
|
|
150
172
|
}
|
|
151
173
|
catch (error) {
|
|
152
174
|
await this.flushTelemetry(options);
|
|
153
|
-
const isAbort =
|
|
175
|
+
const isAbort = abortScope.isAborted;
|
|
154
176
|
this.updateState({ status: isAbort ? 'cancelled' : 'failed' });
|
|
155
177
|
if (!isAbort) {
|
|
156
178
|
this.eventBus.emit({ type: "error", message: String(error), error });
|
|
157
179
|
}
|
|
158
|
-
return {
|
|
180
|
+
return {
|
|
181
|
+
runId: this.runId,
|
|
182
|
+
messages: list?.responseDelta() ?? [],
|
|
183
|
+
finishReason: 'error',
|
|
184
|
+
error,
|
|
185
|
+
getState: () => this.getState(),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
abortScope.dispose();
|
|
159
190
|
}
|
|
160
191
|
}
|
|
161
192
|
async stream(input, options) {
|
|
162
|
-
const
|
|
193
|
+
const abortScope = this.eventBus.createAbortScope(options?.abortSignal);
|
|
163
194
|
let list;
|
|
164
195
|
try {
|
|
165
196
|
list = await this.initRun(input, options);
|
|
166
197
|
}
|
|
167
198
|
catch (error) {
|
|
168
|
-
const isAbort =
|
|
199
|
+
const isAbort = abortScope.isAborted;
|
|
169
200
|
this.updateState({ status: isAbort ? 'cancelled' : 'failed' });
|
|
170
201
|
if (!isAbort) {
|
|
171
202
|
this.eventBus.emit({ type: "error", message: String(error), error });
|
|
172
203
|
}
|
|
173
|
-
|
|
204
|
+
abortScope.dispose();
|
|
205
|
+
return { runId: this.runId, stream: (0, runtime_helpers_1.makeErrorStream)(error), getState: () => this.getState() };
|
|
174
206
|
}
|
|
175
|
-
return {
|
|
207
|
+
return {
|
|
208
|
+
runId: this.runId,
|
|
209
|
+
stream: this.startStreamLoop({ list, options, abortScope }),
|
|
210
|
+
getState: () => this.getState(),
|
|
211
|
+
};
|
|
176
212
|
}
|
|
177
213
|
async resume(method, data, options) {
|
|
178
|
-
|
|
214
|
+
this.runId = options.runId;
|
|
215
|
+
const state = await this.runState.resume(this.runId);
|
|
179
216
|
if (!state)
|
|
180
|
-
throw new Error(`No suspended run found for runId: ${
|
|
217
|
+
throw new Error(`No suspended run found for runId: ${this.runId}`);
|
|
181
218
|
const toolCall = state.pendingToolCalls[options.toolCallId];
|
|
182
219
|
if (!toolCall)
|
|
183
220
|
throw new Error(`No tool call found for toolCallId: ${options.toolCallId}`);
|
|
@@ -187,7 +224,8 @@ class AgentRuntime {
|
|
|
187
224
|
if (!toolForValidation)
|
|
188
225
|
throw new Error(`Tool ${toolCall.toolName} not found`);
|
|
189
226
|
let resumeData = data;
|
|
190
|
-
|
|
227
|
+
let abortScope;
|
|
228
|
+
if (!(0, cancellation_1.isCancellation)(resumeData) && toolForValidation.resumeSchema) {
|
|
191
229
|
const parseResult = await (0, parse_1.parseWithSchema)(toolForValidation.resumeSchema, data);
|
|
192
230
|
if (!parseResult.success) {
|
|
193
231
|
throw new Error(`Invalid resume payload: ${parseResult.error}`);
|
|
@@ -217,7 +255,8 @@ class AgentRuntime {
|
|
|
217
255
|
persistence: state.persistence,
|
|
218
256
|
...mergedExecOptions,
|
|
219
257
|
};
|
|
220
|
-
this.eventBus.
|
|
258
|
+
abortScope = this.eventBus.createAbortScope(resumeOptions.abortSignal);
|
|
259
|
+
const activeAbortScope = abortScope;
|
|
221
260
|
const pendingResume = {
|
|
222
261
|
pendingToolCalls: state.pendingToolCalls,
|
|
223
262
|
resumeToolCallId: options.toolCallId,
|
|
@@ -227,42 +266,50 @@ class AgentRuntime {
|
|
|
227
266
|
await this.ensureModelCost();
|
|
228
267
|
await this.setListObservationLogMemory(list, state.persistence);
|
|
229
268
|
if (method === 'generate') {
|
|
230
|
-
const rawResult = await this.withTelemetryRootSpan('generate', resumeOptions,
|
|
269
|
+
const rawResult = await this.withTelemetryRootSpan('generate', resumeOptions, this.runId, async () => await this.runGenerateLoop({
|
|
231
270
|
list,
|
|
232
271
|
options: resumeOptions,
|
|
233
|
-
|
|
272
|
+
abortScope: activeAbortScope,
|
|
234
273
|
pendingResume,
|
|
235
274
|
}));
|
|
236
275
|
if (!rawResult.pendingSuspend) {
|
|
237
|
-
await this.cleanupRun(
|
|
276
|
+
await this.cleanupRun();
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
return this.finalizeGenerate(rawResult, list);
|
|
280
|
+
}
|
|
281
|
+
finally {
|
|
282
|
+
abortScope.dispose();
|
|
238
283
|
}
|
|
239
|
-
return this.finalizeGenerate(rawResult, list, options.runId);
|
|
240
284
|
}
|
|
241
285
|
return {
|
|
242
|
-
runId:
|
|
286
|
+
runId: this.runId,
|
|
243
287
|
stream: this.startStreamLoop({
|
|
244
288
|
list,
|
|
245
289
|
options: resumeOptions,
|
|
246
|
-
|
|
290
|
+
abortScope: activeAbortScope,
|
|
247
291
|
pendingResume,
|
|
248
292
|
}),
|
|
293
|
+
getState: () => this.getState(),
|
|
249
294
|
};
|
|
250
295
|
}
|
|
251
296
|
catch (error) {
|
|
252
|
-
const isAbort =
|
|
297
|
+
const isAbort = abortScope?.isAborted ?? false;
|
|
298
|
+
abortScope?.dispose();
|
|
253
299
|
this.updateState({ status: isAbort ? 'cancelled' : 'failed' });
|
|
254
300
|
if (!isAbort) {
|
|
255
301
|
this.eventBus.emit({ type: "error", message: String(error), error });
|
|
256
302
|
}
|
|
257
303
|
if (method === 'generate') {
|
|
258
304
|
return {
|
|
259
|
-
runId:
|
|
305
|
+
runId: this.runId,
|
|
260
306
|
messages: [],
|
|
261
307
|
finishReason: 'error',
|
|
262
308
|
error,
|
|
309
|
+
getState: () => this.getState(),
|
|
263
310
|
};
|
|
264
311
|
}
|
|
265
|
-
return { runId:
|
|
312
|
+
return { runId: this.runId, stream: (0, runtime_helpers_1.makeErrorStream)(error), getState: () => this.getState() };
|
|
266
313
|
}
|
|
267
314
|
}
|
|
268
315
|
async buildMessageList(input, options) {
|
|
@@ -273,9 +320,6 @@ class AgentRuntime {
|
|
|
273
320
|
list.addHistory((0, strip_orphaned_tool_messages_1.stripOrphanedToolMessages)(memMessages));
|
|
274
321
|
}
|
|
275
322
|
}
|
|
276
|
-
if (this.config.semanticRecall && options?.persistence?.threadId) {
|
|
277
|
-
await this.performSemanticRecall(list, input, options.persistence, options.executionCounter);
|
|
278
|
-
}
|
|
279
323
|
await this.setListObservationLogMemory(list, options?.persistence);
|
|
280
324
|
list.addInput(input);
|
|
281
325
|
return list;
|
|
@@ -300,87 +344,7 @@ class AgentRuntime {
|
|
|
300
344
|
resourceId,
|
|
301
345
|
});
|
|
302
346
|
}
|
|
303
|
-
async performSemanticRecall(list, input, persistence, executionCounter) {
|
|
304
|
-
if (!this.config.semanticRecall || !this.config.memory)
|
|
305
|
-
return;
|
|
306
|
-
const userText = input
|
|
307
|
-
.filter((m) => (0, message_1.isLlmMessage)(m) && m.role === 'user')
|
|
308
|
-
.flatMap((m) => ((0, message_1.isLlmMessage)(m) ? m.content : []))
|
|
309
|
-
.filter((c) => c.type === 'text')
|
|
310
|
-
.map((c) => c.text)
|
|
311
|
-
.join(' ');
|
|
312
|
-
if (!userText)
|
|
313
|
-
return;
|
|
314
|
-
let recalled = [];
|
|
315
|
-
if (this.config.memory.queryEmbeddings && this.config.semanticRecall.embedder) {
|
|
316
|
-
const { embed } = getAiSdk();
|
|
317
|
-
const embeddingModel = (0, model_factory_1.createEmbeddingModel)(this.config.semanticRecall.embedder, this.config.semanticRecall.apiKey);
|
|
318
|
-
const { embedding, usage } = await embed({ model: embeddingModel, value: userText });
|
|
319
|
-
(0, execution_counter_1.incrementTokenCountFromUsage)(executionCounter, usage);
|
|
320
|
-
const hits = await this.config.memory.queryEmbeddings({
|
|
321
|
-
scope: this.config.semanticRecall.scope ?? 'resource',
|
|
322
|
-
threadId: persistence.threadId,
|
|
323
|
-
resourceId: persistence.resourceId,
|
|
324
|
-
vector: embedding,
|
|
325
|
-
topK: this.config.semanticRecall.topK,
|
|
326
|
-
});
|
|
327
|
-
if (hits.length > 0) {
|
|
328
|
-
const hitIds = new Set(hits.map((h) => h.id));
|
|
329
|
-
const allMsgs = await this.config.memory.getMessages(persistence.threadId);
|
|
330
|
-
if (this.config.semanticRecall.messageRange) {
|
|
331
|
-
recalled = this.expandMessageRange(allMsgs, hitIds, this.config.semanticRecall.messageRange);
|
|
332
|
-
}
|
|
333
|
-
else {
|
|
334
|
-
recalled = allMsgs.filter((m) => {
|
|
335
|
-
const id = m.id;
|
|
336
|
-
return id !== undefined && hitIds.has(id);
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
else if (this.config.memory.search) {
|
|
342
|
-
recalled = await this.config.memory.search(userText, {
|
|
343
|
-
threadId: persistence.threadId,
|
|
344
|
-
resourceId: persistence.resourceId,
|
|
345
|
-
topK: this.config.semanticRecall.topK,
|
|
346
|
-
messageRange: this.config.semanticRecall.messageRange,
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
if (recalled.length === 0)
|
|
350
|
-
return;
|
|
351
|
-
const { historyIds } = list.serialize();
|
|
352
|
-
const historyIdSet = new Set(historyIds);
|
|
353
|
-
const newRecalled = recalled.filter((m) => {
|
|
354
|
-
const id = m.id;
|
|
355
|
-
return !id || !historyIdSet.has(id);
|
|
356
|
-
});
|
|
357
|
-
if (newRecalled.length > 0) {
|
|
358
|
-
list.addHistory(newRecalled);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
expandMessageRange(allMsgs, hitIds, range) {
|
|
362
|
-
const expandedIds = new Set();
|
|
363
|
-
for (const msg of allMsgs) {
|
|
364
|
-
const id = 'id' in msg && typeof msg.id === 'string' ? msg.id : undefined;
|
|
365
|
-
if (!id || !hitIds.has(id))
|
|
366
|
-
continue;
|
|
367
|
-
const idx = allMsgs.indexOf(msg);
|
|
368
|
-
const start = Math.max(0, idx - (range.before ?? 0));
|
|
369
|
-
const end = Math.min(allMsgs.length - 1, idx + (range.after ?? 0));
|
|
370
|
-
for (let i = start; i <= end; i++) {
|
|
371
|
-
const el = allMsgs[i];
|
|
372
|
-
const mid = 'id' in el && typeof el.id === 'string' ? el.id : undefined;
|
|
373
|
-
if (mid)
|
|
374
|
-
expandedIds.add(mid);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return allMsgs.filter((m) => {
|
|
378
|
-
const mid = 'id' in m && typeof m.id === 'string' ? m.id : undefined;
|
|
379
|
-
return mid && expandedIds.has(mid);
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
347
|
async initRun(input, options) {
|
|
383
|
-
this.eventBus.resetAbort(options?.abortSignal);
|
|
384
348
|
this.updateState({
|
|
385
349
|
status: 'running',
|
|
386
350
|
persistence: options?.persistence,
|
|
@@ -391,14 +355,13 @@ class AgentRuntime {
|
|
|
391
355
|
this.incrementMessageCount(options?.executionCounter);
|
|
392
356
|
return await this.buildMessageList(normalizedInput, options);
|
|
393
357
|
}
|
|
394
|
-
finalizeGenerate(result, list
|
|
395
|
-
result.runId = runId;
|
|
358
|
+
finalizeGenerate(result, list) {
|
|
359
|
+
result.runId = this.runId;
|
|
396
360
|
result.usage = this.applyCost(result.usage);
|
|
397
361
|
result.model = this.modelIdString;
|
|
398
|
-
const finalized = (0, runtime_helpers_1.applySubAgentUsage)(result);
|
|
399
362
|
this.updateState({ status: 'success', messageList: list.serialize() });
|
|
400
|
-
this.eventBus.emit({ type: "agent_end", messages:
|
|
401
|
-
return
|
|
363
|
+
this.eventBus.emit({ type: "agent_end", messages: result.messages });
|
|
364
|
+
return { ...result, getState: () => this.getState() };
|
|
402
365
|
}
|
|
403
366
|
resolveTelemetry(options) {
|
|
404
367
|
if (this.config.telemetry)
|
|
@@ -422,6 +385,12 @@ class AgentRuntime {
|
|
|
422
385
|
},
|
|
423
386
|
};
|
|
424
387
|
}
|
|
388
|
+
buildSmoothStreamTransformOptions(options) {
|
|
389
|
+
if (options?.smoothStream === false)
|
|
390
|
+
return {};
|
|
391
|
+
const { smoothStream } = (0, lazy_ai_1.loadAi)();
|
|
392
|
+
return { experimental_transform: smoothStream(options?.smoothStream ?? {}) };
|
|
393
|
+
}
|
|
425
394
|
buildTelemetryOptions(options) {
|
|
426
395
|
const t = this.resolveTelemetry(options);
|
|
427
396
|
if (!t?.enabled)
|
|
@@ -537,13 +506,12 @@ class AgentRuntime {
|
|
|
537
506
|
});
|
|
538
507
|
}
|
|
539
508
|
async runGenerateLoop(ctx) {
|
|
540
|
-
const { list, options,
|
|
509
|
+
const { list, options, abortScope, pendingResume } = ctx;
|
|
541
510
|
this.hydrateDeferredToolsFromList(list);
|
|
542
511
|
let totalUsage;
|
|
543
512
|
let lastFinishReason = 'stop';
|
|
544
513
|
let structuredOutput;
|
|
545
514
|
const toolCallSummary = [];
|
|
546
|
-
const collectedSubAgentUsage = [];
|
|
547
515
|
const runTelemetry = this.resolveTelemetry(options);
|
|
548
516
|
const staticLoopContext = this.buildStaticLoopContext({
|
|
549
517
|
...options,
|
|
@@ -553,10 +521,12 @@ class AgentRuntime {
|
|
|
553
521
|
const pendingToolCtx = {
|
|
554
522
|
toolMap: pendingLoopContext.toolMap,
|
|
555
523
|
list,
|
|
556
|
-
runId,
|
|
524
|
+
runId: this.runId,
|
|
557
525
|
persistence: options?.persistence,
|
|
558
526
|
telemetry: runTelemetry,
|
|
559
527
|
executionCounter: options?.executionCounter,
|
|
528
|
+
abortSignal: abortScope.signal,
|
|
529
|
+
isAborted: () => abortScope.isAborted,
|
|
560
530
|
};
|
|
561
531
|
const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS;
|
|
562
532
|
let iterationCount = options?.iterationCount ?? 0;
|
|
@@ -568,11 +538,9 @@ class AgentRuntime {
|
|
|
568
538
|
});
|
|
569
539
|
for (const r of batch.results) {
|
|
570
540
|
toolCallSummary.push(r.toolEntry);
|
|
571
|
-
if (r.subAgentUsage)
|
|
572
|
-
collectedSubAgentUsage.push(...r.subAgentUsage);
|
|
573
541
|
}
|
|
574
542
|
if (Object.keys(batch.pending).length > 0) {
|
|
575
|
-
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage,
|
|
543
|
+
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, maxIterations, iterationCount);
|
|
576
544
|
return {
|
|
577
545
|
runId: suspendRunId,
|
|
578
546
|
messages: list.responseDelta(),
|
|
@@ -586,21 +554,24 @@ class AgentRuntime {
|
|
|
586
554
|
suspendPayload: s.payload,
|
|
587
555
|
resumeSchema: s.resumeSchema,
|
|
588
556
|
})),
|
|
557
|
+
getState: () => this.getState(),
|
|
589
558
|
};
|
|
590
559
|
}
|
|
591
560
|
}
|
|
592
561
|
const { generateText } = (0, lazy_ai_1.loadAi)();
|
|
593
562
|
for (; iterationCount < maxIterations; iterationCount++) {
|
|
594
|
-
if (
|
|
563
|
+
if (abortScope.isAborted) {
|
|
595
564
|
this.updateState({ status: 'cancelled' });
|
|
596
565
|
throw new Error('Agent run was aborted');
|
|
597
566
|
}
|
|
598
567
|
this.eventBus.emit({ type: "turn_start" });
|
|
599
568
|
const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools, options?.persistence, options?.executionCounter);
|
|
569
|
+
const { system, messages } = list.forLlm(effectiveInstructions, this.config.instructionProviderOptions);
|
|
600
570
|
const result = await generateText({
|
|
601
571
|
model: staticLoopContext.model,
|
|
602
|
-
|
|
603
|
-
|
|
572
|
+
system,
|
|
573
|
+
messages,
|
|
574
|
+
abortSignal: abortScope.signal,
|
|
604
575
|
...(hasTools ? { tools: aiTools } : {}),
|
|
605
576
|
...(staticLoopContext.providerOptions
|
|
606
577
|
? { providerOptions: staticLoopContext.providerOptions }
|
|
@@ -626,19 +597,19 @@ class AgentRuntime {
|
|
|
626
597
|
const batch = await this.iterateToolCallsConcurrent({
|
|
627
598
|
toolMap,
|
|
628
599
|
list,
|
|
629
|
-
runId,
|
|
600
|
+
runId: this.runId,
|
|
630
601
|
persistence: options?.persistence,
|
|
631
602
|
telemetry: runTelemetry,
|
|
632
603
|
executionCounter: options?.executionCounter,
|
|
604
|
+
abortSignal: abortScope.signal,
|
|
605
|
+
isAborted: () => abortScope.isAborted,
|
|
633
606
|
toolCalls: result.toolCalls,
|
|
634
607
|
});
|
|
635
608
|
for (const r of batch.results) {
|
|
636
609
|
toolCallSummary.push(r.toolEntry);
|
|
637
|
-
if (r.subAgentUsage)
|
|
638
|
-
collectedSubAgentUsage.push(...r.subAgentUsage);
|
|
639
610
|
}
|
|
640
611
|
if (Object.keys(batch.pending).length > 0) {
|
|
641
|
-
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage,
|
|
612
|
+
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, maxIterations, iterationCount + 1);
|
|
642
613
|
return {
|
|
643
614
|
runId: suspendRunId,
|
|
644
615
|
messages: list.responseDelta(),
|
|
@@ -652,6 +623,7 @@ class AgentRuntime {
|
|
|
652
623
|
suspendPayload: s.payload,
|
|
653
624
|
resumeSchema: s.resumeSchema,
|
|
654
625
|
})),
|
|
626
|
+
getState: () => this.getState(),
|
|
655
627
|
};
|
|
656
628
|
}
|
|
657
629
|
this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(list.responseDelta()));
|
|
@@ -677,35 +649,63 @@ class AgentRuntime {
|
|
|
677
649
|
}
|
|
678
650
|
}
|
|
679
651
|
return {
|
|
680
|
-
runId: runId
|
|
652
|
+
runId: this.runId,
|
|
681
653
|
messages: list.responseDelta(),
|
|
682
654
|
finishReason: lastFinishReason,
|
|
683
655
|
usage: totalUsage,
|
|
684
656
|
...(structuredOutput !== undefined && { structuredOutput }),
|
|
685
657
|
...(toolCallSummary.length > 0 && { toolCalls: toolCallSummary }),
|
|
686
|
-
|
|
658
|
+
getState: () => this.getState(),
|
|
687
659
|
};
|
|
688
660
|
}
|
|
689
661
|
startStreamLoop(ctx) {
|
|
690
|
-
const { options
|
|
662
|
+
const { options } = ctx;
|
|
691
663
|
const { readable, writable } = new TransformStream();
|
|
692
664
|
const writer = writable.getWriter();
|
|
665
|
+
const writeEventChunk = (chunk) => {
|
|
666
|
+
writer.write(chunk).catch(() => { });
|
|
667
|
+
};
|
|
693
668
|
const onToolExecutionStart = (data) => {
|
|
694
669
|
if (data.type !== "tool_execution_start")
|
|
695
670
|
return;
|
|
696
|
-
|
|
697
|
-
.write({
|
|
671
|
+
writeEventChunk({
|
|
698
672
|
type: 'tool-execution-start',
|
|
699
673
|
toolCallId: data.toolCallId,
|
|
700
674
|
toolName: data.toolName,
|
|
701
|
-
|
|
702
|
-
|
|
675
|
+
startTime: Date.now(),
|
|
676
|
+
});
|
|
677
|
+
};
|
|
678
|
+
const onToolExecutionEnd = (data) => {
|
|
679
|
+
if (data.type !== "tool_execution_end")
|
|
680
|
+
return;
|
|
681
|
+
writeEventChunk({
|
|
682
|
+
type: 'tool-execution-end',
|
|
683
|
+
toolCallId: data.toolCallId,
|
|
684
|
+
toolName: data.toolName,
|
|
685
|
+
isError: data.isError,
|
|
686
|
+
endTime: Date.now(),
|
|
687
|
+
});
|
|
688
|
+
};
|
|
689
|
+
const onSubAgentStarted = (data) => {
|
|
690
|
+
if (data.type !== "subagent_started")
|
|
691
|
+
return;
|
|
692
|
+
const { type: _type, ...payload } = data;
|
|
693
|
+
writeEventChunk({ type: 'subagent-started', ...payload });
|
|
694
|
+
};
|
|
695
|
+
const onSubAgentCompleted = (data) => {
|
|
696
|
+
if (data.type !== "subagent_completed")
|
|
697
|
+
return;
|
|
698
|
+
const { type: _type, ...payload } = data;
|
|
699
|
+
writeEventChunk({ type: 'subagent-completed', ...payload });
|
|
703
700
|
};
|
|
704
701
|
this.eventBus.on("tool_execution_start", onToolExecutionStart);
|
|
705
|
-
this.
|
|
702
|
+
this.eventBus.on("tool_execution_end", onToolExecutionEnd);
|
|
703
|
+
this.eventBus.on("subagent_started", onSubAgentStarted);
|
|
704
|
+
this.eventBus.on("subagent_completed", onSubAgentCompleted);
|
|
705
|
+
this.withTelemetryRootSpan('stream', options, this.runId, async () => await this.runStreamLoop({ ...ctx, writer }))
|
|
706
706
|
.catch(async (error) => {
|
|
707
707
|
await this.flushTelemetry(options);
|
|
708
|
-
await this.cleanupRun(
|
|
708
|
+
await this.cleanupRun();
|
|
709
709
|
try {
|
|
710
710
|
await writer.write({ type: 'error', error });
|
|
711
711
|
await writer.write({ type: 'finish', finishReason: 'error' });
|
|
@@ -717,11 +717,15 @@ class AgentRuntime {
|
|
|
717
717
|
})
|
|
718
718
|
.finally(() => {
|
|
719
719
|
this.eventBus.off("tool_execution_start", onToolExecutionStart);
|
|
720
|
+
this.eventBus.off("tool_execution_end", onToolExecutionEnd);
|
|
721
|
+
this.eventBus.off("subagent_started", onSubAgentStarted);
|
|
722
|
+
this.eventBus.off("subagent_completed", onSubAgentCompleted);
|
|
723
|
+
ctx.abortScope.dispose();
|
|
720
724
|
});
|
|
721
725
|
return readable;
|
|
722
726
|
}
|
|
723
727
|
async runStreamLoop(ctx) {
|
|
724
|
-
const { list, options,
|
|
728
|
+
const { list, options, abortScope, pendingResume, writer } = ctx;
|
|
725
729
|
this.hydrateDeferredToolsFromList(list);
|
|
726
730
|
const writeChunk = async (chunk) => {
|
|
727
731
|
await writer.write(chunk);
|
|
@@ -729,20 +733,19 @@ class AgentRuntime {
|
|
|
729
733
|
let totalUsage;
|
|
730
734
|
let lastFinishReason = 'stop';
|
|
731
735
|
let structuredOutput;
|
|
732
|
-
const collectedSubAgentUsage = [];
|
|
733
736
|
const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS;
|
|
734
737
|
let iterationCount = options?.iterationCount ?? 0;
|
|
735
738
|
let reachedStopCondition = false;
|
|
736
739
|
const { streamText } = (0, lazy_ai_1.loadAi)();
|
|
737
740
|
const closeStreamWithError = async (error, status) => {
|
|
738
|
-
await this.cleanupRun(
|
|
741
|
+
await this.cleanupRun();
|
|
739
742
|
this.updateState({ status });
|
|
740
743
|
await writer.write({ type: 'error', error });
|
|
741
744
|
await writer.write({ type: 'finish', finishReason: 'error' });
|
|
742
745
|
await writer.close();
|
|
743
746
|
};
|
|
744
747
|
const handleAbort = async () => {
|
|
745
|
-
if (!
|
|
748
|
+
if (!abortScope.isAborted)
|
|
746
749
|
return false;
|
|
747
750
|
await closeStreamWithError(new Error('Agent run was aborted'), 'cancelled');
|
|
748
751
|
return true;
|
|
@@ -756,10 +759,12 @@ class AgentRuntime {
|
|
|
756
759
|
const pendingToolCtx = {
|
|
757
760
|
toolMap: pendingLoopContext.toolMap,
|
|
758
761
|
list,
|
|
759
|
-
runId,
|
|
762
|
+
runId: this.runId,
|
|
760
763
|
persistence: options?.persistence,
|
|
761
764
|
telemetry: runTelemetry,
|
|
762
765
|
executionCounter: options?.executionCounter,
|
|
766
|
+
abortSignal: abortScope.signal,
|
|
767
|
+
isAborted: () => abortScope.isAborted,
|
|
763
768
|
};
|
|
764
769
|
if (pendingResume) {
|
|
765
770
|
try {
|
|
@@ -768,13 +773,12 @@ class AgentRuntime {
|
|
|
768
773
|
pendingResume,
|
|
769
774
|
});
|
|
770
775
|
for (const r of batch.results) {
|
|
771
|
-
if (r.subAgentUsage)
|
|
772
|
-
collectedSubAgentUsage.push(...r.subAgentUsage);
|
|
773
776
|
await writer.write({
|
|
774
777
|
type: 'tool-result',
|
|
775
778
|
toolCallId: r.toolCallId,
|
|
776
779
|
toolName: r.toolName,
|
|
777
780
|
output: r.modelOutput,
|
|
781
|
+
...(r.toolEntry.canceled ? { canceled: true } : {}),
|
|
778
782
|
});
|
|
779
783
|
if (r.customMessage) {
|
|
780
784
|
await writer.write({ type: 'message', message: r.customMessage });
|
|
@@ -790,7 +794,7 @@ class AgentRuntime {
|
|
|
790
794
|
});
|
|
791
795
|
}
|
|
792
796
|
if (Object.keys(batch.pending).length > 0) {
|
|
793
|
-
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage,
|
|
797
|
+
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, maxIterations, iterationCount);
|
|
794
798
|
for (const s of batch.suspensions) {
|
|
795
799
|
await writer.write({
|
|
796
800
|
type: 'tool-call-suspended',
|
|
@@ -818,25 +822,45 @@ class AgentRuntime {
|
|
|
818
822
|
return;
|
|
819
823
|
this.eventBus.emit({ type: "turn_start" });
|
|
820
824
|
const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools, options?.persistence, options?.executionCounter);
|
|
821
|
-
const messages = list.forLlm(effectiveInstructions, this.config.instructionProviderOptions);
|
|
825
|
+
const { system, messages } = list.forLlm(effectiveInstructions, this.config.instructionProviderOptions);
|
|
822
826
|
const result = streamText({
|
|
823
827
|
model: staticLoopContext.model,
|
|
828
|
+
system,
|
|
824
829
|
messages,
|
|
825
|
-
abortSignal:
|
|
830
|
+
abortSignal: abortScope.signal,
|
|
826
831
|
...(hasTools ? { tools: aiTools } : {}),
|
|
827
832
|
...(staticLoopContext.providerOptions
|
|
828
833
|
? { providerOptions: staticLoopContext.providerOptions }
|
|
829
834
|
: {}),
|
|
830
835
|
...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}),
|
|
831
836
|
...this.buildAiSdkOptions(toolMap, options),
|
|
837
|
+
...this.buildSmoothStreamTransformOptions(options),
|
|
832
838
|
});
|
|
833
839
|
try {
|
|
834
840
|
for await (const chunk of result.fullStream) {
|
|
835
841
|
if (chunk.type === 'finish')
|
|
836
842
|
continue;
|
|
843
|
+
if ((chunk.type === 'tool-result' || chunk.type === 'tool-error') &&
|
|
844
|
+
chunk.providerExecuted) {
|
|
845
|
+
await writeChunk({
|
|
846
|
+
type: 'tool-execution-end',
|
|
847
|
+
toolCallId: chunk.toolCallId,
|
|
848
|
+
toolName: chunk.toolName ?? '',
|
|
849
|
+
isError: chunk.type === 'tool-error',
|
|
850
|
+
endTime: Date.now(),
|
|
851
|
+
});
|
|
852
|
+
}
|
|
837
853
|
const converted = (0, stream_1.convertChunk)(chunk);
|
|
838
854
|
if (converted)
|
|
839
855
|
await writeChunk(converted);
|
|
856
|
+
if (chunk.type === 'tool-call' && chunk.providerExecuted) {
|
|
857
|
+
await writeChunk({
|
|
858
|
+
type: 'tool-execution-start',
|
|
859
|
+
toolCallId: chunk.toolCallId,
|
|
860
|
+
toolName: chunk.toolName ?? '',
|
|
861
|
+
startTime: Date.now(),
|
|
862
|
+
});
|
|
863
|
+
}
|
|
840
864
|
}
|
|
841
865
|
}
|
|
842
866
|
catch (streamError) {
|
|
@@ -874,22 +898,23 @@ class AgentRuntime {
|
|
|
874
898
|
const batch = await this.iterateToolCallsConcurrent({
|
|
875
899
|
toolMap,
|
|
876
900
|
list,
|
|
877
|
-
runId,
|
|
901
|
+
runId: this.runId,
|
|
878
902
|
persistence: options?.persistence,
|
|
879
903
|
telemetry: runTelemetry,
|
|
880
904
|
executionCounter: options?.executionCounter,
|
|
905
|
+
abortSignal: abortScope.signal,
|
|
906
|
+
isAborted: () => abortScope.isAborted,
|
|
881
907
|
toolCalls,
|
|
882
908
|
});
|
|
883
909
|
if (await handleAbort())
|
|
884
910
|
return;
|
|
885
911
|
for (const r of batch.results) {
|
|
886
|
-
if (r.subAgentUsage)
|
|
887
|
-
collectedSubAgentUsage.push(...r.subAgentUsage);
|
|
888
912
|
await writer.write({
|
|
889
913
|
type: 'tool-result',
|
|
890
914
|
toolCallId: r.toolCallId,
|
|
891
915
|
toolName: r.toolName,
|
|
892
916
|
output: r.modelOutput,
|
|
917
|
+
...(r.toolEntry.canceled ? { canceled: true } : {}),
|
|
893
918
|
});
|
|
894
919
|
if (r.customMessage) {
|
|
895
920
|
await writer.write({ type: 'message', message: r.customMessage });
|
|
@@ -905,7 +930,7 @@ class AgentRuntime {
|
|
|
905
930
|
});
|
|
906
931
|
}
|
|
907
932
|
if (Object.keys(batch.pending).length > 0) {
|
|
908
|
-
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage,
|
|
933
|
+
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, maxIterations, iterationCount + 1);
|
|
909
934
|
for (const s of batch.suspensions) {
|
|
910
935
|
await writer.write({
|
|
911
936
|
type: 'tool-call-suspended',
|
|
@@ -933,18 +958,12 @@ class AgentRuntime {
|
|
|
933
958
|
lastFinishReason = 'max-iterations';
|
|
934
959
|
}
|
|
935
960
|
const costUsage = this.applyCost(totalUsage);
|
|
936
|
-
const parentCost = costUsage?.cost ?? 0;
|
|
937
|
-
const subCost = collectedSubAgentUsage.reduce((sum, s) => sum + (s.usage.cost ?? 0), 0);
|
|
938
961
|
await writer.write({
|
|
939
962
|
type: 'finish',
|
|
940
963
|
finishReason: lastFinishReason,
|
|
941
964
|
...(costUsage && { usage: costUsage }),
|
|
942
965
|
model: this.modelIdString,
|
|
943
966
|
...(structuredOutput !== undefined && { structuredOutput }),
|
|
944
|
-
...(collectedSubAgentUsage.length > 0 && {
|
|
945
|
-
subAgentUsage: collectedSubAgentUsage,
|
|
946
|
-
totalCost: parentCost + subCost,
|
|
947
|
-
}),
|
|
948
967
|
});
|
|
949
968
|
try {
|
|
950
969
|
await this.saveToMemory(list, options);
|
|
@@ -963,7 +982,7 @@ class AgentRuntime {
|
|
|
963
982
|
await titlePromise;
|
|
964
983
|
}
|
|
965
984
|
}
|
|
966
|
-
await this.cleanupRun(
|
|
985
|
+
await this.cleanupRun();
|
|
967
986
|
await this.flushTelemetry(options);
|
|
968
987
|
this.updateState({ status: 'success', messageList: list.serialize() });
|
|
969
988
|
this.eventBus.emit({ type: "agent_end", messages: list.responseDelta() });
|
|
@@ -979,9 +998,6 @@ class AgentRuntime {
|
|
|
979
998
|
if (delta.length === 0)
|
|
980
999
|
return;
|
|
981
1000
|
await (0, memory_store_1.saveMessagesToThread)(this.config.memory, options.persistence.threadId, options.persistence.resourceId, delta);
|
|
982
|
-
if (this.config.semanticRecall?.embedder && this.config.memory.saveEmbeddings) {
|
|
983
|
-
await this.saveEmbeddingsForMessages(options.persistence.threadId, options.persistence.resourceId, delta, options.executionCounter);
|
|
984
|
-
}
|
|
985
1001
|
const observationTasks = this.scheduleObservationLogJobs(options.persistence, options.executionCounter);
|
|
986
1002
|
this.scheduleEpisodicMemoryJob(options.persistence, observationTasks, options.executionCounter);
|
|
987
1003
|
}
|
|
@@ -1119,43 +1135,6 @@ class AgentRuntime {
|
|
|
1119
1135
|
observationScopeId: persistence.threadId,
|
|
1120
1136
|
};
|
|
1121
1137
|
}
|
|
1122
|
-
async saveEmbeddingsForMessages(threadId, resourceId, messages, executionCounter) {
|
|
1123
|
-
const embeddable = [];
|
|
1124
|
-
for (const msg of messages) {
|
|
1125
|
-
if (!(0, message_1.isLlmMessage)(msg) || (msg.role !== 'user' && msg.role !== 'assistant'))
|
|
1126
|
-
continue;
|
|
1127
|
-
const text = msg.content
|
|
1128
|
-
.filter((c) => c.type === 'text')
|
|
1129
|
-
.map((c) => c.text)
|
|
1130
|
-
.join('\n');
|
|
1131
|
-
if (!text)
|
|
1132
|
-
continue;
|
|
1133
|
-
embeddable.push({ id: msg.id, text });
|
|
1134
|
-
}
|
|
1135
|
-
if (embeddable.length === 0)
|
|
1136
|
-
return;
|
|
1137
|
-
const embedder = this.config.semanticRecall?.embedder;
|
|
1138
|
-
if (!embedder)
|
|
1139
|
-
return;
|
|
1140
|
-
const { embedMany } = getAiSdk();
|
|
1141
|
-
const embeddingModel = (0, model_factory_1.createEmbeddingModel)(embedder, this.config.semanticRecall?.apiKey);
|
|
1142
|
-
const { embeddings, usage } = await embedMany({
|
|
1143
|
-
model: embeddingModel,
|
|
1144
|
-
values: embeddable.map((e) => e.text),
|
|
1145
|
-
});
|
|
1146
|
-
(0, execution_counter_1.incrementTokenCountFromUsage)(executionCounter, usage);
|
|
1147
|
-
await this.config.memory.saveEmbeddings({
|
|
1148
|
-
scope: this.config.semanticRecall?.scope ?? 'resource',
|
|
1149
|
-
threadId,
|
|
1150
|
-
resourceId,
|
|
1151
|
-
entries: embeddable.map((e, i) => ({
|
|
1152
|
-
id: e.id,
|
|
1153
|
-
vector: embeddings[i],
|
|
1154
|
-
text: e.text,
|
|
1155
|
-
model: embedder,
|
|
1156
|
-
})),
|
|
1157
|
-
});
|
|
1158
|
-
}
|
|
1159
1138
|
buildThinkingProviderOptions() {
|
|
1160
1139
|
if (!this.config.thinking)
|
|
1161
1140
|
return undefined;
|
|
@@ -1215,8 +1194,39 @@ class AgentRuntime {
|
|
|
1215
1194
|
}
|
|
1216
1195
|
return merged;
|
|
1217
1196
|
}
|
|
1197
|
+
isDelegateSubAgentCall(toolName) {
|
|
1198
|
+
return toolName === delegate_sub_agent_tool_1.DELEGATE_SUB_AGENT_TOOL_NAME;
|
|
1199
|
+
}
|
|
1200
|
+
getToolCallBatchSize(toolName, toolMap) {
|
|
1201
|
+
if (!this.isDelegateSubAgentCall(toolName))
|
|
1202
|
+
return this.concurrency;
|
|
1203
|
+
const tool = toolMap.get(toolName);
|
|
1204
|
+
const delegateOptions = tool ? (0, delegate_sub_agent_tool_1.getInlineDelegateSubAgentToolOptions)(tool) : undefined;
|
|
1205
|
+
return delegateOptions?.policy?.maxChildren ?? sub_agent_task_path_1.DEFAULT_SUB_AGENT_MAX_CHILDREN;
|
|
1206
|
+
}
|
|
1207
|
+
takeNextToolCallBatch(calls, start, toolMap) {
|
|
1208
|
+
const first = calls[start];
|
|
1209
|
+
if (!first) {
|
|
1210
|
+
throw new Error('Unable to build tool-call batch');
|
|
1211
|
+
}
|
|
1212
|
+
const isDelegateBatch = this.isDelegateSubAgentCall(first.toolName);
|
|
1213
|
+
const batchSize = this.getToolCallBatchSize(first.toolName, toolMap);
|
|
1214
|
+
if (batchSize < 1 ||
|
|
1215
|
+
Number.isNaN(batchSize) ||
|
|
1216
|
+
(isDelegateBatch && !Number.isFinite(batchSize))) {
|
|
1217
|
+
throw new Error(`Invalid tool-call batch size for ${first.toolName}: ${batchSize}`);
|
|
1218
|
+
}
|
|
1219
|
+
const batch = [];
|
|
1220
|
+
for (let i = start; i < calls.length && batch.length < batchSize; i++) {
|
|
1221
|
+
const candidate = calls[i];
|
|
1222
|
+
if (this.isDelegateSubAgentCall(candidate.toolName) !== isDelegateBatch)
|
|
1223
|
+
break;
|
|
1224
|
+
batch.push(candidate);
|
|
1225
|
+
}
|
|
1226
|
+
return batch;
|
|
1227
|
+
}
|
|
1218
1228
|
async iterateToolCallsConcurrent(ctx) {
|
|
1219
|
-
const { toolCalls, toolMap, list, runId, telemetry: resolvedTelemetry, executionCounter } = ctx;
|
|
1229
|
+
const { toolCalls, toolMap, list, runId, telemetry: resolvedTelemetry, executionCounter, abortSignal, } = ctx;
|
|
1220
1230
|
const executableCalls = toolCalls.filter((tc) => !tc.providerExecuted);
|
|
1221
1231
|
const providerExecutedCount = toolCalls.length - executableCalls.length;
|
|
1222
1232
|
for (let i = 0; i < providerExecutedCount; i++) {
|
|
@@ -1224,18 +1234,18 @@ class AgentRuntime {
|
|
|
1224
1234
|
}
|
|
1225
1235
|
const executableCallsById = new Map(executableCalls.map((tc) => [tc.toolCallId, tc]));
|
|
1226
1236
|
const unexecutedIds = new Set(executableCalls.map((tc) => tc.toolCallId));
|
|
1227
|
-
const batchSize = this.concurrency;
|
|
1228
1237
|
const results = [];
|
|
1229
1238
|
const suspensions = [];
|
|
1230
1239
|
const errors = [];
|
|
1231
1240
|
const pending = {};
|
|
1232
|
-
for (let batchStart = 0; batchStart < executableCalls.length;
|
|
1233
|
-
if (
|
|
1241
|
+
for (let batchStart = 0; batchStart < executableCalls.length;) {
|
|
1242
|
+
if (ctx.isAborted()) {
|
|
1234
1243
|
this.updateState({ status: 'cancelled' });
|
|
1235
1244
|
throw new Error('Agent run was aborted');
|
|
1236
1245
|
}
|
|
1237
|
-
const batch =
|
|
1238
|
-
|
|
1246
|
+
const batch = this.takeNextToolCallBatch(executableCalls, batchStart, toolMap);
|
|
1247
|
+
batchStart += batch.length;
|
|
1248
|
+
const settledResults = await Promise.allSettled(batch.map(async (tc) => await this.processToolCall(tc.toolCallId, tc.toolName, tc.input, toolMap, list, runId, ctx.persistence, undefined, resolvedTelemetry, executionCounter, abortSignal, true)));
|
|
1239
1249
|
for (const tc of batch) {
|
|
1240
1250
|
unexecutedIds.delete(tc.toolCallId);
|
|
1241
1251
|
}
|
|
@@ -1279,7 +1289,6 @@ class AgentRuntime {
|
|
|
1279
1289
|
input: toolInput,
|
|
1280
1290
|
toolEntry: result.value.toolEntry,
|
|
1281
1291
|
modelOutput: result.value.modelOutput,
|
|
1282
|
-
subAgentUsage: result.value.subAgentUsage,
|
|
1283
1292
|
customMessage: result.value.customMessage,
|
|
1284
1293
|
});
|
|
1285
1294
|
}
|
|
@@ -1310,7 +1319,7 @@ class AgentRuntime {
|
|
|
1310
1319
|
return { results, suspensions, errors, pending };
|
|
1311
1320
|
}
|
|
1312
1321
|
async iteratePendingToolCallsConcurrent(ctx) {
|
|
1313
|
-
const { pendingResume, toolMap, list, runId, persistence, telemetry: resolvedTelemetry, executionCounter, } = ctx;
|
|
1322
|
+
const { pendingResume, toolMap, list, runId, persistence, telemetry: resolvedTelemetry, executionCounter, abortSignal, } = ctx;
|
|
1314
1323
|
const resumedId = pendingResume.resumeToolCallId;
|
|
1315
1324
|
const resumedEntry = pendingResume.pendingToolCalls[resumedId];
|
|
1316
1325
|
if (!resumedEntry) {
|
|
@@ -1321,7 +1330,7 @@ class AgentRuntime {
|
|
|
1321
1330
|
const suspensions = [];
|
|
1322
1331
|
const errors = [];
|
|
1323
1332
|
const pending = {};
|
|
1324
|
-
const processResult = await this.processToolCall(resumedEntry.toolCallId, resumedToolName, resumedEntry.input, toolMap, list, runId, persistence, pendingResume.resumeData, resolvedTelemetry, executionCounter, false);
|
|
1333
|
+
const processResult = await this.processToolCall(resumedEntry.toolCallId, resumedToolName, resumedEntry.input, toolMap, list, runId, persistence, pendingResume.resumeData, resolvedTelemetry, executionCounter, abortSignal, false);
|
|
1325
1334
|
if (processResult.outcome === 'suspended') {
|
|
1326
1335
|
pending[resumedId] = {
|
|
1327
1336
|
...resumedEntry,
|
|
@@ -1345,10 +1354,44 @@ class AgentRuntime {
|
|
|
1345
1354
|
input: resumedEntry.input,
|
|
1346
1355
|
toolEntry: processResult.toolEntry,
|
|
1347
1356
|
modelOutput: processResult.modelOutput,
|
|
1348
|
-
subAgentUsage: processResult.subAgentUsage,
|
|
1349
1357
|
customMessage: processResult.customMessage,
|
|
1350
1358
|
});
|
|
1351
1359
|
}
|
|
1360
|
+
else if (processResult.outcome === 'cancelled') {
|
|
1361
|
+
results.push({
|
|
1362
|
+
toolCallId: resumedEntry.toolCallId,
|
|
1363
|
+
toolName: resumedToolName,
|
|
1364
|
+
input: resumedEntry.input,
|
|
1365
|
+
toolEntry: processResult.toolEntry,
|
|
1366
|
+
modelOutput: processResult.modelOutput,
|
|
1367
|
+
});
|
|
1368
|
+
list.addInput([
|
|
1369
|
+
{ role: 'user', content: [{ type: 'text', text: processResult.userMessage }] },
|
|
1370
|
+
]);
|
|
1371
|
+
for (const id of Object.keys(pendingResume.pendingToolCalls)) {
|
|
1372
|
+
if (id !== resumedId) {
|
|
1373
|
+
const siblingEntry = pendingResume.pendingToolCalls[id];
|
|
1374
|
+
const modelOutput = '[Skipped: a sibling tool call was cancelled]';
|
|
1375
|
+
list.setToolCallResult(id, modelOutput, {
|
|
1376
|
+
canceled: true,
|
|
1377
|
+
});
|
|
1378
|
+
results.push({
|
|
1379
|
+
toolCallId: siblingEntry.toolCallId,
|
|
1380
|
+
toolName: siblingEntry.toolName,
|
|
1381
|
+
input: siblingEntry.input,
|
|
1382
|
+
toolEntry: {
|
|
1383
|
+
tool: siblingEntry.toolName,
|
|
1384
|
+
input: siblingEntry.input,
|
|
1385
|
+
output: modelOutput,
|
|
1386
|
+
transformed: false,
|
|
1387
|
+
canceled: true,
|
|
1388
|
+
},
|
|
1389
|
+
modelOutput,
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
return { results, suspensions, errors, pending };
|
|
1394
|
+
}
|
|
1352
1395
|
else if (processResult.outcome === 'error') {
|
|
1353
1396
|
errors.push({
|
|
1354
1397
|
toolCallId: resumedEntry.toolCallId,
|
|
@@ -1391,6 +1434,8 @@ class AgentRuntime {
|
|
|
1391
1434
|
persistence,
|
|
1392
1435
|
telemetry: resolvedTelemetry,
|
|
1393
1436
|
executionCounter,
|
|
1437
|
+
abortSignal,
|
|
1438
|
+
isAborted: ctx.isAborted,
|
|
1394
1439
|
});
|
|
1395
1440
|
results.push(...batch.results);
|
|
1396
1441
|
suspensions.push(...batch.suspensions);
|
|
@@ -1399,14 +1444,8 @@ class AgentRuntime {
|
|
|
1399
1444
|
}
|
|
1400
1445
|
return { results, suspensions, errors, pending };
|
|
1401
1446
|
}
|
|
1402
|
-
async processToolCall(toolCallId, toolName, toolInput, toolMap, list, runId, persistence, resumeData, resolvedTelemetry, executionCounter, countToolCall = true) {
|
|
1447
|
+
async processToolCall(toolCallId, toolName, toolInput, toolMap, list, runId, persistence, resumeData, resolvedTelemetry, executionCounter, abortSignal, countToolCall = true) {
|
|
1403
1448
|
const builtTool = toolMap.get(toolName);
|
|
1404
|
-
this.eventBus.emit({
|
|
1405
|
-
type: "tool_execution_start",
|
|
1406
|
-
toolCallId,
|
|
1407
|
-
toolName,
|
|
1408
|
-
args: toolInput,
|
|
1409
|
-
});
|
|
1410
1449
|
const makeToolError = (error) => {
|
|
1411
1450
|
this.eventBus.emit({
|
|
1412
1451
|
type: "tool_execution_end",
|
|
@@ -1442,6 +1481,30 @@ class AgentRuntime {
|
|
|
1442
1481
|
});
|
|
1443
1482
|
return { outcome: 'noop' };
|
|
1444
1483
|
}
|
|
1484
|
+
if ((0, cancellation_1.isCancellation)(resumeData) && !builtTool.handleCancellation) {
|
|
1485
|
+
const modelOutput = `[Tool call cancelled. User said: "${resumeData.message}"]`;
|
|
1486
|
+
this.eventBus.emit({
|
|
1487
|
+
type: "tool_execution_end",
|
|
1488
|
+
toolCallId,
|
|
1489
|
+
toolName,
|
|
1490
|
+
result: modelOutput,
|
|
1491
|
+
isError: false,
|
|
1492
|
+
});
|
|
1493
|
+
list.setToolCallResult(toolCallId, modelOutput, { canceled: true });
|
|
1494
|
+
return {
|
|
1495
|
+
outcome: 'cancelled',
|
|
1496
|
+
toolEntry: {
|
|
1497
|
+
tool: toolName,
|
|
1498
|
+
input: toolInput,
|
|
1499
|
+
output: modelOutput,
|
|
1500
|
+
transformed: false,
|
|
1501
|
+
canceled: true,
|
|
1502
|
+
},
|
|
1503
|
+
modelOutput,
|
|
1504
|
+
userMessage: resumeData.message,
|
|
1505
|
+
canceled: true,
|
|
1506
|
+
};
|
|
1507
|
+
}
|
|
1445
1508
|
if (countToolCall) {
|
|
1446
1509
|
this.incrementToolCallCount(executionCounter);
|
|
1447
1510
|
}
|
|
@@ -1452,11 +1515,22 @@ class AgentRuntime {
|
|
|
1452
1515
|
}
|
|
1453
1516
|
toolInput = result.data;
|
|
1454
1517
|
}
|
|
1518
|
+
if (shouldEmitToolExecutionStart(builtTool, resumeData)) {
|
|
1519
|
+
this.eventBus.emit({
|
|
1520
|
+
type: "tool_execution_start",
|
|
1521
|
+
toolCallId,
|
|
1522
|
+
toolName,
|
|
1523
|
+
args: toolInput,
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1455
1526
|
let toolResult;
|
|
1456
1527
|
try {
|
|
1457
1528
|
toolResult = await this.withTelemetryToolSpan(toolCallId, toolName, toolInput, resolvedTelemetry, async () => await (0, tool_adapter_1.executeTool)(toolInput, builtTool, resumeData, resolvedTelemetry, toolCallId, {
|
|
1458
1529
|
runId,
|
|
1459
1530
|
persistence,
|
|
1531
|
+
emitEvent: (event) => this.eventBus.emit(event),
|
|
1532
|
+
abortSignal,
|
|
1533
|
+
executionCounter,
|
|
1460
1534
|
}));
|
|
1461
1535
|
}
|
|
1462
1536
|
catch (error) {
|
|
@@ -1474,9 +1548,7 @@ class AgentRuntime {
|
|
|
1474
1548
|
const error = new Error(`Tool ${toolName} has no resume schema`);
|
|
1475
1549
|
return makeToolError(error);
|
|
1476
1550
|
}
|
|
1477
|
-
const resumeSchema = (
|
|
1478
|
-
? (0, zod_to_json_schema_1.zodToJsonSchema)(builtTool.resumeSchema)
|
|
1479
|
-
: builtTool.resumeSchema;
|
|
1551
|
+
const resumeSchema = getToolResumeJsonSchema(builtTool);
|
|
1480
1552
|
if (!resumeSchema) {
|
|
1481
1553
|
return makeToolError(new Error('Invalid resume schema'));
|
|
1482
1554
|
}
|
|
@@ -1486,24 +1558,16 @@ class AgentRuntime {
|
|
|
1486
1558
|
resumeSchema,
|
|
1487
1559
|
};
|
|
1488
1560
|
}
|
|
1489
|
-
let actualResult = toolResult;
|
|
1490
|
-
let extractedSubAgentUsage;
|
|
1491
|
-
if ((0, tool_adapter_1.isAgentToolResult)(toolResult)) {
|
|
1492
|
-
actualResult = toolResult.output;
|
|
1493
|
-
extractedSubAgentUsage = toolResult.subAgentUsage;
|
|
1494
|
-
}
|
|
1495
1561
|
this.eventBus.emit({
|
|
1496
1562
|
type: "tool_execution_end",
|
|
1497
1563
|
toolCallId,
|
|
1498
1564
|
toolName,
|
|
1499
|
-
result:
|
|
1565
|
+
result: toolResult,
|
|
1500
1566
|
isError: false,
|
|
1501
1567
|
});
|
|
1502
|
-
const modelResult = builtTool.toModelOutput
|
|
1503
|
-
? builtTool.toModelOutput(actualResult)
|
|
1504
|
-
: actualResult;
|
|
1568
|
+
const modelResult = builtTool.toModelOutput ? builtTool.toModelOutput(toolResult) : toolResult;
|
|
1505
1569
|
list.setToolCallResult(toolCallId, (0, json_value_1.toJsonValue)(modelResult));
|
|
1506
|
-
const customMessage = builtTool?.toMessage?.(
|
|
1570
|
+
const customMessage = builtTool?.toMessage?.(toolResult);
|
|
1507
1571
|
if (customMessage) {
|
|
1508
1572
|
list.addResponse([customMessage]);
|
|
1509
1573
|
}
|
|
@@ -1512,27 +1576,43 @@ class AgentRuntime {
|
|
|
1512
1576
|
toolEntry: {
|
|
1513
1577
|
tool: toolName,
|
|
1514
1578
|
input: toolInput,
|
|
1515
|
-
output:
|
|
1579
|
+
output: toolResult,
|
|
1516
1580
|
transformed: !!builtTool.toModelOutput,
|
|
1517
1581
|
},
|
|
1518
1582
|
modelOutput: modelResult,
|
|
1519
|
-
subAgentUsage: extractedSubAgentUsage,
|
|
1520
1583
|
customMessage,
|
|
1521
1584
|
};
|
|
1522
1585
|
}
|
|
1523
1586
|
buildStaticLoopContext(execOptions) {
|
|
1524
|
-
const { Output } = getAiSdk();
|
|
1587
|
+
const { Output, jsonSchema } = getAiSdk();
|
|
1525
1588
|
const aiProviderTools = (0, tool_adapter_1.toAiSdkProviderTools)(this.config.providerTools);
|
|
1526
1589
|
const model = (0, model_factory_1.createModel)(this.config.model);
|
|
1590
|
+
const outputSchema = this.config.structuredOutput;
|
|
1591
|
+
const isRawJsonSchemaOutput = outputSchema !== undefined && !(0, zod_1.isZodSchema)(outputSchema);
|
|
1592
|
+
const providerOptions = this.relaxStrictJsonSchemaIfNeeded(this.buildCallProviderOptions(execOptions?.providerOptions), isRawJsonSchemaOutput);
|
|
1593
|
+
const outputSpec = outputSchema
|
|
1594
|
+
? Output.object({
|
|
1595
|
+
schema: (0, zod_1.isZodSchema)(outputSchema)
|
|
1596
|
+
? outputSchema
|
|
1597
|
+
: jsonSchema((0, json_schema_1.lockAdditionalProperties)(outputSchema)),
|
|
1598
|
+
})
|
|
1599
|
+
: undefined;
|
|
1527
1600
|
return {
|
|
1528
1601
|
model,
|
|
1529
1602
|
aiProviderTools,
|
|
1530
|
-
providerOptions
|
|
1531
|
-
outputSpec
|
|
1532
|
-
? Output.object({ schema: this.config.structuredOutput })
|
|
1533
|
-
: undefined,
|
|
1603
|
+
providerOptions,
|
|
1604
|
+
outputSpec,
|
|
1534
1605
|
};
|
|
1535
1606
|
}
|
|
1607
|
+
relaxStrictJsonSchemaIfNeeded(providerOptions, isRawJsonSchemaOutput) {
|
|
1608
|
+
if (!isRawJsonSchemaOutput)
|
|
1609
|
+
return providerOptions;
|
|
1610
|
+
const result = { ...providerOptions };
|
|
1611
|
+
for (const provider of ['openai', 'groq']) {
|
|
1612
|
+
result[provider] = { strictJsonSchema: false, ...result[provider] };
|
|
1613
|
+
}
|
|
1614
|
+
return result;
|
|
1615
|
+
}
|
|
1536
1616
|
buildToolLoopContext(aiProviderTools, persistence, executionCounter) {
|
|
1537
1617
|
const allUserTools = this.getCurrentTools(persistence, executionCounter);
|
|
1538
1618
|
const aiTools = (0, tool_adapter_1.toAiSdkTools)(allUserTools);
|
|
@@ -1592,8 +1672,7 @@ class AgentRuntime {
|
|
|
1592
1672
|
const block = `<built_in_rules>\n${fragments.map((f) => `- ${f}`).join('\n')}\n</built_in_rules>`;
|
|
1593
1673
|
return userInstructions ? `${block}\n\n${userInstructions}` : block;
|
|
1594
1674
|
}
|
|
1595
|
-
async persistSuspension(pendingToolCalls, options, list, totalUsage,
|
|
1596
|
-
const runId = existingRunId ?? (0, run_state_1.generateRunId)();
|
|
1675
|
+
async persistSuspension(pendingToolCalls, options, list, totalUsage, maxIterations, iterationCount) {
|
|
1597
1676
|
const resolvedMaxIterations = maxIterations ?? options?.maxIterations;
|
|
1598
1677
|
const resolvedIterationCount = iterationCount ?? options?.iterationCount;
|
|
1599
1678
|
const executionOptions = resolvedMaxIterations !== undefined ? { maxIterations: resolvedMaxIterations } : undefined;
|
|
@@ -1606,14 +1685,12 @@ class AgentRuntime {
|
|
|
1606
1685
|
executionOptions,
|
|
1607
1686
|
...(resolvedIterationCount !== undefined ? { iterationCount: resolvedIterationCount } : {}),
|
|
1608
1687
|
};
|
|
1609
|
-
await this.runState.suspend(runId, state);
|
|
1688
|
+
await this.runState.suspend(this.runId, state);
|
|
1610
1689
|
this.updateState({ status: 'suspended', pendingToolCalls, messageList: list.serialize() });
|
|
1611
|
-
return runId;
|
|
1690
|
+
return this.runId;
|
|
1612
1691
|
}
|
|
1613
|
-
async cleanupRun(
|
|
1614
|
-
|
|
1615
|
-
await this.runState.complete(runId);
|
|
1616
|
-
}
|
|
1692
|
+
async cleanupRun() {
|
|
1693
|
+
await this.runState.complete(this.runId);
|
|
1617
1694
|
}
|
|
1618
1695
|
emitTurnEnd(newMessages, toolResults) {
|
|
1619
1696
|
const assistantMsg = newMessages.find((m) => 'role' in m && m.role === 'assistant');
|