llmist 11.0.0 → 11.1.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/index.cjs +351 -202
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -7
- package/dist/index.d.ts +37 -7
- package/dist/index.js +351 -202
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -756,6 +756,20 @@ var init_execution_tree = __esm({
|
|
|
756
756
|
});
|
|
757
757
|
return node;
|
|
758
758
|
}
|
|
759
|
+
/**
|
|
760
|
+
* Update a gadget's parameters (e.g., after interceptor modifies them).
|
|
761
|
+
* This is called after the gadget is added to the tree but before execution.
|
|
762
|
+
*/
|
|
763
|
+
updateGadgetParameters(invocationId, parameters) {
|
|
764
|
+
const nodeId = this.invocationIdToNodeId.get(invocationId);
|
|
765
|
+
if (!nodeId) {
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
const node = this.nodes.get(nodeId);
|
|
769
|
+
if (node?.type === "gadget") {
|
|
770
|
+
node.parameters = parameters;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
759
773
|
/**
|
|
760
774
|
* Mark a gadget as started (running).
|
|
761
775
|
*/
|
|
@@ -8685,6 +8699,9 @@ var init_stream_processor = __esm({
|
|
|
8685
8699
|
parameters = this.hooks.interceptors.interceptGadgetParameters(parameters, context);
|
|
8686
8700
|
}
|
|
8687
8701
|
call.parameters = parameters;
|
|
8702
|
+
if (this.tree) {
|
|
8703
|
+
this.tree.updateGadgetParameters(call.invocationId, parameters);
|
|
8704
|
+
}
|
|
8688
8705
|
let shouldSkip = false;
|
|
8689
8706
|
let syntheticResult;
|
|
8690
8707
|
if (this.hooks.controllers?.beforeGadgetExecution) {
|
|
@@ -8705,20 +8722,6 @@ var init_stream_processor = __esm({
|
|
|
8705
8722
|
});
|
|
8706
8723
|
}
|
|
8707
8724
|
}
|
|
8708
|
-
const startObservers = [];
|
|
8709
|
-
if (this.hooks.observers?.onGadgetExecutionStart) {
|
|
8710
|
-
startObservers.push(async () => {
|
|
8711
|
-
const context = {
|
|
8712
|
-
iteration: this.iteration,
|
|
8713
|
-
gadgetName: call.gadgetName,
|
|
8714
|
-
invocationId: call.invocationId,
|
|
8715
|
-
parameters,
|
|
8716
|
-
logger: this.logger
|
|
8717
|
-
};
|
|
8718
|
-
await this.hooks.observers?.onGadgetExecutionStart?.(context);
|
|
8719
|
-
});
|
|
8720
|
-
}
|
|
8721
|
-
await this.runObserversInParallel(startObservers);
|
|
8722
8725
|
if (this.tree) {
|
|
8723
8726
|
const gadgetNode = this.tree.getNodeByInvocationId(call.invocationId);
|
|
8724
8727
|
if (gadgetNode) {
|
|
@@ -8737,7 +8740,6 @@ var init_stream_processor = __esm({
|
|
|
8737
8740
|
} else {
|
|
8738
8741
|
result = await this.executor.execute(call);
|
|
8739
8742
|
}
|
|
8740
|
-
const originalResult = result.result;
|
|
8741
8743
|
if (result.result && this.hooks.interceptors?.interceptGadgetResult) {
|
|
8742
8744
|
const context = {
|
|
8743
8745
|
iteration: this.iteration,
|
|
@@ -8774,26 +8776,6 @@ var init_stream_processor = __esm({
|
|
|
8774
8776
|
};
|
|
8775
8777
|
}
|
|
8776
8778
|
}
|
|
8777
|
-
const completeObservers = [];
|
|
8778
|
-
if (this.hooks.observers?.onGadgetExecutionComplete) {
|
|
8779
|
-
completeObservers.push(async () => {
|
|
8780
|
-
const context = {
|
|
8781
|
-
iteration: this.iteration,
|
|
8782
|
-
gadgetName: result.gadgetName,
|
|
8783
|
-
invocationId: result.invocationId,
|
|
8784
|
-
parameters,
|
|
8785
|
-
originalResult,
|
|
8786
|
-
finalResult: result.result,
|
|
8787
|
-
error: result.error,
|
|
8788
|
-
executionTimeMs: result.executionTimeMs,
|
|
8789
|
-
breaksLoop: result.breaksLoop,
|
|
8790
|
-
cost: result.cost,
|
|
8791
|
-
logger: this.logger
|
|
8792
|
-
};
|
|
8793
|
-
await this.hooks.observers?.onGadgetExecutionComplete?.(context);
|
|
8794
|
-
});
|
|
8795
|
-
}
|
|
8796
|
-
await this.runObserversInParallel(completeObservers);
|
|
8797
8779
|
if (this.tree) {
|
|
8798
8780
|
const gadgetNode = this.tree.getNodeByInvocationId(result.invocationId);
|
|
8799
8781
|
if (gadgetNode) {
|
|
@@ -8938,18 +8920,6 @@ var init_stream_processor = __esm({
|
|
|
8938
8920
|
failedDependencyError: depError
|
|
8939
8921
|
};
|
|
8940
8922
|
events.push(skipEvent);
|
|
8941
|
-
if (this.hooks.observers?.onGadgetSkipped) {
|
|
8942
|
-
const observeContext = {
|
|
8943
|
-
iteration: this.iteration,
|
|
8944
|
-
gadgetName: call.gadgetName,
|
|
8945
|
-
invocationId: call.invocationId,
|
|
8946
|
-
parameters: call.parameters ?? {},
|
|
8947
|
-
failedDependency: failedDep,
|
|
8948
|
-
failedDependencyError: depError,
|
|
8949
|
-
logger: this.logger
|
|
8950
|
-
};
|
|
8951
|
-
await this.safeObserve(() => this.hooks.observers?.onGadgetSkipped?.(observeContext));
|
|
8952
|
-
}
|
|
8953
8923
|
this.logger.info("Gadget skipped due to failed dependency", {
|
|
8954
8924
|
gadgetName: call.gadgetName,
|
|
8955
8925
|
invocationId: call.invocationId,
|
|
@@ -9127,6 +9097,160 @@ var init_stream_processor = __esm({
|
|
|
9127
9097
|
}
|
|
9128
9098
|
});
|
|
9129
9099
|
|
|
9100
|
+
// src/agent/tree-hook-bridge.ts
|
|
9101
|
+
function findParentGadgetInvocationId(tree, nodeId) {
|
|
9102
|
+
let currentId = nodeId;
|
|
9103
|
+
while (currentId) {
|
|
9104
|
+
const node = tree.getNode(currentId);
|
|
9105
|
+
if (!node) break;
|
|
9106
|
+
currentId = node.parentId;
|
|
9107
|
+
if (!currentId) break;
|
|
9108
|
+
const parentNode = tree.getNode(currentId);
|
|
9109
|
+
if (parentNode?.type === "gadget") {
|
|
9110
|
+
return parentNode.invocationId;
|
|
9111
|
+
}
|
|
9112
|
+
}
|
|
9113
|
+
return void 0;
|
|
9114
|
+
}
|
|
9115
|
+
function getIterationFromTree(tree, nodeId) {
|
|
9116
|
+
let currentId = nodeId;
|
|
9117
|
+
while (currentId) {
|
|
9118
|
+
const node = tree.getNode(currentId);
|
|
9119
|
+
if (!node) break;
|
|
9120
|
+
if (node.type === "llm_call") {
|
|
9121
|
+
return node.iteration;
|
|
9122
|
+
}
|
|
9123
|
+
currentId = node.parentId;
|
|
9124
|
+
}
|
|
9125
|
+
return 0;
|
|
9126
|
+
}
|
|
9127
|
+
function buildSubagentContext(tree, event) {
|
|
9128
|
+
const parentGadgetInvocationId = findParentGadgetInvocationId(tree, event.nodeId);
|
|
9129
|
+
if (!parentGadgetInvocationId) {
|
|
9130
|
+
return void 0;
|
|
9131
|
+
}
|
|
9132
|
+
return {
|
|
9133
|
+
parentGadgetInvocationId,
|
|
9134
|
+
depth: event.depth
|
|
9135
|
+
};
|
|
9136
|
+
}
|
|
9137
|
+
function getSubagentContextForNode(tree, nodeId) {
|
|
9138
|
+
const node = tree.getNode(nodeId);
|
|
9139
|
+
if (!node) return void 0;
|
|
9140
|
+
const parentGadgetInvocationId = findParentGadgetInvocationId(tree, nodeId);
|
|
9141
|
+
if (!parentGadgetInvocationId) {
|
|
9142
|
+
return void 0;
|
|
9143
|
+
}
|
|
9144
|
+
return {
|
|
9145
|
+
parentGadgetInvocationId,
|
|
9146
|
+
depth: node.depth
|
|
9147
|
+
};
|
|
9148
|
+
}
|
|
9149
|
+
async function safeObserve(fn, logger, eventType) {
|
|
9150
|
+
try {
|
|
9151
|
+
await fn();
|
|
9152
|
+
} catch (error) {
|
|
9153
|
+
logger.warn(`Observer error in ${eventType}:`, error);
|
|
9154
|
+
}
|
|
9155
|
+
}
|
|
9156
|
+
function bridgeTreeToHooks(tree, hooks, logger) {
|
|
9157
|
+
return tree.onAll((event) => {
|
|
9158
|
+
const subagentContext = buildSubagentContext(tree, event);
|
|
9159
|
+
switch (event.type) {
|
|
9160
|
+
case "gadget_start": {
|
|
9161
|
+
if (hooks.observers?.onGadgetExecutionStart) {
|
|
9162
|
+
const gadgetEvent = event;
|
|
9163
|
+
const gadgetNode = tree.getNodeByInvocationId(gadgetEvent.invocationId);
|
|
9164
|
+
const context = {
|
|
9165
|
+
iteration: getIterationFromTree(tree, event.nodeId),
|
|
9166
|
+
gadgetName: gadgetEvent.name,
|
|
9167
|
+
invocationId: gadgetEvent.invocationId,
|
|
9168
|
+
parameters: gadgetNode?.parameters ?? {},
|
|
9169
|
+
logger,
|
|
9170
|
+
subagentContext
|
|
9171
|
+
};
|
|
9172
|
+
safeObserve(
|
|
9173
|
+
() => hooks.observers.onGadgetExecutionStart(context),
|
|
9174
|
+
logger,
|
|
9175
|
+
"onGadgetExecutionStart"
|
|
9176
|
+
);
|
|
9177
|
+
}
|
|
9178
|
+
break;
|
|
9179
|
+
}
|
|
9180
|
+
case "gadget_complete": {
|
|
9181
|
+
if (hooks.observers?.onGadgetExecutionComplete) {
|
|
9182
|
+
const gadgetEvent = event;
|
|
9183
|
+
const gadgetNode = tree.getNodeByInvocationId(gadgetEvent.invocationId);
|
|
9184
|
+
const context = {
|
|
9185
|
+
iteration: getIterationFromTree(tree, event.nodeId),
|
|
9186
|
+
gadgetName: gadgetEvent.name,
|
|
9187
|
+
invocationId: gadgetEvent.invocationId,
|
|
9188
|
+
parameters: gadgetNode?.parameters ?? {},
|
|
9189
|
+
finalResult: gadgetEvent.result,
|
|
9190
|
+
executionTimeMs: gadgetEvent.executionTimeMs,
|
|
9191
|
+
cost: gadgetEvent.cost,
|
|
9192
|
+
logger,
|
|
9193
|
+
subagentContext
|
|
9194
|
+
};
|
|
9195
|
+
safeObserve(
|
|
9196
|
+
() => hooks.observers.onGadgetExecutionComplete(context),
|
|
9197
|
+
logger,
|
|
9198
|
+
"onGadgetExecutionComplete"
|
|
9199
|
+
);
|
|
9200
|
+
}
|
|
9201
|
+
break;
|
|
9202
|
+
}
|
|
9203
|
+
case "gadget_error": {
|
|
9204
|
+
if (hooks.observers?.onGadgetExecutionComplete) {
|
|
9205
|
+
const gadgetNode = tree.getNodeByInvocationId(event.invocationId);
|
|
9206
|
+
const context = {
|
|
9207
|
+
iteration: getIterationFromTree(tree, event.nodeId),
|
|
9208
|
+
gadgetName: event.name,
|
|
9209
|
+
invocationId: event.invocationId,
|
|
9210
|
+
parameters: gadgetNode?.parameters ?? {},
|
|
9211
|
+
error: event.error,
|
|
9212
|
+
executionTimeMs: event.executionTimeMs,
|
|
9213
|
+
logger,
|
|
9214
|
+
subagentContext
|
|
9215
|
+
};
|
|
9216
|
+
safeObserve(
|
|
9217
|
+
() => hooks.observers.onGadgetExecutionComplete(context),
|
|
9218
|
+
logger,
|
|
9219
|
+
"onGadgetExecutionComplete"
|
|
9220
|
+
);
|
|
9221
|
+
}
|
|
9222
|
+
break;
|
|
9223
|
+
}
|
|
9224
|
+
case "gadget_skipped": {
|
|
9225
|
+
if (hooks.observers?.onGadgetSkipped) {
|
|
9226
|
+
const gadgetNode = tree.getNodeByInvocationId(event.invocationId);
|
|
9227
|
+
const context = {
|
|
9228
|
+
iteration: getIterationFromTree(tree, event.nodeId),
|
|
9229
|
+
gadgetName: event.name,
|
|
9230
|
+
invocationId: event.invocationId,
|
|
9231
|
+
parameters: gadgetNode?.parameters ?? {},
|
|
9232
|
+
failedDependency: event.failedDependency ?? "unknown",
|
|
9233
|
+
failedDependencyError: event.failedDependencyError ?? event.error,
|
|
9234
|
+
logger,
|
|
9235
|
+
subagentContext
|
|
9236
|
+
};
|
|
9237
|
+
safeObserve(
|
|
9238
|
+
() => hooks.observers.onGadgetSkipped(context),
|
|
9239
|
+
logger,
|
|
9240
|
+
"onGadgetSkipped"
|
|
9241
|
+
);
|
|
9242
|
+
}
|
|
9243
|
+
break;
|
|
9244
|
+
}
|
|
9245
|
+
}
|
|
9246
|
+
});
|
|
9247
|
+
}
|
|
9248
|
+
var init_tree_hook_bridge = __esm({
|
|
9249
|
+
"src/agent/tree-hook-bridge.ts"() {
|
|
9250
|
+
"use strict";
|
|
9251
|
+
}
|
|
9252
|
+
});
|
|
9253
|
+
|
|
9130
9254
|
// src/agent/agent.ts
|
|
9131
9255
|
var import_p_retry, Agent;
|
|
9132
9256
|
var init_agent = __esm({
|
|
@@ -9148,6 +9272,7 @@ var init_agent = __esm({
|
|
|
9148
9272
|
init_gadget_output_store();
|
|
9149
9273
|
init_hook_validators();
|
|
9150
9274
|
init_stream_processor();
|
|
9275
|
+
init_tree_hook_bridge();
|
|
9151
9276
|
Agent = class {
|
|
9152
9277
|
client;
|
|
9153
9278
|
model;
|
|
@@ -9454,6 +9579,14 @@ var init_agent = __esm({
|
|
|
9454
9579
|
* Run the agent loop.
|
|
9455
9580
|
* Clean, simple orchestration - all complexity is in StreamProcessor.
|
|
9456
9581
|
*
|
|
9582
|
+
* ## Event Architecture
|
|
9583
|
+
*
|
|
9584
|
+
* ExecutionTree is the single source of truth for all agent events.
|
|
9585
|
+
* Gadget observer hooks (`onGadgetExecutionStart`, `onGadgetExecutionComplete`,
|
|
9586
|
+
* `onGadgetSkipped`) are derived from tree events via `tree-hook-bridge.ts`.
|
|
9587
|
+
* This ensures consistent `subagentContext` for nested agents - both the TUI
|
|
9588
|
+
* and user hook observers receive identical event context.
|
|
9589
|
+
*
|
|
9457
9590
|
* @throws {Error} If no user prompt was provided (when using build() without ask())
|
|
9458
9591
|
*/
|
|
9459
9592
|
async *run() {
|
|
@@ -9462,173 +9595,179 @@ var init_agent = __esm({
|
|
|
9462
9595
|
"No user prompt provided. Use .ask(prompt) instead of .build(), or call agent.run() after providing a prompt."
|
|
9463
9596
|
);
|
|
9464
9597
|
}
|
|
9598
|
+
const unsubscribeBridge = bridgeTreeToHooks(this.tree, this.hooks, this.logger);
|
|
9465
9599
|
let currentIteration = 0;
|
|
9466
9600
|
this.logger.info("Starting agent loop", {
|
|
9467
9601
|
model: this.model,
|
|
9468
9602
|
maxIterations: this.maxIterations
|
|
9469
9603
|
});
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
while (this.pendingUserMessages.length > 0) {
|
|
9475
|
-
const msg = this.pendingUserMessages.shift();
|
|
9476
|
-
this.conversation.addUserMessage(msg);
|
|
9477
|
-
this.logger.info("Injected user message into conversation", {
|
|
9478
|
-
iteration: currentIteration,
|
|
9479
|
-
messageLength: msg.length
|
|
9480
|
-
});
|
|
9481
|
-
}
|
|
9482
|
-
this.logger.debug("Starting iteration", { iteration: currentIteration });
|
|
9483
|
-
try {
|
|
9484
|
-
const compactionEvent = await this.checkAndPerformCompaction(currentIteration);
|
|
9485
|
-
if (compactionEvent) {
|
|
9486
|
-
yield compactionEvent;
|
|
9604
|
+
try {
|
|
9605
|
+
while (currentIteration < this.maxIterations) {
|
|
9606
|
+
if (await this.checkAbortAndNotify(currentIteration)) {
|
|
9607
|
+
return;
|
|
9487
9608
|
}
|
|
9488
|
-
|
|
9489
|
-
|
|
9490
|
-
|
|
9491
|
-
this.
|
|
9492
|
-
|
|
9493
|
-
|
|
9609
|
+
while (this.pendingUserMessages.length > 0) {
|
|
9610
|
+
const msg = this.pendingUserMessages.shift();
|
|
9611
|
+
this.conversation.addUserMessage(msg);
|
|
9612
|
+
this.logger.info("Injected user message into conversation", {
|
|
9613
|
+
iteration: currentIteration,
|
|
9614
|
+
messageLength: msg.length
|
|
9615
|
+
});
|
|
9494
9616
|
}
|
|
9495
|
-
this.logger.
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
});
|
|
9503
|
-
const llmNode = this.tree.addLLMCall({
|
|
9504
|
-
iteration: currentIteration,
|
|
9505
|
-
model: llmOptions.model,
|
|
9506
|
-
parentId: this.parentNodeId,
|
|
9507
|
-
request: llmOptions.messages
|
|
9508
|
-
});
|
|
9509
|
-
const currentLLMNodeId = llmNode.id;
|
|
9510
|
-
const stream2 = await this.createStreamWithRetry(llmOptions, currentIteration);
|
|
9511
|
-
const processor = new StreamProcessor({
|
|
9512
|
-
iteration: currentIteration,
|
|
9513
|
-
registry: this.registry,
|
|
9514
|
-
gadgetStartPrefix: this.gadgetStartPrefix,
|
|
9515
|
-
gadgetEndPrefix: this.gadgetEndPrefix,
|
|
9516
|
-
gadgetArgPrefix: this.gadgetArgPrefix,
|
|
9517
|
-
hooks: this.hooks,
|
|
9518
|
-
logger: this.logger.getSubLogger({ name: "stream-processor" }),
|
|
9519
|
-
requestHumanInput: this.requestHumanInput,
|
|
9520
|
-
defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
|
|
9521
|
-
client: this.client,
|
|
9522
|
-
mediaStore: this.mediaStore,
|
|
9523
|
-
agentConfig: this.agentContextConfig,
|
|
9524
|
-
subagentConfig: this.subagentConfig,
|
|
9525
|
-
// Tree context for execution tracking
|
|
9526
|
-
tree: this.tree,
|
|
9527
|
-
parentNodeId: currentLLMNodeId,
|
|
9528
|
-
// Gadgets are children of this LLM call
|
|
9529
|
-
baseDepth: this.baseDepth,
|
|
9530
|
-
// Cross-iteration dependency tracking
|
|
9531
|
-
priorCompletedInvocations: this.completedInvocationIds,
|
|
9532
|
-
priorFailedInvocations: this.failedInvocationIds
|
|
9533
|
-
});
|
|
9534
|
-
let streamMetadata = null;
|
|
9535
|
-
let gadgetCallCount = 0;
|
|
9536
|
-
const textOutputs = [];
|
|
9537
|
-
const gadgetResults = [];
|
|
9538
|
-
for await (const event of processor.process(stream2)) {
|
|
9539
|
-
if (event.type === "stream_complete") {
|
|
9540
|
-
streamMetadata = event;
|
|
9541
|
-
continue;
|
|
9617
|
+
this.logger.debug("Starting iteration", { iteration: currentIteration });
|
|
9618
|
+
let currentLLMNodeId;
|
|
9619
|
+
let llmOptions;
|
|
9620
|
+
try {
|
|
9621
|
+
const compactionEvent = await this.checkAndPerformCompaction(currentIteration);
|
|
9622
|
+
if (compactionEvent) {
|
|
9623
|
+
yield compactionEvent;
|
|
9542
9624
|
}
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9625
|
+
const prepared = await this.prepareLLMCall(currentIteration);
|
|
9626
|
+
llmOptions = prepared.options;
|
|
9627
|
+
currentLLMNodeId = prepared.llmNodeId;
|
|
9628
|
+
if (prepared.skipWithSynthetic !== void 0) {
|
|
9629
|
+
this.conversation.addAssistantMessage(prepared.skipWithSynthetic);
|
|
9630
|
+
yield { type: "text", content: prepared.skipWithSynthetic };
|
|
9631
|
+
break;
|
|
9548
9632
|
}
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9564
|
-
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9633
|
+
this.logger.info("Calling LLM", { model: this.model });
|
|
9634
|
+
this.logger.silly("LLM request details", {
|
|
9635
|
+
model: llmOptions.model,
|
|
9636
|
+
temperature: llmOptions.temperature,
|
|
9637
|
+
maxTokens: llmOptions.maxTokens,
|
|
9638
|
+
messageCount: llmOptions.messages.length,
|
|
9639
|
+
messages: llmOptions.messages
|
|
9640
|
+
});
|
|
9641
|
+
const stream2 = await this.createStreamWithRetry(llmOptions, currentIteration);
|
|
9642
|
+
const processor = new StreamProcessor({
|
|
9643
|
+
iteration: currentIteration,
|
|
9644
|
+
registry: this.registry,
|
|
9645
|
+
gadgetStartPrefix: this.gadgetStartPrefix,
|
|
9646
|
+
gadgetEndPrefix: this.gadgetEndPrefix,
|
|
9647
|
+
gadgetArgPrefix: this.gadgetArgPrefix,
|
|
9648
|
+
hooks: this.hooks,
|
|
9649
|
+
logger: this.logger.getSubLogger({ name: "stream-processor" }),
|
|
9650
|
+
requestHumanInput: this.requestHumanInput,
|
|
9651
|
+
defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
|
|
9652
|
+
client: this.client,
|
|
9653
|
+
mediaStore: this.mediaStore,
|
|
9654
|
+
agentConfig: this.agentContextConfig,
|
|
9655
|
+
subagentConfig: this.subagentConfig,
|
|
9656
|
+
// Tree context for execution tracking
|
|
9657
|
+
tree: this.tree,
|
|
9658
|
+
parentNodeId: currentLLMNodeId,
|
|
9659
|
+
// Gadgets are children of this LLM call
|
|
9660
|
+
baseDepth: this.baseDepth,
|
|
9661
|
+
// Cross-iteration dependency tracking
|
|
9662
|
+
priorCompletedInvocations: this.completedInvocationIds,
|
|
9663
|
+
priorFailedInvocations: this.failedInvocationIds
|
|
9664
|
+
});
|
|
9665
|
+
let streamMetadata = null;
|
|
9666
|
+
let gadgetCallCount = 0;
|
|
9667
|
+
const textOutputs = [];
|
|
9668
|
+
const gadgetResults = [];
|
|
9669
|
+
for await (const event of processor.process(stream2)) {
|
|
9670
|
+
if (event.type === "stream_complete") {
|
|
9671
|
+
streamMetadata = event;
|
|
9672
|
+
continue;
|
|
9673
|
+
}
|
|
9674
|
+
if (event.type === "text") {
|
|
9675
|
+
textOutputs.push(event.content);
|
|
9676
|
+
} else if (event.type === "gadget_result") {
|
|
9677
|
+
gadgetCallCount++;
|
|
9678
|
+
gadgetResults.push(event);
|
|
9679
|
+
}
|
|
9680
|
+
yield event;
|
|
9581
9681
|
}
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
result
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
this.
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9682
|
+
if (!streamMetadata) {
|
|
9683
|
+
throw new Error("Stream processing completed without metadata event");
|
|
9684
|
+
}
|
|
9685
|
+
for (const id of processor.getCompletedInvocationIds()) {
|
|
9686
|
+
this.completedInvocationIds.add(id);
|
|
9687
|
+
}
|
|
9688
|
+
for (const id of processor.getFailedInvocationIds()) {
|
|
9689
|
+
this.failedInvocationIds.add(id);
|
|
9690
|
+
}
|
|
9691
|
+
const result = streamMetadata;
|
|
9692
|
+
this.logger.info("LLM response completed", {
|
|
9693
|
+
finishReason: result.finishReason,
|
|
9694
|
+
usage: result.usage,
|
|
9695
|
+
didExecuteGadgets: result.didExecuteGadgets
|
|
9696
|
+
});
|
|
9697
|
+
this.logger.silly("LLM response details", {
|
|
9698
|
+
rawResponse: result.rawResponse
|
|
9699
|
+
});
|
|
9700
|
+
await this.safeObserve(async () => {
|
|
9701
|
+
if (this.hooks.observers?.onLLMCallComplete) {
|
|
9702
|
+
const subagentContext = getSubagentContextForNode(this.tree, currentLLMNodeId);
|
|
9703
|
+
const context = {
|
|
9704
|
+
iteration: currentIteration,
|
|
9705
|
+
options: llmOptions,
|
|
9706
|
+
finishReason: result.finishReason,
|
|
9707
|
+
usage: result.usage,
|
|
9708
|
+
rawResponse: result.rawResponse,
|
|
9709
|
+
finalMessage: result.finalMessage,
|
|
9710
|
+
logger: this.logger,
|
|
9711
|
+
subagentContext
|
|
9712
|
+
};
|
|
9713
|
+
await this.hooks.observers.onLLMCallComplete(context);
|
|
9714
|
+
}
|
|
9715
|
+
});
|
|
9716
|
+
this.completeLLMCallInTree(currentLLMNodeId, result);
|
|
9717
|
+
const finalMessage = await this.processAfterLLMCallController(
|
|
9718
|
+
currentIteration,
|
|
9719
|
+
llmOptions,
|
|
9720
|
+
result,
|
|
9721
|
+
gadgetCallCount
|
|
9722
|
+
);
|
|
9723
|
+
const shouldBreakFromTextOnly = await this.updateConversationWithResults(
|
|
9724
|
+
result.didExecuteGadgets,
|
|
9725
|
+
textOutputs,
|
|
9726
|
+
gadgetResults,
|
|
9727
|
+
finalMessage
|
|
9728
|
+
);
|
|
9729
|
+
if (shouldBreakFromTextOnly) {
|
|
9730
|
+
break;
|
|
9731
|
+
}
|
|
9732
|
+
if (result.shouldBreakLoop) {
|
|
9733
|
+
this.logger.info("Loop terminated by gadget or processor");
|
|
9734
|
+
break;
|
|
9735
|
+
}
|
|
9736
|
+
} catch (error) {
|
|
9737
|
+
const errorHandled = await this.handleLLMError(error, currentIteration);
|
|
9738
|
+
await this.safeObserve(async () => {
|
|
9739
|
+
if (this.hooks.observers?.onLLMCallError) {
|
|
9740
|
+
const options = llmOptions ?? {
|
|
9610
9741
|
model: this.model,
|
|
9611
9742
|
messages: this.conversation.getMessages(),
|
|
9612
9743
|
temperature: this.temperature,
|
|
9613
9744
|
maxTokens: this.defaultMaxTokens
|
|
9614
|
-
}
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
|
|
9745
|
+
};
|
|
9746
|
+
const subagentContext = currentLLMNodeId ? getSubagentContextForNode(this.tree, currentLLMNodeId) : void 0;
|
|
9747
|
+
const context = {
|
|
9748
|
+
iteration: currentIteration,
|
|
9749
|
+
options,
|
|
9750
|
+
error,
|
|
9751
|
+
recovered: errorHandled,
|
|
9752
|
+
logger: this.logger,
|
|
9753
|
+
subagentContext
|
|
9754
|
+
};
|
|
9755
|
+
await this.hooks.observers.onLLMCallError(context);
|
|
9756
|
+
}
|
|
9757
|
+
});
|
|
9758
|
+
if (!errorHandled) {
|
|
9759
|
+
throw error;
|
|
9620
9760
|
}
|
|
9621
|
-
});
|
|
9622
|
-
if (!errorHandled) {
|
|
9623
|
-
throw error;
|
|
9624
9761
|
}
|
|
9762
|
+
currentIteration++;
|
|
9625
9763
|
}
|
|
9626
|
-
|
|
9764
|
+
this.logger.info("Agent loop completed", {
|
|
9765
|
+
totalIterations: currentIteration,
|
|
9766
|
+
reason: currentIteration >= this.maxIterations ? "max_iterations" : "natural_completion"
|
|
9767
|
+
});
|
|
9768
|
+
} finally {
|
|
9769
|
+
unsubscribeBridge();
|
|
9627
9770
|
}
|
|
9628
|
-
this.logger.info("Agent loop completed", {
|
|
9629
|
-
totalIterations: currentIteration,
|
|
9630
|
-
reason: currentIteration >= this.maxIterations ? "max_iterations" : "natural_completion"
|
|
9631
|
-
});
|
|
9632
9771
|
}
|
|
9633
9772
|
/**
|
|
9634
9773
|
* Create LLM stream with retry logic.
|
|
@@ -9849,8 +9988,8 @@ var init_agent = __esm({
|
|
|
9849
9988
|
return { type: "compaction", event: compactionEvent };
|
|
9850
9989
|
}
|
|
9851
9990
|
/**
|
|
9852
|
-
* Prepare LLM call options and process beforeLLMCall controller.
|
|
9853
|
-
* @returns options and optional skipWithSynthetic response if controller wants to skip
|
|
9991
|
+
* Prepare LLM call options, create tree node, and process beforeLLMCall controller.
|
|
9992
|
+
* @returns options, node ID, and optional skipWithSynthetic response if controller wants to skip
|
|
9854
9993
|
*/
|
|
9855
9994
|
async prepareLLMCall(iteration) {
|
|
9856
9995
|
let llmOptions = {
|
|
@@ -9860,12 +9999,20 @@ var init_agent = __esm({
|
|
|
9860
9999
|
maxTokens: this.defaultMaxTokens,
|
|
9861
10000
|
signal: this.signal
|
|
9862
10001
|
};
|
|
10002
|
+
const llmNode = this.tree.addLLMCall({
|
|
10003
|
+
iteration,
|
|
10004
|
+
model: llmOptions.model,
|
|
10005
|
+
parentId: this.parentNodeId,
|
|
10006
|
+
request: llmOptions.messages
|
|
10007
|
+
});
|
|
9863
10008
|
await this.safeObserve(async () => {
|
|
9864
10009
|
if (this.hooks.observers?.onLLMCallStart) {
|
|
10010
|
+
const subagentContext = getSubagentContextForNode(this.tree, llmNode.id);
|
|
9865
10011
|
const context = {
|
|
9866
10012
|
iteration,
|
|
9867
10013
|
options: llmOptions,
|
|
9868
|
-
logger: this.logger
|
|
10014
|
+
logger: this.logger,
|
|
10015
|
+
subagentContext
|
|
9869
10016
|
};
|
|
9870
10017
|
await this.hooks.observers.onLLMCallStart(context);
|
|
9871
10018
|
}
|
|
@@ -9881,23 +10028,25 @@ var init_agent = __esm({
|
|
|
9881
10028
|
validateBeforeLLMCallAction(action);
|
|
9882
10029
|
if (action.action === "skip") {
|
|
9883
10030
|
this.logger.info("Controller skipped LLM call, using synthetic response");
|
|
9884
|
-
return { options: llmOptions, skipWithSynthetic: action.syntheticResponse };
|
|
10031
|
+
return { options: llmOptions, llmNodeId: llmNode.id, skipWithSynthetic: action.syntheticResponse };
|
|
9885
10032
|
} else if (action.action === "proceed" && action.modifiedOptions) {
|
|
9886
10033
|
llmOptions = { ...llmOptions, ...action.modifiedOptions };
|
|
9887
10034
|
}
|
|
9888
10035
|
}
|
|
9889
10036
|
await this.safeObserve(async () => {
|
|
9890
10037
|
if (this.hooks.observers?.onLLMCallReady) {
|
|
10038
|
+
const subagentContext = getSubagentContextForNode(this.tree, llmNode.id);
|
|
9891
10039
|
const context = {
|
|
9892
10040
|
iteration,
|
|
9893
10041
|
maxIterations: this.maxIterations,
|
|
9894
10042
|
options: llmOptions,
|
|
9895
|
-
logger: this.logger
|
|
10043
|
+
logger: this.logger,
|
|
10044
|
+
subagentContext
|
|
9896
10045
|
};
|
|
9897
10046
|
await this.hooks.observers.onLLMCallReady(context);
|
|
9898
10047
|
}
|
|
9899
10048
|
});
|
|
9900
|
-
return { options: llmOptions };
|
|
10049
|
+
return { options: llmOptions, llmNodeId: llmNode.id };
|
|
9901
10050
|
}
|
|
9902
10051
|
/**
|
|
9903
10052
|
* Calculate cost and complete LLM call in execution tree.
|