@n8n/agents 0.8.1 → 0.9.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/index.d.ts +10 -2
- package/dist/index.js +57 -4
- package/dist/index.js.map +1 -1
- package/dist/integrations/langsmith.js +28 -2
- package/dist/integrations/langsmith.js.map +1 -1
- package/dist/runtime/agent-runtime.d.ts +12 -1
- package/dist/runtime/agent-runtime.js +243 -119
- package/dist/runtime/agent-runtime.js.map +1 -1
- package/dist/runtime/episodic-memory-defaults.d.ts +17 -0
- package/dist/runtime/episodic-memory-defaults.js +615 -0
- package/dist/runtime/episodic-memory-defaults.js.map +1 -0
- package/dist/runtime/episodic-memory.d.ts +45 -0
- package/dist/runtime/episodic-memory.js +479 -0
- package/dist/runtime/episodic-memory.js.map +1 -0
- package/dist/runtime/execution-counter.d.ts +9 -0
- package/dist/runtime/execution-counter.js +16 -0
- package/dist/runtime/execution-counter.js.map +1 -0
- package/dist/runtime/fix-tool-call.d.ts +7 -0
- package/dist/runtime/fix-tool-call.js +38 -0
- package/dist/runtime/fix-tool-call.js.map +1 -0
- package/dist/runtime/lazy-ai.d.ts +2 -0
- package/dist/runtime/lazy-ai.js +12 -0
- package/dist/runtime/lazy-ai.js.map +1 -0
- package/dist/runtime/mcp-connection.d.ts +1 -1
- package/dist/runtime/mcp-connection.js +71 -16
- package/dist/runtime/mcp-connection.js.map +1 -1
- package/dist/runtime/memory-lifecycle.d.ts +34 -0
- package/dist/runtime/memory-lifecycle.js +63 -0
- package/dist/runtime/memory-lifecycle.js.map +1 -0
- package/dist/runtime/memory-store.d.ts +22 -7
- package/dist/runtime/memory-store.js +240 -50
- package/dist/runtime/memory-store.js.map +1 -1
- package/dist/runtime/message-list.d.ts +1 -0
- package/dist/runtime/message-list.js +5 -0
- package/dist/runtime/message-list.js.map +1 -1
- package/dist/runtime/messages.js +14 -1
- package/dist/runtime/messages.js.map +1 -1
- package/dist/runtime/model-factory.d.ts +5 -1
- package/dist/runtime/model-factory.js +3 -2
- package/dist/runtime/model-factory.js.map +1 -1
- package/dist/runtime/observation-log-defaults.js +6 -5
- package/dist/runtime/observation-log-defaults.js.map +1 -1
- package/dist/runtime/observation-log-observer.d.ts +7 -13
- package/dist/runtime/observation-log-observer.js +11 -21
- package/dist/runtime/observation-log-observer.js.map +1 -1
- package/dist/runtime/observation-log-reflector.d.ts +5 -5
- package/dist/runtime/observation-log-reflector.js +9 -21
- package/dist/runtime/observation-log-reflector.js.map +1 -1
- package/dist/runtime/scoped-memory-task-runner.d.ts +2 -4
- package/dist/runtime/scoped-memory-task-runner.js +3 -7
- package/dist/runtime/scoped-memory-task-runner.js.map +1 -1
- package/dist/runtime/stream.js +11 -1
- package/dist/runtime/stream.js.map +1 -1
- package/dist/runtime/title-generation.d.ts +5 -2
- package/dist/runtime/title-generation.js +7 -3
- package/dist/runtime/title-generation.js.map +1 -1
- package/dist/runtime/tool-adapter.d.ts +1 -1
- package/dist/runtime/tool-adapter.js +5 -4
- package/dist/runtime/tool-adapter.js.map +1 -1
- package/dist/sdk/agent.d.ts +10 -0
- package/dist/sdk/agent.js +77 -11
- package/dist/sdk/agent.js.map +1 -1
- package/dist/sdk/memory.d.ts +6 -2
- package/dist/sdk/memory.js +57 -3
- package/dist/sdk/memory.js.map +1 -1
- package/dist/sdk/telemetry.d.ts +1 -0
- package/dist/sdk/telemetry.js +7 -0
- package/dist/sdk/telemetry.js.map +1 -1
- package/dist/skills/index.d.ts +6 -0
- package/dist/skills/index.js +29 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/prompt.d.ts +6 -0
- package/dist/skills/prompt.js +49 -0
- package/dist/skills/prompt.js.map +1 -0
- package/dist/skills/registry.d.ts +14 -0
- package/dist/skills/registry.js +380 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/tools.d.ts +6 -0
- package/dist/skills/tools.js +312 -0
- package/dist/skills/tools.js.map +1 -0
- package/dist/skills/types.d.ts +141 -0
- package/dist/skills/types.js +15 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/skills/validator.d.ts +15 -0
- package/dist/skills/validator.js +336 -0
- package/dist/skills/validator.js.map +1 -0
- package/dist/types/index.d.ts +4 -4
- package/dist/types/index.js +1 -3
- package/dist/types/index.js.map +1 -1
- package/dist/types/runtime/event.d.ts +1 -1
- package/dist/types/sdk/agent-builder.d.ts +4 -1
- package/dist/types/sdk/agent.d.ts +2 -1
- package/dist/types/sdk/memory.d.ts +153 -2
- package/dist/types/sdk/observation-log.d.ts +7 -10
- package/dist/types/sdk/observation-log.js +0 -9
- package/dist/types/sdk/observation-log.js.map +1 -1
- package/dist/types/sdk/observation.d.ts +1 -4
- package/dist/workspace/tools/execute-command.js +2 -0
- package/dist/workspace/tools/execute-command.js.map +1 -1
- package/dist/workspace/types.d.ts +1 -0
- package/dist/workspace/types.js.map +1 -1
- package/package.json +28 -3
|
@@ -1,47 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.AgentRuntime = void 0;
|
|
37
|
-
const ai_1 = require("ai");
|
|
38
4
|
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
39
5
|
const catalog_1 = require("../sdk/catalog");
|
|
40
6
|
const message_1 = require("../sdk/message");
|
|
41
7
|
const background_task_tracker_1 = require("./background-task-tracker");
|
|
42
8
|
const deferred_tool_manager_1 = require("./deferred-tool-manager");
|
|
9
|
+
const episodic_memory_1 = require("./episodic-memory");
|
|
43
10
|
const event_bus_1 = require("./event-bus");
|
|
11
|
+
const execution_counter_1 = require("./execution-counter");
|
|
12
|
+
const fix_tool_call_1 = require("./fix-tool-call");
|
|
44
13
|
const json_value_1 = require("./json-value");
|
|
14
|
+
const lazy_ai_1 = require("./lazy-ai");
|
|
45
15
|
const logger_1 = require("./logger");
|
|
46
16
|
const memory_store_1 = require("./memory-store");
|
|
47
17
|
const message_list_1 = require("./message-list");
|
|
@@ -58,7 +28,7 @@ const stream_1 = require("./stream");
|
|
|
58
28
|
const strip_orphaned_tool_messages_1 = require("./strip-orphaned-tool-messages");
|
|
59
29
|
const title_generation_1 = require("./title-generation");
|
|
60
30
|
const tool_adapter_1 = require("./tool-adapter");
|
|
61
|
-
const
|
|
31
|
+
const telemetry_1 = require("../sdk/telemetry");
|
|
62
32
|
const parse_1 = require("../utils/parse");
|
|
63
33
|
const zod_1 = require("../utils/zod");
|
|
64
34
|
function isActiveSpanTracer(value) {
|
|
@@ -119,8 +89,12 @@ function buildAgentRootInputAttributes(config) {
|
|
|
119
89
|
...(serialized ? { 'gen_ai.prompt': serialized } : {}),
|
|
120
90
|
};
|
|
121
91
|
}
|
|
122
|
-
const MAX_LOOP_ITERATIONS =
|
|
92
|
+
const MAX_LOOP_ITERATIONS = 30;
|
|
93
|
+
const DEFAULT_MEMORY_TASK_LOCK_TTL_MS = 30_000;
|
|
123
94
|
const logger = (0, logger_1.createFilteredLogger)();
|
|
95
|
+
function getAiSdk() {
|
|
96
|
+
return (0, lazy_ai_1.loadAi)();
|
|
97
|
+
}
|
|
124
98
|
const EMPTY_MESSAGE_LIST = {
|
|
125
99
|
messages: [],
|
|
126
100
|
historyIds: [],
|
|
@@ -132,13 +106,14 @@ function hasFunctionProperty(value, property) {
|
|
|
132
106
|
}
|
|
133
107
|
function hasObservationLogObserverMemory(memory) {
|
|
134
108
|
return ((0, observation_log_store_1.hasObservationLogStore)(memory) &&
|
|
135
|
-
hasFunctionProperty(memory, '
|
|
109
|
+
hasFunctionProperty(memory, 'getMessagesForObservationScope') &&
|
|
136
110
|
hasFunctionProperty(memory, 'getCursor') &&
|
|
137
111
|
hasFunctionProperty(memory, 'setCursor'));
|
|
138
112
|
}
|
|
139
113
|
class AgentRuntime {
|
|
140
114
|
constructor(config) {
|
|
141
115
|
this.backgroundTasks = new background_task_tracker_1.BackgroundTaskTracker();
|
|
116
|
+
this.episodicMemoryTasksByResource = new Map();
|
|
142
117
|
this.config = config;
|
|
143
118
|
if (config.deferredTools && config.deferredTools.length > 0) {
|
|
144
119
|
this.deferredToolManager = new deferred_tool_manager_1.DeferredToolManager(config.deferredTools, config.toolSearch);
|
|
@@ -152,6 +127,9 @@ class AgentRuntime {
|
|
|
152
127
|
pendingToolCalls: {},
|
|
153
128
|
};
|
|
154
129
|
}
|
|
130
|
+
setTelemetry(telemetry) {
|
|
131
|
+
this.config.telemetry = telemetry;
|
|
132
|
+
}
|
|
155
133
|
async dispose() {
|
|
156
134
|
await this.backgroundTasks.flush();
|
|
157
135
|
}
|
|
@@ -205,12 +183,12 @@ class AgentRuntime {
|
|
|
205
183
|
throw new Error(`No tool call found for toolCallId: ${options.toolCallId}`);
|
|
206
184
|
const list = message_list_1.AgentMessageList.deserialize(state.messageList);
|
|
207
185
|
this.hydrateDeferredToolsFromList(list);
|
|
208
|
-
const
|
|
209
|
-
if (!
|
|
186
|
+
const toolForValidation = this.getCurrentTools(state.persistence).find((t) => t.name === toolCall.toolName);
|
|
187
|
+
if (!toolForValidation)
|
|
210
188
|
throw new Error(`Tool ${toolCall.toolName} not found`);
|
|
211
189
|
let resumeData = data;
|
|
212
|
-
if (
|
|
213
|
-
const parseResult = await (0, parse_1.parseWithSchema)(
|
|
190
|
+
if (toolForValidation.resumeSchema) {
|
|
191
|
+
const parseResult = await (0, parse_1.parseWithSchema)(toolForValidation.resumeSchema, data);
|
|
214
192
|
if (!parseResult.success) {
|
|
215
193
|
throw new Error(`Invalid resume payload: ${parseResult.error}`);
|
|
216
194
|
}
|
|
@@ -219,10 +197,22 @@ class AgentRuntime {
|
|
|
219
197
|
try {
|
|
220
198
|
const { runId: _rid, toolCallId: _tcid, ...callerExecOptions } = options;
|
|
221
199
|
const persisted = state.executionOptions ?? {};
|
|
200
|
+
const persistedMaxIterations = persisted.maxIterations;
|
|
201
|
+
const callerMaxIterations = callerExecOptions.maxIterations;
|
|
202
|
+
if (callerMaxIterations !== undefined &&
|
|
203
|
+
persistedMaxIterations !== undefined &&
|
|
204
|
+
callerMaxIterations < persistedMaxIterations) {
|
|
205
|
+
throw new Error(`Cannot decrease maxIterations when resuming a run. Expected >= ${persistedMaxIterations}, received ${callerMaxIterations}.`);
|
|
206
|
+
}
|
|
207
|
+
const mergedMaxIterations = callerMaxIterations ?? persistedMaxIterations;
|
|
222
208
|
const mergedExecOptions = {
|
|
223
|
-
...persisted,
|
|
224
209
|
...callerExecOptions,
|
|
210
|
+
...(mergedMaxIterations !== undefined ? { maxIterations: mergedMaxIterations } : {}),
|
|
211
|
+
...(state.iterationCount !== undefined ? { iterationCount: state.iterationCount } : {}),
|
|
225
212
|
};
|
|
213
|
+
const tool = this.getCurrentTools(state.persistence, mergedExecOptions.executionCounter).find((t) => t.name === toolCall.toolName);
|
|
214
|
+
if (!tool)
|
|
215
|
+
throw new Error(`Tool ${toolCall.toolName} not found`);
|
|
226
216
|
const resumeOptions = {
|
|
227
217
|
persistence: state.persistence,
|
|
228
218
|
...mergedExecOptions,
|
|
@@ -278,22 +268,40 @@ class AgentRuntime {
|
|
|
278
268
|
async buildMessageList(input, options) {
|
|
279
269
|
const list = new message_list_1.AgentMessageList();
|
|
280
270
|
if (this.config.memory && options?.persistence?.threadId) {
|
|
281
|
-
const memMessages = await this.
|
|
282
|
-
limit: this.config.lastMessages ?? 10,
|
|
283
|
-
resourceId: options.persistence.resourceId,
|
|
284
|
-
});
|
|
271
|
+
const memMessages = await this.loadHistoryMessages(options.persistence);
|
|
285
272
|
if (memMessages.length > 0) {
|
|
286
273
|
list.addHistory((0, strip_orphaned_tool_messages_1.stripOrphanedToolMessages)(memMessages));
|
|
287
274
|
}
|
|
288
275
|
}
|
|
289
276
|
if (this.config.semanticRecall && options?.persistence?.threadId) {
|
|
290
|
-
await this.performSemanticRecall(list, input, options.persistence
|
|
277
|
+
await this.performSemanticRecall(list, input, options.persistence, options.executionCounter);
|
|
291
278
|
}
|
|
292
279
|
await this.setListObservationLogMemory(list, options?.persistence);
|
|
293
280
|
list.addInput(input);
|
|
294
281
|
return list;
|
|
295
282
|
}
|
|
296
|
-
async
|
|
283
|
+
async loadHistoryMessages(persistence) {
|
|
284
|
+
const memory = this.config.memory;
|
|
285
|
+
if (!memory)
|
|
286
|
+
return [];
|
|
287
|
+
const { threadId, resourceId } = persistence;
|
|
288
|
+
if (this.config.observationalMemory && hasObservationLogObserverMemory(memory)) {
|
|
289
|
+
const cursor = await memory.getCursor(threadId);
|
|
290
|
+
if (cursor) {
|
|
291
|
+
return await memory.getMessagesForObservationScope(threadId, {
|
|
292
|
+
since: {
|
|
293
|
+
sinceCreatedAt: cursor.lastObservedAt,
|
|
294
|
+
sinceMessageId: cursor.lastObservedMessageId,
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return await memory.getMessages(threadId, {
|
|
300
|
+
limit: this.config.lastMessages ?? 10,
|
|
301
|
+
resourceId,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
async performSemanticRecall(list, input, persistence, executionCounter) {
|
|
297
305
|
if (!this.config.semanticRecall || !this.config.memory)
|
|
298
306
|
return;
|
|
299
307
|
const userText = input
|
|
@@ -306,19 +314,20 @@ class AgentRuntime {
|
|
|
306
314
|
return;
|
|
307
315
|
let recalled = [];
|
|
308
316
|
if (this.config.memory.queryEmbeddings && this.config.semanticRecall.embedder) {
|
|
309
|
-
const { embed } =
|
|
317
|
+
const { embed } = getAiSdk();
|
|
310
318
|
const embeddingModel = (0, model_factory_1.createEmbeddingModel)(this.config.semanticRecall.embedder, this.config.semanticRecall.apiKey);
|
|
311
|
-
const { embedding } = await embed({ model: embeddingModel, value: userText });
|
|
319
|
+
const { embedding, usage } = await embed({ model: embeddingModel, value: userText });
|
|
320
|
+
(0, execution_counter_1.incrementTokenCountFromUsage)(executionCounter, usage);
|
|
312
321
|
const hits = await this.config.memory.queryEmbeddings({
|
|
313
322
|
scope: this.config.semanticRecall.scope ?? 'resource',
|
|
314
|
-
threadId,
|
|
315
|
-
resourceId,
|
|
323
|
+
threadId: persistence.threadId,
|
|
324
|
+
resourceId: persistence.resourceId,
|
|
316
325
|
vector: embedding,
|
|
317
326
|
topK: this.config.semanticRecall.topK,
|
|
318
327
|
});
|
|
319
328
|
if (hits.length > 0) {
|
|
320
329
|
const hitIds = new Set(hits.map((h) => h.id));
|
|
321
|
-
const allMsgs = await this.config.memory.getMessages(threadId);
|
|
330
|
+
const allMsgs = await this.config.memory.getMessages(persistence.threadId);
|
|
322
331
|
if (this.config.semanticRecall.messageRange) {
|
|
323
332
|
recalled = this.expandMessageRange(allMsgs, hitIds, this.config.semanticRecall.messageRange);
|
|
324
333
|
}
|
|
@@ -332,8 +341,8 @@ class AgentRuntime {
|
|
|
332
341
|
}
|
|
333
342
|
else if (this.config.memory.search) {
|
|
334
343
|
recalled = await this.config.memory.search(userText, {
|
|
335
|
-
threadId,
|
|
336
|
-
resourceId,
|
|
344
|
+
threadId: persistence.threadId,
|
|
345
|
+
resourceId: persistence.resourceId,
|
|
337
346
|
topK: this.config.semanticRecall.topK,
|
|
338
347
|
messageRange: this.config.semanticRecall.messageRange,
|
|
339
348
|
});
|
|
@@ -401,14 +410,18 @@ class AgentRuntime {
|
|
|
401
410
|
return { ...inherited, functionId: this.config.name };
|
|
402
411
|
}
|
|
403
412
|
async flushTelemetry(options) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
413
|
+
await telemetry_1.Telemetry.forceFlush(this.resolveTelemetry(options));
|
|
414
|
+
}
|
|
415
|
+
buildAiSdkOptions(toolMap, options) {
|
|
416
|
+
return {
|
|
417
|
+
...this.buildTelemetryOptions(options),
|
|
418
|
+
experimental_repairToolCall: async (options) => {
|
|
419
|
+
return await (0, fix_tool_call_1.fixToolCall)({
|
|
420
|
+
toolCall: options.toolCall,
|
|
421
|
+
error: options.error,
|
|
422
|
+
}, toolMap);
|
|
423
|
+
},
|
|
424
|
+
};
|
|
412
425
|
}
|
|
413
426
|
buildTelemetryOptions(options) {
|
|
414
427
|
const t = this.resolveTelemetry(options);
|
|
@@ -469,12 +482,7 @@ class AgentRuntime {
|
|
|
469
482
|
this.recordExecutionCounter(() => counter.incrementToolCallCount());
|
|
470
483
|
}
|
|
471
484
|
incrementTokenCount(counter, usage) {
|
|
472
|
-
|
|
473
|
-
return;
|
|
474
|
-
const tokenCount = usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);
|
|
475
|
-
if (tokenCount <= 0)
|
|
476
|
-
return;
|
|
477
|
-
this.recordExecutionCounter(() => counter.incrementTokenCount(tokenCount));
|
|
485
|
+
(0, execution_counter_1.incrementTokenCountFromUsage)(counter, usage);
|
|
478
486
|
}
|
|
479
487
|
async withTelemetryRootSpan(operation, options, runId, fn) {
|
|
480
488
|
const t = this.resolveTelemetry(options);
|
|
@@ -542,7 +550,7 @@ class AgentRuntime {
|
|
|
542
550
|
...options,
|
|
543
551
|
persistence: options?.persistence,
|
|
544
552
|
});
|
|
545
|
-
const pendingLoopContext = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
|
|
553
|
+
const pendingLoopContext = this.buildToolLoopContext(staticLoopContext.aiProviderTools, options?.persistence, options?.executionCounter);
|
|
546
554
|
const pendingToolCtx = {
|
|
547
555
|
toolMap: pendingLoopContext.toolMap,
|
|
548
556
|
list,
|
|
@@ -550,6 +558,9 @@ class AgentRuntime {
|
|
|
550
558
|
telemetry: runTelemetry,
|
|
551
559
|
executionCounter: options?.executionCounter,
|
|
552
560
|
};
|
|
561
|
+
const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS;
|
|
562
|
+
let iterationCount = options?.iterationCount ?? 0;
|
|
563
|
+
let reachedStopCondition = false;
|
|
553
564
|
if (pendingResume) {
|
|
554
565
|
const batch = await this.iteratePendingToolCallsConcurrent({
|
|
555
566
|
...pendingToolCtx,
|
|
@@ -561,7 +572,7 @@ class AgentRuntime {
|
|
|
561
572
|
collectedSubAgentUsage.push(...r.subAgentUsage);
|
|
562
573
|
}
|
|
563
574
|
if (Object.keys(batch.pending).length > 0) {
|
|
564
|
-
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId);
|
|
575
|
+
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId, maxIterations, iterationCount);
|
|
565
576
|
return {
|
|
566
577
|
runId: suspendRunId,
|
|
567
578
|
messages: list.responseDelta(),
|
|
@@ -578,15 +589,15 @@ class AgentRuntime {
|
|
|
578
589
|
};
|
|
579
590
|
}
|
|
580
591
|
}
|
|
581
|
-
const
|
|
582
|
-
for (
|
|
592
|
+
const { generateText } = (0, lazy_ai_1.loadAi)();
|
|
593
|
+
for (; iterationCount < maxIterations; iterationCount++) {
|
|
583
594
|
if (this.eventBus.isAborted) {
|
|
584
595
|
this.updateState({ status: 'cancelled' });
|
|
585
596
|
throw new Error('Agent run was aborted');
|
|
586
597
|
}
|
|
587
598
|
this.eventBus.emit({ type: "turn_start" });
|
|
588
|
-
const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
|
|
589
|
-
const result = await
|
|
599
|
+
const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools, options?.persistence, options?.executionCounter);
|
|
600
|
+
const result = await generateText({
|
|
590
601
|
model: staticLoopContext.model,
|
|
591
602
|
messages: list.forLlm(effectiveInstructions, this.config.instructionProviderOptions),
|
|
592
603
|
abortSignal: this.eventBus.signal,
|
|
@@ -595,7 +606,7 @@ class AgentRuntime {
|
|
|
595
606
|
? { providerOptions: staticLoopContext.providerOptions }
|
|
596
607
|
: {}),
|
|
597
608
|
...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}),
|
|
598
|
-
...this.
|
|
609
|
+
...this.buildAiSdkOptions(toolMap, options),
|
|
599
610
|
});
|
|
600
611
|
const aiFinishReason = result.finishReason;
|
|
601
612
|
lastFinishReason = (0, messages_1.fromAiFinishReason)(aiFinishReason);
|
|
@@ -609,6 +620,7 @@ class AgentRuntime {
|
|
|
609
620
|
structuredOutput = result.output;
|
|
610
621
|
}
|
|
611
622
|
this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(newMessages));
|
|
623
|
+
reachedStopCondition = true;
|
|
612
624
|
break;
|
|
613
625
|
}
|
|
614
626
|
const batch = await this.iterateToolCallsConcurrent({
|
|
@@ -625,7 +637,7 @@ class AgentRuntime {
|
|
|
625
637
|
collectedSubAgentUsage.push(...r.subAgentUsage);
|
|
626
638
|
}
|
|
627
639
|
if (Object.keys(batch.pending).length > 0) {
|
|
628
|
-
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId);
|
|
640
|
+
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId, maxIterations, iterationCount + 1);
|
|
629
641
|
return {
|
|
630
642
|
runId: suspendRunId,
|
|
631
643
|
messages: list.responseDelta(),
|
|
@@ -643,8 +655,8 @@ class AgentRuntime {
|
|
|
643
655
|
}
|
|
644
656
|
this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(list.responseDelta()));
|
|
645
657
|
}
|
|
646
|
-
if (
|
|
647
|
-
|
|
658
|
+
if (!reachedStopCondition && iterationCount >= maxIterations) {
|
|
659
|
+
lastFinishReason = 'max-iterations';
|
|
648
660
|
}
|
|
649
661
|
await this.saveToMemory(list, options);
|
|
650
662
|
await this.flushTelemetry(options);
|
|
@@ -656,6 +668,7 @@ class AgentRuntime {
|
|
|
656
668
|
titleConfig: this.config.titleGeneration,
|
|
657
669
|
agentModel: this.config.model,
|
|
658
670
|
turnDelta: list.turnDelta(),
|
|
671
|
+
executionCounter: options.executionCounter,
|
|
659
672
|
});
|
|
660
673
|
this.backgroundTasks.track(titlePromise);
|
|
661
674
|
if (this.config.titleGeneration.sync) {
|
|
@@ -717,6 +730,9 @@ class AgentRuntime {
|
|
|
717
730
|
let structuredOutput;
|
|
718
731
|
const collectedSubAgentUsage = [];
|
|
719
732
|
const maxIterations = options?.maxIterations ?? MAX_LOOP_ITERATIONS;
|
|
733
|
+
let iterationCount = options?.iterationCount ?? 0;
|
|
734
|
+
let reachedStopCondition = false;
|
|
735
|
+
const { streamText } = (0, lazy_ai_1.loadAi)();
|
|
720
736
|
const closeStreamWithError = async (error, status) => {
|
|
721
737
|
await this.cleanupRun(runId);
|
|
722
738
|
this.updateState({ status });
|
|
@@ -735,7 +751,7 @@ class AgentRuntime {
|
|
|
735
751
|
...options,
|
|
736
752
|
persistence: options?.persistence,
|
|
737
753
|
});
|
|
738
|
-
const pendingLoopContext = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
|
|
754
|
+
const pendingLoopContext = this.buildToolLoopContext(staticLoopContext.aiProviderTools, options?.persistence, options?.executionCounter);
|
|
739
755
|
const pendingToolCtx = {
|
|
740
756
|
toolMap: pendingLoopContext.toolMap,
|
|
741
757
|
list,
|
|
@@ -772,7 +788,7 @@ class AgentRuntime {
|
|
|
772
788
|
});
|
|
773
789
|
}
|
|
774
790
|
if (Object.keys(batch.pending).length > 0) {
|
|
775
|
-
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId);
|
|
791
|
+
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId, maxIterations, iterationCount);
|
|
776
792
|
for (const s of batch.suspensions) {
|
|
777
793
|
await writer.write({
|
|
778
794
|
type: 'tool-call-suspended',
|
|
@@ -795,13 +811,13 @@ class AgentRuntime {
|
|
|
795
811
|
return;
|
|
796
812
|
}
|
|
797
813
|
}
|
|
798
|
-
for (
|
|
814
|
+
for (; iterationCount < maxIterations; iterationCount++) {
|
|
799
815
|
if (await handleAbort())
|
|
800
816
|
return;
|
|
801
817
|
this.eventBus.emit({ type: "turn_start" });
|
|
802
|
-
const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
|
|
818
|
+
const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools, options?.persistence, options?.executionCounter);
|
|
803
819
|
const messages = list.forLlm(effectiveInstructions, this.config.instructionProviderOptions);
|
|
804
|
-
const result =
|
|
820
|
+
const result = streamText({
|
|
805
821
|
model: staticLoopContext.model,
|
|
806
822
|
messages,
|
|
807
823
|
abortSignal: this.eventBus.signal,
|
|
@@ -810,7 +826,7 @@ class AgentRuntime {
|
|
|
810
826
|
? { providerOptions: staticLoopContext.providerOptions }
|
|
811
827
|
: {}),
|
|
812
828
|
...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}),
|
|
813
|
-
...this.
|
|
829
|
+
...this.buildAiSdkOptions(toolMap, options),
|
|
814
830
|
});
|
|
815
831
|
try {
|
|
816
832
|
for await (const chunk of result.fullStream) {
|
|
@@ -848,6 +864,7 @@ class AgentRuntime {
|
|
|
848
864
|
structuredOutput = await result.output;
|
|
849
865
|
}
|
|
850
866
|
this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(newMessages));
|
|
867
|
+
reachedStopCondition = true;
|
|
851
868
|
break;
|
|
852
869
|
}
|
|
853
870
|
const toolCalls = await result.toolCalls;
|
|
@@ -885,7 +902,7 @@ class AgentRuntime {
|
|
|
885
902
|
});
|
|
886
903
|
}
|
|
887
904
|
if (Object.keys(batch.pending).length > 0) {
|
|
888
|
-
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId);
|
|
905
|
+
const suspendRunId = await this.persistSuspension(batch.pending, options, list, totalUsage, runId, maxIterations, iterationCount + 1);
|
|
889
906
|
for (const s of batch.suspensions) {
|
|
890
907
|
await writer.write({
|
|
891
908
|
type: 'tool-call-suspended',
|
|
@@ -909,6 +926,9 @@ class AgentRuntime {
|
|
|
909
926
|
}
|
|
910
927
|
this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(list.responseDelta()));
|
|
911
928
|
}
|
|
929
|
+
if (!reachedStopCondition && iterationCount >= maxIterations) {
|
|
930
|
+
lastFinishReason = 'max-iterations';
|
|
931
|
+
}
|
|
912
932
|
const costUsage = this.applyCost(totalUsage);
|
|
913
933
|
const parentCost = costUsage?.cost ?? 0;
|
|
914
934
|
const subCost = collectedSubAgentUsage.reduce((sum, s) => sum + (s.usage.cost ?? 0), 0);
|
|
@@ -933,6 +953,7 @@ class AgentRuntime {
|
|
|
933
953
|
titleConfig: this.config.titleGeneration,
|
|
934
954
|
agentModel: this.config.model,
|
|
935
955
|
turnDelta: list.turnDelta(),
|
|
956
|
+
executionCounter: options.executionCounter,
|
|
936
957
|
});
|
|
937
958
|
this.backgroundTasks.track(titlePromise);
|
|
938
959
|
if (this.config.titleGeneration.sync) {
|
|
@@ -956,49 +977,126 @@ class AgentRuntime {
|
|
|
956
977
|
return;
|
|
957
978
|
await (0, memory_store_1.saveMessagesToThread)(this.config.memory, options.persistence.threadId, options.persistence.resourceId, delta);
|
|
958
979
|
if (this.config.semanticRecall?.embedder && this.config.memory.saveEmbeddings) {
|
|
959
|
-
await this.saveEmbeddingsForMessages(options.persistence.threadId, options.persistence.resourceId, delta);
|
|
980
|
+
await this.saveEmbeddingsForMessages(options.persistence.threadId, options.persistence.resourceId, delta, options.executionCounter);
|
|
960
981
|
}
|
|
961
|
-
this.scheduleObservationLogJobs(options.persistence);
|
|
982
|
+
const observationTasks = this.scheduleObservationLogJobs(options.persistence, options.executionCounter);
|
|
983
|
+
this.scheduleEpisodicMemoryJob(options.persistence, observationTasks, options.executionCounter);
|
|
962
984
|
}
|
|
963
|
-
scheduleObservationLogJobs(persistence) {
|
|
985
|
+
scheduleObservationLogJobs(persistence, executionCounter) {
|
|
964
986
|
const { memory, observationalMemory } = this.config;
|
|
965
987
|
if (!memory || !observationalMemory || !(0, observation_log_store_1.hasObservationLogStore)(memory))
|
|
966
|
-
return;
|
|
988
|
+
return [];
|
|
967
989
|
const scope = this.getObservationLogScope(persistence);
|
|
968
|
-
const runner = this.getMemoryTaskRunner(memory, observationalMemory);
|
|
990
|
+
const runner = this.getMemoryTaskRunner(memory, observationalMemory.lockTtlMs);
|
|
969
991
|
const observe = observationalMemory.observe;
|
|
970
992
|
const observerThresholdTokens = observationalMemory.observerThresholdTokens;
|
|
993
|
+
const tasks = [];
|
|
971
994
|
if (observe &&
|
|
972
995
|
observerThresholdTokens !== undefined &&
|
|
973
996
|
hasObservationLogObserverMemory(memory)) {
|
|
974
|
-
|
|
997
|
+
tasks.push(this.scheduleMemoryTask(runner, scope, 'observer', async () => await (0, observation_log_observer_1.runObservationLogObserver)({
|
|
975
998
|
memory,
|
|
976
999
|
...scope,
|
|
977
1000
|
observerThresholdTokens,
|
|
978
1001
|
observationLogTailLimit: observationalMemory.observationLogTailLimit ?? 0,
|
|
979
1002
|
observe,
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
resourceId: persistence.resourceId,
|
|
983
|
-
},
|
|
984
|
-
}));
|
|
1003
|
+
executionCounter,
|
|
1004
|
+
})));
|
|
985
1005
|
}
|
|
986
1006
|
const reflect = observationalMemory.reflect;
|
|
987
1007
|
const reflectorThresholdTokens = observationalMemory.reflectorThresholdTokens;
|
|
988
1008
|
if (reflect && reflectorThresholdTokens !== undefined) {
|
|
989
|
-
|
|
1009
|
+
tasks.push(this.scheduleMemoryTask(runner, scope, 'reflector', async () => await (0, observation_log_reflector_1.runObservationLogReflector)({
|
|
990
1010
|
memory,
|
|
991
1011
|
...scope,
|
|
992
1012
|
reflectorThresholdTokens,
|
|
993
1013
|
reflect,
|
|
994
|
-
|
|
1014
|
+
executionCounter,
|
|
1015
|
+
})));
|
|
1016
|
+
}
|
|
1017
|
+
return tasks;
|
|
1018
|
+
}
|
|
1019
|
+
scheduleEpisodicMemoryJob(persistence, observationTasks, executionCounter) {
|
|
1020
|
+
const { memory, episodicMemory } = this.config;
|
|
1021
|
+
if (!memory ||
|
|
1022
|
+
!episodicMemory ||
|
|
1023
|
+
!(0, episodic_memory_1.isEpisodicMemoryEnabled)(episodicMemory) ||
|
|
1024
|
+
!(0, episodic_memory_1.hasEpisodicMemoryStore)(memory) ||
|
|
1025
|
+
!(0, observation_log_store_1.hasObservationLogStore)(memory) ||
|
|
1026
|
+
!episodicMemory.extract) {
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
const scope = (0, episodic_memory_1.getEpisodicMemoryScope)(persistence);
|
|
1030
|
+
if (!scope)
|
|
1031
|
+
return;
|
|
1032
|
+
const observationScope = this.getObservationLogScope(persistence);
|
|
1033
|
+
this.scheduleEpisodicMemoryTask(memory, scope.resourceId, async () => {
|
|
1034
|
+
await Promise.allSettled(observationTasks);
|
|
1035
|
+
await (0, episodic_memory_1.runEpisodicMemoryIndexer)({
|
|
1036
|
+
memory,
|
|
1037
|
+
config: episodicMemory,
|
|
1038
|
+
scope,
|
|
1039
|
+
observationScope,
|
|
1040
|
+
threadId: persistence.threadId,
|
|
1041
|
+
executionCounter,
|
|
1042
|
+
});
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
scheduleEpisodicMemoryTask(memory, resourceId, task) {
|
|
1046
|
+
const id = crypto.randomUUID();
|
|
1047
|
+
const previous = this.episodicMemoryTasksByResource.get(resourceId) ?? Promise.resolve();
|
|
1048
|
+
const done = previous
|
|
1049
|
+
.catch(() => undefined)
|
|
1050
|
+
.then(async () => await this.runEpisodicMemoryTask(memory, resourceId, id, task));
|
|
1051
|
+
const queued = done.finally(() => {
|
|
1052
|
+
if (this.episodicMemoryTasksByResource.get(resourceId) === queued) {
|
|
1053
|
+
this.episodicMemoryTasksByResource.delete(resourceId);
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
this.episodicMemoryTasksByResource.set(resourceId, queued);
|
|
1057
|
+
this.backgroundTasks.track(queued);
|
|
1058
|
+
}
|
|
1059
|
+
async runEpisodicMemoryTask(memory, resourceId, holderId, task) {
|
|
1060
|
+
const taskLock = memory.episodic?.taskLock;
|
|
1061
|
+
let lock = null;
|
|
1062
|
+
try {
|
|
1063
|
+
if (taskLock) {
|
|
1064
|
+
lock = await taskLock.acquire(resourceId, {
|
|
1065
|
+
holderId,
|
|
1066
|
+
ttlMs: this.config.observationalMemory?.lockTtlMs ?? DEFAULT_MEMORY_TASK_LOCK_TTL_MS,
|
|
1067
|
+
});
|
|
1068
|
+
if (!lock)
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
await task();
|
|
1072
|
+
}
|
|
1073
|
+
catch (error) {
|
|
1074
|
+
const message = 'Episodic memory indexing task failed';
|
|
1075
|
+
logger.warn(message, { error, resourceId });
|
|
1076
|
+
this.eventBus.emit({ type: "error", message, error, source: 'episodic-memory' });
|
|
1077
|
+
}
|
|
1078
|
+
finally {
|
|
1079
|
+
if (lock) {
|
|
1080
|
+
await this.releaseEpisodicMemoryTaskLock(taskLock, lock, resourceId);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
async releaseEpisodicMemoryTaskLock(taskLock, lock, resourceId) {
|
|
1085
|
+
try {
|
|
1086
|
+
await taskLock?.release(lock);
|
|
1087
|
+
}
|
|
1088
|
+
catch (error) {
|
|
1089
|
+
logger.warn('Episodic memory indexing lock release failed', { error, resourceId });
|
|
995
1090
|
}
|
|
996
1091
|
}
|
|
997
|
-
|
|
1092
|
+
async scheduleMemoryTask(runner, scope, taskKind, task) {
|
|
1093
|
+
return await runner.schedule({ ...scope, taskKind }, task).done;
|
|
1094
|
+
}
|
|
1095
|
+
getMemoryTaskRunner(memory, lockTtlMs) {
|
|
998
1096
|
this.memoryTasks ??= new scoped_memory_task_runner_1.ScopedMemoryTaskRunner({
|
|
999
1097
|
tracker: this.backgroundTasks,
|
|
1000
1098
|
lockStore: (0, observation_log_store_1.hasObservationLogTaskLockStore)(memory) ? memory : undefined,
|
|
1001
|
-
lockTtlMs
|
|
1099
|
+
lockTtlMs,
|
|
1002
1100
|
onEvent: (event) => {
|
|
1003
1101
|
if (event.type !== 'failed')
|
|
1004
1102
|
return;
|
|
@@ -1006,8 +1104,7 @@ class AgentRuntime {
|
|
|
1006
1104
|
const message = `Observation log ${source} task failed`;
|
|
1007
1105
|
logger.warn(message, {
|
|
1008
1106
|
error: event.error,
|
|
1009
|
-
|
|
1010
|
-
scopeId: event.task.scopeId,
|
|
1107
|
+
observationScopeId: event.task.observationScopeId,
|
|
1011
1108
|
});
|
|
1012
1109
|
this.eventBus.emit({ type: "error", message, error: event.error, source });
|
|
1013
1110
|
},
|
|
@@ -1016,11 +1113,10 @@ class AgentRuntime {
|
|
|
1016
1113
|
}
|
|
1017
1114
|
getObservationLogScope(persistence) {
|
|
1018
1115
|
return {
|
|
1019
|
-
|
|
1020
|
-
scopeId: (0, observation_log_1.createObservationLogThreadScopeId)(persistence.threadId, persistence.resourceId),
|
|
1116
|
+
observationScopeId: persistence.threadId,
|
|
1021
1117
|
};
|
|
1022
1118
|
}
|
|
1023
|
-
async saveEmbeddingsForMessages(threadId, resourceId, messages) {
|
|
1119
|
+
async saveEmbeddingsForMessages(threadId, resourceId, messages, executionCounter) {
|
|
1024
1120
|
const embeddable = [];
|
|
1025
1121
|
for (const msg of messages) {
|
|
1026
1122
|
if (!(0, message_1.isLlmMessage)(msg) || (msg.role !== 'user' && msg.role !== 'assistant'))
|
|
@@ -1038,12 +1134,13 @@ class AgentRuntime {
|
|
|
1038
1134
|
const embedder = this.config.semanticRecall?.embedder;
|
|
1039
1135
|
if (!embedder)
|
|
1040
1136
|
return;
|
|
1041
|
-
const { embedMany } =
|
|
1137
|
+
const { embedMany } = getAiSdk();
|
|
1042
1138
|
const embeddingModel = (0, model_factory_1.createEmbeddingModel)(embedder, this.config.semanticRecall?.apiKey);
|
|
1043
|
-
const { embeddings } = await embedMany({
|
|
1139
|
+
const { embeddings, usage } = await embedMany({
|
|
1044
1140
|
model: embeddingModel,
|
|
1045
1141
|
values: embeddable.map((e) => e.text),
|
|
1046
1142
|
});
|
|
1143
|
+
(0, execution_counter_1.incrementTokenCountFromUsage)(executionCounter, usage);
|
|
1047
1144
|
await this.config.memory.saveEmbeddings({
|
|
1048
1145
|
scope: this.config.semanticRecall?.scope ?? 'resource',
|
|
1049
1146
|
threadId,
|
|
@@ -1417,6 +1514,7 @@ class AgentRuntime {
|
|
|
1417
1514
|
};
|
|
1418
1515
|
}
|
|
1419
1516
|
buildStaticLoopContext(execOptions) {
|
|
1517
|
+
const { Output } = getAiSdk();
|
|
1420
1518
|
const aiProviderTools = (0, tool_adapter_1.toAiSdkProviderTools)(this.config.providerTools);
|
|
1421
1519
|
const model = (0, model_factory_1.createModel)(this.config.model);
|
|
1422
1520
|
return {
|
|
@@ -1424,12 +1522,12 @@ class AgentRuntime {
|
|
|
1424
1522
|
aiProviderTools,
|
|
1425
1523
|
providerOptions: this.buildCallProviderOptions(execOptions?.providerOptions),
|
|
1426
1524
|
outputSpec: this.config.structuredOutput
|
|
1427
|
-
?
|
|
1525
|
+
? Output.object({ schema: this.config.structuredOutput })
|
|
1428
1526
|
: undefined,
|
|
1429
1527
|
};
|
|
1430
1528
|
}
|
|
1431
|
-
buildToolLoopContext(aiProviderTools) {
|
|
1432
|
-
const allUserTools = this.getCurrentTools();
|
|
1529
|
+
buildToolLoopContext(aiProviderTools, persistence, executionCounter) {
|
|
1530
|
+
const allUserTools = this.getCurrentTools(persistence, executionCounter);
|
|
1433
1531
|
const aiTools = (0, tool_adapter_1.toAiSdkTools)(allUserTools);
|
|
1434
1532
|
const allTools = { ...aiTools, ...aiProviderTools };
|
|
1435
1533
|
const aiToolCount = Object.keys(allTools).length;
|
|
@@ -1442,15 +1540,35 @@ class AgentRuntime {
|
|
|
1442
1540
|
effectiveInstructions,
|
|
1443
1541
|
};
|
|
1444
1542
|
}
|
|
1445
|
-
getCurrentTools() {
|
|
1543
|
+
getCurrentTools(persistence, executionCounter) {
|
|
1446
1544
|
const baseTools = this.config.tools ?? [];
|
|
1447
|
-
|
|
1448
|
-
return baseTools;
|
|
1449
|
-
return [
|
|
1545
|
+
const tools = [
|
|
1450
1546
|
...baseTools,
|
|
1451
|
-
...this.deferredToolManager
|
|
1452
|
-
|
|
1547
|
+
...(this.deferredToolManager?.hasTools
|
|
1548
|
+
? [
|
|
1549
|
+
...this.deferredToolManager.getControllerTools(),
|
|
1550
|
+
...this.deferredToolManager.getLoadedTools(),
|
|
1551
|
+
]
|
|
1552
|
+
: []),
|
|
1453
1553
|
];
|
|
1554
|
+
const recallTool = this.createRecallMemoryToolForRun(persistence, tools, executionCounter);
|
|
1555
|
+
return recallTool ? [...tools, recallTool] : tools;
|
|
1556
|
+
}
|
|
1557
|
+
createRecallMemoryToolForRun(persistence, existingTools, executionCounter) {
|
|
1558
|
+
const { memory, episodicMemory } = this.config;
|
|
1559
|
+
if (!memory ||
|
|
1560
|
+
!episodicMemory ||
|
|
1561
|
+
!(0, episodic_memory_1.isEpisodicMemoryEnabled)(episodicMemory) ||
|
|
1562
|
+
!(0, episodic_memory_1.hasEpisodicMemoryStore)(memory)) {
|
|
1563
|
+
return undefined;
|
|
1564
|
+
}
|
|
1565
|
+
const scope = (0, episodic_memory_1.getEpisodicMemoryScope)(persistence);
|
|
1566
|
+
if (!scope)
|
|
1567
|
+
return undefined;
|
|
1568
|
+
if (existingTools.some((tool) => tool.name === episodic_memory_1.RECALL_MEMORY_TOOL_NAME)) {
|
|
1569
|
+
throw new Error(`Tool name "${episodic_memory_1.RECALL_MEMORY_TOOL_NAME}" is reserved while episodic memory is enabled.`);
|
|
1570
|
+
}
|
|
1571
|
+
return (0, episodic_memory_1.createRecallMemoryTool)({ memory, config: episodicMemory, scope, executionCounter });
|
|
1454
1572
|
}
|
|
1455
1573
|
hydrateDeferredToolsFromList(list) {
|
|
1456
1574
|
if (!this.deferredToolManager?.hasTools)
|
|
@@ -1467,9 +1585,11 @@ class AgentRuntime {
|
|
|
1467
1585
|
const block = `<built_in_rules>\n${fragments.map((f) => `- ${f}`).join('\n')}\n</built_in_rules>`;
|
|
1468
1586
|
return userInstructions ? `${block}\n\n${userInstructions}` : block;
|
|
1469
1587
|
}
|
|
1470
|
-
async persistSuspension(pendingToolCalls, options, list, totalUsage, existingRunId) {
|
|
1588
|
+
async persistSuspension(pendingToolCalls, options, list, totalUsage, existingRunId, maxIterations, iterationCount) {
|
|
1471
1589
|
const runId = existingRunId ?? (0, run_state_1.generateRunId)();
|
|
1472
|
-
const
|
|
1590
|
+
const resolvedMaxIterations = maxIterations ?? options?.maxIterations;
|
|
1591
|
+
const resolvedIterationCount = iterationCount ?? options?.iterationCount;
|
|
1592
|
+
const executionOptions = resolvedMaxIterations !== undefined ? { maxIterations: resolvedMaxIterations } : undefined;
|
|
1473
1593
|
const state = {
|
|
1474
1594
|
persistence: options?.persistence,
|
|
1475
1595
|
status: 'suspended',
|
|
@@ -1477,6 +1597,7 @@ class AgentRuntime {
|
|
|
1477
1597
|
pendingToolCalls,
|
|
1478
1598
|
usage: totalUsage,
|
|
1479
1599
|
executionOptions,
|
|
1600
|
+
...(resolvedIterationCount !== undefined ? { iterationCount: resolvedIterationCount } : {}),
|
|
1480
1601
|
};
|
|
1481
1602
|
await this.runState.suspend(runId, state);
|
|
1482
1603
|
this.updateState({ status: 'suspended', pendingToolCalls, messageList: list.serialize() });
|
|
@@ -1539,6 +1660,9 @@ class AgentRuntime {
|
|
|
1539
1660
|
(0, observation_log_renderer_1.renderObservationLog)(observations, {
|
|
1540
1661
|
renderTokenBudget: this.config.observationLog?.renderTokenBudget,
|
|
1541
1662
|
}) ?? undefined;
|
|
1663
|
+
if (observations.length > 0) {
|
|
1664
|
+
list.seedLastCreatedAt(observations[observations.length - 1].createdAt.getTime());
|
|
1665
|
+
}
|
|
1542
1666
|
}
|
|
1543
1667
|
getConfiguredTelemetry() {
|
|
1544
1668
|
return this.config.telemetry;
|