llmist 10.0.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
  }
@@ -7294,6 +7301,12 @@ declare class StreamProcessor {
7294
7301
  private inFlightExecutions;
7295
7302
  /** Queue of completed gadget results ready to be yielded (for real-time streaming) */
7296
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;
7297
7310
  /** Invocation IDs completed in previous iterations (read-only reference from Agent) */
7298
7311
  private readonly priorCompletedInvocations;
7299
7312
  /** Invocation IDs that failed in previous iterations (read-only reference from Agent) */
@@ -7325,6 +7338,20 @@ declare class StreamProcessor {
7325
7338
  * enabling real-time UI feedback.
7326
7339
  */
7327
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;
7328
7355
  /**
7329
7356
  * Execute a gadget through the full hook lifecycle and yield events.
7330
7357
  * Handles parameter interception, before/after controllers, observers,
@@ -7352,6 +7379,19 @@ declare class StreamProcessor {
7352
7379
  * Clears the inFlightExecutions map after all gadgets complete.
7353
7380
  */
7354
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;
7355
7395
  /**
7356
7396
  * Handle a gadget that cannot execute because a dependency failed.
7357
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
  }
@@ -7294,6 +7301,12 @@ declare class StreamProcessor {
7294
7301
  private inFlightExecutions;
7295
7302
  /** Queue of completed gadget results ready to be yielded (for real-time streaming) */
7296
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;
7297
7310
  /** Invocation IDs completed in previous iterations (read-only reference from Agent) */
7298
7311
  private readonly priorCompletedInvocations;
7299
7312
  /** Invocation IDs that failed in previous iterations (read-only reference from Agent) */
@@ -7325,6 +7338,20 @@ declare class StreamProcessor {
7325
7338
  * enabling real-time UI feedback.
7326
7339
  */
7327
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;
7328
7355
  /**
7329
7356
  * Execute a gadget through the full hook lifecycle and yield events.
7330
7357
  * Handles parameter interception, before/after controllers, observers,
@@ -7352,6 +7379,19 @@ declare class StreamProcessor {
7352
7379
  * Clears the inFlightExecutions map after all gadgets complete.
7353
7380
  */
7354
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;
7355
7395
  /**
7356
7396
  * Handle a gadget that cannot execute because a dependency failed.
7357
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.