@n8n/agents 0.7.1 → 0.8.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 -7
- package/dist/index.js +30 -10
- package/dist/index.js.map +1 -1
- package/dist/runtime/agent-runtime.d.ts +24 -12
- package/dist/runtime/agent-runtime.js +241 -91
- package/dist/runtime/agent-runtime.js.map +1 -1
- package/dist/runtime/background-task-tracker.d.ts +6 -0
- package/dist/runtime/background-task-tracker.js +26 -0
- package/dist/runtime/background-task-tracker.js.map +1 -0
- package/dist/runtime/deferred-tool-manager.d.ts +28 -0
- package/dist/runtime/deferred-tool-manager.js +205 -0
- package/dist/runtime/deferred-tool-manager.js.map +1 -0
- package/dist/runtime/memory-store.d.ts +21 -36
- package/dist/runtime/memory-store.js +118 -51
- package/dist/runtime/memory-store.js.map +1 -1
- package/dist/runtime/message-list.d.ts +1 -7
- package/dist/runtime/message-list.js +3 -6
- package/dist/runtime/message-list.js.map +1 -1
- package/dist/runtime/observation-log-defaults.d.ts +20 -0
- package/dist/runtime/observation-log-defaults.js +523 -0
- package/dist/runtime/observation-log-defaults.js.map +1 -0
- package/dist/runtime/observation-log-observer.d.ts +64 -0
- package/dist/runtime/observation-log-observer.js +235 -0
- package/dist/runtime/observation-log-observer.js.map +1 -0
- package/dist/runtime/observation-log-reflector.d.ts +36 -0
- package/dist/runtime/observation-log-reflector.js +292 -0
- package/dist/runtime/observation-log-reflector.js.map +1 -0
- package/dist/runtime/observation-log-renderer.d.ts +6 -0
- package/dist/runtime/observation-log-renderer.js +73 -0
- package/dist/runtime/observation-log-renderer.js.map +1 -0
- package/dist/runtime/observation-log-store.d.ts +3 -0
- package/dist/runtime/observation-log-store.js +26 -0
- package/dist/runtime/observation-log-store.js.map +1 -0
- package/dist/runtime/scoped-memory-task-runner.d.ts +79 -0
- package/dist/runtime/scoped-memory-task-runner.js +134 -0
- package/dist/runtime/scoped-memory-task-runner.js.map +1 -0
- package/dist/sdk/agent.d.ts +13 -1
- package/dist/sdk/agent.js +58 -9
- package/dist/sdk/agent.js.map +1 -1
- package/dist/sdk/catalog.d.ts +1 -0
- package/dist/sdk/catalog.js +1 -0
- package/dist/sdk/catalog.js.map +1 -1
- package/dist/sdk/memory.d.ts +12 -12
- package/dist/sdk/memory.js +71 -51
- package/dist/sdk/memory.js.map +1 -1
- package/dist/storage/base-memory.d.ts +0 -10
- package/dist/storage/base-memory.js +0 -6
- package/dist/storage/base-memory.js.map +1 -1
- package/dist/types/index.d.ts +5 -4
- package/dist/types/index.js +7 -3
- package/dist/types/index.js.map +1 -1
- package/dist/types/runtime/event.d.ts +1 -0
- package/dist/types/sdk/agent-builder.d.ts +5 -0
- package/dist/types/sdk/agent.d.ts +6 -0
- package/dist/types/sdk/memory.d.ts +16 -24
- package/dist/types/sdk/observation-log.d.ts +99 -0
- package/dist/types/sdk/observation-log.js +17 -0
- package/dist/types/sdk/observation-log.js.map +1 -0
- package/dist/types/sdk/observation.d.ts +3 -94
- package/dist/types/sdk/observation.js +0 -2
- package/dist/types/sdk/observation.js.map +1 -1
- package/dist/types/sdk/provider.d.ts +5 -2
- package/package.json +3 -7
- package/dist/runtime/working-memory.d.ts +0 -14
- package/dist/runtime/working-memory.js +0 -69
- package/dist/runtime/working-memory.js.map +0 -1
- package/dist/storage/postgres-memory.d.ts +0 -96
- package/dist/storage/postgres-memory.js +0 -431
- package/dist/storage/postgres-memory.js.map +0 -1
- package/dist/storage/sqlite-memory.d.ts +0 -70
- package/dist/storage/sqlite-memory.js +0 -354
- package/dist/storage/sqlite-memory.js.map +0 -1
|
@@ -38,19 +38,27 @@ const ai_1 = require("ai");
|
|
|
38
38
|
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
39
39
|
const catalog_1 = require("../sdk/catalog");
|
|
40
40
|
const message_1 = require("../sdk/message");
|
|
41
|
+
const background_task_tracker_1 = require("./background-task-tracker");
|
|
42
|
+
const deferred_tool_manager_1 = require("./deferred-tool-manager");
|
|
41
43
|
const event_bus_1 = require("./event-bus");
|
|
42
44
|
const json_value_1 = require("./json-value");
|
|
45
|
+
const logger_1 = require("./logger");
|
|
43
46
|
const memory_store_1 = require("./memory-store");
|
|
44
47
|
const message_list_1 = require("./message-list");
|
|
45
48
|
const messages_1 = require("./messages");
|
|
46
49
|
const model_factory_1 = require("./model-factory");
|
|
50
|
+
const observation_log_observer_1 = require("./observation-log-observer");
|
|
51
|
+
const observation_log_reflector_1 = require("./observation-log-reflector");
|
|
52
|
+
const observation_log_renderer_1 = require("./observation-log-renderer");
|
|
53
|
+
const observation_log_store_1 = require("./observation-log-store");
|
|
47
54
|
const run_state_1 = require("./run-state");
|
|
48
55
|
const runtime_helpers_1 = require("./runtime-helpers");
|
|
56
|
+
const scoped_memory_task_runner_1 = require("./scoped-memory-task-runner");
|
|
49
57
|
const stream_1 = require("./stream");
|
|
50
58
|
const strip_orphaned_tool_messages_1 = require("./strip-orphaned-tool-messages");
|
|
51
59
|
const title_generation_1 = require("./title-generation");
|
|
52
60
|
const tool_adapter_1 = require("./tool-adapter");
|
|
53
|
-
const
|
|
61
|
+
const observation_log_1 = require("../types/sdk/observation-log");
|
|
54
62
|
const parse_1 = require("../utils/parse");
|
|
55
63
|
const zod_1 = require("../utils/zod");
|
|
56
64
|
function isActiveSpanTracer(value) {
|
|
@@ -112,15 +120,29 @@ function buildAgentRootInputAttributes(config) {
|
|
|
112
120
|
};
|
|
113
121
|
}
|
|
114
122
|
const MAX_LOOP_ITERATIONS = 20;
|
|
123
|
+
const logger = (0, logger_1.createFilteredLogger)();
|
|
115
124
|
const EMPTY_MESSAGE_LIST = {
|
|
116
125
|
messages: [],
|
|
117
126
|
historyIds: [],
|
|
118
127
|
inputIds: [],
|
|
119
128
|
responseIds: [],
|
|
120
129
|
};
|
|
130
|
+
function hasFunctionProperty(value, property) {
|
|
131
|
+
return property in value && typeof Reflect.get(value, property) === 'function';
|
|
132
|
+
}
|
|
133
|
+
function hasObservationLogObserverMemory(memory) {
|
|
134
|
+
return ((0, observation_log_store_1.hasObservationLogStore)(memory) &&
|
|
135
|
+
hasFunctionProperty(memory, 'getMessagesForScope') &&
|
|
136
|
+
hasFunctionProperty(memory, 'getCursor') &&
|
|
137
|
+
hasFunctionProperty(memory, 'setCursor'));
|
|
138
|
+
}
|
|
121
139
|
class AgentRuntime {
|
|
122
140
|
constructor(config) {
|
|
141
|
+
this.backgroundTasks = new background_task_tracker_1.BackgroundTaskTracker();
|
|
123
142
|
this.config = config;
|
|
143
|
+
if (config.deferredTools && config.deferredTools.length > 0) {
|
|
144
|
+
this.deferredToolManager = new deferred_tool_manager_1.DeferredToolManager(config.deferredTools, config.toolSearch);
|
|
145
|
+
}
|
|
124
146
|
this.runState = new run_state_1.RunStateManager(config.checkpointStorage);
|
|
125
147
|
this.eventBus = config.eventBus ?? new event_bus_1.AgentEventBus();
|
|
126
148
|
this.currentState = {
|
|
@@ -130,6 +152,9 @@ class AgentRuntime {
|
|
|
130
152
|
pendingToolCalls: {},
|
|
131
153
|
};
|
|
132
154
|
}
|
|
155
|
+
async dispose() {
|
|
156
|
+
await this.backgroundTasks.flush();
|
|
157
|
+
}
|
|
133
158
|
getState() {
|
|
134
159
|
return { ...this.currentState };
|
|
135
160
|
}
|
|
@@ -178,7 +203,9 @@ class AgentRuntime {
|
|
|
178
203
|
const toolCall = state.pendingToolCalls[options.toolCallId];
|
|
179
204
|
if (!toolCall)
|
|
180
205
|
throw new Error(`No tool call found for toolCallId: ${options.toolCallId}`);
|
|
181
|
-
const
|
|
206
|
+
const list = message_list_1.AgentMessageList.deserialize(state.messageList);
|
|
207
|
+
this.hydrateDeferredToolsFromList(list);
|
|
208
|
+
const tool = this.getCurrentTools().find((t) => t.name === toolCall.toolName);
|
|
182
209
|
if (!tool)
|
|
183
210
|
throw new Error(`Tool ${toolCall.toolName} not found`);
|
|
184
211
|
let resumeData = data;
|
|
@@ -190,7 +217,6 @@ class AgentRuntime {
|
|
|
190
217
|
resumeData = parseResult.data;
|
|
191
218
|
}
|
|
192
219
|
try {
|
|
193
|
-
const list = message_list_1.AgentMessageList.deserialize(state.messageList);
|
|
194
220
|
const { runId: _rid, toolCallId: _tcid, ...callerExecOptions } = options;
|
|
195
221
|
const persisted = state.executionOptions ?? {};
|
|
196
222
|
const mergedExecOptions = {
|
|
@@ -209,7 +235,7 @@ class AgentRuntime {
|
|
|
209
235
|
messages: state.messageList.messages,
|
|
210
236
|
};
|
|
211
237
|
await this.ensureModelCost();
|
|
212
|
-
await this.
|
|
238
|
+
await this.setListObservationLogMemory(list, state.persistence);
|
|
213
239
|
if (method === 'generate') {
|
|
214
240
|
const rawResult = await this.withTelemetryRootSpan('generate', resumeOptions, options.runId, async () => await this.runGenerateLoop({
|
|
215
241
|
list,
|
|
@@ -254,6 +280,7 @@ class AgentRuntime {
|
|
|
254
280
|
if (this.config.memory && options?.persistence?.threadId) {
|
|
255
281
|
const memMessages = await this.config.memory.getMessages(options.persistence.threadId, {
|
|
256
282
|
limit: this.config.lastMessages ?? 10,
|
|
283
|
+
resourceId: options.persistence.resourceId,
|
|
257
284
|
});
|
|
258
285
|
if (memMessages.length > 0) {
|
|
259
286
|
list.addHistory((0, strip_orphaned_tool_messages_1.stripOrphanedToolMessages)(memMessages));
|
|
@@ -262,7 +289,7 @@ class AgentRuntime {
|
|
|
262
289
|
if (this.config.semanticRecall && options?.persistence?.threadId) {
|
|
263
290
|
await this.performSemanticRecall(list, input, options.persistence.threadId, options.persistence.resourceId);
|
|
264
291
|
}
|
|
265
|
-
await this.
|
|
292
|
+
await this.setListObservationLogMemory(list, options?.persistence);
|
|
266
293
|
list.addInput(input);
|
|
267
294
|
return list;
|
|
268
295
|
}
|
|
@@ -353,6 +380,7 @@ class AgentRuntime {
|
|
|
353
380
|
this.eventBus.emit({ type: "agent_start" });
|
|
354
381
|
await this.ensureModelCost();
|
|
355
382
|
const normalizedInput = (0, runtime_helpers_1.normalizeInput)(input);
|
|
383
|
+
this.incrementMessageCount(options?.executionCounter);
|
|
356
384
|
return await this.buildMessageList(normalizedInput, options);
|
|
357
385
|
}
|
|
358
386
|
finalizeGenerate(result, list, runId) {
|
|
@@ -423,6 +451,31 @@ class AgentRuntime {
|
|
|
423
451
|
...this.buildTelemetryMetadataAttributes(t, 'ai.telemetry.metadata'),
|
|
424
452
|
};
|
|
425
453
|
}
|
|
454
|
+
recordExecutionCounter(fn) {
|
|
455
|
+
try {
|
|
456
|
+
fn();
|
|
457
|
+
}
|
|
458
|
+
catch {
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
incrementMessageCount(counter) {
|
|
462
|
+
if (!counter)
|
|
463
|
+
return;
|
|
464
|
+
this.recordExecutionCounter(() => counter.incrementMessageCount());
|
|
465
|
+
}
|
|
466
|
+
incrementToolCallCount(counter) {
|
|
467
|
+
if (!counter)
|
|
468
|
+
return;
|
|
469
|
+
this.recordExecutionCounter(() => counter.incrementToolCallCount());
|
|
470
|
+
}
|
|
471
|
+
incrementTokenCount(counter, usage) {
|
|
472
|
+
if (!counter || !usage)
|
|
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));
|
|
478
|
+
}
|
|
426
479
|
async withTelemetryRootSpan(operation, options, runId, fn) {
|
|
427
480
|
const t = this.resolveTelemetry(options);
|
|
428
481
|
if (!t?.enabled || t.runtimeRootSpanEnabled === false || !isActiveSpanTracer(t.tracer)) {
|
|
@@ -478,16 +531,30 @@ class AgentRuntime {
|
|
|
478
531
|
}
|
|
479
532
|
async runGenerateLoop(ctx) {
|
|
480
533
|
const { list, options, runId, pendingResume } = ctx;
|
|
481
|
-
|
|
534
|
+
this.hydrateDeferredToolsFromList(list);
|
|
482
535
|
let totalUsage;
|
|
483
536
|
let lastFinishReason = 'stop';
|
|
484
537
|
let structuredOutput;
|
|
485
538
|
const toolCallSummary = [];
|
|
486
539
|
const collectedSubAgentUsage = [];
|
|
487
540
|
const runTelemetry = this.resolveTelemetry(options);
|
|
488
|
-
const
|
|
541
|
+
const staticLoopContext = this.buildStaticLoopContext({
|
|
542
|
+
...options,
|
|
543
|
+
persistence: options?.persistence,
|
|
544
|
+
});
|
|
545
|
+
const pendingLoopContext = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
|
|
546
|
+
const pendingToolCtx = {
|
|
547
|
+
toolMap: pendingLoopContext.toolMap,
|
|
548
|
+
list,
|
|
549
|
+
runId,
|
|
550
|
+
telemetry: runTelemetry,
|
|
551
|
+
executionCounter: options?.executionCounter,
|
|
552
|
+
};
|
|
489
553
|
if (pendingResume) {
|
|
490
|
-
const batch = await this.iteratePendingToolCallsConcurrent({
|
|
554
|
+
const batch = await this.iteratePendingToolCallsConcurrent({
|
|
555
|
+
...pendingToolCtx,
|
|
556
|
+
pendingResume,
|
|
557
|
+
});
|
|
491
558
|
for (const r of batch.results) {
|
|
492
559
|
toolCallSummary.push(r.toolEntry);
|
|
493
560
|
if (r.subAgentUsage)
|
|
@@ -518,32 +585,38 @@ class AgentRuntime {
|
|
|
518
585
|
throw new Error('Agent run was aborted');
|
|
519
586
|
}
|
|
520
587
|
this.eventBus.emit({ type: "turn_start" });
|
|
588
|
+
const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
|
|
521
589
|
const result = await (0, ai_1.generateText)({
|
|
522
|
-
model,
|
|
590
|
+
model: staticLoopContext.model,
|
|
523
591
|
messages: list.forLlm(effectiveInstructions, this.config.instructionProviderOptions),
|
|
524
592
|
abortSignal: this.eventBus.signal,
|
|
525
593
|
...(hasTools ? { tools: aiTools } : {}),
|
|
526
|
-
...(providerOptions
|
|
527
|
-
? { providerOptions: providerOptions }
|
|
594
|
+
...(staticLoopContext.providerOptions
|
|
595
|
+
? { providerOptions: staticLoopContext.providerOptions }
|
|
528
596
|
: {}),
|
|
529
|
-
...(outputSpec ? { output: outputSpec } : {}),
|
|
597
|
+
...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}),
|
|
530
598
|
...this.buildTelemetryOptions(options),
|
|
531
599
|
});
|
|
532
600
|
const aiFinishReason = result.finishReason;
|
|
533
601
|
lastFinishReason = (0, messages_1.fromAiFinishReason)(aiFinishReason);
|
|
534
602
|
totalUsage = (0, runtime_helpers_1.accumulateUsage)(totalUsage, result.usage);
|
|
603
|
+
this.incrementTokenCount(options?.executionCounter, result.usage);
|
|
535
604
|
const responseMessages = result.response.messages;
|
|
536
605
|
const newMessages = (0, messages_1.fromAiMessages)(responseMessages);
|
|
537
606
|
list.addResponse(newMessages);
|
|
538
607
|
if (aiFinishReason !== 'tool-calls') {
|
|
539
|
-
if (outputSpec) {
|
|
608
|
+
if (staticLoopContext.outputSpec) {
|
|
540
609
|
structuredOutput = result.output;
|
|
541
610
|
}
|
|
542
611
|
this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(newMessages));
|
|
543
612
|
break;
|
|
544
613
|
}
|
|
545
614
|
const batch = await this.iterateToolCallsConcurrent({
|
|
546
|
-
|
|
615
|
+
toolMap,
|
|
616
|
+
list,
|
|
617
|
+
runId,
|
|
618
|
+
telemetry: runTelemetry,
|
|
619
|
+
executionCounter: options?.executionCounter,
|
|
547
620
|
toolCalls: result.toolCalls,
|
|
548
621
|
});
|
|
549
622
|
for (const r of batch.results) {
|
|
@@ -584,6 +657,7 @@ class AgentRuntime {
|
|
|
584
657
|
agentModel: this.config.model,
|
|
585
658
|
turnDelta: list.turnDelta(),
|
|
586
659
|
});
|
|
660
|
+
this.backgroundTasks.track(titlePromise);
|
|
587
661
|
if (this.config.titleGeneration.sync) {
|
|
588
662
|
await titlePromise;
|
|
589
663
|
}
|
|
@@ -634,7 +708,7 @@ class AgentRuntime {
|
|
|
634
708
|
}
|
|
635
709
|
async runStreamLoop(ctx) {
|
|
636
710
|
const { list, options, runId, pendingResume, writer } = ctx;
|
|
637
|
-
|
|
711
|
+
this.hydrateDeferredToolsFromList(list);
|
|
638
712
|
const writeChunk = async (chunk) => {
|
|
639
713
|
await writer.write(chunk);
|
|
640
714
|
};
|
|
@@ -657,11 +731,22 @@ class AgentRuntime {
|
|
|
657
731
|
return true;
|
|
658
732
|
};
|
|
659
733
|
const runTelemetry = this.resolveTelemetry(options);
|
|
660
|
-
const
|
|
734
|
+
const staticLoopContext = this.buildStaticLoopContext({
|
|
735
|
+
...options,
|
|
736
|
+
persistence: options?.persistence,
|
|
737
|
+
});
|
|
738
|
+
const pendingLoopContext = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
|
|
739
|
+
const pendingToolCtx = {
|
|
740
|
+
toolMap: pendingLoopContext.toolMap,
|
|
741
|
+
list,
|
|
742
|
+
runId,
|
|
743
|
+
telemetry: runTelemetry,
|
|
744
|
+
executionCounter: options?.executionCounter,
|
|
745
|
+
};
|
|
661
746
|
if (pendingResume) {
|
|
662
747
|
try {
|
|
663
748
|
const batch = await this.iteratePendingToolCallsConcurrent({
|
|
664
|
-
...
|
|
749
|
+
...pendingToolCtx,
|
|
665
750
|
pendingResume,
|
|
666
751
|
});
|
|
667
752
|
for (const r of batch.results) {
|
|
@@ -714,16 +799,17 @@ class AgentRuntime {
|
|
|
714
799
|
if (await handleAbort())
|
|
715
800
|
return;
|
|
716
801
|
this.eventBus.emit({ type: "turn_start" });
|
|
802
|
+
const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
|
|
717
803
|
const messages = list.forLlm(effectiveInstructions, this.config.instructionProviderOptions);
|
|
718
804
|
const result = (0, ai_1.streamText)({
|
|
719
|
-
model,
|
|
805
|
+
model: staticLoopContext.model,
|
|
720
806
|
messages,
|
|
721
807
|
abortSignal: this.eventBus.signal,
|
|
722
808
|
...(hasTools ? { tools: aiTools } : {}),
|
|
723
|
-
...(providerOptions
|
|
724
|
-
? { providerOptions: providerOptions }
|
|
809
|
+
...(staticLoopContext.providerOptions
|
|
810
|
+
? { providerOptions: staticLoopContext.providerOptions }
|
|
725
811
|
: {}),
|
|
726
|
-
...(outputSpec ? { output: outputSpec } : {}),
|
|
812
|
+
...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}),
|
|
727
813
|
...this.buildTelemetryOptions(options),
|
|
728
814
|
});
|
|
729
815
|
try {
|
|
@@ -753,11 +839,12 @@ class AgentRuntime {
|
|
|
753
839
|
const response = await result.response;
|
|
754
840
|
lastFinishReason = (0, messages_1.fromAiFinishReason)(aiFinishReason);
|
|
755
841
|
totalUsage = (0, runtime_helpers_1.accumulateUsage)(totalUsage, usage);
|
|
842
|
+
this.incrementTokenCount(options?.executionCounter, usage);
|
|
756
843
|
const responseMessages = response.messages;
|
|
757
844
|
const newMessages = (0, messages_1.fromAiMessages)(responseMessages);
|
|
758
845
|
list.addResponse(newMessages);
|
|
759
846
|
if (aiFinishReason !== 'tool-calls') {
|
|
760
|
-
if (outputSpec) {
|
|
847
|
+
if (staticLoopContext.outputSpec) {
|
|
761
848
|
structuredOutput = await result.output;
|
|
762
849
|
}
|
|
763
850
|
this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(newMessages));
|
|
@@ -765,7 +852,14 @@ class AgentRuntime {
|
|
|
765
852
|
}
|
|
766
853
|
const toolCalls = await result.toolCalls;
|
|
767
854
|
try {
|
|
768
|
-
const batch = await this.iterateToolCallsConcurrent({
|
|
855
|
+
const batch = await this.iterateToolCallsConcurrent({
|
|
856
|
+
toolMap,
|
|
857
|
+
list,
|
|
858
|
+
runId,
|
|
859
|
+
telemetry: runTelemetry,
|
|
860
|
+
executionCounter: options?.executionCounter,
|
|
861
|
+
toolCalls,
|
|
862
|
+
});
|
|
769
863
|
if (await handleAbort())
|
|
770
864
|
return;
|
|
771
865
|
for (const r of batch.results) {
|
|
@@ -840,6 +934,7 @@ class AgentRuntime {
|
|
|
840
934
|
agentModel: this.config.model,
|
|
841
935
|
turnDelta: list.turnDelta(),
|
|
842
936
|
});
|
|
937
|
+
this.backgroundTasks.track(titlePromise);
|
|
843
938
|
if (this.config.titleGeneration.sync) {
|
|
844
939
|
await titlePromise;
|
|
845
940
|
}
|
|
@@ -863,6 +958,67 @@ class AgentRuntime {
|
|
|
863
958
|
if (this.config.semanticRecall?.embedder && this.config.memory.saveEmbeddings) {
|
|
864
959
|
await this.saveEmbeddingsForMessages(options.persistence.threadId, options.persistence.resourceId, delta);
|
|
865
960
|
}
|
|
961
|
+
this.scheduleObservationLogJobs(options.persistence);
|
|
962
|
+
}
|
|
963
|
+
scheduleObservationLogJobs(persistence) {
|
|
964
|
+
const { memory, observationalMemory } = this.config;
|
|
965
|
+
if (!memory || !observationalMemory || !(0, observation_log_store_1.hasObservationLogStore)(memory))
|
|
966
|
+
return;
|
|
967
|
+
const scope = this.getObservationLogScope(persistence);
|
|
968
|
+
const runner = this.getMemoryTaskRunner(memory, observationalMemory);
|
|
969
|
+
const observe = observationalMemory.observe;
|
|
970
|
+
const observerThresholdTokens = observationalMemory.observerThresholdTokens;
|
|
971
|
+
if (observe &&
|
|
972
|
+
observerThresholdTokens !== undefined &&
|
|
973
|
+
hasObservationLogObserverMemory(memory)) {
|
|
974
|
+
runner.schedule({ ...scope, taskKind: 'observer' }, async () => await (0, observation_log_observer_1.runObservationLogObserver)({
|
|
975
|
+
memory,
|
|
976
|
+
...scope,
|
|
977
|
+
observerThresholdTokens,
|
|
978
|
+
observationLogTailLimit: observationalMemory.observationLogTailLimit ?? 0,
|
|
979
|
+
observe,
|
|
980
|
+
messageSource: {
|
|
981
|
+
threadId: persistence.threadId,
|
|
982
|
+
resourceId: persistence.resourceId,
|
|
983
|
+
},
|
|
984
|
+
}));
|
|
985
|
+
}
|
|
986
|
+
const reflect = observationalMemory.reflect;
|
|
987
|
+
const reflectorThresholdTokens = observationalMemory.reflectorThresholdTokens;
|
|
988
|
+
if (reflect && reflectorThresholdTokens !== undefined) {
|
|
989
|
+
runner.schedule({ ...scope, taskKind: 'reflector' }, async () => await (0, observation_log_reflector_1.runObservationLogReflector)({
|
|
990
|
+
memory,
|
|
991
|
+
...scope,
|
|
992
|
+
reflectorThresholdTokens,
|
|
993
|
+
reflect,
|
|
994
|
+
}));
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
getMemoryTaskRunner(memory, observationalMemory) {
|
|
998
|
+
this.memoryTasks ??= new scoped_memory_task_runner_1.ScopedMemoryTaskRunner({
|
|
999
|
+
tracker: this.backgroundTasks,
|
|
1000
|
+
lockStore: (0, observation_log_store_1.hasObservationLogTaskLockStore)(memory) ? memory : undefined,
|
|
1001
|
+
lockTtlMs: observationalMemory.lockTtlMs,
|
|
1002
|
+
onEvent: (event) => {
|
|
1003
|
+
if (event.type !== 'failed')
|
|
1004
|
+
return;
|
|
1005
|
+
const source = event.task.taskKind;
|
|
1006
|
+
const message = `Observation log ${source} task failed`;
|
|
1007
|
+
logger.warn(message, {
|
|
1008
|
+
error: event.error,
|
|
1009
|
+
scopeKind: event.task.scopeKind,
|
|
1010
|
+
scopeId: event.task.scopeId,
|
|
1011
|
+
});
|
|
1012
|
+
this.eventBus.emit({ type: "error", message, error: event.error, source });
|
|
1013
|
+
},
|
|
1014
|
+
});
|
|
1015
|
+
return this.memoryTasks;
|
|
1016
|
+
}
|
|
1017
|
+
getObservationLogScope(persistence) {
|
|
1018
|
+
return {
|
|
1019
|
+
scopeKind: 'thread',
|
|
1020
|
+
scopeId: (0, observation_log_1.createObservationLogThreadScopeId)(persistence.threadId, persistence.resourceId),
|
|
1021
|
+
};
|
|
866
1022
|
}
|
|
867
1023
|
async saveEmbeddingsForMessages(threadId, resourceId, messages) {
|
|
868
1024
|
const embeddable = [];
|
|
@@ -908,12 +1064,12 @@ class AgentRuntime {
|
|
|
908
1064
|
switch (provider) {
|
|
909
1065
|
case 'anthropic': {
|
|
910
1066
|
const cfg = thinking;
|
|
1067
|
+
if (cfg.mode === 'adaptive') {
|
|
1068
|
+
return { anthropic: { thinking: { type: 'adaptive' } } };
|
|
1069
|
+
}
|
|
911
1070
|
return {
|
|
912
1071
|
anthropic: {
|
|
913
|
-
thinking: {
|
|
914
|
-
type: 'enabled',
|
|
915
|
-
budgetTokens: cfg.budgetTokens ?? 10000,
|
|
916
|
-
},
|
|
1072
|
+
thinking: { type: 'enabled', budgetTokens: cfg.budgetTokens ?? 10000 },
|
|
917
1073
|
},
|
|
918
1074
|
};
|
|
919
1075
|
}
|
|
@@ -960,8 +1116,12 @@ class AgentRuntime {
|
|
|
960
1116
|
return merged;
|
|
961
1117
|
}
|
|
962
1118
|
async iterateToolCallsConcurrent(ctx) {
|
|
963
|
-
const { toolCalls, toolMap, list, runId, telemetry: resolvedTelemetry } = ctx;
|
|
1119
|
+
const { toolCalls, toolMap, list, runId, telemetry: resolvedTelemetry, executionCounter } = ctx;
|
|
964
1120
|
const executableCalls = toolCalls.filter((tc) => !tc.providerExecuted);
|
|
1121
|
+
const providerExecutedCount = toolCalls.length - executableCalls.length;
|
|
1122
|
+
for (let i = 0; i < providerExecutedCount; i++) {
|
|
1123
|
+
this.incrementToolCallCount(executionCounter);
|
|
1124
|
+
}
|
|
965
1125
|
const executableCallsById = new Map(executableCalls.map((tc) => [tc.toolCallId, tc]));
|
|
966
1126
|
const unexecutedIds = new Set(executableCalls.map((tc) => tc.toolCallId));
|
|
967
1127
|
const batchSize = this.concurrency;
|
|
@@ -975,7 +1135,7 @@ class AgentRuntime {
|
|
|
975
1135
|
throw new Error('Agent run was aborted');
|
|
976
1136
|
}
|
|
977
1137
|
const batch = executableCalls.slice(batchStart, batchStart + batchSize);
|
|
978
|
-
const settledResults = await Promise.allSettled(batch.map(async (tc) => await this.processToolCall(tc.toolCallId, tc.toolName, tc.input, toolMap, list, undefined, resolvedTelemetry)));
|
|
1138
|
+
const settledResults = await Promise.allSettled(batch.map(async (tc) => await this.processToolCall(tc.toolCallId, tc.toolName, tc.input, toolMap, list, undefined, resolvedTelemetry, executionCounter, true)));
|
|
979
1139
|
for (const tc of batch) {
|
|
980
1140
|
unexecutedIds.delete(tc.toolCallId);
|
|
981
1141
|
}
|
|
@@ -1050,7 +1210,7 @@ class AgentRuntime {
|
|
|
1050
1210
|
return { results, suspensions, errors, pending };
|
|
1051
1211
|
}
|
|
1052
1212
|
async iteratePendingToolCallsConcurrent(ctx) {
|
|
1053
|
-
const { pendingResume, toolMap, list, runId, telemetry: resolvedTelemetry } = ctx;
|
|
1213
|
+
const { pendingResume, toolMap, list, runId, telemetry: resolvedTelemetry, executionCounter, } = ctx;
|
|
1054
1214
|
const resumedId = pendingResume.resumeToolCallId;
|
|
1055
1215
|
const resumedEntry = pendingResume.pendingToolCalls[resumedId];
|
|
1056
1216
|
if (!resumedEntry) {
|
|
@@ -1061,7 +1221,7 @@ class AgentRuntime {
|
|
|
1061
1221
|
const suspensions = [];
|
|
1062
1222
|
const errors = [];
|
|
1063
1223
|
const pending = {};
|
|
1064
|
-
const processResult = await this.processToolCall(resumedEntry.toolCallId, resumedToolName, resumedEntry.input, toolMap, list, pendingResume.resumeData, resolvedTelemetry);
|
|
1224
|
+
const processResult = await this.processToolCall(resumedEntry.toolCallId, resumedToolName, resumedEntry.input, toolMap, list, pendingResume.resumeData, resolvedTelemetry, executionCounter, false);
|
|
1065
1225
|
if (processResult.outcome === 'suspended') {
|
|
1066
1226
|
pending[resumedId] = {
|
|
1067
1227
|
...resumedEntry,
|
|
@@ -1129,6 +1289,7 @@ class AgentRuntime {
|
|
|
1129
1289
|
list,
|
|
1130
1290
|
runId,
|
|
1131
1291
|
telemetry: resolvedTelemetry,
|
|
1292
|
+
executionCounter,
|
|
1132
1293
|
});
|
|
1133
1294
|
results.push(...batch.results);
|
|
1134
1295
|
suspensions.push(...batch.suspensions);
|
|
@@ -1137,7 +1298,7 @@ class AgentRuntime {
|
|
|
1137
1298
|
}
|
|
1138
1299
|
return { results, suspensions, errors, pending };
|
|
1139
1300
|
}
|
|
1140
|
-
async processToolCall(toolCallId, toolName, toolInput, toolMap, list, resumeData, resolvedTelemetry) {
|
|
1301
|
+
async processToolCall(toolCallId, toolName, toolInput, toolMap, list, resumeData, resolvedTelemetry, executionCounter, countToolCall = true) {
|
|
1141
1302
|
const builtTool = toolMap.get(toolName);
|
|
1142
1303
|
this.eventBus.emit({
|
|
1143
1304
|
type: "tool_execution_start",
|
|
@@ -1180,6 +1341,9 @@ class AgentRuntime {
|
|
|
1180
1341
|
});
|
|
1181
1342
|
return { outcome: 'noop' };
|
|
1182
1343
|
}
|
|
1344
|
+
if (countToolCall) {
|
|
1345
|
+
this.incrementToolCallCount(executionCounter);
|
|
1346
|
+
}
|
|
1183
1347
|
if (builtTool.inputSchema) {
|
|
1184
1348
|
const result = await (0, parse_1.parseWithSchema)(builtTool.inputSchema, toolInput);
|
|
1185
1349
|
if (!result.success) {
|
|
@@ -1252,27 +1416,47 @@ class AgentRuntime {
|
|
|
1252
1416
|
customMessage,
|
|
1253
1417
|
};
|
|
1254
1418
|
}
|
|
1255
|
-
|
|
1256
|
-
const wmTool = this.buildWorkingMemoryToolForRun(execOptions?.persistence);
|
|
1257
|
-
const allUserTools = wmTool
|
|
1258
|
-
? [...(this.config.tools ?? []), wmTool]
|
|
1259
|
-
: (this.config.tools ?? []);
|
|
1260
|
-
const aiTools = (0, tool_adapter_1.toAiSdkTools)(allUserTools);
|
|
1419
|
+
buildStaticLoopContext(execOptions) {
|
|
1261
1420
|
const aiProviderTools = (0, tool_adapter_1.toAiSdkProviderTools)(this.config.providerTools);
|
|
1262
|
-
const allTools = { ...aiTools, ...aiProviderTools };
|
|
1263
1421
|
const model = (0, model_factory_1.createModel)(this.config.model);
|
|
1264
1422
|
return {
|
|
1265
1423
|
model,
|
|
1266
|
-
|
|
1267
|
-
aiTools: allTools,
|
|
1424
|
+
aiProviderTools,
|
|
1268
1425
|
providerOptions: this.buildCallProviderOptions(execOptions?.providerOptions),
|
|
1269
|
-
hasTools: Object.keys(allTools).length > 0,
|
|
1270
1426
|
outputSpec: this.config.structuredOutput
|
|
1271
1427
|
? ai_1.Output.object({ schema: this.config.structuredOutput })
|
|
1272
1428
|
: undefined,
|
|
1273
|
-
effectiveInstructions: this.composeEffectiveInstructions(allUserTools),
|
|
1274
1429
|
};
|
|
1275
1430
|
}
|
|
1431
|
+
buildToolLoopContext(aiProviderTools) {
|
|
1432
|
+
const allUserTools = this.getCurrentTools();
|
|
1433
|
+
const aiTools = (0, tool_adapter_1.toAiSdkTools)(allUserTools);
|
|
1434
|
+
const allTools = { ...aiTools, ...aiProviderTools };
|
|
1435
|
+
const aiToolCount = Object.keys(allTools).length;
|
|
1436
|
+
const toolMap = (0, tool_adapter_1.buildToolMap)(allUserTools);
|
|
1437
|
+
const effectiveInstructions = this.composeEffectiveInstructions(allUserTools);
|
|
1438
|
+
return {
|
|
1439
|
+
toolMap,
|
|
1440
|
+
aiTools: allTools,
|
|
1441
|
+
hasTools: aiToolCount > 0,
|
|
1442
|
+
effectiveInstructions,
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
getCurrentTools() {
|
|
1446
|
+
const baseTools = this.config.tools ?? [];
|
|
1447
|
+
if (!this.deferredToolManager?.hasTools)
|
|
1448
|
+
return baseTools;
|
|
1449
|
+
return [
|
|
1450
|
+
...baseTools,
|
|
1451
|
+
...this.deferredToolManager.getControllerTools(),
|
|
1452
|
+
...this.deferredToolManager.getLoadedTools(),
|
|
1453
|
+
];
|
|
1454
|
+
}
|
|
1455
|
+
hydrateDeferredToolsFromList(list) {
|
|
1456
|
+
if (!this.deferredToolManager?.hasTools)
|
|
1457
|
+
return;
|
|
1458
|
+
this.deferredToolManager.hydrateLoadedToolsFromMessages(list.serialize().messages);
|
|
1459
|
+
}
|
|
1276
1460
|
composeEffectiveInstructions(tools) {
|
|
1277
1461
|
const fragments = tools
|
|
1278
1462
|
.map((t) => t.systemInstruction)
|
|
@@ -1283,16 +1467,6 @@ class AgentRuntime {
|
|
|
1283
1467
|
const block = `<built_in_rules>\n${fragments.map((f) => `- ${f}`).join('\n')}\n</built_in_rules>`;
|
|
1284
1468
|
return userInstructions ? `${block}\n\n${userInstructions}` : block;
|
|
1285
1469
|
}
|
|
1286
|
-
buildWorkingMemoryToolForRun(persistence) {
|
|
1287
|
-
const wmParams = this.resolveWorkingMemoryParams(persistence);
|
|
1288
|
-
if (!wmParams)
|
|
1289
|
-
return undefined;
|
|
1290
|
-
return (0, working_memory_1.buildWorkingMemoryTool)({
|
|
1291
|
-
structured: wmParams.structured,
|
|
1292
|
-
schema: wmParams.schema,
|
|
1293
|
-
persist: wmParams.persistFn,
|
|
1294
|
-
});
|
|
1295
|
-
}
|
|
1296
1470
|
async persistSuspension(pendingToolCalls, options, list, totalUsage, existingRunId) {
|
|
1297
1471
|
const runId = existingRunId ?? (0, run_state_1.generateRunId)();
|
|
1298
1472
|
const executionOptions = options?.maxIterations !== undefined ? { maxIterations: options.maxIterations } : undefined;
|
|
@@ -1352,46 +1526,22 @@ class AgentRuntime {
|
|
|
1352
1526
|
return usage;
|
|
1353
1527
|
return { ...usage, cost: (0, catalog_1.computeCost)(usage, this.modelCost) };
|
|
1354
1528
|
}
|
|
1355
|
-
async
|
|
1356
|
-
const
|
|
1357
|
-
if (!
|
|
1529
|
+
async setListObservationLogMemory(list, options) {
|
|
1530
|
+
const memory = this.config.memory;
|
|
1531
|
+
if (!memory || !options?.threadId || !(0, observation_log_store_1.hasObservationLogStore)(memory))
|
|
1358
1532
|
return;
|
|
1359
|
-
const
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1533
|
+
const scope = this.getObservationLogScope(options);
|
|
1534
|
+
const observations = await memory.getActiveObservationLog({
|
|
1535
|
+
...scope,
|
|
1536
|
+
order: 'asc',
|
|
1537
|
+
});
|
|
1538
|
+
list.observationLogMemory =
|
|
1539
|
+
(0, observation_log_renderer_1.renderObservationLog)(observations, {
|
|
1540
|
+
renderTokenBudget: this.config.observationLog?.renderTokenBudget,
|
|
1541
|
+
}) ?? undefined;
|
|
1366
1542
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
return null;
|
|
1370
|
-
if (!this.config.workingMemory)
|
|
1371
|
-
return null;
|
|
1372
|
-
const scope = this.config.workingMemory?.scope ?? 'resource';
|
|
1373
|
-
if (scope === 'resource' && !options.resourceId) {
|
|
1374
|
-
throw new Error('Working memory scope is "resource" but no resourceId was provided. ' +
|
|
1375
|
-
'Pass a resourceId in RunOptions or change the scope to "thread".');
|
|
1376
|
-
}
|
|
1377
|
-
if (!options)
|
|
1378
|
-
return null;
|
|
1379
|
-
const memoryParams = { ...options, scope };
|
|
1380
|
-
const persistFn = this.config.workingMemory && this.config.memory?.saveWorkingMemory && options
|
|
1381
|
-
? async (content) => {
|
|
1382
|
-
await this.config.memory.saveWorkingMemory(memoryParams, content);
|
|
1383
|
-
}
|
|
1384
|
-
: undefined;
|
|
1385
|
-
if (!persistFn)
|
|
1386
|
-
return null;
|
|
1387
|
-
return {
|
|
1388
|
-
persistFn,
|
|
1389
|
-
memoryParams,
|
|
1390
|
-
template: this.config.workingMemory.template,
|
|
1391
|
-
structured: this.config.workingMemory.structured,
|
|
1392
|
-
schema: this.config.workingMemory.schema,
|
|
1393
|
-
instruction: this.config.workingMemory.instruction,
|
|
1394
|
-
};
|
|
1543
|
+
getConfiguredTelemetry() {
|
|
1544
|
+
return this.config.telemetry;
|
|
1395
1545
|
}
|
|
1396
1546
|
}
|
|
1397
1547
|
exports.AgentRuntime = AgentRuntime;
|