llmist 16.0.4 → 16.2.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
@@ -632,8 +632,6 @@ interface CompleteGadgetParams {
632
632
  storedMedia?: StoredMedia[];
633
633
  }
634
634
 
635
- /** Event listener function type */
636
- type EventListener = (event: ExecutionEvent) => void;
637
635
  /**
638
636
  * The Execution Tree - single source of truth for all execution state.
639
637
  *
@@ -668,12 +666,9 @@ type EventListener = (event: ExecutionEvent) => void;
668
666
  declare class ExecutionTree {
669
667
  private nodes;
670
668
  private rootIds;
671
- private eventListeners;
672
- private eventIdCounter;
673
669
  private invocationIdToNodeId;
674
- private eventQueue;
675
- private eventWaiters;
676
- private isCompleted;
670
+ private emitter;
671
+ private aggregator;
677
672
  /**
678
673
  * Base depth for all nodes in this tree.
679
674
  * Used when this tree is a subagent's view into a parent tree.
@@ -831,11 +826,11 @@ declare class ExecutionTree {
831
826
  * });
832
827
  * ```
833
828
  */
834
- on(type: ExecutionEventType, listener: EventListener): () => void;
829
+ on(type: ExecutionEventType, listener: (event: ExecutionEvent) => void): () => void;
835
830
  /**
836
831
  * Subscribe to all events.
837
832
  */
838
- onAll(listener: EventListener): () => void;
833
+ onAll(listener: (event: ExecutionEvent) => void): () => void;
839
834
  /**
840
835
  * Get async iterable of all events.
841
836
  * Events are yielded as they occur.
@@ -843,6 +838,7 @@ declare class ExecutionTree {
843
838
  events(): AsyncGenerator<ExecutionEvent>;
844
839
  /**
845
840
  * Mark the tree as complete (no more events will be emitted).
841
+ * Wakes up any consumers waiting in the events() async generator.
846
842
  */
847
843
  complete(): void;
848
844
  /**
@@ -1127,7 +1123,6 @@ declare function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>):
1127
1123
  throwIfAborted(ctx?: ExecutionContext): void;
1128
1124
  onAbort(ctx: ExecutionContext | undefined, cleanup: () => void | Promise<void>): void;
1129
1125
  createLinkedAbortController(ctx?: ExecutionContext): AbortController;
1130
- get instruction(): string;
1131
1126
  getInstruction(optionsOrArgPrefix?: string | {
1132
1127
  argPrefix?: string;
1133
1128
  startPrefix?: string;
@@ -1138,6 +1133,253 @@ declare function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>):
1138
1133
  };
1139
1134
  };
1140
1135
 
1136
+ /**
1137
+ * Proactive rate limiting for LLM API calls.
1138
+ *
1139
+ * Tracks request and token usage in sliding windows to prevent rate limit errors
1140
+ * before they occur. Works in conjunction with reactive backoff (retry.ts) for
1141
+ * comprehensive rate limit handling.
1142
+ */
1143
+ /**
1144
+ * Configuration for proactive rate limiting.
1145
+ *
1146
+ * Set these values based on your API tier to prevent rate limit errors.
1147
+ * When limits are approached, requests will be automatically delayed.
1148
+ *
1149
+ * @example
1150
+ * ```typescript
1151
+ * // Gemini free tier limits
1152
+ * const agent = LLMist.createAgent()
1153
+ * .withRateLimits({
1154
+ * requestsPerMinute: 15,
1155
+ * tokensPerMinute: 1_000_000,
1156
+ * safetyMargin: 0.8,
1157
+ * });
1158
+ *
1159
+ * // OpenAI Tier 1 limits
1160
+ * const agent = LLMist.createAgent()
1161
+ * .withRateLimits({
1162
+ * requestsPerMinute: 500,
1163
+ * tokensPerMinute: 200_000,
1164
+ * });
1165
+ * ```
1166
+ */
1167
+ interface RateLimitConfig {
1168
+ /**
1169
+ * Maximum requests per minute.
1170
+ * Set based on your API tier. If not set, RPM limiting is disabled.
1171
+ */
1172
+ requestsPerMinute?: number;
1173
+ /**
1174
+ * Maximum tokens per minute (input + output combined).
1175
+ * Set based on your API tier. If not set, TPM limiting is disabled.
1176
+ */
1177
+ tokensPerMinute?: number;
1178
+ /**
1179
+ * Maximum tokens per day (optional).
1180
+ * Useful for Gemini free tier which has daily limits.
1181
+ * If not set, daily limiting is disabled.
1182
+ */
1183
+ tokensPerDay?: number;
1184
+ /**
1185
+ * Safety margin - start throttling at this percentage of limit.
1186
+ * A value of 0.9 means throttling starts at 90% of the limit.
1187
+ * Lower values provide more safety but may reduce throughput.
1188
+ * @default 0.9
1189
+ */
1190
+ safetyMargin?: number;
1191
+ /**
1192
+ * Whether proactive rate limiting is enabled.
1193
+ * @default true (when any limit is configured)
1194
+ */
1195
+ enabled?: boolean;
1196
+ }
1197
+ /**
1198
+ * Resolved rate limit configuration with all defaults applied.
1199
+ */
1200
+ interface ResolvedRateLimitConfig {
1201
+ requestsPerMinute?: number;
1202
+ tokensPerMinute?: number;
1203
+ tokensPerDay?: number;
1204
+ safetyMargin: number;
1205
+ enabled: boolean;
1206
+ }
1207
+ /**
1208
+ * Default rate limit configuration values.
1209
+ */
1210
+ declare const DEFAULT_RATE_LIMIT_CONFIG: Pick<ResolvedRateLimitConfig, "safetyMargin" | "enabled">;
1211
+ /**
1212
+ * Resolves a partial rate limit configuration by applying defaults.
1213
+ *
1214
+ * @param config - Partial configuration (optional)
1215
+ * @returns Fully resolved configuration
1216
+ */
1217
+ declare function resolveRateLimitConfig(config?: RateLimitConfig): ResolvedRateLimitConfig;
1218
+ /**
1219
+ * Information about a triggered rate limit.
1220
+ */
1221
+ interface TriggeredLimitInfo {
1222
+ /** Current usage value */
1223
+ current: number;
1224
+ /** Configured limit value */
1225
+ limit: number;
1226
+ /** Effective limit after safety margin (limit × safetyMargin) */
1227
+ effectiveLimit: number;
1228
+ }
1229
+ /**
1230
+ * Usage statistics from the rate limit tracker.
1231
+ */
1232
+ interface RateLimitStats {
1233
+ /** Current requests per minute */
1234
+ rpm: number;
1235
+ /** Current tokens per minute */
1236
+ tpm: number;
1237
+ /** Tokens used today (UTC) */
1238
+ dailyTokens: number;
1239
+ /** Whether any limit is currently being approached */
1240
+ isApproachingLimit: boolean;
1241
+ /** Delay required before next request (0 if none) */
1242
+ requiredDelayMs: number;
1243
+ /** Which limit(s) triggered throttling, if any (present when requiredDelayMs > 0) */
1244
+ triggeredBy?: {
1245
+ rpm?: TriggeredLimitInfo;
1246
+ tpm?: TriggeredLimitInfo;
1247
+ daily?: TriggeredLimitInfo;
1248
+ };
1249
+ }
1250
+ /**
1251
+ * Tracks API usage and calculates required delays for proactive rate limiting.
1252
+ *
1253
+ * Uses sliding windows to track requests and token usage, automatically
1254
+ * calculating delays needed to stay within configured limits.
1255
+ *
1256
+ * @example
1257
+ * ```typescript
1258
+ * const tracker = new RateLimitTracker({
1259
+ * requestsPerMinute: 60,
1260
+ * tokensPerMinute: 100000,
1261
+ * });
1262
+ *
1263
+ * // Before each request
1264
+ * const delay = tracker.getRequiredDelayMs();
1265
+ * if (delay > 0) {
1266
+ * await sleep(delay);
1267
+ * }
1268
+ *
1269
+ * // After each request
1270
+ * tracker.recordUsage(inputTokens, outputTokens);
1271
+ * ```
1272
+ */
1273
+ declare class RateLimitTracker {
1274
+ private config;
1275
+ /** Timestamps of requests in the current minute window */
1276
+ private requestTimestamps;
1277
+ /** Token usage entries in the current minute window */
1278
+ private tokenUsage;
1279
+ /** Daily token count */
1280
+ private dailyTokens;
1281
+ /** Date string (YYYY-MM-DD UTC) for daily reset tracking */
1282
+ private dailyResetDate;
1283
+ /** Count of pending reservations (for backward compatibility) */
1284
+ private pendingReservations;
1285
+ constructor(config?: RateLimitConfig);
1286
+ /**
1287
+ * Record a completed request with its token usage.
1288
+ *
1289
+ * If reserveRequest() was called before the LLM call (recommended for concurrent
1290
+ * scenarios), the request timestamp was already recorded. Otherwise, this method
1291
+ * will add it for backward compatibility.
1292
+ *
1293
+ * @param inputTokens - Number of input tokens used
1294
+ * @param outputTokens - Number of output tokens generated
1295
+ */
1296
+ recordUsage(inputTokens: number, outputTokens: number): void;
1297
+ /**
1298
+ * Calculate the delay needed before the next request.
1299
+ *
1300
+ * Returns 0 if no delay is needed, otherwise returns the number of
1301
+ * milliseconds to wait to stay within rate limits.
1302
+ *
1303
+ * @returns Delay in milliseconds (0 if none needed)
1304
+ */
1305
+ getRequiredDelayMs(): number;
1306
+ /**
1307
+ * Check if we're approaching any configured limits.
1308
+ *
1309
+ * @returns true if any limit is at or above the safety margin threshold
1310
+ */
1311
+ isApproachingLimit(): boolean;
1312
+ /**
1313
+ * Get current usage statistics.
1314
+ *
1315
+ * @returns Current usage stats for monitoring/logging
1316
+ */
1317
+ getUsageStats(): RateLimitStats;
1318
+ /**
1319
+ * Reset all tracking state.
1320
+ * Useful for testing or when switching API keys/tiers.
1321
+ */
1322
+ reset(): void;
1323
+ /**
1324
+ * Update configuration dynamically.
1325
+ * Useful when API tier changes or for testing.
1326
+ *
1327
+ * @param config - New configuration to apply
1328
+ */
1329
+ updateConfig(config: RateLimitConfig): void;
1330
+ /**
1331
+ * Reserve a request slot before making an LLM call.
1332
+ *
1333
+ * This is critical for concurrent subagents sharing a rate limiter.
1334
+ * Without reservation, multiple subagents checking getRequiredDelayMs()
1335
+ * simultaneously would all see zero usage and proceed, causing rate limit errors.
1336
+ *
1337
+ * Call this AFTER waiting for getRequiredDelayMs() but BEFORE making the LLM call.
1338
+ * The reservation ensures subsequent concurrent checks see the pending request.
1339
+ *
1340
+ * @example
1341
+ * ```typescript
1342
+ * // Proactive rate limiting with reservation
1343
+ * const delay = tracker.getRequiredDelayMs();
1344
+ * if (delay > 0) await sleep(delay);
1345
+ *
1346
+ * tracker.reserveRequest(); // Claim slot BEFORE making call
1347
+ * try {
1348
+ * const result = await llm.call();
1349
+ * tracker.recordUsage(result.inputTokens, result.outputTokens);
1350
+ * } catch (error) {
1351
+ * // Request already reserved; recordUsage updates token count
1352
+ * throw error;
1353
+ * }
1354
+ * ```
1355
+ */
1356
+ reserveRequest(): void;
1357
+ /**
1358
+ * Calculate delay needed based on RPM limit.
1359
+ */
1360
+ private calculateRpmDelay;
1361
+ /**
1362
+ * Calculate delay needed based on TPM limit.
1363
+ */
1364
+ private calculateTpmDelay;
1365
+ /**
1366
+ * Remove entries older than 1 minute from the sliding window.
1367
+ */
1368
+ private pruneOldEntries;
1369
+ /**
1370
+ * Check if the day has changed (UTC) and reset daily counters.
1371
+ */
1372
+ private checkDailyReset;
1373
+ /**
1374
+ * Get current date in YYYY-MM-DD format (UTC).
1375
+ */
1376
+ private getCurrentDateUTC;
1377
+ /**
1378
+ * Calculate milliseconds until midnight UTC.
1379
+ */
1380
+ private getTimeUntilMidnightUTC;
1381
+ }
1382
+
1141
1383
  /**
1142
1384
  * Model Catalog Types
1143
1385
  *
@@ -1457,255 +1699,8 @@ interface ResolvedCompactionConfig {
1457
1699
  }
1458
1700
 
1459
1701
  /**
1460
- * Proactive rate limiting for LLM API calls.
1461
- *
1462
- * Tracks request and token usage in sliding windows to prevent rate limit errors
1463
- * before they occur. Works in conjunction with reactive backoff (retry.ts) for
1464
- * comprehensive rate limit handling.
1465
- */
1466
- /**
1467
- * Configuration for proactive rate limiting.
1468
- *
1469
- * Set these values based on your API tier to prevent rate limit errors.
1470
- * When limits are approached, requests will be automatically delayed.
1471
- *
1472
- * @example
1473
- * ```typescript
1474
- * // Gemini free tier limits
1475
- * const agent = LLMist.createAgent()
1476
- * .withRateLimits({
1477
- * requestsPerMinute: 15,
1478
- * tokensPerMinute: 1_000_000,
1479
- * safetyMargin: 0.8,
1480
- * });
1481
- *
1482
- * // OpenAI Tier 1 limits
1483
- * const agent = LLMist.createAgent()
1484
- * .withRateLimits({
1485
- * requestsPerMinute: 500,
1486
- * tokensPerMinute: 200_000,
1487
- * });
1488
- * ```
1489
- */
1490
- interface RateLimitConfig {
1491
- /**
1492
- * Maximum requests per minute.
1493
- * Set based on your API tier. If not set, RPM limiting is disabled.
1494
- */
1495
- requestsPerMinute?: number;
1496
- /**
1497
- * Maximum tokens per minute (input + output combined).
1498
- * Set based on your API tier. If not set, TPM limiting is disabled.
1499
- */
1500
- tokensPerMinute?: number;
1501
- /**
1502
- * Maximum tokens per day (optional).
1503
- * Useful for Gemini free tier which has daily limits.
1504
- * If not set, daily limiting is disabled.
1505
- */
1506
- tokensPerDay?: number;
1507
- /**
1508
- * Safety margin - start throttling at this percentage of limit.
1509
- * A value of 0.9 means throttling starts at 90% of the limit.
1510
- * Lower values provide more safety but may reduce throughput.
1511
- * @default 0.9
1512
- */
1513
- safetyMargin?: number;
1514
- /**
1515
- * Whether proactive rate limiting is enabled.
1516
- * @default true (when any limit is configured)
1517
- */
1518
- enabled?: boolean;
1519
- }
1520
- /**
1521
- * Resolved rate limit configuration with all defaults applied.
1522
- */
1523
- interface ResolvedRateLimitConfig {
1524
- requestsPerMinute?: number;
1525
- tokensPerMinute?: number;
1526
- tokensPerDay?: number;
1527
- safetyMargin: number;
1528
- enabled: boolean;
1529
- }
1530
- /**
1531
- * Default rate limit configuration values.
1532
- */
1533
- declare const DEFAULT_RATE_LIMIT_CONFIG: Pick<ResolvedRateLimitConfig, "safetyMargin" | "enabled">;
1534
- /**
1535
- * Resolves a partial rate limit configuration by applying defaults.
1536
- *
1537
- * @param config - Partial configuration (optional)
1538
- * @returns Fully resolved configuration
1539
- */
1540
- declare function resolveRateLimitConfig(config?: RateLimitConfig): ResolvedRateLimitConfig;
1541
- /**
1542
- * Information about a triggered rate limit.
1543
- */
1544
- interface TriggeredLimitInfo {
1545
- /** Current usage value */
1546
- current: number;
1547
- /** Configured limit value */
1548
- limit: number;
1549
- /** Effective limit after safety margin (limit × safetyMargin) */
1550
- effectiveLimit: number;
1551
- }
1552
- /**
1553
- * Usage statistics from the rate limit tracker.
1554
- */
1555
- interface RateLimitStats {
1556
- /** Current requests per minute */
1557
- rpm: number;
1558
- /** Current tokens per minute */
1559
- tpm: number;
1560
- /** Tokens used today (UTC) */
1561
- dailyTokens: number;
1562
- /** Whether any limit is currently being approached */
1563
- isApproachingLimit: boolean;
1564
- /** Delay required before next request (0 if none) */
1565
- requiredDelayMs: number;
1566
- /** Which limit(s) triggered throttling, if any (present when requiredDelayMs > 0) */
1567
- triggeredBy?: {
1568
- rpm?: TriggeredLimitInfo;
1569
- tpm?: TriggeredLimitInfo;
1570
- daily?: TriggeredLimitInfo;
1571
- };
1572
- }
1573
- /**
1574
- * Tracks API usage and calculates required delays for proactive rate limiting.
1575
- *
1576
- * Uses sliding windows to track requests and token usage, automatically
1577
- * calculating delays needed to stay within configured limits.
1578
- *
1579
- * @example
1580
- * ```typescript
1581
- * const tracker = new RateLimitTracker({
1582
- * requestsPerMinute: 60,
1583
- * tokensPerMinute: 100000,
1584
- * });
1585
- *
1586
- * // Before each request
1587
- * const delay = tracker.getRequiredDelayMs();
1588
- * if (delay > 0) {
1589
- * await sleep(delay);
1590
- * }
1591
- *
1592
- * // After each request
1593
- * tracker.recordUsage(inputTokens, outputTokens);
1594
- * ```
1595
- */
1596
- declare class RateLimitTracker {
1597
- private config;
1598
- /** Timestamps of requests in the current minute window */
1599
- private requestTimestamps;
1600
- /** Token usage entries in the current minute window */
1601
- private tokenUsage;
1602
- /** Daily token count */
1603
- private dailyTokens;
1604
- /** Date string (YYYY-MM-DD UTC) for daily reset tracking */
1605
- private dailyResetDate;
1606
- /** Count of pending reservations (for backward compatibility) */
1607
- private pendingReservations;
1608
- constructor(config?: RateLimitConfig);
1609
- /**
1610
- * Record a completed request with its token usage.
1611
- *
1612
- * If reserveRequest() was called before the LLM call (recommended for concurrent
1613
- * scenarios), the request timestamp was already recorded. Otherwise, this method
1614
- * will add it for backward compatibility.
1615
- *
1616
- * @param inputTokens - Number of input tokens used
1617
- * @param outputTokens - Number of output tokens generated
1618
- */
1619
- recordUsage(inputTokens: number, outputTokens: number): void;
1620
- /**
1621
- * Calculate the delay needed before the next request.
1622
- *
1623
- * Returns 0 if no delay is needed, otherwise returns the number of
1624
- * milliseconds to wait to stay within rate limits.
1625
- *
1626
- * @returns Delay in milliseconds (0 if none needed)
1627
- */
1628
- getRequiredDelayMs(): number;
1629
- /**
1630
- * Check if we're approaching any configured limits.
1631
- *
1632
- * @returns true if any limit is at or above the safety margin threshold
1633
- */
1634
- isApproachingLimit(): boolean;
1635
- /**
1636
- * Get current usage statistics.
1637
- *
1638
- * @returns Current usage stats for monitoring/logging
1639
- */
1640
- getUsageStats(): RateLimitStats;
1641
- /**
1642
- * Reset all tracking state.
1643
- * Useful for testing or when switching API keys/tiers.
1644
- */
1645
- reset(): void;
1646
- /**
1647
- * Update configuration dynamically.
1648
- * Useful when API tier changes or for testing.
1649
- *
1650
- * @param config - New configuration to apply
1651
- */
1652
- updateConfig(config: RateLimitConfig): void;
1653
- /**
1654
- * Reserve a request slot before making an LLM call.
1655
- *
1656
- * This is critical for concurrent subagents sharing a rate limiter.
1657
- * Without reservation, multiple subagents checking getRequiredDelayMs()
1658
- * simultaneously would all see zero usage and proceed, causing rate limit errors.
1659
- *
1660
- * Call this AFTER waiting for getRequiredDelayMs() but BEFORE making the LLM call.
1661
- * The reservation ensures subsequent concurrent checks see the pending request.
1662
- *
1663
- * @example
1664
- * ```typescript
1665
- * // Proactive rate limiting with reservation
1666
- * const delay = tracker.getRequiredDelayMs();
1667
- * if (delay > 0) await sleep(delay);
1668
- *
1669
- * tracker.reserveRequest(); // Claim slot BEFORE making call
1670
- * try {
1671
- * const result = await llm.call();
1672
- * tracker.recordUsage(result.inputTokens, result.outputTokens);
1673
- * } catch (error) {
1674
- * // Request already reserved; recordUsage updates token count
1675
- * throw error;
1676
- * }
1677
- * ```
1678
- */
1679
- reserveRequest(): void;
1680
- /**
1681
- * Calculate delay needed based on RPM limit.
1682
- */
1683
- private calculateRpmDelay;
1684
- /**
1685
- * Calculate delay needed based on TPM limit.
1686
- */
1687
- private calculateTpmDelay;
1688
- /**
1689
- * Remove entries older than 1 minute from the sliding window.
1690
- */
1691
- private pruneOldEntries;
1692
- /**
1693
- * Check if the day has changed (UTC) and reset daily counters.
1694
- */
1695
- private checkDailyReset;
1696
- /**
1697
- * Get current date in YYYY-MM-DD format (UTC).
1698
- */
1699
- private getCurrentDateUTC;
1700
- /**
1701
- * Calculate milliseconds until midnight UTC.
1702
- */
1703
- private getTimeUntilMidnightUTC;
1704
- }
1705
-
1706
- /**
1707
- * Metadata present when an event originates from a subagent.
1708
- * Undefined for top-level agent events.
1702
+ * Metadata present when an event originates from a subagent.
1703
+ * Undefined for top-level agent events.
1709
1704
  *
1710
1705
  * When using subagent gadgets (like BrowseWeb), hook observers receive events
1711
1706
  * from both the main agent AND subagents. Check this context to distinguish.
@@ -1823,13 +1818,6 @@ interface ObserveGadgetCompleteContext {
1823
1818
  gadgetName: string;
1824
1819
  invocationId: string;
1825
1820
  parameters: Readonly<Record<string, unknown>>;
1826
- /**
1827
- * Original result before interceptors.
1828
- * @deprecated No longer populated. Use `finalResult` instead.
1829
- * With the unified event architecture, observers receive the final (post-interceptor)
1830
- * result from the ExecutionTree.
1831
- */
1832
- originalResult?: string;
1833
1821
  /** Final result after interceptors (the value stored in ExecutionTree) */
