llmist 9.7.0 → 10.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.d.cts CHANGED
@@ -2545,6 +2545,13 @@ interface SubagentConfig {
2545
2545
  * Set to 0 to disable timeout for this gadget.
2546
2546
  */
2547
2547
  timeoutMs?: number;
2548
+ /**
2549
+ * Maximum number of concurrent executions allowed for this gadget.
2550
+ * When the limit is reached, additional calls are queued and processed
2551
+ * as earlier executions complete (FIFO order).
2552
+ * Set to 0 or omit to allow unlimited concurrent executions (default).
2553
+ */
2554
+ maxConcurrent?: number;
2548
2555
  /** Additional subagent-specific options */
2549
2556
  [key: string]: unknown;
2550
2557
  }
@@ -5791,6 +5798,9 @@ declare class AgentBuilder {
5791
5798
  * **Signal Forwarding** - When parent context includes a signal, it's automatically
5792
5799
  * forwarded to the subagent for proper cancellation propagation.
5793
5800
  *
5801
+ * **Logger Inheritance** - When parent context includes a logger, it's inherited
5802
+ * by the subagent for consistent structured logging.
5803
+ *
5794
5804
  * @param ctx - ExecutionContext passed to the gadget's execute() method
5795
5805
  * @param depth - Nesting depth (default: 1 for direct child)
5796
5806
  * @returns This builder for chaining
@@ -7291,6 +7301,12 @@ declare class StreamProcessor {
7291
7301
  private inFlightExecutions;
7292
7302
  /** Queue of completed gadget results ready to be yielded (for real-time streaming) */
7293
7303
  private completedResultsQueue;
7304
+ /** Subagent configuration map for checking maxConcurrent limits */
7305
+ private readonly subagentConfig?;
7306
+ /** Track active execution count per gadget name */
7307
+ private activeCountByGadget;
7308
+ /** Queue of gadgets waiting for a concurrency slot (per gadget name) */
7309
+ private concurrencyQueue;
7294
7310
  /** Invocation IDs completed in previous iterations (read-only reference from Agent) */
7295
7311
  private readonly priorCompletedInvocations;
7296
7312
  /** Invocation IDs that failed in previous iterations (read-only reference from Agent) */
@@ -7322,6 +7338,20 @@ declare class StreamProcessor {
7322
7338
  * enabling real-time UI feedback.
7323
7339
  */
7324
7340
  private processGadgetCallGenerator;
7341
+ /**
7342
+ * Get the concurrency limit for a gadget from subagent config.
7343
+ * Returns 0 if no limit is set (unlimited).
7344
+ */
7345
+ private getConcurrencyLimit;
7346
+ /**
7347
+ * Start a gadget execution with concurrency tracking.
7348
+ * Increments active count, starts execution, and schedules queue processing on completion.
7349
+ */
7350
+ private startGadgetWithConcurrencyTracking;
7351
+ /**
7352
+ * Process the next queued gadget for a given gadget name if a slot is available.
7353
+ */
7354
+ private processQueuedGadget;
7325
7355
  /**
7326
7356
  * Execute a gadget through the full hook lifecycle and yield events.
7327
7357
  * Handles parameter interception, before/after controllers, observers,
@@ -7349,6 +7379,19 @@ declare class StreamProcessor {
7349
7379
  * Clears the inFlightExecutions map after all gadgets complete.
7350
7380
  */
7351
7381
  private waitForInFlightExecutions;
7382
+ /**
7383
+ * Check if there are any gadgets waiting in concurrency queues.
7384
+ */
7385
+ private hasQueuedGadgets;
7386
+ /**
7387
+ * Get total count of queued gadgets across all queues.
7388
+ */
7389
+ private getQueuedGadgetCount;
7390
+ /**
7391
+ * Get total count of actively executing gadgets across all types.
7392
+ * Used to know when all work is truly complete (not just when allDone resolves).
7393
+ */
7394
+ private getTotalActiveGadgetCount;
7352
7395
  /**
7353
7396
  * Handle a gadget that cannot execute because a dependency failed.
7354
7397
  * Calls the onDependencySkipped controller to allow customization.
package/dist/index.d.ts CHANGED
@@ -2545,6 +2545,13 @@ interface SubagentConfig {
2545
2545
  * Set to 0 to disable timeout for this gadget.
2546
2546
  */
2547
2547
  timeoutMs?: number;
2548
+ /**
2549
+ * Maximum number of concurrent executions allowed for this gadget.
2550
+ * When the limit is reached, additional calls are queued and processed
2551
+ * as earlier executions complete (FIFO order).
2552
+ * Set to 0 or omit to allow unlimited concurrent executions (default).
2553
+ */
2554
+ maxConcurrent?: number;
2548
2555
  /** Additional subagent-specific options */
2549
2556
  [key: string]: unknown;
2550
2557
  }
@@ -5791,6 +5798,9 @@ declare class AgentBuilder {
5791
5798
  * **Signal Forwarding** - When parent context includes a signal, it's automatically
5792
5799
  * forwarded to the subagent for proper cancellation propagation.
5793
5800
  *
5801
+ * **Logger Inheritance** - When parent context includes a logger, it's inherited
5802
+ * by the subagent for consistent structured logging.
5803
+ *
5794
5804
  * @param ctx - ExecutionContext passed to the gadget's execute() method
5795
5805
  * @param depth - Nesting depth (default: 1 for direct child)
5796
5806
  * @returns This builder for chaining
@@ -7291,6 +7301,12 @@ declare class StreamProcessor {
7291
7301
  private inFlightExecutions;
7292
7302
  /** Queue of completed gadget results ready to be yielded (for real-time streaming) */
7293
7303
  private completedResultsQueue;
7304
+ /** Subagent configuration map for checking maxConcurrent limits */
7305
+ private readonly subagentConfig?;
7306
+ /** Track active execution count per gadget name */
7307
+ private activeCountByGadget;
7308
+ /** Queue of gadgets waiting for a concurrency slot (per gadget name) */
7309
+ private concurrencyQueue;
7294
7310
  /** Invocation IDs completed in previous iterations (read-only reference from Agent) */
7295
7311
  private readonly priorCompletedInvocations;
7296
7312
  /** Invocation IDs that failed in previous iterations (read-only reference from Agent) */
@@ -7322,6 +7338,20 @@ declare class StreamProcessor {
7322
7338
  * enabling real-time UI feedback.
7323
7339
  */
7324
7340
  private processGadgetCallGenerator;
7341
+ /**
7342
+ * Get the concurrency limit for a gadget from subagent config.
7343
+ * Returns 0 if no limit is set (unlimited).
7344
+ */
7345
+ private getConcurrencyLimit;
7346
+ /**
7347
+ * Start a gadget execution with concurrency tracking.
7348
+ * Increments active count, starts execution, and schedules queue processing on completion.
7349
+ */
7350
+ private startGadgetWithConcurrencyTracking;
7351
+ /**
7352
+ * Process the next queued gadget for a given gadget name if a slot is available.
7353
+ */
7354
+ private processQueuedGadget;
7325
7355
  /**
7326
7356
  * Execute a gadget through the full hook lifecycle and yield events.
7327
7357
  * Handles parameter interception, before/after controllers, observers,
@@ -7349,6 +7379,19 @@ declare class StreamProcessor {
7349
7379
  * Clears the inFlightExecutions map after all gadgets complete.
7350
7380
  */
7351
7381
  private waitForInFlightExecutions;
7382
+ /**
7383
+ * Check if there are any gadgets waiting in concurrency queues.
7384
+ */
7385
+ private hasQueuedGadgets;
7386
+ /**
7387
+ * Get total count of queued gadgets across all queues.
7388
+ */
7389
+ private getQueuedGadgetCount;
7390
+ /**
7391
+ * Get total count of actively executing gadgets across all types.
7392
+ * Used to know when all work is truly complete (not just when allDone resolves).
7393
+ */
7394
+ private getTotalActiveGadgetCount;
7352
7395
  /**
7353
7396
  * Handle a gadget that cannot execute because a dependency failed.
7354
7397
  * Calls the onDependencySkipped controller to allow customization.
package/dist/index.js CHANGED
@@ -8318,6 +8318,13 @@ var init_stream_processor = __esm({
8318
8318
  inFlightExecutions = /* @__PURE__ */ new Map();
8319
8319
  /** Queue of completed gadget results ready to be yielded (for real-time streaming) */
8320
8320
  completedResultsQueue = [];
8321
+ // Concurrency limiting
8322
+ /** Subagent configuration map for checking maxConcurrent limits */
8323
+ subagentConfig;
8324
+ /** Track active execution count per gadget name */
8325
+ activeCountByGadget = /* @__PURE__ */ new Map();
8326
+ /** Queue of gadgets waiting for a concurrency slot (per gadget name) */
8327
+ concurrencyQueue = /* @__PURE__ */ new Map();
8321
8328
  // Cross-iteration dependency tracking
8322
8329
  /** Invocation IDs completed in previous iterations (read-only reference from Agent) */
8323
8330
  priorCompletedInvocations;
@@ -8333,6 +8340,7 @@ var init_stream_processor = __esm({
8333
8340
  this.baseDepth = options.baseDepth ?? 0;
8334
8341
  this.priorCompletedInvocations = options.priorCompletedInvocations ?? /* @__PURE__ */ new Set();
8335
8342
  this.priorFailedInvocations = options.priorFailedInvocations ?? /* @__PURE__ */ new Set();
8343
+ this.subagentConfig = options.subagentConfig;
8336
8344
  this.parser = new GadgetCallParser({
8337
8345
  startPrefix: options.gadgetStartPrefix,
8338
8346
  endPrefix: options.gadgetEndPrefix,
@@ -8596,9 +8604,63 @@ var init_stream_processor = __esm({
8596
8604
  }
8597
8605
  return;
8598
8606
  }
8599
- const executionPromise = this.executeGadgetAndCollect(call);
8607
+ const limit = this.getConcurrencyLimit(call.gadgetName);
8608
+ const activeCount = this.activeCountByGadget.get(call.gadgetName) ?? 0;
8609
+ if (limit > 0 && activeCount >= limit) {
8610
+ this.logger.debug("Gadget queued due to concurrency limit", {
8611
+ gadgetName: call.gadgetName,
8612
+ invocationId: call.invocationId,
8613
+ activeCount,
8614
+ limit
8615
+ });
8616
+ const queue = this.concurrencyQueue.get(call.gadgetName) ?? [];
8617
+ queue.push(call);
8618
+ this.concurrencyQueue.set(call.gadgetName, queue);
8619
+ return;
8620
+ }
8621
+ this.startGadgetWithConcurrencyTracking(call);
8622
+ }
8623
+ /**
8624
+ * Get the concurrency limit for a gadget from subagent config.
8625
+ * Returns 0 if no limit is set (unlimited).
8626
+ */
8627
+ getConcurrencyLimit(gadgetName) {
8628
+ const config = this.subagentConfig?.[gadgetName];
8629
+ return config?.maxConcurrent ?? 0;
8630
+ }
8631
+ /**
8632
+ * Start a gadget execution with concurrency tracking.
8633
+ * Increments active count, starts execution, and schedules queue processing on completion.
8634
+ */
8635
+ startGadgetWithConcurrencyTracking(call) {
8636
+ const gadgetName = call.gadgetName;
8637
+ const currentCount = this.activeCountByGadget.get(gadgetName) ?? 0;
8638
+ this.activeCountByGadget.set(gadgetName, currentCount + 1);
8639
+ const executionPromise = this.executeGadgetAndCollect(call).finally(() => {
8640
+ const newCount = (this.activeCountByGadget.get(gadgetName) ?? 1) - 1;
8641
+ this.activeCountByGadget.set(gadgetName, newCount);
8642
+ this.processQueuedGadget(gadgetName);
8643
+ });
8600
8644
  this.inFlightExecutions.set(call.invocationId, executionPromise);
8601
8645
  }
8646
+ /**
8647
+ * Process the next queued gadget for a given gadget name if a slot is available.
8648
+ */
8649
+ processQueuedGadget(gadgetName) {
8650
+ const queue = this.concurrencyQueue.get(gadgetName);
8651
+ if (!queue || queue.length === 0) return;
8652
+ const limit = this.getConcurrencyLimit(gadgetName);
8653
+ const activeCount = this.activeCountByGadget.get(gadgetName) ?? 0;
8654
+ if (limit === 0 || activeCount < limit) {
8655
+ const nextCall = queue.shift();
8656
+ this.logger.debug("Processing queued gadget", {
8657
+ gadgetName,
8658
+ invocationId: nextCall.invocationId,
8659
+ remainingInQueue: queue.length
8660
+ });
8661
+ this.startGadgetWithConcurrencyTracking(nextCall);
8662
+ }
8663
+ }
8602
8664
  /**
8603
8665
  * Execute a gadget through the full hook lifecycle and yield events.
8604
8666
  * Handles parameter interception, before/after controllers, observers,
@@ -8786,27 +8848,58 @@ var init_stream_processor = __esm({
8786
8848
  * Clears the inFlightExecutions map after all gadgets complete.
8787
8849
  */
8788
8850
  async *waitForInFlightExecutions() {
8789
- if (this.inFlightExecutions.size === 0) {
8851
+ if (this.inFlightExecutions.size === 0 && !this.hasQueuedGadgets()) {
8790
8852
  return;
8791
8853
  }
8792
8854
  this.logger.debug("Waiting for in-flight gadget executions", {
8793
8855
  count: this.inFlightExecutions.size,
8794
- invocationIds: Array.from(this.inFlightExecutions.keys())
8856
+ invocationIds: Array.from(this.inFlightExecutions.keys()),
8857
+ queuedCount: this.getQueuedGadgetCount()
8795
8858
  });
8796
- const allDone = Promise.all(this.inFlightExecutions.values()).then(() => "done");
8797
8859
  const POLL_INTERVAL_MS = 100;
8798
- while (true) {
8860
+ while (this.inFlightExecutions.size > 0 || this.hasQueuedGadgets()) {
8861
+ const allDone = this.inFlightExecutions.size > 0 ? Promise.all(this.inFlightExecutions.values()).then(() => "done") : Promise.resolve("done");
8799
8862
  const result = await Promise.race([
8800
8863
  allDone,
8801
8864
  new Promise((resolve) => setTimeout(() => resolve("poll"), POLL_INTERVAL_MS))
8802
8865
  ]);
8803
8866
  yield* this.drainCompletedResults();
8804
- if (result === "done") {
8867
+ if (result === "done" && this.getTotalActiveGadgetCount() === 0 && !this.hasQueuedGadgets()) {
8805
8868
  break;
8806
8869
  }
8807
8870
  }
8808
8871
  this.inFlightExecutions.clear();
8809
8872
  }
8873
+ /**
8874
+ * Check if there are any gadgets waiting in concurrency queues.
8875
+ */
8876
+ hasQueuedGadgets() {
8877
+ for (const queue of this.concurrencyQueue.values()) {
8878
+ if (queue.length > 0) return true;
8879
+ }
8880
+ return false;
8881
+ }
8882
+ /**
8883
+ * Get total count of queued gadgets across all queues.
8884
+ */
8885
+ getQueuedGadgetCount() {
8886
+ let count = 0;
8887
+ for (const queue of this.concurrencyQueue.values()) {
8888
+ count += queue.length;
8889
+ }
8890
+ return count;
8891
+ }
8892
+ /**
8893
+ * Get total count of actively executing gadgets across all types.
8894
+ * Used to know when all work is truly complete (not just when allDone resolves).
8895
+ */
8896
+ getTotalActiveGadgetCount() {
8897
+ let total = 0;
8898
+ for (const count of this.activeCountByGadget.values()) {
8899
+ total += count;
8900
+ }
8901
+ return total;
8902
+ }
8810
8903
  /**
8811
8904
  * Handle a gadget that cannot execute because a dependency failed.
8812
8905
  * Calls the onDependencySkipped controller to allow customization.
@@ -10636,6 +10729,9 @@ var init_builder = __esm({
10636
10729
  * **Signal Forwarding** - When parent context includes a signal, it's automatically
10637
10730
  * forwarded to the subagent for proper cancellation propagation.
10638
10731
  *
10732
+ * **Logger Inheritance** - When parent context includes a logger, it's inherited
10733
+ * by the subagent for consistent structured logging.
10734
+ *
10639
10735
  * @param ctx - ExecutionContext passed to the gadget's execute() method
10640
10736
  * @param depth - Nesting depth (default: 1 for direct child)
10641
10737
  * @returns This builder for chaining
@@ -10675,6 +10771,9 @@ var init_builder = __esm({
10675
10771
  if (ctx.signal && !this.signal) {
10676
10772
  this.signal = ctx.signal;
10677
10773
  }
10774
+ if (ctx.logger && !this.logger) {
10775
+ this.logger = ctx.logger;
10776
+ }
10678
10777
  return this;
10679
10778
  }
10680
10779
  /**