llmist 15.14.2 → 15.15.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 +154 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -2
- package/dist/index.d.ts +40 -2
- package/dist/index.js +154 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -10625,6 +10625,7 @@ var init_builder = __esm({
|
|
|
10625
10625
|
textWithGadgetsHandler;
|
|
10626
10626
|
defaultGadgetTimeoutMs;
|
|
10627
10627
|
gadgetExecutionMode;
|
|
10628
|
+
maxGadgetsPerResponse;
|
|
10628
10629
|
gadgetOutputLimit;
|
|
10629
10630
|
gadgetOutputLimitPercent;
|
|
10630
10631
|
compactionConfig;
|
|
@@ -11025,6 +11026,37 @@ var init_builder = __esm({
|
|
|
11025
11026
|
this.gadgetExecutionMode = mode;
|
|
11026
11027
|
return this;
|
|
11027
11028
|
}
|
|
11029
|
+
/**
|
|
11030
|
+
* Set the maximum number of gadgets to execute per LLM response.
|
|
11031
|
+
*
|
|
11032
|
+
* When the limit is reached, remaining gadgets are skipped with an informative
|
|
11033
|
+
* message visible to the LLM, allowing it to adjust on the next iteration.
|
|
11034
|
+
* Gadgets already in-flight (executing in parallel) are allowed to complete.
|
|
11035
|
+
*
|
|
11036
|
+
* @param max - Maximum gadgets per response (0 = unlimited, default)
|
|
11037
|
+
* @returns This builder for chaining
|
|
11038
|
+
* @throws {Error} If max is negative or non-integer
|
|
11039
|
+
*
|
|
11040
|
+
* @example
|
|
11041
|
+
* ```typescript
|
|
11042
|
+
* // Limit to 5 gadgets per response
|
|
11043
|
+
* LLMist.createAgent()
|
|
11044
|
+
* .withModel("sonnet")
|
|
11045
|
+
* .withGadgets(ReadFile, WriteFile, Search)
|
|
11046
|
+
* .withMaxGadgetsPerResponse(5)
|
|
11047
|
+
* .ask("Process these files...");
|
|
11048
|
+
* ```
|
|
11049
|
+
*/
|
|
11050
|
+
withMaxGadgetsPerResponse(max) {
|
|
11051
|
+
if (max < 0) {
|
|
11052
|
+
throw new Error("maxGadgetsPerResponse must be a non-negative number");
|
|
11053
|
+
}
|
|
11054
|
+
if (!Number.isInteger(max)) {
|
|
11055
|
+
throw new Error("maxGadgetsPerResponse must be an integer");
|
|
11056
|
+
}
|
|
11057
|
+
this.maxGadgetsPerResponse = max;
|
|
11058
|
+
return this;
|
|
11059
|
+
}
|
|
11028
11060
|
/**
|
|
11029
11061
|
* Enable or disable gadget output limiting.
|
|
11030
11062
|
*
|
|
@@ -11623,6 +11655,7 @@ ${endPrefix}`
|
|
|
11623
11655
|
textWithGadgetsHandler: this.textWithGadgetsHandler,
|
|
11624
11656
|
defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
|
|
11625
11657
|
gadgetExecutionMode: this.gadgetExecutionMode,
|
|
11658
|
+
maxGadgetsPerResponse: this.maxGadgetsPerResponse,
|
|
11626
11659
|
gadgetOutputLimit: this.gadgetOutputLimit,
|
|
11627
11660
|
gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,
|
|
11628
11661
|
compactionConfig: this.compactionConfig,
|
|
@@ -11812,6 +11845,7 @@ ${endPrefix}`
|
|
|
11812
11845
|
textWithGadgetsHandler: this.textWithGadgetsHandler,
|
|
11813
11846
|
defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
|
|
11814
11847
|
gadgetExecutionMode: this.gadgetExecutionMode,
|
|
11848
|
+
maxGadgetsPerResponse: this.maxGadgetsPerResponse,
|
|
11815
11849
|
gadgetOutputLimit: this.gadgetOutputLimit,
|
|
11816
11850
|
gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,
|
|
11817
11851
|
compactionConfig: this.compactionConfig,
|
|
@@ -13449,6 +13483,9 @@ var init_stream_processor = __esm({
|
|
|
13449
13483
|
priorFailedInvocations;
|
|
13450
13484
|
// Parent observer hooks for subagent visibility
|
|
13451
13485
|
parentObservers;
|
|
13486
|
+
// Gadget limiting per response
|
|
13487
|
+
maxGadgetsPerResponse;
|
|
13488
|
+
gadgetStartedCount = 0;
|
|
13452
13489
|
constructor(options) {
|
|
13453
13490
|
this.iteration = options.iteration;
|
|
13454
13491
|
this.registry = options.registry;
|
|
@@ -13462,6 +13499,7 @@ var init_stream_processor = __esm({
|
|
|
13462
13499
|
this.priorFailedInvocations = options.priorFailedInvocations ?? /* @__PURE__ */ new Set();
|
|
13463
13500
|
this.subagentConfig = options.subagentConfig;
|
|
13464
13501
|
this.parentObservers = options.parentObservers;
|
|
13502
|
+
this.maxGadgetsPerResponse = options.maxGadgetsPerResponse ?? 0;
|
|
13465
13503
|
this.parser = new GadgetCallParser({
|
|
13466
13504
|
startPrefix: options.gadgetStartPrefix,
|
|
13467
13505
|
endPrefix: options.gadgetEndPrefix,
|
|
@@ -13757,6 +13795,15 @@ var init_stream_processor = __esm({
|
|
|
13757
13795
|
this.gadgetsAwaitingDependencies.set(call.invocationId, call);
|
|
13758
13796
|
return;
|
|
13759
13797
|
}
|
|
13798
|
+
const limitCheckGen2 = this.checkGadgetLimitExceeded(call);
|
|
13799
|
+
let limitResult2 = await limitCheckGen2.next();
|
|
13800
|
+
while (!limitResult2.done) {
|
|
13801
|
+
yield limitResult2.value;
|
|
13802
|
+
limitResult2 = await limitCheckGen2.next();
|
|
13803
|
+
}
|
|
13804
|
+
if (limitResult2.value === true) {
|
|
13805
|
+
return;
|
|
13806
|
+
}
|
|
13760
13807
|
for await (const evt of this.executeGadgetGenerator(call)) {
|
|
13761
13808
|
yield evt;
|
|
13762
13809
|
}
|
|
@@ -13765,6 +13812,15 @@ var init_stream_processor = __esm({
|
|
|
13765
13812
|
}
|
|
13766
13813
|
return;
|
|
13767
13814
|
}
|
|
13815
|
+
const limitCheckGen = this.checkGadgetLimitExceeded(call);
|
|
13816
|
+
let limitResult = await limitCheckGen.next();
|
|
13817
|
+
while (!limitResult.done) {
|
|
13818
|
+
yield limitResult.value;
|
|
13819
|
+
limitResult = await limitCheckGen.next();
|
|
13820
|
+
}
|
|
13821
|
+
if (limitResult.value === true) {
|
|
13822
|
+
return;
|
|
13823
|
+
}
|
|
13768
13824
|
const limit = this.getConcurrencyLimit(call.gadgetName);
|
|
13769
13825
|
const activeCount = this.activeCountByGadget.get(call.gadgetName) ?? 0;
|
|
13770
13826
|
if (limit > 0 && activeCount >= limit) {
|
|
@@ -14200,6 +14256,80 @@ var init_stream_processor = __esm({
|
|
|
14200
14256
|
}
|
|
14201
14257
|
return events;
|
|
14202
14258
|
}
|
|
14259
|
+
/**
|
|
14260
|
+
* Check if gadget execution should be skipped due to maxGadgetsPerResponse limit.
|
|
14261
|
+
* If limit is exceeded, yields skip events and returns true.
|
|
14262
|
+
* If execution can proceed, increments counter and returns false.
|
|
14263
|
+
*
|
|
14264
|
+
* @returns true if gadget should be skipped, false if execution can proceed
|
|
14265
|
+
*/
|
|
14266
|
+
async *checkGadgetLimitExceeded(call) {
|
|
14267
|
+
if (this.maxGadgetsPerResponse <= 0) {
|
|
14268
|
+
this.gadgetStartedCount++;
|
|
14269
|
+
return false;
|
|
14270
|
+
}
|
|
14271
|
+
if (this.gadgetStartedCount >= this.maxGadgetsPerResponse) {
|
|
14272
|
+
const errorMessage = `Gadget limit (${this.maxGadgetsPerResponse}) exceeded. Consider calling fewer gadgets per response.`;
|
|
14273
|
+
this.logger.info("Gadget skipped due to maxGadgetsPerResponse limit", {
|
|
14274
|
+
gadgetName: call.gadgetName,
|
|
14275
|
+
invocationId: call.invocationId,
|
|
14276
|
+
limit: this.maxGadgetsPerResponse,
|
|
14277
|
+
currentCount: this.gadgetStartedCount
|
|
14278
|
+
});
|
|
14279
|
+
this.failedInvocations.add(call.invocationId);
|
|
14280
|
+
if (this.tree) {
|
|
14281
|
+
const gadgetNode = this.tree.getNodeByInvocationId(call.invocationId);
|
|
14282
|
+
if (gadgetNode) {
|
|
14283
|
+
this.tree.skipGadget(
|
|
14284
|
+
gadgetNode.id,
|
|
14285
|
+
"maxGadgetsPerResponse",
|
|
14286
|
+
errorMessage,
|
|
14287
|
+
"limit_exceeded"
|
|
14288
|
+
);
|
|
14289
|
+
}
|
|
14290
|
+
}
|
|
14291
|
+
const skipEvent = {
|
|
14292
|
+
type: "gadget_skipped",
|
|
14293
|
+
gadgetName: call.gadgetName,
|
|
14294
|
+
invocationId: call.invocationId,
|
|
14295
|
+
parameters: call.parameters ?? {},
|
|
14296
|
+
failedDependency: "maxGadgetsPerResponse",
|
|
14297
|
+
failedDependencyError: errorMessage
|
|
14298
|
+
};
|
|
14299
|
+
yield skipEvent;
|
|
14300
|
+
const limitSkipNode = this.tree?.getNodeByInvocationId(call.invocationId);
|
|
14301
|
+
const limitSkipSubagentContext = this.tree && limitSkipNode ? getSubagentContextForNode(this.tree, limitSkipNode.id) : void 0;
|
|
14302
|
+
if (this.hooks.observers?.onGadgetSkipped) {
|
|
14303
|
+
const context = {
|
|
14304
|
+
iteration: this.iteration,
|
|
14305
|
+
gadgetName: call.gadgetName,
|
|
14306
|
+
invocationId: call.invocationId,
|
|
14307
|
+
parameters: call.parameters ?? {},
|
|
14308
|
+
failedDependency: "maxGadgetsPerResponse",
|
|
14309
|
+
failedDependencyError: errorMessage,
|
|
14310
|
+
logger: this.logger,
|
|
14311
|
+
subagentContext: limitSkipSubagentContext
|
|
14312
|
+
};
|
|
14313
|
+
await this.safeObserve(() => this.hooks.observers.onGadgetSkipped(context));
|
|
14314
|
+
}
|
|
14315
|
+
if (this.parentObservers?.onGadgetSkipped) {
|
|
14316
|
+
const context = {
|
|
14317
|
+
iteration: this.iteration,
|
|
14318
|
+
gadgetName: call.gadgetName,
|
|
14319
|
+
invocationId: call.invocationId,
|
|
14320
|
+
parameters: call.parameters ?? {},
|
|
14321
|
+
failedDependency: "maxGadgetsPerResponse",
|
|
14322
|
+
failedDependencyError: errorMessage,
|
|
14323
|
+
logger: this.logger,
|
|
14324
|
+
subagentContext: limitSkipSubagentContext
|
|
14325
|
+
};
|
|
14326
|
+
await this.safeObserve(() => this.parentObservers.onGadgetSkipped(context));
|
|
14327
|
+
}
|
|
14328
|
+
return true;
|
|
14329
|
+
}
|
|
14330
|
+
this.gadgetStartedCount++;
|
|
14331
|
+
return false;
|
|
14332
|
+
}
|
|
14203
14333
|
/**
|
|
14204
14334
|
* Process pending gadgets whose dependencies are now satisfied.
|
|
14205
14335
|
* Yields events in real-time as gadgets complete.
|
|
@@ -14246,6 +14376,15 @@ var init_stream_processor = __esm({
|
|
|
14246
14376
|
invocationIds: readyToExecute.map((c) => c.invocationId)
|
|
14247
14377
|
});
|
|
14248
14378
|
for (const call of readyToExecute) {
|
|
14379
|
+
const limitCheckGen = this.checkGadgetLimitExceeded(call);
|
|
14380
|
+
let limitResult = await limitCheckGen.next();
|
|
14381
|
+
while (!limitResult.done) {
|
|
14382
|
+
yield limitResult.value;
|
|
14383
|
+
limitResult = await limitCheckGen.next();
|
|
14384
|
+
}
|
|
14385
|
+
if (limitResult.value === true) {
|
|
14386
|
+
continue;
|
|
14387
|
+
}
|
|
14249
14388
|
for await (const evt of this.executeGadgetGenerator(call)) {
|
|
14250
14389
|
yield evt;
|
|
14251
14390
|
}
|
|
@@ -14258,6 +14397,15 @@ var init_stream_processor = __esm({
|
|
|
14258
14397
|
const eventSets = await Promise.all(
|
|
14259
14398
|
readyToExecute.map(async (call) => {
|
|
14260
14399
|
const events = [];
|
|
14400
|
+
const limitCheckGen = this.checkGadgetLimitExceeded(call);
|
|
14401
|
+
let limitResult = await limitCheckGen.next();
|
|
14402
|
+
while (!limitResult.done) {
|
|
14403
|
+
events.push(limitResult.value);
|
|
14404
|
+
limitResult = await limitCheckGen.next();
|
|
14405
|
+
}
|
|
14406
|
+
if (limitResult.value === true) {
|
|
14407
|
+
return events;
|
|
14408
|
+
}
|
|
14261
14409
|
for await (const evt of this.executeGadgetGenerator(call)) {
|
|
14262
14410
|
events.push(evt);
|
|
14263
14411
|
}
|
|
@@ -14443,6 +14591,8 @@ var init_agent = __esm({
|
|
|
14443
14591
|
// Subagent configuration
|
|
14444
14592
|
agentContextConfig;
|
|
14445
14593
|
subagentConfig;
|
|
14594
|
+
// Gadget limiting
|
|
14595
|
+
maxGadgetsPerResponse;
|
|
14446
14596
|
// Counter for generating synthetic invocation IDs for wrapped text content
|
|
14447
14597
|
syntheticInvocationCounter = 0;
|
|
14448
14598
|
// Cross-iteration dependency tracking - allows gadgets to depend on results from prior iterations
|
|
@@ -14543,6 +14693,7 @@ var init_agent = __esm({
|
|
|
14543
14693
|
temperature: this.temperature
|
|
14544
14694
|
};
|
|
14545
14695
|
this.subagentConfig = options.subagentConfig;
|
|
14696
|
+
this.maxGadgetsPerResponse = options.maxGadgetsPerResponse ?? 0;
|
|
14546
14697
|
this.tree = options.parentTree ?? new ExecutionTree();
|
|
14547
14698
|
this.parentNodeId = options.parentNodeId ?? null;
|
|
14548
14699
|
this.baseDepth = options.baseDepth ?? 0;
|
|
@@ -14830,7 +14981,9 @@ var init_agent = __esm({
|
|
|
14830
14981
|
parentObservers: this.parentObservers,
|
|
14831
14982
|
// Shared rate limit tracker and retry config for subagents
|
|
14832
14983
|
rateLimitTracker: this.rateLimitTracker,
|
|
14833
|
-
retryConfig: this.retryConfig
|
|
14984
|
+
retryConfig: this.retryConfig,
|
|
14985
|
+
// Gadget limiting
|
|
14986
|
+
maxGadgetsPerResponse: this.maxGadgetsPerResponse
|
|
14834
14987
|
});
|
|
14835
14988
|
for await (const event of processor.process(stream2)) {
|
|
14836
14989
|
if (event.type === "stream_complete") {
|