1834
1822
  finalResult?: string;
1835
1823
  error?: string;
@@ -1908,6 +1896,8 @@ interface Observers {
1908
1896
  onRateLimitThrottle?: (context: ObserveRateLimitThrottleContext) => void | Promise<void>;
1909
1897
  /** Called when a retry attempt is made after a failed LLM call */
1910
1898
  onRetryAttempt?: (context: ObserveRetryAttemptContext) => void | Promise<void>;
1899
+ /** Called when a skill is activated (via UseSkill gadget or pre-activation) */
1900
+ onSkillActivated?: (context: ObserveSkillActivatedContext) => void | Promise<void>;
1911
1901
  }
1912
1902
  /**
1913
1903
  * Context provided when context compaction occurs.
@@ -1976,24 +1966,71 @@ interface ObserveRetryAttemptContext {
1976
1966
  subagentContext?: SubagentContext;
1977
1967
  }
1978
1968
  /**
1979
- * Context for chunk interception.
1969
+ * Context provided when a skill is activated.
1970
+ * Read-only observation point.
1980
1971
  */
1981
- interface ChunkInterceptorContext {
1972
+ interface ObserveSkillActivatedContext {
1973
+ /** Name of the activated skill */
1974
+ skillName: string;
1975
+ /** Arguments passed to the skill (if any) */
1976
+ arguments?: string;
1977
+ /** Current iteration when activation occurred */
1982
1978
  iteration: number;
1983
- accumulatedText: string;
1979
+ /** Logger instance */
1984
1980
  logger: Logger<ILogObj>;
1985
1981
  }
1986
1982
  /**
1987
- * Context for message interception.
1983
+ * Context for skill activation controller.
1988
1984
  */
1989
- interface MessageInterceptorContext {
1985
+ interface SkillActivationControllerContext {
1986
+ /** Name of the skill being activated */
1987
+ skillName: string;
1988
+ /** Arguments passed to the skill */
1989
+ arguments?: string;
1990
+ /** Current iteration */
1990
1991
  iteration: number;
1991
- /** The raw LLM response */
1992
- rawResponse: string;
1992
+ /** Logger instance */
1993
1993
  logger: Logger<ILogObj>;
1994
1994
  }
1995
1995
  /**
1996
- * Context for gadget parameter interception.
1996
+ * Action returned by beforeSkillActivation controller.
1997
+ */
1998
+ type BeforeSkillActivationAction = {
1999
+ action: "proceed";
2000
+ } | {
2001
+ action: "skip";
2002
+ reason?: string;
2003
+ };
2004
+ /**
2005
+ * Context for skill instruction interception.
2006
+ */
2007
+ interface SkillInstructionInterceptorContext {
2008
+ /** Name of the skill being activated */
2009
+ skillName: string;
2010
+ /** Arguments passed to the skill */
2011
+ arguments?: string;
2012
+ /** Logger instance */
2013
+ logger: Logger<ILogObj>;
2014
+ }
2015
+ /**
2016
+ * Context for chunk interception.
2017
+ */
2018
+ interface ChunkInterceptorContext {
2019
+ iteration: number;
2020
+ accumulatedText: string;
2021
+ logger: Logger<ILogObj>;
2022
+ }
2023
+ /**
2024
+ * Context for message interception.
2025
+ */
2026
+ interface MessageInterceptorContext {
2027
+ iteration: number;
2028
+ /** The raw LLM response */
2029
+ rawResponse: string;
2030
+ logger: Logger<ILogObj>;
2031
+ }
2032
+ /**
2033
+ * Context for gadget parameter interception.
1997
2034
  */
1998
2035
  interface GadgetParameterInterceptorContext {
1999
2036
  iteration: number;
@@ -2067,6 +2104,14 @@ interface Interceptors {
2067
2104
  * @returns Transformed text (cannot be suppressed)
2068
2105
  */
2069
2106
  interceptGadgetResult?: (result: string, context: GadgetResultInterceptorContext) => string;
2107
+ /**
2108
+ * Intercept and transform skill instructions before they are returned to the LLM.
2109
+ *
2110
+ * @param instructions - The resolved skill instructions
2111
+ * @param context - Context including skill name and arguments
2112
+ * @returns Transformed instructions, or null to suppress the skill activation
2113
+ */
2114
+ interceptSkillInstructions?: (instructions: string, context: SkillInstructionInterceptorContext) => string | null;
2070
2115
  }
2071
2116
  /**
2072
2117
  * Context for LLM call controller.
@@ -2260,6 +2305,11 @@ interface Controllers {
2260
2305
  * Can override the default skip behavior to execute anyway or provide a fallback.
2261
2306
  */
2262
2307
  onDependencySkipped?: (context: DependencySkipControllerContext) => Promise<DependencySkipAction>;
2308
+ /**
2309
+ * Called before activating a skill.
2310
+ * Can skip the activation (e.g., for permission checks or cost limits).
2311
+ */
2312
+ beforeSkillActivation?: (context: SkillActivationControllerContext) => Promise<BeforeSkillActivationAction>;
2263
2313
  }
2264
2314
  /**
2265
2315
  * Clean hooks system with three distinct categories:
@@ -2942,302 +2992,113 @@ declare function parseRetryAfterHeader(value: string): number | null;
2942
2992
  declare function extractRetryAfterMs(error: Error): number | null;
2943
2993
 
2944
2994
  /**
2945
- * Example of gadget usage to help LLMs understand proper invocation.
2946
- *
2947
- * Examples are rendered alongside the schema in `getInstruction()` to provide
2948
- * concrete usage patterns for the LLM.
2995
+ * Subagent configuration types.
2949
2996
  *
2950
- * @template TParams - Inferred parameter type from Zod schema (defaults to Record<string, unknown>)
2997
+ * Simple config shapes passed to gadgets for subagent configuration.
2998
+ * No external dependencies — self-contained data shapes.
2951
2999
  *
2952
- * @example
2953
- * ```typescript
2954
- * const calculator = createGadget({
2955
- * schema: z.object({ a: z.number(), b: z.number() }),
2956
- * examples: [
2957
- * { params: { a: 5, b: 3 }, output: "8", comment: "Addition example" }
2958
- * ],
2959
- * // ...
2960
- * });
2961
- * ```
2962
- */
2963
- interface GadgetExample<TParams = Record<string, unknown>> {
2964
- /** Example parameter values (typed to match schema) */
2965
- params: TParams;
2966
- /** Optional expected output/result string */
2967
- output?: string;
2968
- /** Optional description explaining what this example demonstrates */
2969
- comment?: string;
2970
- }
2971
- /**
2972
- * Supported media types for gadget output.
2973
- * Extensible via union - add new types as needed.
3000
+ * @module
2974
3001
  */
2975
- type MediaKind = "image" | "audio" | "video" | "file";
2976
3002
  /**
2977
- * Type-specific metadata for media outputs.
2978
- * Extensible via index signature for future media types.
3003
+ * Parent agent configuration passed to gadgets.
3004
+ * Contains settings that subagents can inherit.
2979
3005
  */
2980
- interface MediaMetadata {
2981
- /** Width in pixels (images, video) */
2982
- width?: number;
2983
- /** Height in pixels (images, video) */
2984
- height?: number;
2985
- /** Duration in milliseconds (audio, video) */
2986
- durationMs?: number;
2987
- /** Allow additional metadata for future extensions */
2988
- [key: string]: unknown;
3006
+ interface AgentContextConfig {
3007
+ /** Model identifier used by the parent agent */
3008
+ model: string;
3009
+ /** Temperature setting used by the parent agent */
3010
+ temperature?: number;
2989
3011
  }
2990
3012
  /**
2991
- * Media output from a gadget execution.
2992
- * Supports images, audio, video, and arbitrary files.
3013
+ * Configuration for a single subagent.
3014
+ * Can be defined globally in `[subagents.Name]` or per-profile in `[profile.subagents.Name]`.
2993
3015
  *
2994
3016
  * @example
2995
- * ```typescript
2996
- * // Image output
2997
- * const imageOutput: GadgetMediaOutput = {
2998
- * kind: "image",
2999
- * data: base64EncodedPng,
3000
- * mimeType: "image/png",
3001
- * description: "Screenshot of webpage",
3002
- * metadata: { width: 1920, height: 1080 }
3003
- * };
3017
+ * ```toml
3018
+ * [subagents.BrowseWeb]
3019
+ * model = "inherit" # Use parent agent's model
3020
+ * maxIterations = 20
3021
+ * headless = true
3004
3022
  * ```
3005
3023
  */
3006
- interface GadgetMediaOutput {
3007
- /** Type of media (discriminator for type-specific handling) */
3008
- kind: MediaKind;
3009
- /** Base64-encoded media data */
3010
- data: string;
3011
- /** Full MIME type (e.g., "image/png", "audio/mp3", "video/mp4") */
3012
- mimeType: string;
3013
- /** Human-readable description of the media */
3014
- description?: string;
3015
- /** Type-specific metadata */
3016
- metadata?: MediaMetadata;
3017
- /** Optional filename to use when saving (if not provided, auto-generated) */
3018
- fileName?: string;
3024
+ interface SubagentConfig {
3025
+ /**
3026
+ * Model to use for this subagent.
3027
+ * - "inherit": Use parent agent's model (default behavior)
3028
+ * - Any model ID: Use specific model (e.g., "sonnet", "haiku", "gpt-4o")
3029
+ */
3030
+ model?: string;
3031
+ /** Maximum iterations for the subagent loop */
3032
+ maxIterations?: number;
3033
+ /** Budget limit in USD for the subagent */
3034
+ budget?: number;
3035
+ /**
3036
+ * Timeout for the subagent gadget execution in milliseconds.
3037
+ * Overrides the gadget's hardcoded timeoutMs when set.
3038
+ * Set to 0 to disable timeout for this gadget.
3039
+ */
3040
+ timeoutMs?: number;
3041
+ /**
3042
+ * Maximum number of concurrent executions allowed for this gadget.
3043
+ * When the limit is reached, additional calls are queued and processed
3044
+ * as earlier executions complete (FIFO order).
3045
+ * Set to 0 or omit to allow unlimited concurrent executions (default).
3046
+ */
3047
+ maxConcurrent?: number;
3048
+ /** Additional subagent-specific options */
3049
+ [key: string]: unknown;
3019
3050
  }
3020
3051
  /**
3021
- * Stored media item with metadata and file path.
3022
- *
3023
- * Created by MediaStore when a gadget returns media outputs.
3024
- * Contains the abstract ID, file path, and metadata for display.
3052
+ * Map of subagent names to their configurations.
3025
3053
  */
3026
- interface StoredMedia {
3027
- /** Unique ID for this media item (e.g., "media_a1b2c3") */
3028
- id: string;
3029
- /** Type of media */
3030
- kind: MediaKind;
3031
- /** Actual file path on disk (internal use) */
3032
- path: string;
3033
- /** MIME type */
3034
- mimeType: string;
3035
- /** File size in bytes */
3036
- sizeBytes: number;
3037
- /** Human-readable description */
3038
- description?: string;
3039
- /** Type-specific metadata */
3040
- metadata?: MediaMetadata;
3041
- /** Name of the gadget that created this media */
3042
- gadgetName: string;
3043
- /** When the media was stored */
3044
- createdAt: Date;
3045
- }
3046
- interface GadgetExecutionResult {
3047
- gadgetName: string;
3048
- invocationId: string;
3049
- parameters: Record<string, unknown>;
3050
- result?: string;
3051
- error?: string;
3052
- executionTimeMs: number;
3053
- breaksLoop?: boolean;
3054
- /** Cost of gadget execution in USD. Defaults to 0 if not provided by gadget. */
3055
- cost?: number;
3056
- /** Media outputs from the gadget (images, audio, video, files) */
3057
- media?: GadgetMediaOutput[];
3058
- /** Abstract IDs for media outputs (e.g., ["media_a1b2c3"]) */
3059
- mediaIds?: string[];
3060
- /** Stored media with paths (for CLI display) */
3061
- storedMedia?: StoredMedia[];
3062
- }
3054
+ type SubagentConfigMap = Record<string, SubagentConfig>;
3063
3055
  /**
3064
- * Result returned by gadget execute() method.
3065
- * Can be a simple string or an object with result and optional cost.
3056
+ * Gadget execution mode controlling how multiple gadgets are executed.
3066
3057
  *
3067
- * @example
3068
- * ```typescript
3069
- * // Simple string return (free gadget)
3070
- * execute: () => "result"
3058
+ * - `'parallel'` (default): Gadgets without dependencies execute concurrently (fire-and-forget).
3059
+ * This maximizes throughput but gadgets may complete in any order.
3071
3060
  *
3072
- * // Object return with cost
3073
- * execute: () => ({ result: "data", cost: 0.001 })
3074
- * ```
3075
- */
3076
- interface GadgetExecuteResult {
3077
- /** The execution result as a string */
3078
- result: string;
3079
- /** Optional cost in USD (e.g., 0.001 for $0.001) */
3080
- cost?: number;
3081
- }
3082
- /**
3083
- * Extended result type with media support.
3084
- * Use this when gadget returns images, audio, video, or files.
3061
+ * - `'sequential'`: Gadgets execute one at a time, each awaiting completion before the next starts.
3062
+ * Useful for:
3063
+ * - Gadgets with implicit ordering dependencies (e.g., file operations)
3064
+ * - Debugging and tracing execution flow
3065
+ * - Resource-constrained environments
3066
+ * - Ensuring deterministic execution order
3067
+ *
3068
+ * Note: Explicit `dependsOn` relationships are always respected regardless of mode.
3069
+ * Sequential mode effectively enforces a global `maxConcurrent: 1` for all gadgets.
3085
3070
  *
3086
3071
  * @example
3087
3072
  * ```typescript
3088
- * // Return with image
3089
- * execute: () => ({
3090
- * result: "Screenshot captured",
3091
- * media: [{
3092
- * kind: "image",
3093
- * data: base64EncodedPng,
3094
- * mimeType: "image/png",
3095
- * description: "Screenshot"
3096
- * }],
3097
- * cost: 0.001
3098
- * })
3073
+ * const agent = LLMist.createAgent()
3074
+ * .withModel("sonnet")
3075
+ * .withGadgets(FileReader, FileWriter)
3076
+ * .withGadgetExecutionMode('sequential') // Execute one at a time
3077
+ * .ask("Process files in order");
3099
3078
  * ```
3100
3079
  */
3101
- interface GadgetExecuteResultWithMedia {
3102
- /** The execution result as a string */
3103
- result: string;
3104
- /** Media outputs (images, audio, video, files) */
3105
- media?: GadgetMediaOutput[];
3106
- /** Optional cost in USD (e.g., 0.001 for $0.001) */
3107
- cost?: number;
3080
+ type GadgetExecutionMode = "parallel" | "sequential";
3081
+
3082
+ /**
3083
+ * Image generation namespace with automatic cost reporting.
3084
+ */
3085
+ interface CostReportingImageNamespace {
3086
+ /**
3087
+ * Generate images from a text prompt.
3088
+ * Costs are automatically reported to the execution context.
3089
+ */
3090
+ generate(options: ImageGenerationOptions): Promise<ImageGenerationResult>;
3108
3091
  }
3109
3092
  /**
3110
- * Union type for backwards-compatible execute() return type.
3111
- * Gadgets can return:
3112
- * - string (legacy, cost = 0)
3113
- * - GadgetExecuteResult (result + optional cost)
3114
- * - GadgetExecuteResultWithMedia (result + optional media + optional cost)
3093
+ * Speech generation namespace with automatic cost reporting.
3115
3094
  */
3116
- type GadgetExecuteReturn = string | GadgetExecuteResult | GadgetExecuteResultWithMedia;
3117
- interface ParsedGadgetCall {
3118
- gadgetName: string;
3119
- invocationId: string;
3120
- parametersRaw: string;
3121
- parameters?: Record<string, unknown>;
3122
- parseError?: string;
3123
- /** List of invocation IDs this gadget depends on. Empty array if no dependencies. */
3124
- dependencies: string[];
3125
- }
3126
-
3127
- /** Event emitted when a gadget is skipped due to a failed dependency */
3128
- interface GadgetSkippedEvent {
3129
- type: "gadget_skipped";
3130
- gadgetName: string;
3131
- invocationId: string;
3132
- parameters: Record<string, unknown>;
3133
- /** The invocation ID of the dependency that failed */
3134
- failedDependency: string;
3135
- /** The error message from the failed dependency */
3136
- failedDependencyError: string;
3137
- }
3138
- /**
3139
- * Event emitted when stream processing completes, containing metadata.
3140
- * This allows the async generator to "return" metadata while still yielding events.
3141
- */
3142
- interface StreamCompletionEvent {
3143
- type: "stream_complete";
3144
- /** The reason the LLM stopped generating (e.g., "stop", "tool_use") */
3145
- finishReason: string | null;
3146
- /** Token usage statistics from the LLM call */
3147
- usage?: TokenUsage;
3148
- /** Raw response text from the LLM */
3149
- rawResponse: string;
3150
- /** Final message after all interceptors applied */
3151
- finalMessage: string;
3152
- /** Whether any gadgets were executed during this iteration */
3153
- didExecuteGadgets: boolean;
3154
- /** Whether to break the agent loop (e.g., TaskComplete was called) */
3155
- shouldBreakLoop: boolean;
3156
- /** Accumulated thinking/reasoning content from reasoning models */
3157
- thinkingContent?: string;
3158
- }
3159
- type StreamEvent = {
3160
- type: "text";
3161
- content: string;
3162
- } | {
3163
- type: "thinking";
3164
- content: string;
3165
- thinkingType: "thinking" | "redacted";
3166
- } | {
3167
- type: "gadget_call";
3168
- call: ParsedGadgetCall;
3169
- } | {
3170
- type: "gadget_result";
3171
- result: GadgetExecutionResult;
3172
- } | GadgetSkippedEvent | {
3173
- type: "human_input_required";
3174
- question: string;
3175
- gadgetName: string;
3176
- invocationId: string;
3177
- } | {
3178
- type: "compaction";
3179
- event: CompactionEvent;
3180
- } | {
3181
- type: "llm_response_end";
3182
- finishReason: string | null;
3183
- usage?: TokenUsage;
3184
- } | StreamCompletionEvent;
3185
-
3186
- type TextOnlyHandler = TextOnlyStrategy | TextOnlyGadgetConfig | TextOnlyCustomHandler;
3187
- /**
3188
- * Simple strategies for common cases
3189
- * - 'terminate': End the loop (default behavior)
3190
- * - 'acknowledge': Continue to next iteration
3191
- * - 'wait_for_input': Request human input
3192
- */
3193
- type TextOnlyStrategy = "terminate" | "acknowledge" | "wait_for_input";
3194
- /**
3195
- * Configuration for triggering a gadget when receiving text-only response
3196
- */
3197
- interface TextOnlyGadgetConfig {
3198
- type: "gadget";
3199
- name: string;
3095
+ interface CostReportingSpeechNamespace {
3200
3096
  /**
3201
- * Optional function to map text to gadget parameters.
3202
- * If not provided, text will be passed as { text: string }
3097
+ * Generate speech audio from text.
3098
+ * Costs are automatically reported to the execution context.
3203
3099
  */
3204
- parameterMapping?: (text: string) => Record<string, unknown>;
3205
- }
3206
- /**
3207
- * Custom handler for complex text-only response scenarios
3208
- */
3209
- interface TextOnlyCustomHandler {
3210
- type: "custom";
3211
- handler: (context: TextOnlyContext) => Promise<TextOnlyAction> | TextOnlyAction;
3212
- }
3213
- /**
3214
- * Context provided to custom text-only handlers
3215
- */
3216
- interface TextOnlyContext {
3217
- /** The complete text response from the LLM */
3218
- text: string;
3219
- /** Current iteration number */
3220
- iteration: number;
3221
- /** Full conversation history */
3222
- conversation: LLMMessage[];
3223
- /** Logger instance */
3224
- logger: Logger<ILogObj>;
3100
+ generate(options: SpeechGenerationOptions): Promise<SpeechGenerationResult>;
3225
3101
  }
3226
- /**
3227
- * Actions that can be returned by text-only handlers
3228
- */
3229
- type TextOnlyAction = {
3230
- action: "continue";
3231
- } | {
3232
- action: "terminate";
3233
- } | {
3234
- action: "wait_for_input";
3235
- question?: string;
3236
- } | {
3237
- action: "trigger_gadget";
3238
- name: string;
3239
- parameters: Record<string, unknown>;
3240
- };
3241
3102
  /**
3242
3103
  * LLMist client interface for use within gadgets.
3243
3104
  *
@@ -3256,26 +3117,6 @@ type TextOnlyAction = {
3256
3117
  * }
3257
3118
  * ```
3258
3119
  */
3259
- /**
3260
- * Image generation namespace with automatic cost reporting.
3261
- */
3262
- interface CostReportingImageNamespace {
3263
- /**
3264
- * Generate images from a text prompt.
3265
- * Costs are automatically reported to the execution context.
3266
- */
3267
- generate(options: ImageGenerationOptions): Promise<ImageGenerationResult>;
3268
- }
3269
- /**
3270
- * Speech generation namespace with automatic cost reporting.
3271
- */
3272
- interface CostReportingSpeechNamespace {
3273
- /**
3274
- * Generate speech audio from text.
3275
- * Costs are automatically reported to the execution context.
3276
- */
3277
- generate(options: SpeechGenerationOptions): Promise<SpeechGenerationResult>;
3278
- }
3279
3120
  interface CostReportingLLMist {
3280
3121
  /**
3281
3122
  * Quick completion - returns final text response.
@@ -3759,92 +3600,347 @@ interface HostExports {
3759
3600
  /** Zod schema builder */
3760
3601
  z: typeof zod.z;
3761
3602
  }
3603
+
3762
3604
  /**
3763
- * Parent agent configuration passed to gadgets.
3764
- * Contains settings that subagents can inherit.
3605
+ * Media output types for gadgets returning images, audio, video, or files.
3606
+ *
3607
+ * This module contains pure data shapes with zero cross-module dependencies.
3608
+ * Imported by execution result types, stream event types, and execution context types.
3609
+ *
3610
+ * @module
3765
3611
  */
3766
- interface AgentContextConfig {
3767
- /** Model identifier used by the parent agent */
3768
- model: string;
3769
- /** Temperature setting used by the parent agent */
3770
- temperature?: number;
3771
- }
3772
3612
  /**
3773
- * Configuration for a single subagent.
3774
- * Can be defined globally in `[subagents.Name]` or per-profile in `[profile.subagents.Name]`.
3775
- *
3776
- * @example
3777
- * ```toml
3778
- * [subagents.BrowseWeb]
3779
- * model = "inherit" # Use parent agent's model
3780
- * maxIterations = 20
3781
- * headless = true
3782
- * ```
3613
+ * Supported media types for gadget output.
3614
+ * Extensible via union - add new types as needed.
3783
3615
  */
3784
- interface SubagentConfig {
3785
- /**
3786
- * Model to use for this subagent.
3787
- * - "inherit": Use parent agent's model (default behavior)
3788
- * - Any model ID: Use specific model (e.g., "sonnet", "haiku", "gpt-4o")
3789
- */
3790
- model?: string;
3791
- /** Maximum iterations for the subagent loop */
3792
- maxIterations?: number;
3793
- /** Budget limit in USD for the subagent */
3794
- budget?: number;
3795
- /**
3796
- * Timeout for the subagent gadget execution in milliseconds.
3797
- * Overrides the gadget's hardcoded timeoutMs when set.
3798
- * Set to 0 to disable timeout for this gadget.
3799
- */
3800
- timeoutMs?: number;
3801
- /**
3802
- * Maximum number of concurrent executions allowed for this gadget.
3803
- * When the limit is reached, additional calls are queued and processed
3804
- * as earlier executions complete (FIFO order).
3805
- * Set to 0 or omit to allow unlimited concurrent executions (default).
3806
- */
3807
- maxConcurrent?: number;
3808
- /** Additional subagent-specific options */
3809
- [key: string]: unknown;
3810
- }
3616
+ type MediaKind = "image" | "audio" | "video" | "file";
3811
3617
  /**
3812
- * Map of subagent names to their configurations.
3618
+ * Type-specific metadata for media outputs.
3619
+ * Extensible via index signature for future media types.
3813
3620
  */
3814
- type SubagentConfigMap = Record<string, SubagentConfig>;
3621
+ interface MediaMetadata {
3622
+ /** Width in pixels (images, video) */
3623
+ width?: number;
3624
+ /** Height in pixels (images, video) */
3625
+ height?: number;
3626
+ /** Duration in milliseconds (audio, video) */
3627
+ durationMs?: number;
3628
+ /** Allow additional metadata for future extensions */
3629
+ [key: string]: unknown;
3630
+ }
3815
3631
  /**
3816
- * Gadget execution mode controlling how multiple gadgets are executed.
3817
- *
3818
- * - `'parallel'` (default): Gadgets without dependencies execute concurrently (fire-and-forget).
3819
- * This maximizes throughput but gadgets may complete in any order.
3820
- *
3821
- * - `'sequential'`: Gadgets execute one at a time, each awaiting completion before the next starts.
3822
- * Useful for:
3823
- * - Gadgets with implicit ordering dependencies (e.g., file operations)
3824
- * - Debugging and tracing execution flow
3825
- * - Resource-constrained environments
3826
- * - Ensuring deterministic execution order
3827
- *
3828
- * Note: Explicit `dependsOn` relationships are always respected regardless of mode.
3829
- * Sequential mode effectively enforces a global `maxConcurrent: 1` for all gadgets.
3632
+ * Media output from a gadget execution.
3633
+ * Supports images, audio, video, and arbitrary files.
3830
3634
  *
3831
3635
  * @example
3832
3636
  * ```typescript
3833
- * const agent = LLMist.createAgent()
3834
- * .withModel("sonnet")
3835
- * .withGadgets(FileReader, FileWriter)
3836
- * .withGadgetExecutionMode('sequential') // Execute one at a time
3837
- * .ask("Process files in order");
3637
+ * // Image output
3638
+ * const imageOutput: GadgetMediaOutput = {
3639
+ * kind: "image",
3640
+ * data: base64EncodedPng,
3641
+ * mimeType: "image/png",
3642
+ * description: "Screenshot of webpage",
3643
+ * metadata: { width: 1920, height: 1080 }
3644
+ * };
3838
3645
  * ```
3839
3646
  */
3840
- type GadgetExecutionMode = "parallel" | "sequential";
3841
-
3647
+ interface GadgetMediaOutput {
3648
+ /** Type of media (discriminator for type-specific handling) */
3649
+ kind: MediaKind;
3650
+ /** Base64-encoded media data */
3651
+ data: string;
3652
+ /** Full MIME type (e.g., "image/png", "audio/mp3", "video/mp4") */
3653
+ mimeType: string;
3654
+ /** Human-readable description of the media */
3655
+ description?: string;
3656
+ /** Type-specific metadata */
3657
+ metadata?: MediaMetadata;
3658
+ /** Optional filename to use when saving (if not provided, auto-generated) */
3659
+ fileName?: string;
3660
+ }
3842
3661
  /**
3843
- * Abstract base class for gadgets. Most users should use the `Gadget()` factory
3844
- * or `createGadget()` function instead, as they provide better type safety
3845
- * and simpler APIs.
3662
+ * Stored media item with metadata and file path.
3846
3663
  *
3847
- * Extend this class directly only when you need advanced control over gadget behavior.
3664
+ * Created by MediaStore when a gadget returns media outputs.
3665
+ * Contains the abstract ID, file path, and metadata for display.
3666
+ */
3667
+ interface StoredMedia {
3668
+ /** Unique ID for this media item (e.g., "media_a1b2c3") */
3669
+ id: string;
3670
+ /** Type of media */
3671
+ kind: MediaKind;
3672
+ /** Actual file path on disk (internal use) */
3673
+ path: string;
3674
+ /** MIME type */
3675
+ mimeType: string;
3676
+ /** File size in bytes */
3677
+ sizeBytes: number;
3678
+ /** Human-readable description */
3679
+ description?: string;
3680
+ /** Type-specific metadata */
3681
+ metadata?: MediaMetadata;
3682
+ /** Name of the gadget that created this media */
3683
+ gadgetName: string;
3684
+ /** When the media was stored */
3685
+ createdAt: Date;
3686
+ }
3687
+ /**
3688
+ * Example of gadget usage to help LLMs understand proper invocation.
3689
+ *
3690
+ * Examples are rendered alongside the schema in `getInstruction()` to provide
3691
+ * concrete usage patterns for the LLM.
3692
+ *
3693
+ * @template TParams - Inferred parameter type from Zod schema (defaults to Record<string, unknown>)
3694
+ *
3695
+ * @example
3696
+ * ```typescript
3697
+ * const calculator = createGadget({
3698
+ * schema: z.object({ a: z.number(), b: z.number() }),
3699
+ * examples: [
3700
+ * { params: { a: 5, b: 3 }, output: "8", comment: "Addition example" }
3701
+ * ],
3702
+ * // ...
3703
+ * });
3704
+ * ```
3705
+ */
3706
+ interface GadgetExample<TParams = Record<string, unknown>> {
3707
+ /** Example parameter values (typed to match schema) */
3708
+ params: TParams;
3709
+ /** Optional expected output/result string */
3710
+ output?: string;
3711
+ /** Optional description explaining what this example demonstrates */
3712
+ comment?: string;
3713
+ }
3714
+
3715
+ /**
3716
+ * Execution result types for gadget calls.
3717
+ *
3718
+ * Contains result types returned by gadget `execute()` methods and the
3719
+ * internal result type used after execution completes.
3720
+ *
3721
+ * @module
3722
+ */
3723
+
3724
+ interface GadgetExecutionResult {
3725
+ gadgetName: string;
3726
+ invocationId: string;
3727
+ parameters: Record<string, unknown>;
3728
+ result?: string;
3729
+ error?: string;
3730
+ executionTimeMs: number;
3731
+ breaksLoop?: boolean;
3732
+ /** Cost of gadget execution in USD. Defaults to 0 if not provided by gadget. */
3733
+ cost?: number;
3734
+ /** Media outputs from the gadget (images, audio, video, files) */
3735
+ media?: GadgetMediaOutput[];
3736
+ /** Abstract IDs for media outputs (e.g., ["media_a1b2c3"]) */
3737
+ mediaIds?: string[];
3738
+ /** Stored media with paths (for CLI display) */
3739
+ storedMedia?: StoredMedia[];
3740
+ }
3741
+ /**
3742
+ * Result returned by gadget execute() method.
3743
+ * Can be a simple string or an object with result and optional cost.
3744
+ *
3745
+ * @example
3746
+ * ```typescript
3747
+ * // Simple string return (free gadget)
3748
+ * execute: () => "result"
3749
+ *
3750
+ * // Object return with cost
3751
+ * execute: () => ({ result: "data", cost: 0.001 })
3752
+ * ```
3753
+ */
3754
+ interface GadgetExecuteResult {
3755
+ /** The execution result as a string */
3756
+ result: string;
3757
+ /** Optional cost in USD (e.g., 0.001 for $0.001) */
3758
+ cost?: number;
3759
+ }
3760
+ /**
3761
+ * Extended result type with media support.
3762
+ * Use this when gadget returns images, audio, video, or files.
3763
+ *
3764
+ * @example
3765
+ * ```typescript
3766
+ * // Return with image
3767
+ * execute: () => ({
3768
+ * result: "Screenshot captured",
3769
+ * media: [{
3770
+ * kind: "image",
3771
+ * data: base64EncodedPng,
3772
+ * mimeType: "image/png",
3773
+ * description: "Screenshot"
3774
+ * }],
3775
+ * cost: 0.001
3776
+ * })
3777
+ * ```
3778
+ */
3779
+ interface GadgetExecuteResultWithMedia {
3780
+ /** The execution result as a string */
3781
+ result: string;
3782
+ /** Media outputs (images, audio, video, files) */
3783
+ media?: GadgetMediaOutput[];
3784
+ /** Optional cost in USD (e.g., 0.001 for $0.001) */
3785
+ cost?: number;
3786
+ }
3787
+ /**
3788
+ * Union type for backwards-compatible execute() return type.
3789
+ * Gadgets can return:
3790
+ * - string (legacy, cost = 0)
3791
+ * - GadgetExecuteResult (result + optional cost)
3792
+ * - GadgetExecuteResultWithMedia (result + optional media + optional cost)
3793
+ */
3794
+ type GadgetExecuteReturn = string | GadgetExecuteResult | GadgetExecuteResultWithMedia;
3795
+ interface ParsedGadgetCall {
3796
+ gadgetName: string;
3797
+ invocationId: string;
3798
+ parametersRaw: string;
3799
+ parameters?: Record<string, unknown>;
3800
+ parseError?: string;
3801
+ /** List of invocation IDs this gadget depends on. Empty array if no dependencies. */
3802
+ dependencies: string[];
3803
+ }
3804
+
3805
+ /**
3806
+ * Stream event types emitted during agent execution.
3807
+ *
3808
+ * Contains all discriminated union members for `StreamEvent`, plus
3809
+ * `StreamCompletionEvent` and `GadgetSkippedEvent`.
3810
+ *
3811
+ * @module
3812
+ */
3813
+
3814
+ /** Event emitted when a gadget is skipped due to a failed dependency */
3815
+ interface GadgetSkippedEvent {
3816
+ type: "gadget_skipped";
3817
+ gadgetName: string;
3818
+ invocationId: string;
3819
+ parameters: Record<string, unknown>;
3820
+ /** The invocation ID of the dependency that failed */
3821
+ failedDependency: string;
3822
+ /** The error message from the failed dependency */
3823
+ failedDependencyError: string;
3824
+ }
3825
+ /**
3826
+ * Event emitted when stream processing completes, containing metadata.
3827
+ * This allows the async generator to "return" metadata while still yielding events.
3828
+ */
3829
+ interface StreamCompletionEvent {
3830
+ type: "stream_complete";
3831
+ /** The reason the LLM stopped generating (e.g., "stop", "tool_use") */
3832
+ finishReason: string | null;
3833
+ /** Token usage statistics from the LLM call */
3834
+ usage?: TokenUsage;
3835
+ /** Raw response text from the LLM */
3836
+ rawResponse: string;
3837
+ /** Final message after all interceptors applied */
3838
+ finalMessage: string;
3839
+ /** Whether any gadgets were executed during this iteration */
3840
+ didExecuteGadgets: boolean;
3841
+ /** Whether to break the agent loop (e.g., TaskComplete was called) */
3842
+ shouldBreakLoop: boolean;
3843
+ /** Accumulated thinking/reasoning content from reasoning models */
3844
+ thinkingContent?: string;
3845
+ }
3846
+ type StreamEvent = {
3847
+ type: "text";
3848
+ content: string;
3849
+ } | {
3850
+ type: "thinking";
3851
+ content: string;
3852
+ thinkingType: "thinking" | "redacted";
3853
+ } | {
3854
+ type: "gadget_call";
3855
+ call: ParsedGadgetCall;
3856
+ } | {
3857
+ type: "gadget_result";
3858
+ result: GadgetExecutionResult;
3859
+ } | GadgetSkippedEvent | {
3860
+ type: "human_input_required";
3861
+ question: string;
3862
+ gadgetName: string;
3863
+ invocationId: string;
3864
+ } | {
3865
+ type: "compaction";
3866
+ event: CompactionEvent;
3867
+ } | {
3868
+ type: "llm_response_end";
3869
+ finishReason: string | null;
3870
+ usage?: TokenUsage;
3871
+ } | StreamCompletionEvent;
3872
+
3873
+ /**
3874
+ * Text-only response handler types.
3875
+ *
3876
+ * Defines the handler configuration for when the LLM returns a text-only response
3877
+ * (no gadget calls). Supports simple strategies, gadget triggers, and custom handlers.
3878
+ *
3879
+ * @module
3880
+ */
3881
+
3882
+ type TextOnlyHandler = TextOnlyStrategy | TextOnlyGadgetConfig | TextOnlyCustomHandler;
3883
+ /**
3884
+ * Simple strategies for common cases
3885
+ * - 'terminate': End the loop (default behavior)
3886
+ * - 'acknowledge': Continue to next iteration
3887
+ * - 'wait_for_input': Request human input
3888
+ */
3889
+ type TextOnlyStrategy = "terminate" | "acknowledge" | "wait_for_input";
3890
+ /**
3891
+ * Configuration for triggering a gadget when receiving text-only response
3892
+ */
3893
+ interface TextOnlyGadgetConfig {
3894
+ type: "gadget";
3895
+ name: string;
3896
+ /**
3897
+ * Optional function to map text to gadget parameters.
3898
+ * If not provided, text will be passed as { text: string }
3899
+ */
3900
+ parameterMapping?: (text: string) => Record<string, unknown>;
3901
+ }
3902
+ /**
3903
+ * Custom handler for complex text-only response scenarios
3904
+ */
3905
+ interface TextOnlyCustomHandler {
3906
+ type: "custom";
3907
+ handler: (context: TextOnlyContext) => Promise<TextOnlyAction> | TextOnlyAction;
3908
+ }
3909
+ /**
3910
+ * Context provided to custom text-only handlers
3911
+ */
3912
+ interface TextOnlyContext {
3913
+ /** The complete text response from the LLM */
3914
+ text: string;
3915
+ /** Current iteration number */
3916
+ iteration: number;
3917
+ /** Full conversation history */
3918
+ conversation: LLMMessage[];
3919
+ /** Logger instance */
3920
+ logger: Logger<ILogObj>;
3921
+ }
3922
+ /**
3923
+ * Actions that can be returned by text-only handlers
3924
+ */
3925
+ type TextOnlyAction = {
3926
+ action: "continue";
3927
+ } | {
3928
+ action: "terminate";
3929
+ } | {
3930
+ action: "wait_for_input";
3931
+ question?: string;
3932
+ } | {
3933
+ action: "trigger_gadget";
3934
+ name: string;
3935
+ parameters: Record<string, unknown>;
3936
+ };
3937
+
3938
+ /**
3939
+ * Abstract base class for gadgets. Most users should use the `Gadget()` factory
3940
+ * or `createGadget()` function instead, as they provide better type safety
3941
+ * and simpler APIs.
3942
+ *
3943
+ * Extend this class directly only when you need advanced control over gadget behavior.
3848
3944
  */
3849
3945
  declare abstract class AbstractGadget {
3850
3946
  /**
@@ -4041,12 +4137,6 @@ declare abstract class AbstractGadget {
4041
4137
  * ```
4042
4138
  */
4043
4139
  createLinkedAbortController(ctx?: ExecutionContext): AbortController;
4044
- /**
4045
- * Auto-generated instruction text for the LLM.
4046
- * Combines name, description, and parameter schema into a formatted instruction.
4047
- * @deprecated Use getInstruction() instead
4048
- */
4049
- get instruction(): string;
4050
4140
  /**
4051
4141
  * Generate instruction text for the LLM.
4052
4142
  * Combines name, description, and parameter schema into a formatted instruction.
@@ -4570,6 +4660,281 @@ declare class GadgetRegistry {
4570
4660
  clear(): void;
4571
4661
  }
4572
4662
 
4663
+ /**
4664
+ * Core type definitions for the Skills system.
4665
+ *
4666
+ * Skills follow the Agent Skills open standard (agentskills.io) — markdown-based
4667
+ * instruction packages that extend agent capabilities through prompt injection
4668
+ * and context management, not code execution.
4669
+ *
4670
+ * Three-tier progressive disclosure:
4671
+ * - Tier 1 (metadata): ~100 tokens, always loaded for discovery
4672
+ * - Tier 2 (instructions): <5K tokens, loaded on activation
4673
+ * - Tier 3 (resources): unlimited, loaded on demand
4674
+ *
4675
+ * @module skills/types
4676
+ */
4677
+
4678
+ /**
4679
+ * Parsed YAML frontmatter from a SKILL.md file.
4680
+ * Follows the Agent Skills open standard with llmist-specific extensions.
4681
+ */
4682
+ interface SkillMetadata {
4683
+ /** Skill identifier. Lowercase letters, numbers, hyphens only. Max 64 chars. */
4684
+ name: string;
4685
+ /** What the skill does and when to use it. Max 1024 chars. Used for auto-triggering. */
4686
+ description: string;
4687
+ /** Hint shown during autocomplete, e.g., "[issue-number]" or "<filename> [format]". */
4688
+ argumentHint?: string;
4689
+ /** Tools the agent can use when this skill is active. */
4690
+ allowedTools?: string[];
4691
+ /** Model override when skill is active, e.g., "sonnet", "flash". */
4692
+ model?: string;
4693
+ /** Execution context. "fork" runs in an isolated subagent. */
4694
+ context?: "fork" | "inline";
4695
+ /** Subagent type for fork mode, e.g., "Explore", "Plan", "general-purpose". */
4696
+ agent?: string;
4697
+ /** Glob patterns for auto-activation based on files being worked on. */
4698
+ paths?: string[];
4699
+ /** Bundled gadget specifiers loaded when skill activates. */
4700
+ gadgets?: string[];
4701
+ /** If true, only the user can invoke this skill (LLM cannot auto-trigger). */
4702
+ disableModelInvocation?: boolean;
4703
+ /** If false, skill is background knowledge only — hidden from user invocation. */
4704
+ userInvocable?: boolean;
4705
+ /** Shell for !`command` preprocessing. */
4706
+ shell?: "bash" | "powershell";
4707
+ /** Semantic version number. */
4708
+ version?: string;
4709
+ }
4710
+ /**
4711
+ * A resource file within a skill's directory (Tier 3).
4712
+ */
4713
+ interface SkillResource {
4714
+ /** Path relative to the skill directory. */
4715
+ relativePath: string;
4716
+ /** Absolute path on disk. */
4717
+ absolutePath: string;
4718
+ /** Category based on parent directory. */
4719
+ category: "scripts" | "references" | "assets";
4720
+ }
4721
+ /**
4722
+ * Where a skill was discovered from.
4723
+ */
4724
+ type SkillSource = {
4725
+ type: "project";
4726
+ path: string;
4727
+ } | {
4728
+ type: "user";
4729
+ path: string;
4730
+ } | {
4731
+ type: "npm";
4732
+ package: string;
4733
+ } | {
4734
+ type: "git";
4735
+ url: string;
4736
+ } | {
4737
+ type: "directory";
4738
+ path: string;
4739
+ };
4740
+ /**
4741
+ * Fully parsed skill representation (all three tiers).
4742
+ */
4743
+ interface ParsedSkill {
4744
+ /** Tier 1: Always-loaded metadata from frontmatter. */
4745
+ metadata: SkillMetadata;
4746
+ /** Tier 2: Full SKILL.md body. null if not yet loaded. */
4747
+ instructions: string | null;
4748
+ /** Tier 3: Discovered resource manifests. */
4749
+ resources: SkillResource[];
4750
+ /** Absolute path to the SKILL.md file. */
4751
+ sourcePath: string;
4752
+ /** Directory containing the skill. */
4753
+ sourceDir: string;
4754
+ /** Origin for debugging and priority resolution. */
4755
+ source: SkillSource;
4756
+ }
4757
+ /**
4758
+ * Result of activating a skill.
4759
+ */
4760
+ interface SkillActivation {
4761
+ /** The skill that was activated. */
4762
+ skillName: string;
4763
+ /** Resolved instructions after $ARGUMENTS substitution and !`command` preprocessing. */
4764
+ resolvedInstructions: string;
4765
+ /** Gadgets made available by this skill (if any). */
4766
+ gadgets: AbstractGadget[];
4767
+ /** Resources loaded for this activation (Tier 3). Keyed by relative path. */
4768
+ loadedResources: Map<string, string>;
4769
+ }
4770
+ /**
4771
+ * Options for skill activation.
4772
+ */
4773
+ interface SkillActivationOptions {
4774
+ /** Arguments passed to the skill (substituted into $ARGUMENTS, $0, $1, etc.). */
4775
+ arguments?: string;
4776
+ /** Whether to load Tier 3 resources eagerly. Default: false. */
4777
+ eagerResources?: boolean;
4778
+ /** Working directory for !`command` preprocessing. */
4779
+ cwd?: string;
4780
+ /** Whether to execute !`command` preprocessing. Default: true. */
4781
+ enableShellPreprocessing?: boolean;
4782
+ /** Timeout for !`command` execution in milliseconds. Default: 10000. */
4783
+ shellTimeoutMs?: number;
4784
+ }
4785
+
4786
+ /**
4787
+ * Skill class with lazy-loading progressive disclosure.
4788
+ *
4789
+ * Tier 1 (metadata) is always available after construction.
4790
+ * Tier 2 (instructions) and Tier 3 (resources) are loaded on demand.
4791
+ *
4792
+ * @module skills/skill
4793
+ */
4794
+
4795
+ declare class Skill {
4796
+ readonly metadata: SkillMetadata;
4797
+ readonly sourcePath: string;
4798
+ readonly sourceDir: string;
4799
+ readonly source: SkillSource;
4800
+ private _instructions;
4801
+ private _resources;
4802
+ private readonly _resourceCache;
4803
+ private readonly _resourceLoading;
4804
+ constructor(parsed: ParsedSkill);
4805
+ /** Skill name for registry lookup. */
4806
+ get name(): string;
4807
+ /** Skill description for LLM matching. */
4808
+ get description(): string;
4809
+ /** Whether the LLM can auto-trigger this skill. */
4810
+ get isModelInvocable(): boolean;
4811
+ /** Whether the user can invoke this skill via /skill-name. */
4812
+ get isUserInvocable(): boolean;
4813
+ /**
4814
+ * Load and cache Tier 2 instructions.
4815
+ * If instructions were loaded during parsing, returns the cached value.
4816
+ */
4817
+ getInstructions(): Promise<string>;
4818
+ /**
4819
+ * List Tier 3 resources.
4820
+ * Resources are discovered at parse time but content is loaded on demand.
4821
+ */
4822
+ getResources(): SkillResource[];
4823
+ /**
4824
+ * Load a specific Tier 3 resource by relative path.
4825
+ * Results are cached for the lifetime of this Skill instance.
4826
+ * Concurrent calls for the same resource share a single read.
4827
+ */
4828
+ getResource(relativePath: string): Promise<string>;
4829
+ /**
4830
+ * Activate this skill with optional arguments.
4831
+ *
4832
+ * Performs:
4833
+ * 1. Variable substitution (${SKILL_DIR}, etc.)
4834
+ * 2. Argument substitution ($ARGUMENTS, $0, $1)
4835
+ * 3. Shell preprocessing (!`command`)
4836
+ * 4. Resource loading (if eagerResources is true)
4837
+ */
4838
+ activate(options?: SkillActivationOptions): Promise<SkillActivation>;
4839
+ /**
4840
+ * Create a Skill from a SKILL.md content string.
4841
+ * Useful for testing or dynamic skill creation.
4842
+ */
4843
+ static fromContent(content: string, sourcePath: string, source?: SkillSource): Skill;
4844
+ }
4845
+
4846
+ /**
4847
+ * SkillRegistry — manages skill discovery, lookup, and metadata summaries.
4848
+ *
4849
+ * Parallel to GadgetRegistry but with different semantics: skills are not
4850
+ * executable tools registered with the LLM directly. They are available
4851
+ * for activation by the agent or user, surfaced via metadata summaries.
4852
+ *
4853
+ * @module skills/registry
4854
+ */
4855
+
4856
+ declare class SkillRegistry {
4857
+ private readonly skills;
4858
+ /**
4859
+ * Register a skill. Overwrites any existing skill with the same name.
4860
+ *
4861
+ * Unlike GadgetRegistry (which throws on duplicates), SkillRegistry allows
4862
+ * overwriting because skills are loaded from multiple sources with intentional
4863
+ * priority ordering (project > user > default).
4864
+ */
4865
+ register(skill: Skill): void;
4866
+ /** Register multiple skills. */
4867
+ registerMany(skills: Skill[]): void;
4868
+ /** Remove a skill by name (case-insensitive). Returns true if removed. */
4869
+ remove(name: string): boolean;
4870
+ /** Remove all registered skills. */
4871
+ clear(): void;
4872
+ /** Get a skill by name (case-insensitive). */
4873
+ get(name: string): Skill | undefined;
4874
+ /** Check if a skill exists by name (case-insensitive). */
4875
+ has(name: string): boolean;
4876
+ /** Get all registered skills. */
4877
+ getAll(): Skill[];
4878
+ /** Get all skill names. */
4879
+ getNames(): string[];
4880
+ /** Number of registered skills. */
4881
+ get size(): number;
4882
+ /**
4883
+ * Get skills that are visible to the LLM for auto-triggering.
4884
+ * Excludes skills with disableModelInvocation: true.
4885
+ */
4886
+ getModelInvocable(): Skill[];
4887
+ /**
4888
+ * Get skills that the user can invoke via /skill-name.
4889
+ * Excludes skills with userInvocable: false.
4890
+ */
4891
+ getUserInvocable(): Skill[];
4892
+ /**
4893
+ * Generate metadata summaries for system prompt injection (Tier 1).
4894
+ *
4895
+ * Each skill contributes a one-line summary: "name — description".
4896
+ * Output is truncated to fit the character budget.
4897
+ *
4898
+ * @param charBudget - Maximum characters for all summaries combined.
4899
+ */
4900
+ getMetadataSummaries(charBudget?: number): string;
4901
+ /**
4902
+ * Find skills whose `paths` patterns match a given file path.
4903
+ * Used for auto-activation when the user is working on specific files.
4904
+ */
4905
+ findByFilePath(filePath: string): Skill[];
4906
+ /**
4907
+ * Merge another registry into this one.
4908
+ * Skills from the other registry overwrite existing skills with the same name.
4909
+ */
4910
+ merge(other: SkillRegistry): void;
4911
+ /** Create a registry from an array of skills. */
4912
+ static from(skills: Skill[]): SkillRegistry;
4913
+ }
4914
+
4915
+ /**
4916
+ * Context available to trailing message functions.
4917
+ * Provides iteration information for dynamic message generation.
4918
+ */
4919
+ type TrailingMessageContext = Pick<LLMCallControllerContext, "iteration" | "maxIterations" | "budget" | "totalCost">;
4920
+ /**
4921
+ * Trailing message can be a static string or a function that generates the message.
4922
+ * The function receives context about the current iteration.
4923
+ */
4924
+ type TrailingMessage = string | ((ctx: TrailingMessageContext) => string);
4925
+
4926
+ /**
4927
+ * Message for conversation history.
4928
+ * User messages can be text (string) or multimodal (ContentPart[]).
4929
+ */
4930
+ type HistoryMessage = {
4931
+ user: string | ContentPart[];
4932
+ } | {
4933
+ assistant: string;
4934
+ } | {
4935
+ system: string;
4936
+ };
4937
+
4573
4938
  /**
4574
4939
  * Event handler sugar for cleaner event processing.
4575
4940
  *
@@ -4681,43 +5046,8 @@ declare function collectText(agentGenerator: AsyncGenerator<StreamEvent>): Promi
4681
5046
 
4682
5047
  /**
4683
5048
  * Fluent builder for creating agents with delightful DX.
4684
- *
4685
- * @example
4686
- * ```typescript
4687
- * const agent = await LLMist.createAgent()
4688
- * .withModel("sonnet")
4689
- * .withSystem("You are a helpful assistant")
4690
- * .withGadgets(Calculator, Weather)
4691
- * .withMaxIterations(10)
4692
- * .ask("What's the weather in Paris?");
4693
- *
4694
- * for await (const event of agent.run()) {
4695
- * // process events
4696
- * }
4697
- * ```
4698
5049
  */
4699
5050
 
4700
- /**
4701
- * Message for conversation history.
4702
- * User messages can be text (string) or multimodal (ContentPart[]).
4703
- */
4704
- type HistoryMessage = {
4705
- user: string | ContentPart[];
4706
- } | {
4707
- assistant: string;
4708
- } | {
4709
- system: string;
4710
- };
4711
- /**
4712
- * Context available to trailing message functions.
4713
- * Provides iteration information for dynamic message generation.
4714
- */
4715
- type TrailingMessageContext = Pick<LLMCallControllerContext, "iteration" | "maxIterations" | "budget" | "totalCost">;
4716
- /**
4717
- * Trailing message can be a static string or a function that generates the message.
4718
- * The function receives context about the current iteration.
4719
- */
4720
- type TrailingMessage = string | ((ctx: TrailingMessageContext) => string);
4721
5051
  /**
4722
5052
  * Fluent builder for creating agents.
4723
5053
  *
@@ -4725,921 +5055,126 @@ type TrailingMessage = string | ((ctx: TrailingMessageContext) => string);
4725
5055
  * making the code more expressive and easier to read.
4726
5056
  */
4727
5057
  declare class AgentBuilder {
4728
- private client?;
4729
- private model?;
4730
- private systemPrompt?;
4731
- private temperature?;
4732
- private maxIterations?;
4733
- private budget?;
4734
- private logger?;
4735
- private hooks?;
4736
- private promptConfig?;
5058
+ private core;
4737
5059
  private gadgets;
4738
- private initialMessages;
4739
- private requestHumanInput?;
4740
- private gadgetStartPrefix?;
4741
- private gadgetEndPrefix?;
4742
- private gadgetArgPrefix?;
4743
- private textOnlyHandler?;
4744
- private textWithGadgetsHandler?;
4745
- private defaultGadgetTimeoutMs?;
4746
- private gadgetExecutionMode?;
4747
- private maxGadgetsPerResponse?;
4748
- private gadgetOutputLimit?;
4749
- private gadgetOutputLimitPercent?;
4750
- private compactionConfig?;
4751
- private retryConfig?;
4752
- private rateLimitConfig?;
4753
- private signal?;
4754
- private trailingMessage?;
4755
- private subagentConfig?;
4756
- private parentContext?;
4757
- private parentObservers?;
4758
- private sharedRateLimitTracker?;
4759
- private sharedRetryConfig?;
4760
- private reasoningConfig?;
4761
- private cachingConfig?;
5060
+ private retry;
5061
+ private subagents;
5062
+ private policies;
5063
+ private skills;
4762
5064
  constructor(client?: LLMist);
4763
- /**
4764
- * Set the model to use.
4765
- * Supports aliases like "gpt4", "sonnet", "flash".
4766
- *
4767
- * @param model - Model name or alias
4768
- * @returns This builder for chaining
4769
- *
4770
- * @example
4771
- * ```typescript
4772
- * .withModel("sonnet") // Alias
4773
- * .withModel("gpt-5-nano") // Auto-detects provider
4774
- * .withModel("openai:gpt-5") // Explicit provider
4775
- * ```
4776
- */
5065
+ /** Set the model to use. Supports aliases like "sonnet", "flash". */
4777
5066
  withModel(model: string): this;
4778
- /**
4779
- * Set the system prompt.
4780
- *
4781
- * @param prompt - System prompt
4782
- * @returns This builder for chaining
4783
- */
5067
+ /** Set the system prompt. */
4784
5068
  withSystem(prompt: string): this;
4785
- /**
4786
- * Set the temperature (0-1).
4787
- *
4788
- * @param temperature - Temperature value
4789
- * @returns This builder for chaining
4790
- */
5069
+ /** Set the temperature (0-1). */
4791
5070
  withTemperature(temperature: number): this;
4792
- /**
4793
- * Set maximum iterations.
4794
- *
4795
- * @param max - Maximum number of iterations
4796
- * @returns This builder for chaining
4797
- */
5071
+ /** Set maximum iterations. */
4798
5072
  withMaxIterations(max: number): this;
4799
- /**
4800
- * Set the budget limit in USD.
4801
- * The agent loop stops when cumulative cost reaches this limit.
4802
- *
4803
- * @param amountUSD - Maximum spend in USD
4804
- * @returns This builder for chaining
4805
- *
4806
- * @example
4807
- * ```typescript
4808
- * .withBudget(0.50) // Stop after $0.50 spent
4809
- * ```
4810
- */
5073
+ /** Set the budget limit in USD. */
4811
5074
  withBudget(amountUSD: number): this;
4812
- /**
4813
- * Set logger instance.
4814
- *
4815
- * @param logger - Logger instance
4816
- * @returns This builder for chaining
4817
- */
4818
- withLogger(logger: Logger<ILogObj>): this;
4819
- /**
4820
- * Add hooks for agent lifecycle events.
4821
- *
4822
- * @param hooks - Agent hooks configuration
4823
- * @returns This builder for chaining
4824
- *
4825
- * @example
4826
- * ```typescript
4827
- * import { HookPresets } from 'llmist/hooks';
4828
- *
4829
- * .withHooks(HookPresets.logging())
4830
- * .withHooks(HookPresets.merge(
4831
- * HookPresets.logging(),
4832
- * HookPresets.timing()
4833
- * ))
4834
- * ```
4835
- */
4836
- withHooks(hooks: AgentHooks): this;
4837
- /**
4838
- * Configure custom prompts for gadget system messages.
4839
- *
4840
- * @param config - Prompt configuration object
4841
- * @returns This builder for chaining
4842
- *
4843
- * @example
4844
- * ```typescript
4845
- * .withPromptTemplateConfig({
4846
- * mainInstruction: "Use the gadget markers below:",
4847
- * rules: ["Always use markers", "Never use function calling"]
4848
- * })
4849
- * ```
4850
- */
4851
- withPromptTemplateConfig(config: PromptTemplateConfig): this;
4852
- /**
4853
- * Add gadgets (classes or instances).
4854
- * Can be called multiple times to add more gadgets.
4855
- *
4856
- * @param gadgets - Gadget classes or instances
4857
- * @returns This builder for chaining
4858
- *
4859
- * @example
4860
- * ```typescript
4861
- * .withGadgets(Calculator, Weather, Email)
4862
- * .withGadgets(new Calculator(), new Weather())
4863
- * .withGadgets(createGadget({ ... }))
4864
- * ```
4865
- */
4866
- withGadgets(...gadgets: GadgetOrClass[]): this;
4867
- /**
4868
- * Add conversation history messages.
4869
- * Useful for continuing previous conversations.
4870
- *
4871
- * @param messages - Array of history messages
4872
- * @returns This builder for chaining
4873
- *
4874
- * @example
4875
- * ```typescript
4876
- * .withHistory([
4877
- * { user: "Hello" },
4878
- * { assistant: "Hi there!" },
4879
- * { user: "How are you?" },
4880
- * { assistant: "I'm doing well, thanks!" }
4881
- * ])
4882
- * ```
4883
- */
4884
- withHistory(messages: HistoryMessage[]): this;
4885
- /**
4886
- * Add a single message to the conversation history.
4887
- *
4888
- * @param message - Single history message
4889
- * @returns This builder for chaining
4890
- *
4891
- * @example
4892
- * ```typescript
4893
- * .addMessage({ user: "Hello" })
4894
- * .addMessage({ assistant: "Hi there!" })
4895
- * ```
4896
- */
5075
+ /** Set logger instance. */
5076
+ withLogger(logger: Logger<ILogObj>): this;
5077
+ /** Add hooks for agent lifecycle events. */
5078
+ withHooks(hooks: AgentHooks): this;
5079
+ /** Configure custom prompts for gadget system messages. */
5080
+ withPromptTemplateConfig(config: PromptTemplateConfig): this;
5081
+ /** Add gadgets (classes or instances). */
5082
+ withGadgets(...gadgets: GadgetOrClass[]): this;
5083
+ /** Add conversation history messages. */
5084
+ withHistory(messages: HistoryMessage[]): this;
5085
+ /** Add a single message to the conversation history. */
4897
5086
  addMessage(message: HistoryMessage): this;
4898
- /**
4899
- * Clear any previously set conversation history.
4900
- * Used before setting new cumulative history in REPL mode.
4901
- *
4902
- * @returns This builder for chaining
4903
- *
4904
- * @example
4905
- * ```typescript
4906
- * // Reset history before setting new cumulative history
4907
- * builder.clearHistory().withHistory(cumulativeHistory);
4908
- * ```
4909
- */
5087
+ /** Clear any previously set conversation history. */
4910
5088
  clearHistory(): this;
4911
- /**
4912
- * Continue conversation from a previous agent's history.
4913
- * Extracts full conversation history and sets it as initial messages.
4914
- *
4915
- * This is the recommended way to implement REPL session continuation.
4916
- * It automatically handles history extraction and format conversion.
4917
- *
4918
- * @param agent - The previous agent to continue from
4919
- * @returns This builder for chaining
4920
- *
4921
- * @example
4922
- * ```typescript
4923
- * // REPL loop with session continuity
4924
- * let previousAgent: Agent | null = null;
4925
- *
4926
- * while (true) {
4927
- * if (previousAgent) {
4928
- * builder.continueFrom(previousAgent);
4929
- * }
4930
- * const agent = builder.ask(prompt);
4931
- * await runAgent(agent);
4932
- * previousAgent = agent;
4933
- * }
4934
- * ```
4935
- */
5089
+ /** Continue conversation from a previous agent's history. */
4936
5090
  continueFrom(agent: Agent): this;
4937
- /**
4938
- * Set the human input handler for interactive conversations.
4939
- *
4940
- * @param handler - Function to handle human input requests
4941
- * @returns This builder for chaining
4942
- *
4943
- * @example
4944
- * ```typescript
4945
- * .onHumanInput(async (question) => {
4946
- * return await promptUser(question);
4947
- * })
4948
- * ```
4949
- */
5091
+ /** Set the human input handler for interactive conversations. */
4950
5092
  onHumanInput(handler: (question: string) => Promise<string>): this;
4951
- /**
4952
- * Set custom gadget marker prefix.
4953
- *
4954
- * @param prefix - Custom start prefix for gadget markers
4955
- * @returns This builder for chaining
4956
- *
4957
- * @example
4958
- * ```typescript
4959
- * .withGadgetStartPrefix("<<GADGET_START>>")
4960
- * ```
4961
- */
5093
+ /** Set custom gadget marker prefix. */
4962
5094
  withGadgetStartPrefix(prefix: string): this;
4963
- /**
4964
- * Set custom gadget marker suffix.
4965
- *
4966
- * @param suffix - Custom end suffix for gadget markers
4967
- * @returns This builder for chaining
4968
- *
4969
- * @example
4970
- * ```typescript
4971
- * .withGadgetEndPrefix("<<GADGET_END>>")
4972
- * ```
4973
- */
5095
+ /** Set custom gadget marker suffix. */
4974
5096
  withGadgetEndPrefix(suffix: string): this;
4975
- /**
4976
- * Set custom argument prefix for block format parameters.
4977
- *
4978
- * @param prefix - Custom prefix for argument markers (default: "!!!ARG:")
4979
- * @returns This builder for chaining
4980
- *
4981
- * @example
4982
- * ```typescript
4983
- * .withGadgetArgPrefix("<<ARG>>")
4984
- * ```
4985
- */
5097
+ /** Set custom argument prefix for block format parameters. */
4986
5098
  withGadgetArgPrefix(prefix: string): this;
4987
- /**
4988
- * Set the text-only handler strategy.
4989
- *
4990
- * Controls what happens when the LLM returns text without calling any gadgets:
4991
- * - "terminate": End the agent loop (default)
4992
- * - "acknowledge": Continue the loop for another iteration
4993
- * - "wait_for_input": Wait for human input
4994
- * - Custom handler: Provide a function for dynamic behavior
4995
- *
4996
- * @param handler - Text-only handler strategy or custom handler
4997
- * @returns This builder for chaining
4998
- *
4999
- * @example
5000
- * ```typescript
5001
- * // Simple strategy
5002
- * .withTextOnlyHandler("acknowledge")
5003
- *
5004
- * // Custom handler
5005
- * .withTextOnlyHandler({
5006
- * type: "custom",
5007
- * handler: async (context) => {
5008
- * if (context.text.includes("?")) {
5009
- * return { action: "wait_for_input", question: context.text };
5010
- * }
5011
- * return { action: "continue" };
5012
- * }
5013
- * })
5014
- * ```
5015
- */
5099
+ /** Set the text-only handler strategy. */
5016
5100
  withTextOnlyHandler(handler: TextOnlyHandler): this;
5017
- /**
5018
- * Set the handler for text content that appears alongside gadget calls.
5019
- *
5020
- * When set, text accompanying gadget responses will be wrapped as a
5021
- * synthetic gadget call before the actual gadget results in the
5022
- * conversation history.
5023
- *
5024
- * @param handler - Configuration for wrapping text
5025
- * @returns This builder for chaining
5026
- *
5027
- * @example
5028
- * ```typescript
5029
- * // Wrap text as TellUser gadget
5030
- * .withTextWithGadgetsHandler({
5031
- * gadgetName: "TellUser",
5032
- * parameterMapping: (text) => ({ message: text, done: false, type: "info" }),
5033
- * resultMapping: (text) => `ℹ️ ${text}`,
5034
- * })
5035
- * ```
5036
- */
5101
+ /** Set the handler for text content that appears alongside gadget calls. */
5037
5102
  withTextWithGadgetsHandler(handler: {
5038
5103
  gadgetName: string;
5039
5104
  parameterMapping: (text: string) => Record<string, unknown>;
5040
5105
  resultMapping?: (text: string) => string;
5041
5106
  }): this;
5042
- /**
5043
- * Set default timeout for gadget execution.
5044
- *
5045
- * @param timeoutMs - Timeout in milliseconds (must be non-negative)
5046
- * @returns This builder for chaining
5047
- * @throws {Error} If timeout is negative
5048
- *
5049
- * @example
5050
- * ```typescript
5051
- * .withDefaultGadgetTimeout(5000) // 5 second timeout
5052
- * ```
5053
- */
5107
+ /** Set default timeout for gadget execution. */
5054
5108
  withDefaultGadgetTimeout(timeoutMs: number): this;
5055
- /**
5056
- * Set the gadget execution mode.
5057
- *
5058
- * Controls how multiple gadgets are executed when the LLM calls them:
5059
- * - `'parallel'` (default): Gadgets without dependencies execute concurrently
5060
- * - `'sequential'`: Gadgets execute one at a time, each awaiting completion
5061
- *
5062
- * @param mode - Execution mode ('parallel' or 'sequential')
5063
- * @returns This builder for chaining
5064
- *
5065
- * @example
5066
- * ```typescript
5067
- * // Sequential execution for ordered file operations
5068
- * .withGadgetExecutionMode('sequential')
5069
- *
5070
- * // Parallel execution (default) for independent operations
5071
- * .withGadgetExecutionMode('parallel')
5072
- * ```
5073
- */
5109
+ /** Set the gadget execution mode ('parallel' or 'sequential'). */
5074
5110
  withGadgetExecutionMode(mode: GadgetExecutionMode): this;
5075
- /**
5076
- * Set the maximum number of gadgets to execute per LLM response.
5077
- *
5078
- * When the limit is reached, remaining gadgets are skipped with an informative
5079
- * message visible to the LLM, allowing it to adjust on the next iteration.
5080
- * Gadgets already in-flight (executing in parallel) are allowed to complete.
5081
- *
5082
- * @param max - Maximum gadgets per response (0 = unlimited, default)
5083
- * @returns This builder for chaining
5084
- * @throws {Error} If max is negative or non-integer
5085
- *
5086
- * @example
5087
- * ```typescript
5088
- * // Limit to 5 gadgets per response
5089
- * LLMist.createAgent()
5090
- * .withModel("sonnet")
5091
- * .withGadgets(ReadFile, WriteFile, Search)
5092
- * .withMaxGadgetsPerResponse(5)
5093
- * .ask("Process these files...");
5094
- * ```
5095
- */
5111
+ /** Set the maximum number of gadgets to execute per LLM response. */
5096
5112
  withMaxGadgetsPerResponse(max: number): this;
5097
- /**
5098
- * Enable or disable gadget output limiting.
5099
- *
5100
- * When enabled, gadget outputs exceeding the configured limit are stored
5101
- * and can be browsed using the GadgetOutputViewer gadget.
5102
- *
5103
- * @param enabled - Whether to enable output limiting (default: true)
5104
- * @returns This builder for chaining
5105
- *
5106
- * @example
5107
- * ```typescript
5108
- * .withGadgetOutputLimit(false) // Disable output limiting
5109
- * ```
5110
- */
5113
+ /** Enable or disable gadget output limiting. */
5111
5114
  withGadgetOutputLimit(enabled: boolean): this;
5112
- /**
5113
- * Set the maximum gadget output as a percentage of the model's context window.
5114
- *
5115
- * Outputs exceeding this limit are stored for later browsing with GadgetOutputViewer.
5116
- *
5117
- * @param percent - Percentage of context window (1-100, default: 15)
5118
- * @returns This builder for chaining
5119
- * @throws {Error} If percent is not between 1 and 100
5120
- *
5121
- * @example
5122
- * ```typescript
5123
- * .withGadgetOutputLimitPercent(25) // 25% of context window
5124
- * ```
5125
- */
5115
+ /** Set the maximum gadget output as a percentage of the context window. */
5126
5116
  withGadgetOutputLimitPercent(percent: number): this;
5127
- /**
5128
- * Configure context compaction.
5129
- *
5130
- * Context compaction automatically manages conversation history to prevent
5131
- * context window overflow in long-running agent conversations.
5132
- *
5133
- * @param config - Compaction configuration options
5134
- * @returns This builder for chaining
5135
- *
5136
- * @example
5137
- * ```typescript
5138
- * // Custom thresholds
5139
- * .withCompaction({
5140
- * triggerThresholdPercent: 70,
5141
- * targetPercent: 40,
5142
- * preserveRecentTurns: 10,
5143
- * })
5144
- *
5145
- * // Different strategy
5146
- * .withCompaction({
5147
- * strategy: 'sliding-window',
5148
- * })
5149
- *
5150
- * // With callback
5151
- * .withCompaction({
5152
- * onCompaction: (event) => {
5153
- * console.log(`Saved ${event.tokensBefore - event.tokensAfter} tokens`);
5154
- * }
5155
- * })
5156
- * ```
5157
- */
5117
+ /** Configure context compaction. */
5158
5118
  withCompaction(config: CompactionConfig): this;
5159
- /**
5160
- * Disable context compaction.
5161
- *
5162
- * By default, compaction is enabled. Use this method to explicitly disable it.
5163
- *
5164
- * @returns This builder for chaining
5165
- *
5166
- * @example
5167
- * ```typescript
5168
- * .withoutCompaction() // Disable automatic compaction
5169
- * ```
5170
- */
5119
+ /** Disable context compaction. */
5171
5120
  withoutCompaction(): this;
5121
+ /** Register a skill registry for this agent. */
5122
+ withSkills(registry: SkillRegistry): this;
5172
5123
  /**
5173
- * Configure retry behavior for LLM API calls.
5174
- *
5175
- * Retry is enabled by default with conservative settings (3 retries, exponential backoff).
5176
- * Use this method to customize retry behavior for rate limits, timeouts, and transient errors.
5177
- *
5178
- * @param config - Retry configuration options
5179
- * @returns This builder for chaining
5180
- *
5181
- * @example
5182
- * ```typescript
5183
- * // Custom retry configuration
5184
- * .withRetry({
5185
- * retries: 5,
5186
- * minTimeout: 2000,
5187
- * maxTimeout: 60000,
5188
- * })
5189
- *
5190
- * // With monitoring callbacks
5191
- * .withRetry({
5192
- * onRetry: (error, attempt) => {
5193
- * console.log(`Retry ${attempt}: ${error.message}`);
5194
- * },
5195
- * onRetriesExhausted: (error, attempts) => {
5196
- * alerting.warn(`Failed after ${attempts} attempts`);
5197
- * }
5198
- * })
5199
- *
5200
- * // Custom retry logic
5201
- * .withRetry({
5202
- * shouldRetry: (error) => error.message.includes('429'),
5203
- * })
5204
- * ```
5205
- */
5206
- withRetry(config: RetryConfig): this;
5207
- /**
5208
- * Disable automatic retry for LLM API calls.
5209
- *
5210
- * By default, retry is enabled. Use this method to explicitly disable it.
5211
- *
5212
- * @returns This builder for chaining
5213
- *
5214
- * @example
5215
- * ```typescript
5216
- * .withoutRetry() // Disable automatic retry
5217
- * ```
5218
- */
5219
- withoutRetry(): this;
5220
- /**
5221
- * Configure proactive rate limiting to prevent rate limit errors.
5222
- *
5223
- * Set limits based on your API tier to automatically throttle requests
5224
- * before hitting provider limits. Works in conjunction with reactive
5225
- * retry/backoff for comprehensive rate limit handling.
5226
- *
5227
- * @param config - Rate limit configuration
5228
- * @returns This builder for chaining
5229
- *
5230
- * @example
5231
- * ```typescript
5232
- * // Gemini free tier limits
5233
- * .withRateLimits({
5234
- * requestsPerMinute: 15,
5235
- * tokensPerMinute: 1_000_000,
5236
- * safetyMargin: 0.8, // Start throttling at 80%
5237
- * })
5238
- *
5239
- * // OpenAI Tier 1 limits
5240
- * .withRateLimits({
5241
- * requestsPerMinute: 500,
5242
- * tokensPerMinute: 200_000,
5243
- * })
5244
- *
5245
- * // With daily limit (Gemini free tier)
5246
- * .withRateLimits({
5247
- * requestsPerMinute: 15,
5248
- * tokensPerDay: 1_500_000,
5249
- * })
5250
- * ```
5251
- */
5252
- withRateLimits(config: RateLimitConfig): this;
5253
- /**
5254
- * Set an abort signal for cancelling requests mid-flight.
5255
- *
5256
- * When the signal is aborted, the current LLM request will be cancelled
5257
- * and the agent loop will exit gracefully.
5258
- *
5259
- * @param signal - AbortSignal from an AbortController
5260
- * @returns This builder for chaining
5261
- *
5262
- * @example
5263
- * ```typescript
5264
- * const controller = new AbortController();
5265
- *
5266
- * // Cancel after 30 seconds
5267
- * setTimeout(() => controller.abort(), 30000);
5268
- *
5269
- * const agent = LLMist.createAgent()
5270
- * .withModel("sonnet")
5271
- * .withSignal(controller.signal)
5272
- * .ask("Write a long story");
5273
- *
5274
- * // Or cancel on user action
5275
- * document.getElementById("cancel").onclick = () => controller.abort();
5276
- * ```
5277
- */
5278
- withSignal(signal: AbortSignal): this;
5279
- /**
5280
- * Enable reasoning/thinking mode for reasoning-capable models.
5281
- *
5282
- * Can be called with:
5283
- * - No args: enables reasoning at "medium" effort
5284
- * - A string effort level: `withReasoning("high")`
5285
- * - A full config object: `withReasoning({ enabled: true, budgetTokens: 10000 })`
5286
- *
5287
- * @param config - Optional effort level or full reasoning config
5288
- * @returns This builder for chaining
5289
- *
5290
- * @example
5291
- * ```typescript
5292
- * // Simple — medium effort
5293
- * LLMist.createAgent()
5294
- * .withModel("o3")
5295
- * .withReasoning()
5296
- * .ask("Solve this logic puzzle...");
5297
- *
5298
- * // Explicit effort level
5299
- * LLMist.createAgent()
5300
- * .withModel("anthropic:claude-4-opus")
5301
- * .withReasoning("high")
5302
- * .ask("Analyze this complex problem");
5303
- *
5304
- * // Full config with explicit token budget
5305
- * LLMist.createAgent()
5306
- * .withModel("anthropic:claude-4-opus")
5307
- * .withReasoning({ enabled: true, budgetTokens: 16000 })
5308
- * .ask("Step through this proof");
5309
- * ```
5310
- */
5311
- withReasoning(config?: ReasoningConfig | ReasoningEffort): this;
5312
- /**
5313
- * Explicitly disable reasoning for this agent, even if the model supports it.
5314
- *
5315
- * By default, reasoning is auto-enabled at "medium" effort for models with
5316
- * `features.reasoning: true`. Use this to opt out.
5317
- *
5318
- * @returns This builder for chaining
5319
- */
5320
- withoutReasoning(): this;
5321
- /**
5322
- * Enable context caching for supported providers.
5323
- *
5324
- * Can be called with:
5325
- * - No args: enables caching with defaults (`{ enabled: true }`)
5326
- * - A full config object: `withCaching({ enabled: true, scope: "system", ttl: "7200s" })`
5327
- *
5328
- * Provider behavior:
5329
- * - **Anthropic**: Caching is always-on by default via `cache_control` markers.
5330
- * Calling `withCaching()` explicitly is a no-op (it's already enabled).
5331
- * - **Gemini**: Creates an explicit cache via `caches.create()` for the configured scope.
5332
- * - **OpenAI**: Server-side automatic caching (no-op).
5333
- *
5334
- * @param config - Optional caching configuration
5335
- * @returns This builder for chaining
5336
- *
5337
- * @example
5338
- * ```typescript
5339
- * // Simple — enable with defaults
5340
- * LLMist.createAgent()
5341
- * .withModel("gemini:gemini-2.5-flash")
5342
- * .withCaching()
5343
- * .ask("Analyze this large codebase...");
5344
- *
5345
- * // Cache only system prompt with longer TTL
5346
- * LLMist.createAgent()
5347
- * .withModel("gemini:gemini-2.5-pro")
5348
- * .withCaching({ enabled: true, scope: "system", ttl: "7200s" })
5349
- * .ask("...");
5350
- * ```
5351
- */
5352
- withCaching(config?: CachingConfig): this;
5353
- /**
5354
- * Explicitly disable context caching.
5355
- *
5356
- * For Anthropic, this removes `cache_control` markers from requests,
5357
- * opting out of prompt caching entirely.
5358
- *
5359
- * @returns This builder for chaining
5360
- *
5361
- * @example
5362
- * ```typescript
5363
- * // Disable Anthropic's automatic caching
5364
- * LLMist.createAgent()
5365
- * .withModel("sonnet")
5366
- * .withoutCaching()
5367
- * .ask("...");
5368
- * ```
5369
- */
5370
- withoutCaching(): this;
5371
- /**
5372
- * Set subagent configuration overrides.
5373
- *
5374
- * Subagent gadgets (like BrowseWeb) can read these settings from ExecutionContext
5375
- * to inherit model and other options from the CLI configuration.
5376
- *
5377
- * @param config - Subagent configuration map keyed by gadget name
5378
- * @returns This builder for chaining
5379
- *
5380
- * @example
5381
- * ```typescript
5382
- * .withSubagentConfig({
5383
- * BrowseWeb: { model: "inherit", maxIterations: 20, headless: true },
5384
- * CodeAnalyzer: { model: "sonnet", maxIterations: 10 }
5385
- * })
5386
- * ```
5387
- */
5388
- withSubagentConfig(config: SubagentConfigMap): this;
5389
- /**
5390
- * Share parent agent's ExecutionTree for unified event visibility.
5391
- *
5392
- * When building a subagent inside a gadget, call this method to share the
5393
- * parent's ExecutionTree. This is the **single source of truth** for all
5394
- * execution events, enabling:
5395
- *
5396
- * - **Unified cost tracking** - All nested agent costs aggregate automatically
5397
- * - **Real-time visibility** - Parent's `tree.onAll()` subscribers see all events
5398
- * - **Depth tracking** - Events have correct `depth` (1 for child, 2 for grandchild, etc.)
5399
- * - **Parent linking** - Events have `parentId` pointing to spawning gadget
5400
- * - **Media aggregation** - Use `tree.getSubtreeMedia(nodeId)` after completion
5401
- *
5402
- * **Signal Forwarding** - When parent context includes a signal, it's automatically
5403
- * forwarded to the subagent for proper cancellation propagation.
5404
- *
5405
- * **Logger Inheritance** - When parent context includes a logger, it's inherited
5406
- * by the subagent for consistent structured logging.
5407
- *
5408
- * @param ctx - ExecutionContext passed to the gadget's execute() method
5409
- * @param depth - Nesting depth (default: 1 for direct child)
5410
- * @returns This builder for chaining
5411
- *
5412
- * @example
5413
- * ```typescript
5414
- * // In a subagent gadget like BrowseWeb:
5415
- * execute: async (params, ctx) => {
5416
- * const agent = new AgentBuilder(client)
5417
- * .withModel(model)
5418
- * .withGadgets(Navigate, Click, Screenshot)
5419
- * .withParentContext(ctx) // <-- Shares parent's tree
5420
- * .ask(params.task);
5421
- *
5422
- * for await (const event of agent.run()) {
5423
- * // Events automatically flow through shared tree
5424
- * if (event.type === "text") {
5425
- * result = event.content;
5426
- * }
5427
- * }
5428
- *
5429
- * // After subagent completes, access aggregated data:
5430
- * const totalCost = ctx.tree?.getSubtreeCost(ctx.nodeId!);
5431
- * const allMedia = ctx.tree?.getSubtreeMedia(ctx.nodeId!);
5432
- * }
5433
- * ```
5434
- */
5435
- withParentContext(ctx: ExecutionContext, depth?: number): this;
5436
- /**
5437
- * Add an ephemeral trailing message that appears at the end of each LLM request.
5124
+ * Pre-activate a specific skill before the agent starts.
5125
+ * Instructions are injected into the system prompt.
5438
5126
  *
5439
- * The message is NOT persisted to conversation history - it only appears in the
5440
- * current LLM call. This is useful for injecting context-specific instructions
5441
- * or reminders without polluting the conversation history.
5442
- *
5443
- * @param message - Static string or function that generates the message
5444
- * @returns This builder for chaining
5445
- *
5446
- * @example
5447
- * ```typescript
5448
- * // Static message
5449
- * .withTrailingMessage("Always respond in JSON format.")
5450
- *
5451
- * // Dynamic message based on iteration
5452
- * .withTrailingMessage((ctx) =>
5453
- * `[Iteration ${ctx.iteration}/${ctx.maxIterations}] Stay focused on the task.`
5454
- * )
5455
- * ```
5127
+ * Note: each call replaces (not appends) the pre-activated skill for that name.
5128
+ * This is safe for REPL loops where the same builder is reused.
5456
5129
  */
5130
+ withSkill(name: string, args?: string): this;
5131
+ /** Clear all pre-activated skills. Call between REPL iterations. */
5132
+ clearPreActivatedSkills(): this;
5133
+ /** Add a directory to scan for skills. */
5134
+ withSkillsFrom(dir: string): this;
5135
+ /** Configure retry behavior for LLM API calls. */
5136
+ withRetry(config: RetryConfig): this;
5137
+ /** Disable automatic retry for LLM API calls. */
5138
+ withoutRetry(): this;
5139
+ /** Configure proactive rate limiting to prevent rate limit errors. */
5140
+ withRateLimits(config: RateLimitConfig): this;
5141
+ /** Set an abort signal for cancelling requests mid-flight. */
5142
+ withSignal(signal: AbortSignal): this;
5143
+ /** Enable reasoning/thinking mode for reasoning-capable models. */
5144
+ withReasoning(config?: ReasoningConfig | ReasoningEffort): this;
5145
+ /** Explicitly disable reasoning for this agent. */
5146
+ withoutReasoning(): this;
5147
+ /** Enable context caching for supported providers. */
5148
+ withCaching(config?: CachingConfig): this;
5149
+ /** Explicitly disable context caching. */
5150
+ withoutCaching(): this;
5151
+ /** Set subagent configuration overrides. */
5152
+ withSubagentConfig(config: SubagentConfigMap): this;
5153
+ /** Share parent agent's ExecutionTree for unified event visibility. */
5154
+ withParentContext(ctx: ExecutionContext, depth?: number): this;
5155
+ /** Add an ephemeral trailing message that appears at the end of each LLM request. */
5457
5156
  withTrailingMessage(message: TrailingMessage): this;
5458
- /**
5459
- * Add a synthetic gadget call to the conversation history.
5460
- *
5461
- * This is useful for in-context learning - showing the LLM what "past self"
5462
- * did correctly so it mimics the pattern. The call is formatted with proper
5463
- * markers and parameter format, including the invocation ID so the LLM can
5464
- * reference previous calls when building dependencies.
5465
- *
5466
- * @param gadgetName - Name of the gadget
5467
- * @param parameters - Parameters passed to the gadget
5468
- * @param result - Result returned by the gadget
5469
- * @param invocationId - Invocation ID (shown to LLM so it can reference for dependencies)
5470
- * @returns This builder for chaining
5471
- *
5472
- * @example
5473
- * ```typescript
5474
- * .withSyntheticGadgetCall(
5475
- * 'TellUser',
5476
- * {
5477
- * message: '👋 Hello!\n\nHere\'s what I can do:\n- Analyze code\n- Run commands',
5478
- * done: false,
5479
- * type: 'info'
5480
- * },
5481
- * 'ℹ️ 👋 Hello!\n\nHere\'s what I can do:\n- Analyze code\n- Run commands',
5482
- * 'gc_1'
5483
- * )
5484
- * ```
5485
- */
5157
+ /** Add a synthetic gadget call to the conversation history for in-context learning. */
5486
5158
  withSyntheticGadgetCall(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string): this;
5487
- /**
5488
- * Compose the final hooks, including trailing message injection if configured.
5489
- *
5490
- * Note: Subagent event visibility is now handled entirely by the ExecutionTree.
5491
- * When a subagent uses withParentContext(ctx), it shares the parent's tree,
5492
- * and all events are automatically visible to tree subscribers (like the TUI).
5493
- *
5494
- * Environment-based file logging (via LLMIST_LOG_RAW_DIRECTORY) is automatically
5495
- * injected if the env var is set. User-provided hooks take precedence.
5496
- */
5497
5159
  private composeHooks;
5160
+ private resolveSkillRegistry;
5498
5161
  /**
5499
- * Format parameters as block format with JSON Pointer paths.
5500
- */
5501
- private formatBlockParameters;
5502
- /**
5503
- * Build and create the agent with the given user prompt.
5504
- * Returns the Agent instance ready to run.
5505
- *
5506
- * @param userPrompt - User's question or request
5507
- * @returns Configured Agent instance
5508
- *
5509
- * @example
5510
- * ```typescript
5511
- * const agent = await LLMist.createAgent()
5512
- * .withModel("sonnet")
5513
- * .withGadgets(Calculator)
5514
- * .ask("What is 2+2?");
5515
- *
5516
- * for await (const event of agent.run()) {
5517
- * // handle events
5518
- * }
5519
- * ```
5520
- */
5521
- /**
5522
- * Build AgentOptions with the given user prompt.
5523
- * Centralizes options construction for ask(), askWithImage(), askWithContent(), and build().
5524
- *
5525
- * @param userPrompt - Optional user prompt (omitted for build() which has no prompt)
5162
+ * Resolve pre-activated skill instructions synchronously.
5163
+ * Reads SKILL.md from disk via readFileSync (skills are local files).
5526
5164
  */
5165
+ private resolvePreActivatedInstructions;
5527
5166
  private buildAgentOptions;
5167
+ /** Create agent and start with a user prompt. */
5528
5168
  ask(userPrompt: string): Agent;
5529
- /**
5530
- * Build and create the agent with a multimodal user prompt (text + image).
5531
- * Returns the Agent instance ready to run.
5532
- *
5533
- * @param textPrompt - Text prompt describing what to do with the image
5534
- * @param imageData - Image data (Buffer, Uint8Array, or base64 string)
5535
- * @param mimeType - Optional MIME type (auto-detected if not provided)
5536
- * @returns Configured Agent instance
5537
- *
5538
- * @example
5539
- * ```typescript
5540
- * const agent = LLMist.createAgent()
5541
- * .withModel("gpt-4o")
5542
- * .withSystem("You analyze images")
5543
- * .askWithImage(
5544
- * "What's in this image?",
5545
- * await fs.readFile("photo.jpg")
5546
- * );
5547
- *
5548
- * for await (const event of agent.run()) {
5549
- * // handle events
5550
- * }
5551
- * ```
5552
- */
5169
+ /** Create agent with multimodal input (text + image). */
5553
5170
  askWithImage(textPrompt: string, imageData: Buffer | Uint8Array | string, mimeType?: ImageMimeType): Agent;
5554
- /**
5555
- * Build and return an Agent configured with multimodal content.
5556
- * More flexible than askWithImage - accepts any combination of content parts.
5557
- *
5558
- * @param content - Array of content parts (text, images, audio)
5559
- * @returns A configured Agent ready for execution
5560
- *
5561
- * @example
5562
- * ```typescript
5563
- * import { text, imageFromBuffer, audioFromBuffer } from "llmist";
5564
- *
5565
- * const agent = LLMist.createAgent()
5566
- * .withModel("gemini:gemini-2.5-flash")
5567
- * .askWithContent([
5568
- * text("Describe this image and transcribe the audio:"),
5569
- * imageFromBuffer(imageData),
5570
- * audioFromBuffer(audioData),
5571
- * ]);
5572
- *
5573
- * for await (const event of agent.run()) {
5574
- * // handle events
5575
- * }
5576
- * ```
5577
- */
5171
+ /** Create agent with flexible multimodal content parts. */
5578
5172
  askWithContent(content: ContentPart[]): Agent;
5579
- /**
5580
- * Build, run, and collect only the text response.
5581
- * Convenient for simple queries where you just want the final answer.
5582
- *
5583
- * @param userPrompt - User's question or request
5584
- * @returns Promise resolving to the complete text response
5585
- *
5586
- * @example
5587
- * ```typescript
5588
- * const answer = await LLMist.createAgent()
5589
- * .withModel("gpt4-mini")
5590
- * .withGadgets(Calculator)
5591
- * .askAndCollect("What is 42 * 7?");
5592
- *
5593
- * console.log(answer); // "294"
5594
- * ```
5595
- */
5173
+ /** Run agent and collect text response. */
5596
5174
  askAndCollect(userPrompt: string): Promise<string>;
5597
- /**
5598
- * Build and run with event handlers.
5599
- * Combines agent creation and event handling in one call.
5600
- *
5601
- * @param userPrompt - User's question or request
5602
- * @param handlers - Event handlers
5603
- *
5604
- * @example
5605
- * ```typescript
5606
- * await LLMist.createAgent()
5607
- * .withModel("sonnet")
5608
- * .withGadgets(Calculator)
5609
- * .askWith("What is 2+2?", {
5610
- * onText: (text) => console.log("LLM:", text),
5611
- * onGadgetResult: (result) => console.log("Result:", result.result),
5612
- * });
5613
- * ```
5614
- */
5175
+ /** Run agent with event handlers. */
5615
5176
  askWith(userPrompt: string, handlers: EventHandlers): Promise<void>;
5616
- /**
5617
- * Build the agent without a user prompt.
5618
- *
5619
- * Returns an Agent instance that can be inspected (e.g., check registered gadgets)
5620
- * but cannot be run without first calling .ask(prompt).
5621
- *
5622
- * This is useful for:
5623
- * - Testing: Inspect the registry, configuration, etc.
5624
- * - Advanced use cases: Build agent configuration separately from execution
5625
- *
5626
- * @returns Configured Agent instance (without user prompt)
5627
- *
5628
- * @example
5629
- * ```typescript
5630
- * // Build agent for inspection
5631
- * const agent = new AgentBuilder()
5632
- * .withModel("sonnet")
5633
- * .withGadgets(Calculator, Weather)
5634
- * .build();
5635
- *
5636
- * // Inspect registered gadgets
5637
- * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']
5638
- *
5639
- * // Note: Calling agent.run() will throw an error
5640
- * // Use .ask(prompt) instead if you want to run the agent
5641
- * ```
5642
- */
5177
+ /** Build agent without a prompt (useful for testing/inspection). */
5643
5178
  build(): Agent;
5644
5179
  }
5645
5180
 
@@ -6258,6 +5793,109 @@ interface IConversationManager {
6258
5793
  getConversationHistory(): LLMMessage[];
6259
5794
  }
6260
5795
 
5796
+ /**
5797
+ * Storage for large gadget outputs that exceed the configured limit.
5798
+ *
5799
+ * When a gadget returns more data than the configured limit, the output
5800
+ * is stored here and can be browsed later using GadgetOutputViewer.
5801
+ */
5802
+ /**
5803
+ * Metadata and content for a stored gadget output.
5804
+ */
5805
+ interface StoredOutput {
5806
+ /** Unique identifier (e.g., "Search_d34db33f") */
5807
+ id: string;
5808
+ /** Name of the gadget that produced this output */
5809
+ gadgetName: string;
5810
+ /** Full output content */
5811
+ content: string;
5812
+ /** Size in bytes */
5813
+ byteSize: number;
5814
+ /** Number of lines */
5815
+ lineCount: number;
5816
+ /** When the output was stored */
5817
+ timestamp: Date;
5818
+ }
5819
+ /**
5820
+ * In-memory store for large gadget outputs.
5821
+ *
5822
+ * Outputs are stored with generated IDs in the format `{GadgetName}_{hex8}`.
5823
+ * The store is tied to an agent run and cleared when the agent completes.
5824
+ *
5825
+ * @example
5826
+ * ```typescript
5827
+ * const store = new GadgetOutputStore();
5828
+ * const id = store.store("Search", largeOutput);
5829
+ * // id = "Search_a1b2c3d4"
5830
+ *
5831
+ * const stored = store.get(id);
5832
+ * console.log(stored?.lineCount); // 4200
5833
+ * ```
5834
+ */
5835
+ declare class GadgetOutputStore {
5836
+ private outputs;
5837
+ /**
5838
+ * Store a gadget output and return its ID.
5839
+ *
5840
+ * @param gadgetName - Name of the gadget that produced the output
5841
+ * @param content - Full output content to store
5842
+ * @returns Generated ID for retrieving the output later
5843
+ */
5844
+ store(gadgetName: string, content: string): string;
5845
+ /**
5846
+ * Retrieve a stored output by ID.
5847
+ *
5848
+ * @param id - The output ID (e.g., "Search_d34db33f")
5849
+ * @returns The stored output or undefined if not found
5850
+ */
5851
+ get(id: string): StoredOutput | undefined;
5852
+ /**
5853
+ * Check if an output exists.
5854
+ *
5855
+ * @param id - The output ID to check
5856
+ * @returns True if the output exists
5857
+ */
5858
+ has(id: string): boolean;
5859
+ /**
5860
+ * Get all stored output IDs.
5861
+ *
5862
+ * @returns Array of output IDs
5863
+ */
5864
+ getIds(): string[];
5865
+ /**
5866
+ * Get the number of stored outputs.
5867
+ */
5868
+ get size(): number;
5869
+ /**
5870
+ * Clear all stored outputs.
5871
+ * Called when the agent run completes.
5872
+ */
5873
+ clear(): void;
5874
+ /**
5875
+ * Generate a unique ID for a stored output.
5876
+ * Format: {GadgetName}_{8 hex chars}
5877
+ */
5878
+ private generateId;
5879
+ }
5880
+
5881
+ /**
5882
+ * OutputLimitManager - Manages gadget output size limiting.
5883
+ *
5884
+ * Calculates character limits from model context windows, registers
5885
+ * GadgetOutputViewer when enabled, and chains the output limiter
5886
+ * interceptor with user-provided hooks.
5887
+ */
5888
+
5889
+ /**
5890
+ * Configuration for output limiting.
5891
+ */
5892
+ interface OutputLimitConfig {
5893
+ /** Whether output limiting is enabled (default: true) */
5894
+ enabled?: boolean;
5895
+ /** Max gadget output as % of model context window (default: 15) */
5896
+ limitPercent?: number;
5897
+ }
5898
+
6261
5899
  /**
6262
5900
  * Agent: Lean orchestrator using the clean hooks architecture.
6263
5901
  *
@@ -6265,6 +5903,46 @@ interface IConversationManager {
6265
5903
  * making it a simple loop orchestrator with clear responsibilities.
6266
5904
  */
6267
5905
 
5906
+ /**
5907
+ * Configuration for the execution tree context (shared tree model with subagents).
5908
+ */
5909
+ interface TreeConfig {
5910
+ /**
5911
+ * Shared execution tree for tracking all LLM calls and gadget executions.
5912
+ * If provided (by a parent subagent), nodes are added to this tree.
5913
+ * If not provided, the Agent creates its own tree.
5914
+ */
5915
+ tree?: ExecutionTree;
5916
+ /**
5917
+ * Parent node ID in the tree (when this agent is a subagent).
5918
+ * Used to set parentId on all nodes created by this agent.
5919
+ */
5920
+ parentNodeId?: NodeId;
5921
+ /**
5922
+ * Base depth for nodes created by this agent.
5923
+ * Root agents use 0; subagents use (parentDepth + 1).
5924
+ */
5925
+ baseDepth?: number;
5926
+ /**
5927
+ * Parent agent's observer hooks for subagent visibility.
5928
+ *
5929
+ * When a subagent is created with withParentContext(ctx), these observers
5930
+ * are also called for gadget events (in addition to the subagent's own hooks),
5931
+ * enabling the parent to observe subagent gadget activity.
5932
+ */
5933
+ parentObservers?: Observers;
5934
+ }
5935
+ /**
5936
+ * Configuration for custom gadget block format prefixes.
5937
+ */
5938
+ interface PrefixConfig {
5939
+ /** Custom gadget start prefix */
5940
+ gadgetStartPrefix?: string;
5941
+ /** Custom gadget end prefix */
5942
+ gadgetEndPrefix?: string;
5943
+ /** Custom gadget argument prefix for block format parameters */
5944
+ gadgetArgPrefix?: string;
5945
+ }
6268
5946
  /**
6269
5947
  * Configuration options for the Agent.
6270
5948
  */
@@ -6291,12 +5969,10 @@ interface AgentOptions {
6291
5969
  hooks?: AgentHooks;
6292
5970
  /** Callback for requesting human input during execution */
6293
5971
  requestHumanInput?: (question: string) => Promise<string>;
6294
- /** Custom gadget start prefix */
6295
- gadgetStartPrefix?: string;
6296
- /** Custom gadget end prefix */
6297
- gadgetEndPrefix?: string;
6298
- /** Custom gadget argument prefix for block format parameters */
6299
- gadgetArgPrefix?: string;
5972
+ /**
5973
+ * Gadget prefix configuration (start/end/arg prefixes for block format).
5974
+ */
5975
+ prefixConfig?: PrefixConfig;
6300
5976
  /** Initial messages. User messages support multimodal content. */
6301
5977
  initialMessages?: Array<{
6302
5978
  role: "system" | "user" | "assistant";
@@ -6322,10 +5998,10 @@ interface AgentOptions {
6322
5998
  gadgetExecutionMode?: GadgetExecutionMode;
6323
5999
  /** Custom prompt configuration for gadget system prompts */
6324
6000
  promptConfig?: PromptTemplateConfig;
6325
- /** Enable gadget output limiting (default: true) */
6326
- gadgetOutputLimit?: boolean;
6327
- /** Max gadget output as % of model context window (default: 15) */
6328
- gadgetOutputLimitPercent?: number;
6001
+ /**
6002
+ * Gadget output limit configuration.
6003
+ */
6004
+ outputLimitConfig?: OutputLimitConfig;
6329
6005
  /** Context compaction configuration (enabled by default) */
6330
6006
  compactionConfig?: CompactionConfig;
6331
6007
  /** Retry configuration for LLM API calls (enabled by default) */
@@ -6343,29 +6019,9 @@ interface AgentOptions {
6343
6019
  /** Maximum gadgets to execute per LLM response (0 = unlimited) */
6344
6020
  maxGadgetsPerResponse?: number;
6345
6021
  /**
6346
- * Shared execution tree for tracking all LLM calls and gadget executions.
6347
- * If provided (by a parent subagent), nodes are added to this tree.
6348
- * If not provided, the Agent creates its own tree.
6349
- */
6350
- parentTree?: ExecutionTree;
6351
- /**
6352
- * Parent node ID in the tree (when this agent is a subagent).
6353
- * Used to set parentId on all nodes created by this agent.
6354
- */
6355
- parentNodeId?: NodeId;
6356
- /**
6357
- * Base depth for nodes created by this agent.
6358
- * Root agents use 0; subagents use (parentDepth + 1).
6359
- */
6360
- baseDepth?: number;
6361
- /**
6362
- * Parent agent's observer hooks for subagent visibility.
6363
- *
6364
- * When a subagent is created with withParentContext(ctx), these observers
6365
- * are also called for gadget events (in addition to the subagent's own hooks),
6366
- * enabling the parent to observe subagent gadget activity.
6022
+ * Execution tree configuration (shared tree model with subagents).
6367
6023
  */
6368
- parentObservers?: Observers;
6024
+ treeConfig?: TreeConfig;
6369
6025
  /**
6370
6026
  * Shared rate limit tracker from parent agent.
6371
6027
  *
@@ -6406,19 +6062,11 @@ declare class Agent {
6406
6062
  private readonly hooks;
6407
6063
  private readonly conversation;
6408
6064
  private readonly registry;
6409
- private readonly gadgetStartPrefix?;
6410
- private readonly gadgetEndPrefix?;
6411
- private readonly gadgetArgPrefix?;
6412
- private readonly requestHumanInput?;
6413
- private readonly textOnlyHandler;
6414
- private readonly textWithGadgetsHandler?;
6415
- private readonly defaultGadgetTimeoutMs?;
6416
- private readonly gadgetExecutionMode;
6065
+ private readonly prefixConfig?;
6066
+ private readonly conversationUpdater;
6417
6067
  private readonly defaultMaxTokens?;
6418
6068
  private hasUserPrompt;
6419
- private readonly outputStore;
6420
- private readonly outputLimitEnabled;
6421
- private readonly outputLimitCharLimit;
6069
+ private readonly outputLimitManager;
6422
6070
  private readonly compactionManager?;
6423
6071
  private readonly mediaStore;
6424
6072
  private readonly signal?;
@@ -6426,17 +6074,13 @@ declare class Agent {
6426
6074
  private readonly caching?;
6427
6075
  private readonly retryConfig;
6428
6076
  private readonly rateLimitTracker?;
6429
- private readonly agentContextConfig;
6430
- private readonly subagentConfig?;
6431
- private readonly maxGadgetsPerResponse;
6432
- private syntheticInvocationCounter;
6433
6077
  private readonly completedInvocationIds;
6434
6078
  private readonly failedInvocationIds;
6435
6079
  private readonly pendingUserMessages;
6436
6080
  private readonly tree;
6437
6081
  private readonly parentNodeId;
6438
- private readonly baseDepth;
6439
- private readonly parentObservers?;
6082
+ private readonly streamProcessorFactory;
6083
+ private readonly llmCallLifecycle;
6440
6084
  /**
6441
6085
  * Creates a new Agent instance.
6442
6086
  * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.
@@ -6617,6 +6261,16 @@ declare class Agent {
6617
6261
  * @throws {Error} If no user prompt was provided (when using build() without ask())
6618
6262
  */
6619
6263
  run(): AsyncGenerator<StreamEvent>;
6264
+ /**
6265
+ * Execute a single LLM call attempt with full retry orchestration.
6266
+ *
6267
+ * Delegates all retry logic to RetryOrchestrator, then propagates the accumulated
6268
+ * invocation IDs back to the agent's cross-iteration tracking sets.
6269
+ *
6270
+ * Yields stream events in real-time and returns the final stream completion metadata
6271
+ * along with accumulated tracking state from the final successful attempt only.
6272
+ */
6273
+ private executeWithRetry;
6620
6274
  /**
6621
6275
  * Create LLM stream with proactive rate limit protection.
6622
6276
  *
@@ -6625,26 +6279,20 @@ declare class Agent {
6625
6279
  */
6626
6280
  private createStream;
6627
6281
  /**
6628
- * Simple sleep utility for rate limit delays.
6629
- */
6630
- private sleep;
6631
- /**
6632
- * Handle LLM error through controller.
6282
+ * Factory method for constructing a StreamProcessor for a given iteration.
6283
+ *
6284
+ * Delegates to StreamProcessorFactory, which encapsulates all static
6285
+ * StreamProcessor configuration. Cross-iteration mutable state is passed here.
6633
6286
  */
6634
- private handleLLMError;
6287
+ private createStreamProcessor;
6635
6288
  /**
6636
- * Handle text-only response (no gadgets called).
6289
+ * Simple sleep utility for rate limit delays.
6637
6290
  */
6638
- private handleTextOnlyResponse;
6291
+ private sleep;
6639
6292
  /**
6640
6293
  * Resolve max tokens from model catalog.
6641
6294
  */
6642
6295
  private resolveMaxTokensFromCatalog;
6643
- /**
6644
- * Chain the output limiter interceptor with user-provided hooks.
6645
- * The limiter runs first, then chains to any user interceptor.
6646
- */
6647
- private chainOutputLimiterWithUserHooks;
6648
6296
  /**
6649
6297
  * Check abort signal and notify observers if aborted.
6650
6298
  * @returns true if agent should terminate
@@ -6655,43 +6303,6 @@ declare class Agent {
6655
6303
  * @returns compaction stream event if compaction occurred, null otherwise
6656
6304
  */
6657
6305
  private checkAndPerformCompaction;
6658
- /**
6659
- * Resolve reasoning configuration with auto-enable logic.
6660
- *
6661
- * Priority: explicit config > auto-enable for reasoning models > undefined
6662
- * When a model has `features.reasoning: true` and no explicit config is set,
6663
- * reasoning is automatically enabled at "medium" effort.
6664
- */
6665
- private resolveReasoningConfig;
6666
- /**
6667
- * Resolve caching configuration.
6668
- *
6669
- * Priority: explicit config > default enabled (preserves Anthropic's existing behavior)
6670
- * Default is `{ enabled: true }` which means:
6671
- * - Anthropic: `cache_control` markers are added (existing behavior preserved)
6672
- * - Gemini: Cache manager is consulted but skips if no explicit config was set
6673
- * - OpenAI: No-op (server-side automatic)
6674
- */
6675
- private resolveCachingConfig;
6676
- /**
6677
- * Prepare LLM call options, create tree node, and process beforeLLMCall controller.
6678
- * @returns options, node ID, and optional skipWithSynthetic response if controller wants to skip
6679
- */
6680
- private prepareLLMCall;
6681
- /**
6682
- * Calculate cost and complete LLM call in execution tree.
6683
- * Also records usage to rate limit tracker for proactive throttling.
6684
- */
6685
- private completeLLMCallInTree;
6686
- /**
6687
- * Process afterLLMCall controller and return modified final message.
6688
- */
6689
- private processAfterLLMCallController;
6690
- /**
6691
- * Update conversation history with gadget results or text-only response.
6692
- * @returns true if loop should break (text-only handler requested termination)
6693
- */
6694
- private updateConversationWithResults;
6695
6306
  /**
6696
6307
  * Run agent with named event handlers (syntactic sugar).
6697
6308
  *
@@ -7851,91 +7462,6 @@ declare class ConversationManager implements IConversationManager {
7851
7462
  getConversationHistory(): LLMMessage[];
7852
7463
  }
7853
7464
 
7854
- /**
7855
- * Storage for large gadget outputs that exceed the configured limit.
7856
- *
7857
- * When a gadget returns more data than the configured limit, the output
7858
- * is stored here and can be browsed later using GadgetOutputViewer.
7859
- */
7860
- /**
7861
- * Metadata and content for a stored gadget output.
7862
- */
7863
- interface StoredOutput {
7864
- /** Unique identifier (e.g., "Search_d34db33f") */
7865
- id: string;
7866
- /** Name of the gadget that produced this output */
7867
- gadgetName: string;
7868
- /** Full output content */
7869
- content: string;
7870
- /** Size in bytes */
7871
- byteSize: number;
7872
- /** Number of lines */
7873
- lineCount: number;
7874
- /** When the output was stored */
7875
- timestamp: Date;
7876
- }
7877
- /**
7878
- * In-memory store for large gadget outputs.
7879
- *
7880
- * Outputs are stored with generated IDs in the format `{GadgetName}_{hex8}`.
7881
- * The store is tied to an agent run and cleared when the agent completes.
7882
- *
7883
- * @example
7884
- * ```typescript
7885
- * const store = new GadgetOutputStore();
7886
- * const id = store.store("Search", largeOutput);
7887
- * // id = "Search_a1b2c3d4"
7888
- *
7889
- * const stored = store.get(id);
7890
- * console.log(stored?.lineCount); // 4200
7891
- * ```
7892
- */
7893
- declare class GadgetOutputStore {
7894
- private outputs;
7895
- /**
7896
- * Store a gadget output and return its ID.
7897
- *
7898
- * @param gadgetName - Name of the gadget that produced the output
7899
- * @param content - Full output content to store
7900
- * @returns Generated ID for retrieving the output later
7901
- */
7902
- store(gadgetName: string, content: string): string;
7903
- /**
7904
- * Retrieve a stored output by ID.
7905
- *
7906
- * @param id - The output ID (e.g., "Search_d34db33f")
7907
- * @returns The stored output or undefined if not found
7908
- */
7909
- get(id: string): StoredOutput | undefined;
7910
- /**
7911
- * Check if an output exists.
7912
- *
7913
- * @param id - The output ID to check
7914
- * @returns True if the output exists
7915
- */
7916
- has(id: string): boolean;
7917
- /**
7918
- * Get all stored output IDs.
7919
- *
7920
- * @returns Array of output IDs
7921
- */
7922
- getIds(): string[];
7923
- /**
7924
- * Get the number of stored outputs.
7925
- */
7926
- get size(): number;
7927
- /**
7928
- * Clear all stored outputs.
7929
- * Called when the agent run completes.
7930
- */
7931
- clear(): void;
7932
- /**
7933
- * Generate a unique ID for a stored output.
7934
- * Format: {GadgetName}_{8 hex chars}
7935
- */
7936
- private generateId;
7937
- }
7938
-
7939
7465
  /**
7940
7466
  * LLM Assistance Hints System
7941
7467
  *
@@ -8114,6 +7640,18 @@ declare function createHints(config: HintsConfig): AgentHooks;
8114
7640
  *
8115
7641
  * Replaces the complex wiring between Agent, ResponseProcessor, and GadgetRuntime.
8116
7642
  * Owns ALL stream processing and hook coordination with a clean, predictable flow.
7643
+ *
7644
+ * After refactoring, StreamProcessor is a thin orchestrator (~300 lines) that:
7645
+ * - Iterates over raw LLM stream chunks
7646
+ * - Applies raw-chunk and text-chunk interceptors
7647
+ * - Delegates gadget dispatch to GadgetDispatcher
7648
+ * - Yields events in real-time
7649
+ * - Applies the final assistant-message interceptor
7650
+ *
7651
+ * Extracted classes:
7652
+ * - GadgetLimitGuard — maxGadgetsPerResponse enforcement
7653
+ * - GadgetHookLifecycle — full hook sequence for a single gadget
7654
+ * - GadgetDispatcher — dispatch decision tree + concurrency + dependency
8117
7655
  */
8118
7656
 
8119
7657
  /**
@@ -8181,6 +7719,11 @@ interface StreamProcessorOptions {
8181
7719
  }
8182
7720
  /**
8183
7721
  * Result of stream processing.
7722
+ *
7723
+ * @deprecated StreamProcessor.process() is now an async generator that yields
7724
+ * StreamEvent items directly. Use StreamCompletionEvent (the final yielded event)
7725
+ * to obtain the metadata formerly returned in this type. This interface is retained
7726
+ * for backward compatibility but is not used internally.
8184
7727
  */
8185
7728
  interface StreamProcessingResult {
8186
7729
  /** All emitted events */
@@ -8199,21 +7742,14 @@ interface StreamProcessingResult {
8199
7742
  finalMessage: string;
8200
7743
  }
8201
7744
  /**
8202
- * StreamProcessor: Coordinates all stream processing and hook execution.
7745
+ * StreamProcessor: Thin orchestrator for stream processing and hook coordination.
8203
7746
  *
8204
7747
  * Execution order:
8205
7748
  * 1. Raw chunk arrives from LLM
8206
7749
  * 2. Interceptor: interceptRawChunk (transform raw text)
8207
7750
  * 3. Observer: onStreamChunk (logging)
8208
7751
  * 4. Parse for gadgets
8209
- * 5. If gadget found:
8210
- * a. Interceptor: interceptGadgetParameters (transform params)
8211
- * b. Controller: beforeGadgetExecution (can skip)
8212
- * c. Observer: onGadgetExecutionStart
8213
- * d. Execute gadget
8214
- * e. Interceptor: interceptGadgetResult (transform result)
8215
- * f. Controller: afterGadgetExecution (can provide fallback)
8216
- * g. Observer: onGadgetExecutionComplete
7752
+ * 5. If gadget found → delegate to GadgetDispatcher
8217
7753
  * 6. If text chunk:
8218
7754
  * a. Interceptor: interceptTextChunk (transform display text)
8219
7755
  * b. Yield to user
@@ -8225,20 +7761,13 @@ declare class StreamProcessor {
8225
7761
  private readonly hooks;
8226
7762
  private readonly logger;
8227
7763
  private readonly parser;
8228
- private readonly executor;
8229
7764
  private readonly tree?;
8230
- private readonly parentNodeId;
8231
- private readonly baseDepth;
8232
- private readonly gadgetExecutionMode;
8233
7765
  private responseText;
8234
7766
  private readonly dependencyResolver;
8235
- private readonly concurrencyManager;
8236
7767
  /** Queue of completed gadget results ready to be yielded (for real-time streaming) */
8237
7768
  private completedResultsQueue;
8238
- private readonly parentObservers?;
8239
- private readonly maxGadgetsPerResponse;
8240
- private gadgetStartedCount;
8241
- private limitExceeded;
7769
+ private readonly dispatcher;
7770
+ private readonly limitGuard;
8242
7771
  constructor(options: StreamProcessorOptions);
8243
7772
  /**
8244
7773
  * Process an LLM stream and yield events in real-time.
@@ -8259,30 +7788,6 @@ declare class StreamProcessor {
8259
7788
  * Process a text event through interceptors.
8260
7789
  */
8261
7790
  private processTextEvent;
8262
- /**
8263
- * Process a gadget call, yielding events in real-time.
8264
- *
8265
- * Yields gadget_call event IMMEDIATELY when parsed (before execution),
8266
- * enabling real-time UI feedback.
8267
- */
8268
- private processGadgetCallGenerator;
8269
- /**
8270
- * Start a gadget execution with concurrency tracking.
8271
- * Delegates tracking to GadgetConcurrencyManager; schedules queue processing on completion.
8272
- */
8273
- private startGadgetWithConcurrencyTracking;
8274
- /**
8275
- * Execute a gadget through the full hook lifecycle and yield events.
8276
- * Handles parameter interception, before/after controllers, observers,
8277
- * execution, result interception, and tree tracking.
8278
- */
8279
- private executeGadgetGenerator;
8280
- /**
8281
- * Execute a gadget and push events to the completed results queue (non-blocking).
8282
- * Used for fire-and-forget parallel execution of independent gadgets.
8283
- * Results are pushed to completedResultsQueue for real-time streaming to the caller.
8284
- */
8285
- private executeGadgetAndCollect;
8286
7791
  /**
8287
7792
  * Drain all completed results from the queue.
8288
7793
  * Used to yield results as they complete during stream processing.
@@ -8290,35 +7795,14 @@ declare class StreamProcessor {
8290
7795
  */
8291
7796
  private drainCompletedResults;
8292
7797
  /**
8293
- * Wait for all in-flight gadget executions to complete, yielding events in real-time.
8294
- * Called at stream end to ensure all parallel executions finish.
8295
- * Results and subagent events are pushed to completedResultsQueue during execution.
8296
- * This generator yields queued events while polling, enabling real-time display
8297
- * of subagent activity (LLM calls, nested gadgets) during long-running gadgets.
8298
- * Clears the inFlightExecutions map after all gadgets complete.
8299
- */
8300
- private waitForInFlightExecutions;
8301
- /**
8302
- * Handle a gadget that cannot execute because a dependency failed.
8303
- * Calls the onDependencySkipped controller to allow customization.
8304
- */
8305
- private handleFailedDependency;
8306
- /**
8307
- * Check if gadget execution should be skipped due to maxGadgetsPerResponse limit.
8308
- * If limit is exceeded, yields skip events and returns true.
8309
- * If execution can proceed, increments counter and returns false.
8310
- *
8311
- * @returns true if gadget should be skipped, false if execution can proceed
8312
- */
8313
- private checkGadgetLimitExceeded;
8314
- /**
8315
- * Process pending gadgets whose dependencies are now satisfied.
8316
- * Yields events in real-time as gadgets complete.
7798
+ * Update gadget result tracking flags based on a stream event.
7799
+ * Checks if the event is a gadget_result and, if so, marks gadgets as executed
7800
+ * and sets the break-loop flag when the result requests it.
8317
7801
  *
8318
- * Gadgets are executed in parallel for efficiency,
8319
- * but results are yielded as they become available.
7802
+ * @param evt - The stream event to inspect
7803
+ * @param state - Mutable state object holding the tracking flags
8320
7804
  */
8321
- private processPendingGadgetsGenerator;
7805
+ private trackGadgetResult;
8322
7806
  /**
8323
7807
  * Execute multiple observers in parallel.
8324
7808
  * All observers run concurrently and failures are tracked but don't crash.
@@ -8492,6 +7976,26 @@ declare function getProvider(model: string): string | undefined;
8492
7976
  * ```
8493
7977
  */
8494
7978
  declare function getModelId(model: string): string;
7979
+ /**
7980
+ * Strip the provider prefix from a model string.
7981
+ *
7982
+ * Identical to {@link getModelId}: removes the `provider:` portion and returns
7983
+ * just the model ID. If there is no prefix, the original string is returned.
7984
+ *
7985
+ * Use this when you need the bare model ID (e.g. for a cost-registry lookup)
7986
+ * and the input may or may not carry a provider prefix.
7987
+ *
7988
+ * @param modelId - Full model string, optionally with provider prefix
7989
+ * @returns Model ID without provider prefix
7990
+ *
7991
+ * @example
7992
+ * ```typescript
7993
+ * stripProviderPrefix('openai:gpt-4o') // → 'gpt-4o'
7994
+ * stripProviderPrefix('anthropic:claude-sonnet') // → 'claude-sonnet'
7995
+ * stripProviderPrefix('gpt-4o') // → 'gpt-4o' (no prefix — returned as-is)
7996
+ * ```
7997
+ */
7998
+ declare function stripProviderPrefix(modelId: string): string;
8495
7999
 
8496
8000
  /**
8497
8001
  * Signal that a gadget throws to indicate task completion and agent termination.
@@ -8656,6 +8160,51 @@ interface ErrorFormatterOptions {
8656
8160
  endPrefix?: string;
8657
8161
  }
8658
8162
 
8163
+ /**
8164
+ * Options for constructing a GadgetExecutor.
8165
+ */
8166
+ interface GadgetExecutorOptions {
8167
+ /** Gadget registry used to look up and execute gadgets */
8168
+ registry: GadgetRegistry;
8169
+ /** Optional callback to request human input during gadget execution */
8170
+ requestHumanInput?: (question: string) => Promise<string>;
8171
+ /** Logger instance; defaults to a new "llmist:executor" logger if omitted */
8172
+ logger?: Logger<ILogObj>;
8173
+ /** Default timeout in milliseconds applied to all gadgets without an explicit timeout */
8174
+ defaultGadgetTimeoutMs?: number;
8175
+ /** Options for formatting gadget execution errors */
8176
+ errorFormatterOptions?: ErrorFormatterOptions;
8177
+ /** LLMist client made available to gadgets via ExecutionContext.llmist */
8178
+ client?: LLMist;
8179
+ /** Media store for persisting gadget media outputs */
8180
+ mediaStore?: MediaStore;
8181
+ /** Parent agent configuration inherited by subagents */
8182
+ agentConfig?: AgentContextConfig;
8183
+ /** Per-gadget configuration overrides (e.g., timeoutMs, model) */
8184
+ subagentConfig?: SubagentConfigMap;
8185
+ /** Execution tree for tracking LLM calls and gadget executions */
8186
+ tree?: ExecutionTree;
8187
+ /** Parent node ID in the execution tree */
8188
+ parentNodeId?: NodeId | null;
8189
+ /** Base depth for nodes created during execution */
8190
+ baseDepth?: number;
8191
+ /**
8192
+ * Parent agent's observer hooks for subagent visibility.
8193
+ * When a subagent uses withParentContext(ctx), these observers are also called
8194
+ * for gadget events in addition to the subagent's own hooks.
8195
+ */
8196
+ parentObservers?: Observers;
8197
+ /**
8198
+ * Current agent's observers.
8199
+ * Passed to ExecutionContext.parentObservers so gadgets creating subagents
8200
+ * can inherit them via withParentContext(ctx).
8201
+ */
8202
+ currentObservers?: Observers;
8203
+ /** Shared rate limit tracker for coordinated throttling across subagents */
8204
+ rateLimitTracker?: RateLimitTracker;
8205
+ /** Shared retry config for consistent backoff behavior across subagents */
8206
+ retryConfig?: ResolvedRetryConfig;
8207
+ }
8659
8208
  declare class GadgetExecutor {
8660
8209
  private readonly registry;
8661
8210
  private readonly requestHumanInput?;
@@ -8674,7 +8223,7 @@ declare class GadgetExecutor {
8674
8223
  private readonly logger;
8675
8224
  private readonly errorFormatter;
8676
8225
  private readonly argPrefix;
8677
- constructor(registry: GadgetRegistry, requestHumanInput?: ((question: string) => Promise<string>) | undefined, logger?: Logger<ILogObj>, defaultGadgetTimeoutMs?: number | undefined, errorFormatterOptions?: ErrorFormatterOptions, client?: LLMist | undefined, mediaStore?: MediaStore | undefined, agentConfig?: AgentContextConfig | undefined, subagentConfig?: SubagentConfigMap | undefined, tree?: ExecutionTree | undefined, parentNodeId?: (NodeId | null) | undefined, baseDepth?: number | undefined, parentObservers?: Observers | undefined, currentObservers?: Observers | undefined, rateLimitTracker?: RateLimitTracker | undefined, retryConfig?: ResolvedRetryConfig | undefined);
8226
+ constructor(options: GadgetExecutorOptions);
8678
8227
  /**
8679
8228
  * Creates a promise that rejects with a TimeoutException after the specified timeout.
8680
8229
  * Aborts the provided AbortController before rejecting, allowing gadgets to clean up.
@@ -8688,7 +8237,6 @@ declare class GadgetExecutor {
8688
8237
  */
8689
8238
  private unifyExecuteResult;
8690
8239
  execute(call: ParsedGadgetCall): Promise<GadgetExecutionResult>;
8691
- executeAll(calls: ParsedGadgetCall[]): Promise<GadgetExecutionResult[]>;
8692
8240
  }
8693
8241
 
8694
8242
  /**
@@ -9543,6 +9091,12 @@ interface LLMistPackageManifest {
9543
9091
  * Session factory metadata.
9544
9092
  */
9545
9093
  session?: SessionManifestEntry;
9094
+ /**
9095
+ * Skills directory relative to package root.
9096
+ * Contains subdirectories with SKILL.md files.
9097
+ * @example "./skills"
9098
+ */
9099
+ skills?: string;
9546
9100
  }
9547
9101
  /**
9548
9102
  * Factory function types that packages can export.
@@ -10440,6 +9994,146 @@ declare class SimpleSessionManager<TSession> extends BaseSessionManager<TSession
10440
9994
  setSession(id: string, data: TSession): void;
10441
9995
  }
10442
9996
 
9997
+ /**
9998
+ * Skill activation logic.
9999
+ *
10000
+ * Handles $ARGUMENTS substitution and !`command` shell preprocessing
10001
+ * to resolve skill instructions before injection into agent context.
10002
+ *
10003
+ * @module skills/activation
10004
+ */
10005
+ /**
10006
+ * Substitute $ARGUMENTS and positional $0, $1, etc. in skill instructions.
10007
+ */
10008
+ declare function substituteArguments(instructions: string, args?: string): string;
10009
+ /**
10010
+ * Substitute ${VARIABLE} environment-style variables in skill instructions.
10011
+ *
10012
+ * Supported variables:
10013
+ * - ${CLAUDE_SKILL_DIR} / ${SKILL_DIR} - directory containing SKILL.md
10014
+ * - ${CLAUDE_SESSION_ID} / ${SESSION_ID} - current session ID (if provided)
10015
+ */
10016
+ declare function substituteVariables(instructions: string, variables: Record<string, string>): string;
10017
+ /**
10018
+ * Full activation pipeline: variables -> arguments -> shell preprocessing.
10019
+ */
10020
+ declare function resolveInstructions(instructions: string, options?: {
10021
+ arguments?: string;
10022
+ variables?: Record<string, string>;
10023
+ cwd?: string;
10024
+ shell?: "bash" | "powershell";
10025
+ shellTimeoutMs?: number;
10026
+ enableShellPreprocessing?: boolean;
10027
+ }): string;
10028
+
10029
+ /**
10030
+ * Filesystem-based skill discovery and loading.
10031
+ *
10032
+ * Scans directories for subdirectories containing SKILL.md files.
10033
+ * Supports standard discovery locations and custom directories.
10034
+ *
10035
+ * @module skills/loader
10036
+ */
10037
+
10038
+ /**
10039
+ * Load skills from a directory.
10040
+ *
10041
+ * Recursively scans for subdirectories containing a SKILL.md file.
10042
+ * Each such directory is treated as a single skill.
10043
+ *
10044
+ * @param dir - Directory to scan
10045
+ * @param source - Origin for all discovered skills
10046
+ */
10047
+ declare function loadSkillsFromDirectory(dir: string, source: SkillSource, onWarning?: (msg: string) => void): Skill[];
10048
+ /**
10049
+ * Discover skills from standard locations.
10050
+ *
10051
+ * Discovery order (later sources overwrite earlier on name collision):
10052
+ * 1. User skills: ~/.llmist/skills/
10053
+ * 2. Project skills: <projectDir>/.llmist/skills/
10054
+ * 3. Additional directories (explicit)
10055
+ */
10056
+ declare function discoverSkills(options?: {
10057
+ projectDir?: string;
10058
+ userDir?: string;
10059
+ additionalDirs?: string[];
10060
+ }): SkillRegistry;
10061
+
10062
+ /**
10063
+ * SKILL.md parser for the Agent Skills open standard.
10064
+ *
10065
+ * Parses YAML frontmatter (between --- markers) and markdown body.
10066
+ * Scans skill directories for Tier 3 resources (scripts/, references/, assets/).
10067
+ *
10068
+ * @module skills/parser
10069
+ */
10070
+
10071
+ /**
10072
+ * Parse YAML frontmatter from SKILL.md content.
10073
+ *
10074
+ * Extracts the YAML block between the first pair of `---` markers
10075
+ * and the remaining markdown body.
10076
+ */
10077
+ declare function parseFrontmatter(content: string): {
10078
+ frontmatter: Record<string, unknown>;
10079
+ body: string;
10080
+ };
10081
+ /**
10082
+ * Convert raw frontmatter to validated SkillMetadata.
10083
+ *
10084
+ * Maps kebab-case YAML keys to camelCase TypeScript properties.
10085
+ * Falls back to directory name for missing name field.
10086
+ */
10087
+ declare function parseMetadata(frontmatter: Record<string, unknown>, fallbackName?: string): SkillMetadata;
10088
+ /**
10089
+ * Scan a skill directory for Tier 3 resource files.
10090
+ */
10091
+ declare function scanResources(skillDir: string): SkillResource[];
10092
+ /**
10093
+ * Parse a SKILL.md file from disk.
10094
+ *
10095
+ * This performs Tier 1 parsing (metadata) and optionally Tier 2 (instructions).
10096
+ * Resources are discovered but not loaded.
10097
+ *
10098
+ * @param skillMdPath - Absolute path to SKILL.md
10099
+ * @param source - Where this skill was discovered from
10100
+ * @param loadInstructions - Whether to load Tier 2 body (default: false for lazy loading)
10101
+ */
10102
+ declare function parseSkillFile(skillMdPath: string, source: SkillSource, loadInstructions?: boolean): ParsedSkill;
10103
+ /**
10104
+ * Parse SKILL.md content from a string.
10105
+ *
10106
+ * Useful for testing without filesystem access.
10107
+ */
10108
+ declare function parseSkillContent(content: string, sourcePath: string, source: SkillSource, loadInstructions?: boolean): ParsedSkill;
10109
+ /**
10110
+ * Validate skill metadata.
10111
+ * Returns an array of validation issues (empty if valid).
10112
+ */
10113
+ declare function validateMetadata(metadata: SkillMetadata): string[];
10114
+
10115
+ /**
10116
+ * UseSkill meta-gadget — bridges the skill system into the gadget execution pipeline.
10117
+ *
10118
+ * When skills are registered with an agent, this gadget is auto-created and added
10119
+ * to the gadget registry. The LLM can invoke it like any other gadget, and the
10120
+ * skill's instructions are returned as the gadget result.
10121
+ *
10122
+ * This approach requires zero changes to the stream processor or agent loop.
10123
+ *
10124
+ * @module skills/use-skill-gadget
10125
+ */
10126
+
10127
+ /** Name for the auto-generated UseSkill gadget. */
10128
+ declare const USE_SKILL_GADGET_NAME = "UseSkill";
10129
+ /**
10130
+ * Create the UseSkill meta-gadget from a skill registry.
10131
+ *
10132
+ * The gadget description includes a summary of all available skills,
10133
+ * so the LLM knows what skills exist and when to use them.
10134
+ */
10135
+ declare function createUseSkillGadget(registry: SkillRegistry): AbstractGadget;
10136
+
10443
10137
  /**
10444
10138
  * Config resolution utility for subagent gadgets.
10445
10139
  *
@@ -10869,4 +10563,4 @@ declare const timing: {
10869
10563
  */
10870
10564
  declare function getHostExports(ctx: ExecutionContext): HostExports;
10871
10565
 
10872
- export { AbortException, AbstractGadget, type AddGadgetParams, type AddLLMCallParams, type AfterGadgetExecutionAction, type AfterGadgetExecutionControllerContext, type AfterLLMCallAction, type AfterLLMCallControllerContext, type AfterLLMErrorAction, Agent, AgentBuilder, type AgentHooks, type AgentOptions, AnthropicMessagesProvider, type AudioContentPart, type AudioMimeType, type AudioSource, type BaseExecutionEvent, BaseSessionManager, type BeforeGadgetExecutionAction, type BeforeLLMCallAction, BudgetPricingUnavailableError, type CachingConfig, type CachingScope, type ChunkInterceptorContext, type CompactionConfig, type CompactionContext, type CompactionEvent, CompactionManager, type CompactionResult, type CompactionStats, type CompactionStrategy, type CompleteGadgetParams, type CompleteLLMCallParams, type ContentPart, type Controllers, ConversationManager, type CostEstimate, type CostReportingLLMist, type CreateGadgetConfig, DEFAULT_COMPACTION_CONFIG, DEFAULT_HINTS, DEFAULT_PROMPTS, DEFAULT_RATE_LIMIT_CONFIG, DEFAULT_RETRY_CONFIG, DEFAULT_SUMMARIZATION_PROMPT, type EventHandlers, type ExecutionContext, type ExecutionEvent, type ExecutionEventType, type ExecutionNode, type ExecutionNodeType, ExecutionTree, FALLBACK_CHARS_PER_TOKEN, type FileLoggingOptions, type FileLoggingState, type FileWrittenInfo, type FormatLLMErrorContext, GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX, Gadget, type GadgetCallEvent, GadgetCallParser, type GadgetClass, type GadgetCompleteEvent, type GadgetConfig, type GadgetErrorEvent, type GadgetEvent, type GadgetExample, type GadgetExecuteResult, type GadgetExecuteResultWithMedia, type GadgetExecuteReturn, type GadgetExecutionControllerContext, type GadgetExecutionMode, type GadgetExecutionResult, GadgetExecutor, type GadgetFactoryExports, type GadgetMediaOutput, type GadgetNode, type GadgetOrClass, GadgetOutputStore, type GadgetParameterInterceptorContext, GadgetRegistry, type GadgetResultInterceptorContext, type GadgetSkippedEvent, type GadgetStartEvent, type GadgetState, GeminiGenerativeProvider, type HintContext, type HintTemplate, type HintsConfig, type HistoryMessage, HookPresets, type HostExports, HuggingFaceProvider, type HumanInputRequiredEvent, HumanInputRequiredException, HybridStrategy, type IConversationManager, type ISessionManager, type ImageBase64Source, type ImageContentPart, type ImageGenerationOptions, type ImageGenerationResult, type ImageMimeType, type ImageModelSpec, type ImageSource, type ImageUrlSource, type Interceptors, type IterationHintOptions, type LLMCallCompleteEvent, type LLMCallControllerContext, type LLMCallErrorEvent, type LLMCallNode, type LLMCallStartEvent, type LLMCallStreamEvent, type LLMErrorControllerContext, type LLMEvent, type LLMGenerationOptions, type LLMMessage, LLMMessageBuilder, type LLMResponseEndEvent, type LLMStream, type LLMStreamChunk, LLMist, type LLMistOptions, type LLMistPackageManifest, type LoggerOptions, type LoggingOptions, MODEL_ALIASES, type MediaKind, type MediaMetadata, MediaStore, type MessageContent, type MessageInterceptorContext, type MessageRole, type MessageTurn, type ModelDescriptor, type ModelFeatures, ModelIdentifierParser, type ModelLimits, type ModelPricing, ModelRegistry, type ModelSpec, type NodeId, type ObserveChunkContext, type ObserveCompactionContext, type ObserveGadgetCompleteContext, type ObserveGadgetStartContext, type ObserveLLMCallContext, type ObserveLLMCompleteContext, type ObserveLLMErrorContext, type ObserveRateLimitThrottleContext, type ObserveRetryAttemptContext, type Observers, OpenAIChatProvider, type OpenAICompatibleConfig, OpenAICompatibleProvider, type OpenRouterConfig, OpenRouterProvider, type OpenRouterRouting, type ParallelGadgetHintOptions, type ParsedGadgetCall, type PresetDefinition, type PromptContext, type PromptTemplate, type PromptTemplateConfig, type ProviderAdapter, type ProviderIdentifier, type RateLimitConfig, type RateLimitStats, RateLimitTracker, type ReasoningConfig, type ReasoningEffort, type ResolveValueOptions, type ResolvedCompactionConfig, type ResolvedRateLimitConfig, type ResolvedRetryConfig, type RetryConfig, type RetryOptions, type SessionManifestEntry, SimpleSessionManager, SlidingWindowStrategy, type SpeechGenerationOptions, type SpeechGenerationResult, type SpeechModelSpec, type StoredMedia, type StoredOutput, type StreamCompleteEvent, type StreamEvent, type StreamProcessingResult, StreamProcessor, type StreamProcessorOptions, type SubagentConfig, type SubagentConfigMap, type SubagentContext, type SubagentManifestEntry, type SubagentOptions, SummarizationStrategy, TaskCompletionSignal, type TextContentPart, type TextEvent, type TextGenerationOptions, type TextOnlyAction, type TextOnlyContext, type TextOnlyCustomHandler, type TextOnlyGadgetConfig, type TextOnlyHandler, type TextOnlyStrategy, type ThinkingChunk, type ThinkingEvent, TimeoutException, type TokenUsage, type TrailingMessage, type TrailingMessageContext, type CompactionEvent$1 as TreeCompactionEvent, type GadgetSkippedEvent$1 as TreeGadgetSkippedEvent, type TriggeredLimitInfo, type ValidationIssue, type ValidationResult, type VisionAnalyzeOptions, type VisionAnalyzeResult, audioFromBase64, audioFromBuffer, collectEvents, collectText, complete, createAnthropicProviderFromEnv, createFileLoggingState, createGadget, createGadgetOutputViewer, createGeminiProviderFromEnv, createHints, createHuggingFaceProviderFromEnv, createLogger, createMediaOutput, createOpenAIProviderFromEnv, createOpenRouterProviderFromEnv, createSubagent, defaultLogger, detectAudioMimeType, detectImageMimeType, discoverProviderAdapters, extractMessageText, extractRetryAfterMs, filterByDepth, filterByParent, filterRootEvents, format, formatBytes, formatCallNumber, formatDate, formatDuration, formatLLMError, formatLlmRequest, gadgetError, gadgetSuccess, getErrorMessage, getHostExports, getModelId, getPresetGadgets, getProvider, getSubagent, groupByParent, hasHostExports, hasPreset, hasProviderPrefix, hasSubagents, humanDelay, imageFromBase64, imageFromBuffer, imageFromUrl, isAbortError, isAudioPart, isDataUrl, isGadgetEvent, isImagePart, isLLMEvent, isRetryableError, isRootEvent, isSubagentEvent, isTextPart, iterationProgressHint, listPresets, listSubagents, normalizeMessageContent, parallelGadgetHint, parseDataUrl, parseManifest, parseRetryAfterHeader, randomDelay, resetFileLoggingState, resolveConfig, resolveHintTemplate, resolveModel, resolvePromptTemplate, resolveRateLimitConfig, resolveRetryConfig, resolveRulesTemplate, resolveSubagentModel, resolveSubagentTimeout, resolveValue, resultWithAudio, resultWithFile, resultWithImage, resultWithImages, resultWithMedia, runWithHandlers, schemaToJSONSchema, stream, text, timing, toBase64, truncate, validateAndApplyDefaults, validateGadgetParams, validateGadgetSchema, withErrorHandling, withRetry, withTimeout };
10566
+ export { AbortException, AbstractGadget, type AddGadgetParams, type AddLLMCallParams, type AfterGadgetExecutionAction, type AfterGadgetExecutionControllerContext, type AfterLLMCallAction, type AfterLLMCallControllerContext, type AfterLLMErrorAction, Agent, AgentBuilder, type AgentHooks, type AgentOptions, AnthropicMessagesProvider, type AudioContentPart, type AudioMimeType, type AudioSource, type BaseExecutionEvent, BaseSessionManager, type BeforeGadgetExecutionAction, type BeforeLLMCallAction, type BeforeSkillActivationAction, BudgetPricingUnavailableError, type CachingConfig, type CachingScope, type ChunkInterceptorContext, type CompactionConfig, type CompactionContext, type CompactionEvent, CompactionManager, type CompactionResult, type CompactionStats, type CompactionStrategy, type CompleteGadgetParams, type CompleteLLMCallParams, type ContentPart, type Controllers, ConversationManager, type CostEstimate, type CostReportingLLMist, type CreateGadgetConfig, DEFAULT_COMPACTION_CONFIG, DEFAULT_HINTS, DEFAULT_PROMPTS, DEFAULT_RATE_LIMIT_CONFIG, DEFAULT_RETRY_CONFIG, DEFAULT_SUMMARIZATION_PROMPT, type EventHandlers, type ExecutionContext, type ExecutionEvent, type ExecutionEventType, type ExecutionNode, type ExecutionNodeType, ExecutionTree, FALLBACK_CHARS_PER_TOKEN, type FileLoggingOptions, type FileLoggingState, type FileWrittenInfo, type FormatLLMErrorContext, GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX, Gadget, type GadgetCallEvent, GadgetCallParser, type GadgetClass, type GadgetCompleteEvent, type GadgetConfig, type GadgetErrorEvent, type GadgetEvent, type GadgetExample, type GadgetExecuteResult, type GadgetExecuteResultWithMedia, type GadgetExecuteReturn, type GadgetExecutionControllerContext, type GadgetExecutionMode, type GadgetExecutionResult, GadgetExecutor, type GadgetExecutorOptions, type GadgetFactoryExports, type GadgetMediaOutput, type GadgetNode, type GadgetOrClass, GadgetOutputStore, type GadgetParameterInterceptorContext, GadgetRegistry, type GadgetResultInterceptorContext, type GadgetSkippedEvent, type GadgetStartEvent, type GadgetState, GeminiGenerativeProvider, type HintContext, type HintTemplate, type HintsConfig, type HistoryMessage, HookPresets, type HostExports, HuggingFaceProvider, type HumanInputRequiredEvent, HumanInputRequiredException, HybridStrategy, type IConversationManager, type ISessionManager, type ImageBase64Source, type ImageContentPart, type ImageGenerationOptions, type ImageGenerationResult, type ImageMimeType, type ImageModelSpec, type ImageSource, type ImageUrlSource, type Interceptors, type IterationHintOptions, type LLMCallCompleteEvent, type LLMCallControllerContext, type LLMCallErrorEvent, type LLMCallNode, type LLMCallStartEvent, type LLMCallStreamEvent, type LLMErrorControllerContext, type LLMEvent, type LLMGenerationOptions, type LLMMessage, LLMMessageBuilder, type LLMResponseEndEvent, type LLMStream, type LLMStreamChunk, LLMist, type LLMistOptions, type LLMistPackageManifest, type LoggerOptions, type LoggingOptions, MODEL_ALIASES, type MediaKind, type MediaMetadata, MediaStore, type MessageContent, type MessageInterceptorContext, type MessageRole, type MessageTurn, type ModelDescriptor, type ModelFeatures, ModelIdentifierParser, type ModelLimits, type ModelPricing, ModelRegistry, type ModelSpec, type NodeId, type ObserveChunkContext, type ObserveCompactionContext, type ObserveGadgetCompleteContext, type ObserveGadgetStartContext, type ObserveLLMCallContext, type ObserveLLMCompleteContext, type ObserveLLMErrorContext, type ObserveRateLimitThrottleContext, type ObserveRetryAttemptContext, type ObserveSkillActivatedContext, type Observers, OpenAIChatProvider, type OpenAICompatibleConfig, OpenAICompatibleProvider, type OpenRouterConfig, OpenRouterProvider, type OpenRouterRouting, type OutputLimitConfig, type ParallelGadgetHintOptions, type ParsedGadgetCall, type ParsedSkill, type PrefixConfig, type PresetDefinition, type PromptContext, type PromptTemplate, type PromptTemplateConfig, type ProviderAdapter, type ProviderIdentifier, type RateLimitConfig, type RateLimitStats, RateLimitTracker, type ReasoningConfig, type ReasoningEffort, type ResolveValueOptions, type ResolvedCompactionConfig, type ResolvedRateLimitConfig, type ResolvedRetryConfig, type RetryConfig, type RetryOptions, type SessionManifestEntry, SimpleSessionManager, Skill, type SkillActivation, type SkillActivationControllerContext, type SkillActivationOptions, type SkillInstructionInterceptorContext, type SkillMetadata, SkillRegistry, type SkillResource, type SkillSource, SlidingWindowStrategy, type SpeechGenerationOptions, type SpeechGenerationResult, type SpeechModelSpec, type StoredMedia, type StoredOutput, type StreamCompleteEvent, type StreamEvent, type StreamProcessingResult, StreamProcessor, type StreamProcessorOptions, type SubagentConfig, type SubagentConfigMap, type SubagentContext, type SubagentManifestEntry, type SubagentOptions, SummarizationStrategy, TaskCompletionSignal, type TextContentPart, type TextEvent, type TextGenerationOptions, type TextOnlyAction, type TextOnlyContext, type TextOnlyCustomHandler, type TextOnlyGadgetConfig, type TextOnlyHandler, type TextOnlyStrategy, type ThinkingChunk, type ThinkingEvent, TimeoutException, type TokenUsage, type TrailingMessage, type TrailingMessageContext, type CompactionEvent$1 as TreeCompactionEvent, type TreeConfig, type GadgetSkippedEvent$1 as TreeGadgetSkippedEvent, type TriggeredLimitInfo, USE_SKILL_GADGET_NAME, type ValidationIssue, type ValidationResult, type VisionAnalyzeOptions, type VisionAnalyzeResult, audioFromBase64, audioFromBuffer, collectEvents, collectText, complete, createAnthropicProviderFromEnv, createFileLoggingState, createGadget, createGadgetOutputViewer, createGeminiProviderFromEnv, createHints, createHuggingFaceProviderFromEnv, createLogger, createMediaOutput, createOpenAIProviderFromEnv, createOpenRouterProviderFromEnv, createSubagent, createUseSkillGadget, defaultLogger, detectAudioMimeType, detectImageMimeType, discoverProviderAdapters, discoverSkills, extractMessageText, extractRetryAfterMs, filterByDepth, filterByParent, filterRootEvents, format, formatBytes, formatCallNumber, formatDate, formatDuration, formatLLMError, formatLlmRequest, gadgetError, gadgetSuccess, getErrorMessage, getHostExports, getModelId, getPresetGadgets, getProvider, getSubagent, groupByParent, hasHostExports, hasPreset, hasProviderPrefix, hasSubagents, humanDelay, imageFromBase64, imageFromBuffer, imageFromUrl, isAbortError, isAudioPart, isDataUrl, isGadgetEvent, isImagePart, isLLMEvent, isRetryableError, isRootEvent, isSubagentEvent, isTextPart, iterationProgressHint, listPresets, listSubagents, loadSkillsFromDirectory, normalizeMessageContent, parallelGadgetHint, parseDataUrl, parseFrontmatter, parseManifest, parseMetadata, parseRetryAfterHeader, parseSkillContent, parseSkillFile, randomDelay, resetFileLoggingState, resolveConfig, resolveHintTemplate, resolveInstructions, resolveModel, resolvePromptTemplate, resolveRateLimitConfig, resolveRetryConfig, resolveRulesTemplate, resolveSubagentModel, resolveSubagentTimeout, resolveValue, resultWithAudio, resultWithFile, resultWithImage, resultWithImages, resultWithMedia, runWithHandlers, scanResources, schemaToJSONSchema, stream, stripProviderPrefix, substituteArguments, substituteVariables, text, timing, toBase64, truncate, validateAndApplyDefaults, validateGadgetParams, validateGadgetSchema, validateMetadata, withErrorHandling, withRetry, withTimeout };