llmist 12.2.4 → 12.3.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.js CHANGED
@@ -1412,6 +1412,137 @@ var init_model_shortcuts = __esm({
1412
1412
  }
1413
1413
  });
1414
1414
 
1415
+ // src/core/retry.ts
1416
+ function resolveRetryConfig(config) {
1417
+ if (!config) {
1418
+ return { ...DEFAULT_RETRY_CONFIG };
1419
+ }
1420
+ return {
1421
+ enabled: config.enabled ?? DEFAULT_RETRY_CONFIG.enabled,
1422
+ retries: config.retries ?? DEFAULT_RETRY_CONFIG.retries,
1423
+ minTimeout: config.minTimeout ?? DEFAULT_RETRY_CONFIG.minTimeout,
1424
+ maxTimeout: config.maxTimeout ?? DEFAULT_RETRY_CONFIG.maxTimeout,
1425
+ factor: config.factor ?? DEFAULT_RETRY_CONFIG.factor,
1426
+ randomize: config.randomize ?? DEFAULT_RETRY_CONFIG.randomize,
1427
+ onRetry: config.onRetry,
1428
+ onRetriesExhausted: config.onRetriesExhausted,
1429
+ shouldRetry: config.shouldRetry
1430
+ };
1431
+ }
1432
+ function isRetryableError(error) {
1433
+ const message = error.message.toLowerCase();
1434
+ const name = error.name;
1435
+ if (message.includes("429") || message.includes("rate limit") || message.includes("rate_limit")) {
1436
+ return true;
1437
+ }
1438
+ if (message.includes("500") || message.includes("502") || message.includes("503") || message.includes("504") || message.includes("internal server error") || message.includes("bad gateway") || message.includes("service unavailable") || message.includes("gateway timeout")) {
1439
+ return true;
1440
+ }
1441
+ if (message.includes("timeout") || message.includes("etimedout") || message.includes("timed out")) {
1442
+ return true;
1443
+ }
1444
+ if (message.includes("econnreset") || message.includes("econnrefused") || message.includes("enotfound") || message.includes("connection") || message.includes("network")) {
1445
+ return true;
1446
+ }
1447
+ if (name === "APIConnectionError" || name === "RateLimitError" || name === "InternalServerError" || name === "ServiceUnavailableError" || name === "APITimeoutError") {
1448
+ return true;
1449
+ }
1450
+ if (message.includes("overloaded") || message.includes("capacity")) {
1451
+ return true;
1452
+ }
1453
+ if (message.includes("401") || message.includes("403") || message.includes("400") || message.includes("404") || message.includes("authentication") || message.includes("unauthorized") || message.includes("forbidden") || message.includes("invalid") || message.includes("content policy") || name === "AuthenticationError" || name === "BadRequestError" || name === "NotFoundError" || name === "PermissionDeniedError") {
1454
+ return false;
1455
+ }
1456
+ return false;
1457
+ }
1458
+ function formatLLMError(error) {
1459
+ const message = error.message;
1460
+ const name = error.name;
1461
+ if (message.includes("RESOURCE_EXHAUSTED") || message.includes("429")) {
1462
+ return "Rate limit exceeded (429) - retry after a few seconds";
1463
+ }
1464
+ if (message.toLowerCase().includes("rate limit") || message.toLowerCase().includes("rate_limit")) {
1465
+ return "Rate limit exceeded - retry after a few seconds";
1466
+ }
1467
+ if (message.toLowerCase().includes("overloaded") || message.toLowerCase().includes("capacity")) {
1468
+ return "API overloaded - retry later";
1469
+ }
1470
+ if (message.includes("500") || message.toLowerCase().includes("internal server error")) {
1471
+ return "Internal server error (500) - the API is experiencing issues";
1472
+ }
1473
+ if (message.includes("502") || message.toLowerCase().includes("bad gateway")) {
1474
+ return "Bad gateway (502) - the API is temporarily unavailable";
1475
+ }
1476
+ if (message.includes("503") || message.toLowerCase().includes("service unavailable")) {
1477
+ return "Service unavailable (503) - the API is temporarily down";
1478
+ }
1479
+ if (message.includes("504") || message.toLowerCase().includes("gateway timeout")) {
1480
+ return "Gateway timeout (504) - the request took too long";
1481
+ }
1482
+ if (message.toLowerCase().includes("timeout") || message.toLowerCase().includes("timed out")) {
1483
+ return "Request timed out - the API took too long to respond";
1484
+ }
1485
+ if (message.toLowerCase().includes("econnrefused")) {
1486
+ return "Connection refused - unable to reach the API";
1487
+ }
1488
+ if (message.toLowerCase().includes("econnreset")) {
1489
+ return "Connection reset - the API closed the connection";
1490
+ }
1491
+ if (message.toLowerCase().includes("enotfound")) {
1492
+ return "DNS error - unable to resolve API hostname";
1493
+ }
1494
+ if (message.includes("401") || message.toLowerCase().includes("unauthorized") || name === "AuthenticationError") {
1495
+ return "Authentication failed - check your API key";
1496
+ }
1497
+ if (message.includes("403") || message.toLowerCase().includes("forbidden") || name === "PermissionDeniedError") {
1498
+ return "Permission denied - your API key lacks required permissions";
1499
+ }
1500
+ if (message.includes("400") || name === "BadRequestError") {
1501
+ const match = message.match(/message['":\s]+['"]?([^'"}\]]+)/i);
1502
+ if (match) {
1503
+ return `Bad request: ${match[1].trim()}`;
1504
+ }
1505
+ return "Bad request - check your input parameters";
1506
+ }
1507
+ if (message.toLowerCase().includes("content policy") || message.toLowerCase().includes("safety")) {
1508
+ return "Content policy violation - the request was blocked";
1509
+ }
1510
+ try {
1511
+ const parsed = JSON.parse(message);
1512
+ const extractedMessage = parsed?.error?.message || parsed?.message;
1513
+ if (typeof extractedMessage === "string" && extractedMessage.length > 0) {
1514
+ return extractedMessage.trim();
1515
+ }
1516
+ } catch {
1517
+ }
1518
+ const jsonMatch = message.match(/["']?message["']?\s*[:=]\s*["']([^"']+)["']/i);
1519
+ if (jsonMatch) {
1520
+ return jsonMatch[1].trim();
1521
+ }
1522
+ if (message.length > 200) {
1523
+ const firstPart = message.split(/[.!?\n]/)[0];
1524
+ if (firstPart && firstPart.length > 10 && firstPart.length < 150) {
1525
+ return firstPart.trim();
1526
+ }
1527
+ return message.slice(0, 150).trim() + "...";
1528
+ }
1529
+ return message;
1530
+ }
1531
+ var DEFAULT_RETRY_CONFIG;
1532
+ var init_retry = __esm({
1533
+ "src/core/retry.ts"() {
1534
+ "use strict";
1535
+ DEFAULT_RETRY_CONFIG = {
1536
+ enabled: true,
1537
+ retries: 3,
1538
+ minTimeout: 1e3,
1539
+ maxTimeout: 3e4,
1540
+ factor: 2,
1541
+ randomize: true
1542
+ };
1543
+ }
1544
+ });
1545
+
1415
1546
  // src/gadgets/media-store.ts
1416
1547
  import { randomBytes } from "crypto";
1417
1548
  import { mkdir, rm, writeFile } from "fs/promises";
@@ -2490,137 +2621,6 @@ var init_agent_internal_key = __esm({
2490
2621
  }
2491
2622
  });
2492
2623
 
2493
- // src/core/retry.ts
2494
- function resolveRetryConfig(config) {
2495
- if (!config) {
2496
- return { ...DEFAULT_RETRY_CONFIG };
2497
- }
2498
- return {
2499
- enabled: config.enabled ?? DEFAULT_RETRY_CONFIG.enabled,
2500
- retries: config.retries ?? DEFAULT_RETRY_CONFIG.retries,
2501
- minTimeout: config.minTimeout ?? DEFAULT_RETRY_CONFIG.minTimeout,
2502
- maxTimeout: config.maxTimeout ?? DEFAULT_RETRY_CONFIG.maxTimeout,
2503
- factor: config.factor ?? DEFAULT_RETRY_CONFIG.factor,
2504
- randomize: config.randomize ?? DEFAULT_RETRY_CONFIG.randomize,
2505
- onRetry: config.onRetry,
2506
- onRetriesExhausted: config.onRetriesExhausted,
2507
- shouldRetry: config.shouldRetry
2508
- };
2509
- }
2510
- function isRetryableError(error) {
2511
- const message = error.message.toLowerCase();
2512
- const name = error.name;
2513
- if (message.includes("429") || message.includes("rate limit") || message.includes("rate_limit")) {
2514
- return true;
2515
- }
2516
- if (message.includes("500") || message.includes("502") || message.includes("503") || message.includes("504") || message.includes("internal server error") || message.includes("bad gateway") || message.includes("service unavailable") || message.includes("gateway timeout")) {
2517
- return true;
2518
- }
2519
- if (message.includes("timeout") || message.includes("etimedout") || message.includes("timed out")) {
2520
- return true;
2521
- }
2522
- if (message.includes("econnreset") || message.includes("econnrefused") || message.includes("enotfound") || message.includes("connection") || message.includes("network")) {
2523
- return true;
2524
- }
2525
- if (name === "APIConnectionError" || name === "RateLimitError" || name === "InternalServerError" || name === "ServiceUnavailableError" || name === "APITimeoutError") {
2526
- return true;
2527
- }
2528
- if (message.includes("overloaded") || message.includes("capacity")) {
2529
- return true;
2530
- }
2531
- if (message.includes("401") || message.includes("403") || message.includes("400") || message.includes("404") || message.includes("authentication") || message.includes("unauthorized") || message.includes("forbidden") || message.includes("invalid") || message.includes("content policy") || name === "AuthenticationError" || name === "BadRequestError" || name === "NotFoundError" || name === "PermissionDeniedError") {
2532
- return false;
2533
- }
2534
- return false;
2535
- }
2536
- function formatLLMError(error) {
2537
- const message = error.message;
2538
- const name = error.name;
2539
- if (message.includes("RESOURCE_EXHAUSTED") || message.includes("429")) {
2540
- return "Rate limit exceeded (429) - retry after a few seconds";
2541
- }
2542
- if (message.toLowerCase().includes("rate limit") || message.toLowerCase().includes("rate_limit")) {
2543
- return "Rate limit exceeded - retry after a few seconds";
2544
- }
2545
- if (message.toLowerCase().includes("overloaded") || message.toLowerCase().includes("capacity")) {
2546
- return "API overloaded - retry later";
2547
- }
2548
- if (message.includes("500") || message.toLowerCase().includes("internal server error")) {
2549
- return "Internal server error (500) - the API is experiencing issues";
2550
- }
2551
- if (message.includes("502") || message.toLowerCase().includes("bad gateway")) {
2552
- return "Bad gateway (502) - the API is temporarily unavailable";
2553
- }
2554
- if (message.includes("503") || message.toLowerCase().includes("service unavailable")) {
2555
- return "Service unavailable (503) - the API is temporarily down";
2556
- }
2557
- if (message.includes("504") || message.toLowerCase().includes("gateway timeout")) {
2558
- return "Gateway timeout (504) - the request took too long";
2559
- }
2560
- if (message.toLowerCase().includes("timeout") || message.toLowerCase().includes("timed out")) {
2561
- return "Request timed out - the API took too long to respond";
2562
- }
2563
- if (message.toLowerCase().includes("econnrefused")) {
2564
- return "Connection refused - unable to reach the API";
2565
- }
2566
- if (message.toLowerCase().includes("econnreset")) {
2567
- return "Connection reset - the API closed the connection";
2568
- }
2569
- if (message.toLowerCase().includes("enotfound")) {
2570
- return "DNS error - unable to resolve API hostname";
2571
- }
2572
- if (message.includes("401") || message.toLowerCase().includes("unauthorized") || name === "AuthenticationError") {
2573
- return "Authentication failed - check your API key";
2574
- }
2575
- if (message.includes("403") || message.toLowerCase().includes("forbidden") || name === "PermissionDeniedError") {
2576
- return "Permission denied - your API key lacks required permissions";
2577
- }
2578
- if (message.includes("400") || name === "BadRequestError") {
2579
- const match = message.match(/message['":\s]+['"]?([^'"}\]]+)/i);
2580
- if (match) {
2581
- return `Bad request: ${match[1].trim()}`;
2582
- }
2583
- return "Bad request - check your input parameters";
2584
- }
2585
- if (message.toLowerCase().includes("content policy") || message.toLowerCase().includes("safety")) {
2586
- return "Content policy violation - the request was blocked";
2587
- }
2588
- try {
2589
- const parsed = JSON.parse(message);
2590
- const extractedMessage = parsed?.error?.message || parsed?.message;
2591
- if (typeof extractedMessage === "string" && extractedMessage.length > 0) {
2592
- return extractedMessage.trim();
2593
- }
2594
- } catch {
2595
- }
2596
- const jsonMatch = message.match(/["']?message["']?\s*[:=]\s*["']([^"']+)["']/i);
2597
- if (jsonMatch) {
2598
- return jsonMatch[1].trim();
2599
- }
2600
- if (message.length > 200) {
2601
- const firstPart = message.split(/[.!?\n]/)[0];
2602
- if (firstPart && firstPart.length > 10 && firstPart.length < 150) {
2603
- return firstPart.trim();
2604
- }
2605
- return message.slice(0, 150).trim() + "...";
2606
- }
2607
- return message;
2608
- }
2609
- var DEFAULT_RETRY_CONFIG;
2610
- var init_retry = __esm({
2611
- "src/core/retry.ts"() {
2612
- "use strict";
2613
- DEFAULT_RETRY_CONFIG = {
2614
- enabled: true,
2615
- retries: 3,
2616
- minTimeout: 1e3,
2617
- maxTimeout: 3e4,
2618
- factor: 2,
2619
- randomize: true
2620
- };
2621
- }
2622
- });
2623
-
2624
2624
  // src/agent/compaction/config.ts
2625
2625
  function resolveCompactionConfig(config = {}) {
2626
2626
  const trigger = config.triggerThresholdPercent ?? DEFAULT_COMPACTION_CONFIG.triggerThresholdPercent;
@@ -8073,6 +8073,10 @@ var init_builder = __esm({
8073
8073
  // Tree context for subagent support - enables shared tree model
8074
8074
  // When a gadget calls withParentContext(ctx), it shares the parent's tree
8075
8075
  parentContext;
8076
+ // Parent observer hooks for subagent visibility
8077
+ // When a gadget calls withParentContext(ctx), these observers are
8078
+ // also called for gadget events in the subagent
8079
+ parentObservers;
8076
8080
  constructor(client) {
8077
8081
  this.client = client;
8078
8082
  }
@@ -8680,6 +8684,9 @@ var init_builder = __esm({
8680
8684
  if (ctx.logger && !this.logger) {
8681
8685
  this.logger = ctx.logger;
8682
8686
  }
8687
+ if (ctx.parentObservers && !this.parentObservers) {
8688
+ this.parentObservers = ctx.parentObservers;
8689
+ }
8683
8690
  return this;
8684
8691
  }
8685
8692
  /**
@@ -9055,7 +9062,9 @@ ${endPrefix}`
9055
9062
  // Tree context for shared tree model (subagents share parent's tree)
9056
9063
  parentTree: this.parentContext?.tree,
9057
9064
  parentNodeId: this.parentContext?.nodeId,
9058
- baseDepth: this.parentContext ? (this.parentContext.depth ?? 0) + 1 : 0
9065
+ baseDepth: this.parentContext ? (this.parentContext.depth ?? 0) + 1 : 0,
9066
+ // Parent observer hooks for subagent visibility
9067
+ parentObservers: this.parentObservers
9059
9068
  };
9060
9069
  return new Agent(AGENT_INTERNAL_KEY, options);
9061
9070
  }
@@ -9938,7 +9947,7 @@ var init_executor = __esm({
9938
9947
  init_parser();
9939
9948
  init_typed_gadget();
9940
9949
  GadgetExecutor = class {
9941
- constructor(registry, requestHumanInput, logger, defaultGadgetTimeoutMs, errorFormatterOptions, client, mediaStore, agentConfig, subagentConfig, tree, parentNodeId, baseDepth) {
9950
+ constructor(registry, requestHumanInput, logger, defaultGadgetTimeoutMs, errorFormatterOptions, client, mediaStore, agentConfig, subagentConfig, tree, parentNodeId, baseDepth, parentObservers) {
9942
9951
  this.registry = registry;
9943
9952
  this.requestHumanInput = requestHumanInput;
9944
9953
  this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
@@ -9949,6 +9958,7 @@ var init_executor = __esm({
9949
9958
  this.tree = tree;
9950
9959
  this.parentNodeId = parentNodeId;
9951
9960
  this.baseDepth = baseDepth;
9961
+ this.parentObservers = parentObservers;
9952
9962
  this.logger = logger ?? createLogger({ name: "llmist:executor" });
9953
9963
  this.errorFormatter = new GadgetExecutionErrorFormatter(errorFormatterOptions);
9954
9964
  this.argPrefix = errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;
@@ -10114,7 +10124,11 @@ var init_executor = __esm({
10114
10124
  // Logger for structured logging (respects CLI's log level/file config)
10115
10125
  logger: this.logger,
10116
10126
  // Human input callback for subagents to bubble up input requests
10117
- requestHumanInput: this.requestHumanInput
10127
+ requestHumanInput: this.requestHumanInput,
10128
+ // Parent observer hooks for subagent visibility
10129
+ // When a subagent uses withParentContext(ctx), it will receive these
10130
+ // and call them for gadget events in addition to its own hooks
10131
+ parentObservers: this.parentObservers
10118
10132
  };
10119
10133
  let rawResult;
10120
10134
  if (timeoutMs && timeoutMs > 0) {
@@ -10467,6 +10481,8 @@ var init_stream_processor = __esm({
10467
10481
  priorCompletedInvocations;
10468
10482
  /** Invocation IDs that failed in previous iterations (read-only reference from Agent) */
10469
10483
  priorFailedInvocations;
10484
+ // Parent observer hooks for subagent visibility
10485
+ parentObservers;
10470
10486
  constructor(options) {
10471
10487
  this.iteration = options.iteration;
10472
10488
  this.registry = options.registry;
@@ -10478,6 +10494,7 @@ var init_stream_processor = __esm({
10478
10494
  this.priorCompletedInvocations = options.priorCompletedInvocations ?? /* @__PURE__ */ new Set();
10479
10495
  this.priorFailedInvocations = options.priorFailedInvocations ?? /* @__PURE__ */ new Set();
10480
10496
  this.subagentConfig = options.subagentConfig;
10497
+ this.parentObservers = options.parentObservers;
10481
10498
  this.parser = new GadgetCallParser({
10482
10499
  startPrefix: options.gadgetStartPrefix,
10483
10500
  endPrefix: options.gadgetEndPrefix,
@@ -10496,7 +10513,9 @@ var init_stream_processor = __esm({
10496
10513
  // Tree context for gadget execution
10497
10514
  options.tree,
10498
10515
  options.parentNodeId,
10499
- options.baseDepth
10516
+ options.baseDepth,
10517
+ // Parent observer hooks for subagent visibility
10518
+ options.parentObservers
10500
10519
  );
10501
10520
  }
10502
10521
  /**
@@ -10702,9 +10721,9 @@ var init_stream_processor = __esm({
10702
10721
  failedDependencyError: errorMessage
10703
10722
  };
10704
10723
  yield skipEvent;
10724
+ const skippedGadgetNode = this.tree?.getNodeByInvocationId(call.invocationId);
10725
+ const skippedSubagentContext = this.tree && skippedGadgetNode ? getSubagentContextForNode(this.tree, skippedGadgetNode.id) : void 0;
10705
10726
  if (this.hooks.observers?.onGadgetSkipped) {
10706
- const gadgetNode = this.tree?.getNodeByInvocationId(call.invocationId);
10707
- const subagentContext = this.tree && gadgetNode ? getSubagentContextForNode(this.tree, gadgetNode.id) : void 0;
10708
10727
  const context = {
10709
10728
  iteration: this.iteration,
10710
10729
  gadgetName: call.gadgetName,
@@ -10713,10 +10732,23 @@ var init_stream_processor = __esm({
10713
10732
  failedDependency: call.invocationId,
10714
10733
  failedDependencyError: errorMessage,
10715
10734
  logger: this.logger,
10716
- subagentContext
10735
+ subagentContext: skippedSubagentContext
10717
10736
  };
10718
10737
  await this.safeObserve(() => this.hooks.observers.onGadgetSkipped(context));
10719
10738
  }
10739
+ if (this.parentObservers?.onGadgetSkipped) {
10740
+ const context = {
10741
+ iteration: this.iteration,
10742
+ gadgetName: call.gadgetName,
10743
+ invocationId: call.invocationId,
10744
+ parameters: call.parameters ?? {},
10745
+ failedDependency: call.invocationId,
10746
+ failedDependencyError: errorMessage,
10747
+ logger: this.logger,
10748
+ subagentContext: skippedSubagentContext
10749
+ };
10750
+ await this.safeObserve(() => this.parentObservers.onGadgetSkipped(context));
10751
+ }
10720
10752
  return;
10721
10753
  }
10722
10754
  const failedDep = call.dependencies.find(
@@ -10859,19 +10891,30 @@ var init_stream_processor = __esm({
10859
10891
  this.tree.startGadget(gadgetNode.id);
10860
10892
  }
10861
10893
  }
10894
+ const gadgetStartNode = this.tree?.getNodeByInvocationId(call.invocationId);
10895
+ const gadgetStartSubagentContext = this.tree && gadgetStartNode ? getSubagentContextForNode(this.tree, gadgetStartNode.id) : void 0;
10862
10896
  if (this.hooks.observers?.onGadgetExecutionStart) {
10863
- const gadgetNode = this.tree?.getNodeByInvocationId(call.invocationId);
10864
- const subagentContext = this.tree && gadgetNode ? getSubagentContextForNode(this.tree, gadgetNode.id) : void 0;
10865
10897
  const context = {
10866
10898
  iteration: this.iteration,
10867
10899
  gadgetName: call.gadgetName,
10868
10900
  invocationId: call.invocationId,
10869
10901
  parameters,
10870
10902
  logger: this.logger,
10871
- subagentContext
10903
+ subagentContext: gadgetStartSubagentContext
10872
10904
  };
10873
10905
  await this.safeObserve(() => this.hooks.observers.onGadgetExecutionStart(context));
10874
10906
  }
10907
+ if (this.parentObservers?.onGadgetExecutionStart) {
10908
+ const context = {
10909
+ iteration: this.iteration,
10910
+ gadgetName: call.gadgetName,
10911
+ invocationId: call.invocationId,
10912
+ parameters,
10913
+ logger: this.logger,
10914
+ subagentContext: gadgetStartSubagentContext
10915
+ };
10916
+ await this.safeObserve(() => this.parentObservers.onGadgetExecutionStart(context));
10917
+ }
10875
10918
  let result;
10876
10919
  if (shouldSkip) {
10877
10920
  result = {
@@ -10939,9 +10982,9 @@ var init_stream_processor = __esm({
10939
10982
  }
10940
10983
  }
10941
10984
  }
10985
+ const gadgetCompleteNode = this.tree?.getNodeByInvocationId(result.invocationId);
10986
+ const gadgetCompleteSubagentContext = this.tree && gadgetCompleteNode ? getSubagentContextForNode(this.tree, gadgetCompleteNode.id) : void 0;
10942
10987
  if (this.hooks.observers?.onGadgetExecutionComplete) {
10943
- const gadgetNode = this.tree?.getNodeByInvocationId(result.invocationId);
10944
- const subagentContext = this.tree && gadgetNode ? getSubagentContextForNode(this.tree, gadgetNode.id) : void 0;
10945
10988
  const context = {
10946
10989
  iteration: this.iteration,
10947
10990
  gadgetName: result.gadgetName,
@@ -10952,10 +10995,25 @@ var init_stream_processor = __esm({
10952
10995
  executionTimeMs: result.executionTimeMs,
10953
10996
  cost: result.cost,
10954
10997
  logger: this.logger,
10955
- subagentContext
10998
+ subagentContext: gadgetCompleteSubagentContext
10956
10999
  };
10957
11000
  await this.safeObserve(() => this.hooks.observers.onGadgetExecutionComplete(context));
10958
11001
  }
11002
+ if (this.parentObservers?.onGadgetExecutionComplete) {
11003
+ const context = {
11004
+ iteration: this.iteration,
11005
+ gadgetName: result.gadgetName,
11006
+ invocationId: result.invocationId,
11007
+ parameters,
11008
+ finalResult: result.result,
11009
+ error: result.error,
11010
+ executionTimeMs: result.executionTimeMs,
11011
+ cost: result.cost,
11012
+ logger: this.logger,
11013
+ subagentContext: gadgetCompleteSubagentContext
11014
+ };
11015
+ await this.safeObserve(() => this.parentObservers.onGadgetExecutionComplete(context));
11016
+ }
10959
11017
  this.completedResults.set(result.invocationId, result);
10960
11018
  if (result.error) {
10961
11019
  this.failedInvocations.add(result.invocationId);
@@ -11081,9 +11139,9 @@ var init_stream_processor = __esm({
11081
11139
  failedDependencyError: depError
11082
11140
  };
11083
11141
  events.push(skipEvent);
11142
+ const gadgetNodeForSkip = this.tree?.getNodeByInvocationId(call.invocationId);
11143
+ const skipSubagentContext = this.tree && gadgetNodeForSkip ? getSubagentContextForNode(this.tree, gadgetNodeForSkip.id) : void 0;
11084
11144
  if (this.hooks.observers?.onGadgetSkipped) {
11085
- const gadgetNode = this.tree?.getNodeByInvocationId(call.invocationId);
11086
- const subagentContext = this.tree && gadgetNode ? getSubagentContextForNode(this.tree, gadgetNode.id) : void 0;
11087
11145
  const context = {
11088
11146
  iteration: this.iteration,
11089
11147
  gadgetName: call.gadgetName,
@@ -11092,10 +11150,23 @@ var init_stream_processor = __esm({
11092
11150
  failedDependency: failedDep,
11093
11151
  failedDependencyError: depError,
11094
11152
  logger: this.logger,
11095
- subagentContext
11153
+ subagentContext: skipSubagentContext
11096
11154
  };
11097
11155
  await this.safeObserve(() => this.hooks.observers.onGadgetSkipped(context));
11098
11156
  }
11157
+ if (this.parentObservers?.onGadgetSkipped) {
11158
+ const context = {
11159
+ iteration: this.iteration,
11160
+ gadgetName: call.gadgetName,
11161
+ invocationId: call.invocationId,
11162
+ parameters: call.parameters ?? {},
11163
+ failedDependency: failedDep,
11164
+ failedDependencyError: depError,
11165
+ logger: this.logger,
11166
+ subagentContext: skipSubagentContext
11167
+ };
11168
+ await this.safeObserve(() => this.parentObservers.onGadgetSkipped(context));
11169
+ }
11099
11170
  this.logger.info("Gadget skipped due to failed dependency", {
11100
11171
  gadgetName: call.gadgetName,
11101
11172
  invocationId: call.invocationId,
@@ -11223,9 +11294,9 @@ var init_stream_processor = __esm({
11223
11294
  failedDependencyError: errorMessage
11224
11295
  };
11225
11296
  yield skipEvent;
11297
+ const gadgetNodeForTimeout = this.tree?.getNodeByInvocationId(invocationId);
11298
+ const timeoutSubagentContext = this.tree && gadgetNodeForTimeout ? getSubagentContextForNode(this.tree, gadgetNodeForTimeout.id) : void 0;
11226
11299
  if (this.hooks.observers?.onGadgetSkipped) {
11227
- const gadgetNode = this.tree?.getNodeByInvocationId(invocationId);
11228
- const subagentContext = this.tree && gadgetNode ? getSubagentContextForNode(this.tree, gadgetNode.id) : void 0;
11229
11300
  const context = {
11230
11301
  iteration: this.iteration,
11231
11302
  gadgetName: call.gadgetName,
@@ -11234,10 +11305,23 @@ var init_stream_processor = __esm({
11234
11305
  failedDependency: missingDeps[0],
11235
11306
  failedDependencyError: errorMessage,
11236
11307
  logger: this.logger,
11237
- subagentContext
11308
+ subagentContext: timeoutSubagentContext
11238
11309
  };
11239
11310
  await this.safeObserve(() => this.hooks.observers.onGadgetSkipped(context));
11240
11311
  }
11312
+ if (this.parentObservers?.onGadgetSkipped) {
11313
+ const context = {
11314
+ iteration: this.iteration,
11315
+ gadgetName: call.gadgetName,
11316
+ invocationId,
11317
+ parameters: call.parameters ?? {},
11318
+ failedDependency: missingDeps[0],
11319
+ failedDependencyError: errorMessage,
11320
+ logger: this.logger,
11321
+ subagentContext: timeoutSubagentContext
11322
+ };
11323
+ await this.safeObserve(() => this.parentObservers.onGadgetSkipped(context));
11324
+ }
11241
11325
  }
11242
11326
  this.gadgetsAwaitingDependencies.clear();
11243
11327
  }
@@ -11296,11 +11380,11 @@ var init_agent = __esm({
11296
11380
  init_execution_tree();
11297
11381
  init_messages();
11298
11382
  init_model_shortcuts();
11383
+ init_retry();
11299
11384
  init_media_store();
11300
11385
  init_output_viewer();
11301
11386
  init_logger();
11302
11387
  init_agent_internal_key();
11303
- init_retry();
11304
11388
  init_manager();
11305
11389
  init_conversation_manager();
11306
11390
  init_event_handlers();
@@ -11352,6 +11436,8 @@ var init_agent = __esm({
11352
11436
  tree;
11353
11437
  parentNodeId;
11354
11438
  baseDepth;
11439
+ // Parent observer hooks for subagent visibility
11440
+ parentObservers;
11355
11441
  /**
11356
11442
  * Creates a new Agent instance.
11357
11443
  * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.
@@ -11431,6 +11517,7 @@ var init_agent = __esm({
11431
11517
  this.tree = options.parentTree ?? new ExecutionTree();
11432
11518
  this.parentNodeId = options.parentNodeId ?? null;
11433
11519
  this.baseDepth = options.baseDepth ?? 0;
11520
+ this.parentObservers = options.parentObservers;
11434
11521
  }
11435
11522
  /**
11436
11523
  * Get the gadget registry for this agent.
@@ -11695,7 +11782,9 @@ var init_agent = __esm({
11695
11782
  baseDepth: this.baseDepth,
11696
11783
  // Cross-iteration dependency tracking
11697
11784
  priorCompletedInvocations: this.completedInvocationIds,
11698
- priorFailedInvocations: this.failedInvocationIds
11785
+ priorFailedInvocations: this.failedInvocationIds,
11786
+ // Parent observer hooks for subagent visibility
11787
+ parentObservers: this.parentObservers
11699
11788
  });
11700
11789
  let streamMetadata = null;
11701
11790
  let gadgetCallCount = 0;
@@ -11812,11 +11901,23 @@ var init_agent = __esm({
11812
11901
  if (!this.retryConfig.enabled) {
11813
11902
  return this.client.stream(llmOptions);
11814
11903
  }
11815
- const { retries, minTimeout, maxTimeout, factor, randomize, onRetry, onRetriesExhausted, shouldRetry } = this.retryConfig;
11904
+ const {
11905
+ retries,
11906
+ minTimeout,
11907
+ maxTimeout,
11908
+ factor,
11909
+ randomize,
11910
+ onRetry,
11911
+ onRetriesExhausted,
11912
+ shouldRetry
11913
+ } = this.retryConfig;
11816
11914
  try {
11817
11915
  return await pRetry(
11818
11916
  async (attemptNumber) => {
11819
- this.logger.debug("Creating LLM stream", { attempt: attemptNumber, maxAttempts: retries + 1 });
11917
+ this.logger.debug("Creating LLM stream", {
11918
+ attempt: attemptNumber,
11919
+ maxAttempts: retries + 1
11920
+ });
11820
11921
  return this.client.stream(llmOptions);
11821
11922
  },
11822
11923
  {
@@ -12063,7 +12164,11 @@ var init_agent = __esm({
12063
12164
  validateBeforeLLMCallAction(action);
12064
12165
  if (action.action === "skip") {
12065
12166
  this.logger.info("Controller skipped LLM call, using synthetic response");
12066
- return { options: llmOptions, llmNodeId: llmNode.id, skipWithSynthetic: action.syntheticResponse };
12167
+ return {
12168
+ options: llmOptions,
12169
+ llmNodeId: llmNode.id,
12170
+ skipWithSynthetic: action.syntheticResponse
12171
+ };
12067
12172
  } else if (action.action === "proceed" && action.modifiedOptions) {
12068
12173
  llmOptions = { ...llmOptions, ...action.modifiedOptions };
12069
12174
  }