llmist 12.3.2 → 12.3.4

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 CHANGED
@@ -10362,6 +10362,18 @@ function findParentGadgetInvocationId(tree, nodeId) {
10362
10362
  }
10363
10363
  return void 0;
10364
10364
  }
10365
+ function getIterationFromTree(tree, nodeId) {
10366
+ let currentId = nodeId;
10367
+ while (currentId) {
10368
+ const node = tree.getNode(currentId);
10369
+ if (!node) break;
10370
+ if (node.type === "llm_call") {
10371
+ return node.iteration;
10372
+ }
10373
+ currentId = node.parentId;
10374
+ }
10375
+ return 0;
10376
+ }
10365
10377
  function buildSubagentContext(tree, event) {
10366
10378
  const parentGadgetInvocationId = findParentGadgetInvocationId(tree, event.nodeId);
10367
10379
  if (!parentGadgetInvocationId) {
@@ -10391,16 +10403,135 @@ async function safeObserve(fn, logger, eventType) {
10391
10403
  logger.warn(`Observer error in ${eventType}:`, error);
10392
10404
  }
10393
10405
  }
10406
+ function chainObserverCall(chainMap, key, fn, logger, eventType, cleanup = false) {
10407
+ const previousPromise = chainMap.get(key) ?? Promise.resolve();
10408
+ const newPromise = previousPromise.then(() => safeObserve(fn, logger, eventType));
10409
+ chainMap.set(key, newPromise);
10410
+ if (cleanup) {
10411
+ newPromise.finally(() => chainMap.delete(key));
10412
+ }
10413
+ }
10394
10414
  function bridgeTreeToHooks(tree, hooks, logger) {
10415
+ const gadgetPromiseChains = /* @__PURE__ */ new Map();
10416
+ const llmPromiseChains = /* @__PURE__ */ new Map();
10395
10417
  return tree.onAll((event) => {
10396
10418
  const subagentContext = buildSubagentContext(tree, event);
10397
10419
  switch (event.type) {
10398
- // NOTE: gadget_start, gadget_complete, gadget_error, gadget_skipped are NOT
10399
- // handled here. They are called directly in stream-processor.ts with await
10400
- // to ensure proper ordering of observer commands.
10401
- // LLM events - bridged for subagent visibility
10402
- // When a subagent makes LLM calls, these events propagate through the shared tree
10403
- // to the parent's hooks, enabling unified monitoring of all LLM activity
10420
+ // =================================================================
10421
+ // GADGET EVENTS - Bridged for subagent visibility
10422
+ // =================================================================
10423
+ // When a subagent executes gadgets, these events propagate through
10424
+ // the shared tree to the parent's hooks.
10425
+ // Only bridged for subagent events (depth > 0) to avoid double-calling
10426
+ // root agent events which are handled directly in stream-processor.ts
10427
+ case "gadget_start": {
10428
+ if (subagentContext && hooks.observers?.onGadgetExecutionStart) {
10429
+ const gadgetEvent = event;
10430
+ const gadgetNode = tree.getNode(event.nodeId);
10431
+ const context = {
10432
+ iteration: getIterationFromTree(tree, event.nodeId),
10433
+ gadgetName: gadgetEvent.name,
10434
+ invocationId: gadgetEvent.invocationId,
10435
+ parameters: gadgetNode?.parameters ?? {},
10436
+ logger,
10437
+ subagentContext
10438
+ };
10439
+ chainObserverCall(
10440
+ gadgetPromiseChains,
10441
+ gadgetEvent.invocationId,
10442
+ () => hooks.observers?.onGadgetExecutionStart?.(context),
10443
+ logger,
10444
+ "onGadgetExecutionStart",
10445
+ false
10446
+ // Don't cleanup - wait for completion event
10447
+ );
10448
+ }
10449
+ break;
10450
+ }
10451
+ case "gadget_complete": {
10452
+ if (subagentContext && hooks.observers?.onGadgetExecutionComplete) {
10453
+ const gadgetEvent = event;
10454
+ const gadgetNode = tree.getNode(event.nodeId);
10455
+ const context = {
10456
+ iteration: getIterationFromTree(tree, event.nodeId),
10457
+ gadgetName: gadgetEvent.name,
10458
+ invocationId: gadgetEvent.invocationId,
10459
+ parameters: gadgetNode?.parameters ?? {},
10460
+ finalResult: gadgetEvent.result,
10461
+ executionTimeMs: gadgetEvent.executionTimeMs,
10462
+ cost: gadgetEvent.cost,
10463
+ logger,
10464
+ subagentContext
10465
+ };
10466
+ chainObserverCall(
10467
+ gadgetPromiseChains,
10468
+ gadgetEvent.invocationId,
10469
+ () => hooks.observers?.onGadgetExecutionComplete?.(context),
10470
+ logger,
10471
+ "onGadgetExecutionComplete",
10472
+ true
10473
+ // Cleanup after completion
10474
+ );
10475
+ }
10476
+ break;
10477
+ }
10478
+ case "gadget_error": {
10479
+ if (subagentContext && hooks.observers?.onGadgetExecutionComplete) {
10480
+ const gadgetEvent = event;
10481
+ const gadgetNode = tree.getNode(event.nodeId);
10482
+ const context = {
10483
+ iteration: getIterationFromTree(tree, event.nodeId),
10484
+ gadgetName: gadgetEvent.name,
10485
+ invocationId: gadgetEvent.invocationId,
10486
+ parameters: gadgetNode?.parameters ?? {},
10487
+ error: gadgetEvent.error,
10488
+ executionTimeMs: gadgetEvent.executionTimeMs,
10489
+ logger,
10490
+ subagentContext
10491
+ };
10492
+ chainObserverCall(
10493
+ gadgetPromiseChains,
10494
+ gadgetEvent.invocationId,
10495
+ () => hooks.observers?.onGadgetExecutionComplete?.(context),
10496
+ logger,
10497
+ "onGadgetExecutionComplete",
10498
+ true
10499
+ // Cleanup after error
10500
+ );
10501
+ }
10502
+ break;
10503
+ }
10504
+ case "gadget_skipped": {
10505
+ if (subagentContext && hooks.observers?.onGadgetSkipped) {
10506
+ const gadgetEvent = event;
10507
+ const gadgetNode = tree.getNode(event.nodeId);
10508
+ const context = {
10509
+ iteration: getIterationFromTree(tree, event.nodeId),
10510
+ gadgetName: gadgetEvent.name,
10511
+ invocationId: gadgetEvent.invocationId,
10512
+ parameters: gadgetNode?.parameters ?? {},
10513
+ failedDependency: gadgetEvent.failedDependency ?? "",
10514
+ failedDependencyError: gadgetEvent.failedDependencyError ?? gadgetEvent.error,
10515
+ logger,
10516
+ subagentContext
10517
+ };
10518
+ chainObserverCall(
10519
+ gadgetPromiseChains,
10520
+ gadgetEvent.invocationId,
10521
+ () => hooks.observers?.onGadgetSkipped?.(context),
10522
+ logger,
10523
+ "onGadgetSkipped",
10524
+ true
10525
+ // Cleanup after skipped
10526
+ );
10527
+ }
10528
+ break;
10529
+ }
10530
+ // =================================================================
10531
+ // LLM EVENTS - Bridged for subagent visibility
10532
+ // =================================================================
10533
+ // When a subagent makes LLM calls, these events propagate through
10534
+ // the shared tree to the parent's hooks.
10404
10535
  case "llm_call_start": {
10405
10536
  if (subagentContext && hooks.observers?.onLLMCallStart) {
10406
10537
  const llmEvent = event;
@@ -10416,7 +10547,15 @@ function bridgeTreeToHooks(tree, hooks, logger) {
10416
10547
  logger,
10417
10548
  subagentContext
10418
10549
  };
10419
- safeObserve(() => hooks.observers.onLLMCallStart(context), logger, "onLLMCallStart");
10550
+ chainObserverCall(
10551
+ llmPromiseChains,
10552
+ event.nodeId,
10553
+ () => hooks.observers?.onLLMCallStart?.(context),
10554
+ logger,
10555
+ "onLLMCallStart",
10556
+ false
10557
+ // Don't cleanup - wait for completion event
10558
+ );
10420
10559
  }
10421
10560
  break;
10422
10561
  }
@@ -10440,10 +10579,14 @@ function bridgeTreeToHooks(tree, hooks, logger) {
10440
10579
  logger,
10441
10580
  subagentContext
10442
10581
  };
10443
- safeObserve(
10444
- () => hooks.observers.onLLMCallComplete(context),
10582
+ chainObserverCall(
10583
+ llmPromiseChains,
10584
+ event.nodeId,
10585
+ () => hooks.observers?.onLLMCallComplete?.(context),
10445
10586
  logger,
10446
- "onLLMCallComplete"
10587
+ "onLLMCallComplete",
10588
+ true
10589
+ // Cleanup after completion
10447
10590
  );
10448
10591
  }
10449
10592
  break;
@@ -10465,7 +10608,15 @@ function bridgeTreeToHooks(tree, hooks, logger) {
10465
10608
  logger,
10466
10609
  subagentContext
10467
10610
  };
10468
- safeObserve(() => hooks.observers.onLLMCallError(context), logger, "onLLMCallError");
10611
+ chainObserverCall(
10612
+ llmPromiseChains,
10613
+ event.nodeId,
10614
+ () => hooks.observers?.onLLMCallError?.(context),
10615
+ logger,
10616
+ "onLLMCallError",
10617
+ true
10618
+ // Cleanup after error
10619
+ );
10469
10620
  }
10470
10621
  break;
10471
10622
  }