llmist 2.6.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -566,13 +566,13 @@ var init_prompt_config = __esm({
566
566
  });
567
567
 
568
568
  // src/core/messages.ts
569
- function normalizeContent(content) {
569
+ function normalizeMessageContent(content) {
570
570
  if (typeof content === "string") {
571
571
  return [{ type: "text", text: content }];
572
572
  }
573
573
  return content;
574
574
  }
575
- function extractText(content) {
575
+ function extractMessageText(content) {
576
576
  if (typeof content === "string") {
577
577
  return content;
578
578
  }
@@ -932,7 +932,17 @@ Produces: { "items": ["first", "second"] }`);
932
932
  this.messages.push({ role: "user", content: parts });
933
933
  return this;
934
934
  }
935
- addGadgetCall(gadget, parameters, result, media, mediaIds) {
935
+ /**
936
+ * Record a gadget execution result in the message history.
937
+ * Creates an assistant message with the gadget invocation and a user message with the result.
938
+ *
939
+ * @param gadget - Name of the gadget that was executed
940
+ * @param parameters - Parameters that were passed to the gadget
941
+ * @param result - Text result from the gadget execution
942
+ * @param media - Optional media outputs from the gadget
943
+ * @param mediaIds - Optional IDs for the media outputs
944
+ */
945
+ addGadgetCallResult(gadget, parameters, result, media, mediaIds) {
936
946
  const paramStr = this.formatBlockParameters(parameters, "");
937
947
  this.messages.push({
938
948
  role: "assistant",
@@ -1200,21 +1210,21 @@ var init_media_store = __esm({
1200
1210
  });
1201
1211
 
1202
1212
  // src/gadgets/exceptions.ts
1203
- var BreakLoopException, HumanInputException, TimeoutException, AbortError;
1213
+ var TaskCompletionSignal, HumanInputRequiredException, TimeoutException, AbortException;
1204
1214
  var init_exceptions = __esm({
1205
1215
  "src/gadgets/exceptions.ts"() {
1206
1216
  "use strict";
1207
- BreakLoopException = class extends Error {
1217
+ TaskCompletionSignal = class extends Error {
1208
1218
  constructor(message) {
1209
1219
  super(message ?? "Agent loop terminated by gadget");
1210
- this.name = "BreakLoopException";
1220
+ this.name = "TaskCompletionSignal";
1211
1221
  }
1212
1222
  };
1213
- HumanInputException = class extends Error {
1223
+ HumanInputRequiredException = class extends Error {
1214
1224
  question;
1215
1225
  constructor(question) {
1216
1226
  super(`Human input required: ${question}`);
1217
- this.name = "HumanInputException";
1227
+ this.name = "HumanInputRequiredException";
1218
1228
  this.question = question;
1219
1229
  }
1220
1230
  };
@@ -1228,10 +1238,10 @@ var init_exceptions = __esm({
1228
1238
  this.timeoutMs = timeoutMs;
1229
1239
  }
1230
1240
  };
1231
- AbortError = class extends Error {
1241
+ AbortException = class extends Error {
1232
1242
  constructor(message) {
1233
1243
  super(message || "Gadget execution was aborted");
1234
- this.name = "AbortError";
1244
+ this.name = "AbortException";
1235
1245
  }
1236
1246
  };
1237
1247
  }
@@ -1400,7 +1410,7 @@ var init_schema_to_json = __esm({
1400
1410
  });
1401
1411
 
1402
1412
  // src/gadgets/gadget.ts
1403
- function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
1413
+ function formatParamsForBlockExample(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
1404
1414
  const lines = [];
1405
1415
  for (const [key, value] of Object.entries(params)) {
1406
1416
  const fullPath = prefix ? `${prefix}/${key}` : key;
@@ -1408,14 +1418,14 @@ function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX)
1408
1418
  value.forEach((item, index) => {
1409
1419
  const itemPath = `${fullPath}/${index}`;
1410
1420
  if (typeof item === "object" && item !== null) {
1411
- lines.push(formatParamsAsBlock(item, itemPath, argPrefix));
1421
+ lines.push(formatParamsForBlockExample(item, itemPath, argPrefix));
1412
1422
  } else {
1413
1423
  lines.push(`${argPrefix}${itemPath}`);
1414
1424
  lines.push(String(item));
1415
1425
  }
1416
1426
  });
1417
1427
  } else if (typeof value === "object" && value !== null) {
1418
- lines.push(formatParamsAsBlock(value, fullPath, argPrefix));
1428
+ lines.push(formatParamsForBlockExample(value, fullPath, argPrefix));
1419
1429
  } else {
1420
1430
  lines.push(`${argPrefix}${fullPath}`);
1421
1431
  lines.push(String(value));
@@ -1504,7 +1514,7 @@ function formatSchemaAsPlainText(schema, indent = "", atRoot = true) {
1504
1514
  }
1505
1515
  return lines.join("\n");
1506
1516
  }
1507
- var BaseGadget;
1517
+ var AbstractGadget;
1508
1518
  var init_gadget = __esm({
1509
1519
  "src/gadgets/gadget.ts"() {
1510
1520
  "use strict";
@@ -1512,7 +1522,7 @@ var init_gadget = __esm({
1512
1522
  init_exceptions();
1513
1523
  init_schema_to_json();
1514
1524
  init_schema_validator();
1515
- BaseGadget = class {
1525
+ AbstractGadget = class {
1516
1526
  /**
1517
1527
  * The name of the gadget. Used for identification when LLM calls it.
1518
1528
  * If not provided, defaults to the class name.
@@ -1540,14 +1550,14 @@ var init_gadget = __esm({
1540
1550
  */
1541
1551
  examples;
1542
1552
  /**
1543
- * Throws an AbortError if the execution has been aborted.
1553
+ * Throws an AbortException if the execution has been aborted.
1544
1554
  *
1545
1555
  * Call this at key checkpoints in long-running gadgets to allow early exit
1546
1556
  * when the gadget has been cancelled (e.g., due to timeout). This enables
1547
1557
  * resource cleanup and prevents unnecessary work after cancellation.
1548
1558
  *
1549
1559
  * @param ctx - The execution context containing the abort signal
1550
- * @throws AbortError if ctx.signal.aborted is true
1560
+ * @throws AbortException if ctx.signal.aborted is true
1551
1561
  *
1552
1562
  * @example
1553
1563
  * ```typescript
@@ -1572,7 +1582,7 @@ var init_gadget = __esm({
1572
1582
  */
1573
1583
  throwIfAborted(ctx) {
1574
1584
  if (ctx?.signal?.aborted) {
1575
- throw new AbortError();
1585
+ throw new AbortException();
1576
1586
  }
1577
1587
  }
1578
1588
  /**
@@ -1714,7 +1724,7 @@ var init_gadget = __esm({
1714
1724
  }
1715
1725
  parts.push(`${effectiveStartPrefix}${gadgetName}`);
1716
1726
  parts.push(
1717
- formatParamsAsBlock(example.params, "", effectiveArgPrefix)
1727
+ formatParamsForBlockExample(example.params, "", effectiveArgPrefix)
1718
1728
  );
1719
1729
  parts.push(effectiveEndPrefix);
1720
1730
  if (example.output !== void 0) {
@@ -1732,7 +1742,7 @@ var init_gadget = __esm({
1732
1742
 
1733
1743
  // src/gadgets/create-gadget.ts
1734
1744
  function createGadget(config) {
1735
- class DynamicGadget extends BaseGadget {
1745
+ class DynamicGadget extends AbstractGadget {
1736
1746
  name = config.name;
1737
1747
  description = config.description;
1738
1748
  parameterSchema = config.schema;
@@ -2370,8 +2380,8 @@ var init_conversation_manager = __esm({
2370
2380
  addAssistantMessage(content) {
2371
2381
  this.historyBuilder.addAssistant(content);
2372
2382
  }
2373
- addGadgetCall(gadgetName, parameters, result, media, mediaIds) {
2374
- this.historyBuilder.addGadgetCall(gadgetName, parameters, result, media, mediaIds);
2383
+ addGadgetCallResult(gadgetName, parameters, result, media, mediaIds) {
2384
+ this.historyBuilder.addGadgetCallResult(gadgetName, parameters, result, media, mediaIds);
2375
2385
  }
2376
2386
  getMessages() {
2377
2387
  return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
@@ -2391,7 +2401,7 @@ var init_conversation_manager = __esm({
2391
2401
  if (msg.role === "user") {
2392
2402
  this.historyBuilder.addUser(msg.content);
2393
2403
  } else if (msg.role === "assistant") {
2394
- this.historyBuilder.addAssistant(extractText(msg.content));
2404
+ this.historyBuilder.addAssistant(extractMessageText(msg.content));
2395
2405
  }
2396
2406
  }
2397
2407
  }
@@ -3271,12 +3281,12 @@ var init_cost_reporting_client = __esm({
3271
3281
  });
3272
3282
 
3273
3283
  // src/gadgets/error-formatter.ts
3274
- var GadgetErrorFormatter;
3284
+ var GadgetExecutionErrorFormatter;
3275
3285
  var init_error_formatter = __esm({
3276
3286
  "src/gadgets/error-formatter.ts"() {
3277
3287
  "use strict";
3278
3288
  init_constants();
3279
- GadgetErrorFormatter = class {
3289
+ GadgetExecutionErrorFormatter = class {
3280
3290
  argPrefix;
3281
3291
  startPrefix;
3282
3292
  endPrefix;
@@ -3362,16 +3372,16 @@ function stripMarkdownFences(content) {
3362
3372
  cleaned = cleaned.replace(closingFence, "");
3363
3373
  return cleaned.trim();
3364
3374
  }
3365
- var globalInvocationCounter, StreamParser;
3375
+ var globalInvocationCounter, GadgetCallParser;
3366
3376
  var init_parser = __esm({
3367
3377
  "src/gadgets/parser.ts"() {
3368
3378
  "use strict";
3369
3379
  init_constants();
3370
3380
  init_block_params();
3371
3381
  globalInvocationCounter = 0;
3372
- StreamParser = class {
3382
+ GadgetCallParser = class {
3373
3383
  buffer = "";
3374
- lastReportedTextLength = 0;
3384
+ lastEmittedTextOffset = 0;
3375
3385
  startPrefix;
3376
3386
  endPrefix;
3377
3387
  argPrefix;
@@ -3380,16 +3390,20 @@ var init_parser = __esm({
3380
3390
  this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
3381
3391
  this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
3382
3392
  }
3383
- takeTextUntil(index) {
3384
- if (index <= this.lastReportedTextLength) {
3393
+ /**
3394
+ * Extract and consume text up to the given index.
3395
+ * Returns undefined if no meaningful text to emit.
3396
+ */
3397
+ extractTextSegment(index) {
3398
+ if (index <= this.lastEmittedTextOffset) {
3385
3399
  return void 0;
3386
3400
  }
3387
- const segment = this.buffer.slice(this.lastReportedTextLength, index);
3388
- this.lastReportedTextLength = index;
3401
+ const segment = this.buffer.slice(this.lastEmittedTextOffset, index);
3402
+ this.lastEmittedTextOffset = index;
3389
3403
  return segment.trim().length > 0 ? segment : void 0;
3390
3404
  }
3391
3405
  /**
3392
- * Parse gadget name with optional invocation ID and dependencies.
3406
+ * Parse gadget invocation metadata from the header line.
3393
3407
  *
3394
3408
  * Supported formats:
3395
3409
  * - `GadgetName` - Auto-generate ID, no dependencies
@@ -3398,24 +3412,24 @@ var init_parser = __esm({
3398
3412
  *
3399
3413
  * Dependencies must be comma-separated invocation IDs.
3400
3414
  */
3401
- parseGadgetName(gadgetName) {
3402
- const parts = gadgetName.split(":");
3415
+ parseInvocationMetadata(headerLine) {
3416
+ const parts = headerLine.split(":");
3403
3417
  if (parts.length === 1) {
3404
3418
  return {
3405
- actualName: parts[0],
3419
+ gadgetName: parts[0],
3406
3420
  invocationId: `gadget_${++globalInvocationCounter}`,
3407
3421
  dependencies: []
3408
3422
  };
3409
3423
  } else if (parts.length === 2) {
3410
3424
  return {
3411
- actualName: parts[0],
3425
+ gadgetName: parts[0],
3412
3426
  invocationId: parts[1].trim(),
3413
3427
  dependencies: []
3414
3428
  };
3415
3429
  } else {
3416
3430
  const deps = parts[2].split(",").map((d) => d.trim()).filter((d) => d.length > 0);
3417
3431
  return {
3418
- actualName: parts[0],
3432
+ gadgetName: parts[0],
3419
3433
  invocationId: parts[1].trim(),
3420
3434
  dependencies: deps
3421
3435
  };
@@ -3447,19 +3461,15 @@ var init_parser = __esm({
3447
3461
  while (true) {
3448
3462
  const partStartIndex = this.buffer.indexOf(this.startPrefix, startIndex);
3449
3463
  if (partStartIndex === -1) break;
3450
- const textBefore = this.takeTextUntil(partStartIndex);
3464
+ const textBefore = this.extractTextSegment(partStartIndex);
3451
3465
  if (textBefore !== void 0) {
3452
3466
  yield { type: "text", content: textBefore };
3453
3467
  }
3454
3468
  const metadataStartIndex = partStartIndex + this.startPrefix.length;
3455
3469
  const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
3456
3470
  if (metadataEndIndex === -1) break;
3457
- const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
3458
- const {
3459
- actualName: actualGadgetName,
3460
- invocationId,
3461
- dependencies
3462
- } = this.parseGadgetName(gadgetName);
3471
+ const headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
3472
+ const { gadgetName, invocationId, dependencies } = this.parseInvocationMetadata(headerLine);
3463
3473
  const contentStartIndex = metadataEndIndex + 1;
3464
3474
  let partEndIndex;
3465
3475
  let endMarkerLength = 0;
@@ -3479,7 +3489,7 @@ var init_parser = __esm({
3479
3489
  yield {
3480
3490
  type: "gadget_call",
3481
3491
  call: {
3482
- gadgetName: actualGadgetName,
3492
+ gadgetName,
3483
3493
  invocationId,
3484
3494
  parametersRaw,
3485
3495
  parameters,
@@ -3488,37 +3498,33 @@ var init_parser = __esm({
3488
3498
  }
3489
3499
  };
3490
3500
  startIndex = partEndIndex + endMarkerLength;
3491
- this.lastReportedTextLength = startIndex;
3501
+ this.lastEmittedTextOffset = startIndex;
3492
3502
  }
3493
3503
  if (startIndex > 0) {
3494
3504
  this.buffer = this.buffer.substring(startIndex);
3495
- this.lastReportedTextLength = 0;
3505
+ this.lastEmittedTextOffset = 0;
3496
3506
  }
3497
3507
  }
3498
3508
  // Finalize parsing and return remaining text or incomplete gadgets
3499
3509
  *finalize() {
3500
- const startIndex = this.buffer.indexOf(this.startPrefix, this.lastReportedTextLength);
3510
+ const startIndex = this.buffer.indexOf(this.startPrefix, this.lastEmittedTextOffset);
3501
3511
  if (startIndex !== -1) {
3502
- const textBefore = this.takeTextUntil(startIndex);
3512
+ const textBefore = this.extractTextSegment(startIndex);
3503
3513
  if (textBefore !== void 0) {
3504
3514
  yield { type: "text", content: textBefore };
3505
3515
  }
3506
3516
  const metadataStartIndex = startIndex + this.startPrefix.length;
3507
3517
  const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
3508
3518
  if (metadataEndIndex !== -1) {
3509
- const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
3510
- const {
3511
- actualName: actualGadgetName,
3512
- invocationId,
3513
- dependencies
3514
- } = this.parseGadgetName(gadgetName);
3519
+ const headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
3520
+ const { gadgetName, invocationId, dependencies } = this.parseInvocationMetadata(headerLine);
3515
3521
  const contentStartIndex = metadataEndIndex + 1;
3516
3522
  const parametersRaw = this.buffer.substring(contentStartIndex).trim();
3517
3523
  const { parameters, parseError } = this.parseParameters(parametersRaw);
3518
3524
  yield {
3519
3525
  type: "gadget_call",
3520
3526
  call: {
3521
- gadgetName: actualGadgetName,
3527
+ gadgetName,
3522
3528
  invocationId,
3523
3529
  parametersRaw,
3524
3530
  parameters,
@@ -3529,7 +3535,7 @@ var init_parser = __esm({
3529
3535
  return;
3530
3536
  }
3531
3537
  }
3532
- const remainingText = this.takeTextUntil(this.buffer.length);
3538
+ const remainingText = this.extractTextSegment(this.buffer.length);
3533
3539
  if (remainingText !== void 0) {
3534
3540
  yield { type: "text", content: remainingText };
3535
3541
  }
@@ -3537,7 +3543,7 @@ var init_parser = __esm({
3537
3543
  // Reset parser state (note: global invocation counter is NOT reset to ensure unique IDs)
3538
3544
  reset() {
3539
3545
  this.buffer = "";
3540
- this.lastReportedTextLength = 0;
3546
+ this.lastEmittedTextOffset = 0;
3541
3547
  }
3542
3548
  };
3543
3549
  }
@@ -3556,14 +3562,16 @@ var init_executor = __esm({
3556
3562
  init_exceptions();
3557
3563
  init_parser();
3558
3564
  GadgetExecutor = class {
3559
- constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs, errorFormatterOptions, client, mediaStore) {
3565
+ constructor(registry, requestHumanInput, logger, defaultGadgetTimeoutMs, errorFormatterOptions, client, mediaStore, agentConfig, subagentConfig) {
3560
3566
  this.registry = registry;
3561
- this.onHumanInputRequired = onHumanInputRequired;
3567
+ this.requestHumanInput = requestHumanInput;
3562
3568
  this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
3563
3569
  this.client = client;
3564
3570
  this.mediaStore = mediaStore;
3571
+ this.agentConfig = agentConfig;
3572
+ this.subagentConfig = subagentConfig;
3565
3573
  this.logger = logger ?? createLogger({ name: "llmist:executor" });
3566
- this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);
3574
+ this.errorFormatter = new GadgetExecutionErrorFormatter(errorFormatterOptions);
3567
3575
  this.argPrefix = errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;
3568
3576
  }
3569
3577
  logger;
@@ -3583,11 +3591,11 @@ var init_executor = __esm({
3583
3591
  });
3584
3592
  }
3585
3593
  /**
3586
- * Normalizes gadget execute result to consistent format.
3594
+ * Unify gadget execute result to consistent internal format.
3587
3595
  * Handles string returns (backwards compat), object returns with cost,
3588
3596
  * and object returns with media.
3589
3597
  */
3590
- normalizeExecuteResult(raw) {
3598
+ unifyExecuteResult(raw) {
3591
3599
  if (typeof raw === "string") {
3592
3600
  return { result: raw, cost: 0 };
3593
3601
  }
@@ -3705,7 +3713,9 @@ var init_executor = __esm({
3705
3713
  const ctx = {
3706
3714
  reportCost,
3707
3715
  llmist: this.client ? new CostReportingLLMistWrapper(this.client, reportCost) : void 0,
3708
- signal: abortController.signal
3716
+ signal: abortController.signal,
3717
+ agentConfig: this.agentConfig,
3718
+ subagentConfig: this.subagentConfig
3709
3719
  };
3710
3720
  let rawResult;
3711
3721
  if (timeoutMs && timeoutMs > 0) {
@@ -3720,7 +3730,7 @@ var init_executor = __esm({
3720
3730
  } else {
3721
3731
  rawResult = await Promise.resolve(gadget.execute(validatedParameters, ctx));
3722
3732
  }
3723
- const { result, media, cost: returnCost } = this.normalizeExecuteResult(rawResult);
3733
+ const { result, media, cost: returnCost } = this.unifyExecuteResult(rawResult);
3724
3734
  const totalCost = callbackCost + returnCost;
3725
3735
  let mediaIds;
3726
3736
  let storedMedia;
@@ -3766,7 +3776,7 @@ var init_executor = __esm({
3766
3776
  storedMedia
3767
3777
  };
3768
3778
  } catch (error) {
3769
- if (error instanceof BreakLoopException) {
3779
+ if (error instanceof TaskCompletionSignal) {
3770
3780
  this.logger.info("Gadget requested loop termination", {
3771
3781
  gadgetName: call.gadgetName,
3772
3782
  message: error.message
@@ -3794,7 +3804,7 @@ var init_executor = __esm({
3794
3804
  executionTimeMs: Date.now() - startTime
3795
3805
  };
3796
3806
  }
3797
- if (error instanceof AbortError) {
3807
+ if (error instanceof AbortException) {
3798
3808
  this.logger.info("Gadget execution was aborted", {
3799
3809
  gadgetName: call.gadgetName,
3800
3810
  executionTimeMs: Date.now() - startTime
@@ -3807,14 +3817,14 @@ var init_executor = __esm({
3807
3817
  executionTimeMs: Date.now() - startTime
3808
3818
  };
3809
3819
  }
3810
- if (error instanceof HumanInputException) {
3820
+ if (error instanceof HumanInputRequiredException) {
3811
3821
  this.logger.info("Gadget requested human input", {
3812
3822
  gadgetName: call.gadgetName,
3813
3823
  question: error.question
3814
3824
  });
3815
- if (this.onHumanInputRequired) {
3825
+ if (this.requestHumanInput) {
3816
3826
  try {
3817
- const answer = await this.onHumanInputRequired(error.question);
3827
+ const answer = await this.requestHumanInput(error.question);
3818
3828
  this.logger.debug("Human input received", {
3819
3829
  gadgetName: call.gadgetName,
3820
3830
  answerLength: answer.length
@@ -3912,13 +3922,13 @@ var init_stream_processor = __esm({
3912
3922
  parser;
3913
3923
  executor;
3914
3924
  stopOnGadgetError;
3915
- shouldContinueAfterError;
3916
- accumulatedText = "";
3917
- shouldStopExecution = false;
3925
+ canRecoverFromGadgetError;
3926
+ responseText = "";
3927
+ executionHalted = false;
3918
3928
  observerFailureCount = 0;
3919
3929
  // Dependency tracking for gadget execution DAG
3920
3930
  /** Gadgets waiting for their dependencies to complete */
3921
- pendingGadgets = /* @__PURE__ */ new Map();
3931
+ gadgetsAwaitingDependencies = /* @__PURE__ */ new Map();
3922
3932
  /** Completed gadget results, keyed by invocation ID */
3923
3933
  completedResults = /* @__PURE__ */ new Map();
3924
3934
  /** Invocation IDs of gadgets that have failed (error or skipped due to dependency) */
@@ -3929,20 +3939,22 @@ var init_stream_processor = __esm({
3929
3939
  this.hooks = options.hooks ?? {};
3930
3940
  this.logger = options.logger ?? createLogger({ name: "llmist:stream-processor" });
3931
3941
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
3932
- this.shouldContinueAfterError = options.shouldContinueAfterError;
3933
- this.parser = new StreamParser({
3942
+ this.canRecoverFromGadgetError = options.canRecoverFromGadgetError;
3943
+ this.parser = new GadgetCallParser({
3934
3944
  startPrefix: options.gadgetStartPrefix,
3935
3945
  endPrefix: options.gadgetEndPrefix,
3936
3946
  argPrefix: options.gadgetArgPrefix
3937
3947
  });
3938
3948
  this.executor = new GadgetExecutor(
3939
3949
  options.registry,
3940
- options.onHumanInputRequired,
3950
+ options.requestHumanInput,
3941
3951
  this.logger.getSubLogger({ name: "executor" }),
3942
3952
  options.defaultGadgetTimeoutMs,
3943
3953
  { argPrefix: options.gadgetArgPrefix },
3944
3954
  options.client,
3945
- options.mediaStore
3955
+ options.mediaStore,
3956
+ options.agentConfig,
3957
+ options.subagentConfig
3946
3958
  );
3947
3959
  }
3948
3960
  /**
@@ -3963,7 +3975,7 @@ var init_stream_processor = __esm({
3963
3975
  if (this.hooks.interceptors?.interceptRawChunk) {
3964
3976
  const context = {
3965
3977
  iteration: this.iteration,
3966
- accumulatedText: this.accumulatedText,
3978
+ accumulatedText: this.responseText,
3967
3979
  logger: this.logger
3968
3980
  };
3969
3981
  const intercepted = this.hooks.interceptors.interceptRawChunk(processedChunk, context);
@@ -3974,7 +3986,7 @@ var init_stream_processor = __esm({
3974
3986
  }
3975
3987
  }
3976
3988
  if (processedChunk) {
3977
- this.accumulatedText += processedChunk;
3989
+ this.responseText += processedChunk;
3978
3990
  }
3979
3991
  }
3980
3992
  if (this.hooks.observers?.onStreamChunk && (processedChunk || chunk.usage)) {
@@ -3983,7 +3995,7 @@ var init_stream_processor = __esm({
3983
3995
  const context = {
3984
3996
  iteration: this.iteration,
3985
3997
  rawChunk: processedChunk,
3986
- accumulatedText: this.accumulatedText,
3998
+ accumulatedText: this.responseText,
3987
3999
  usage,
3988
4000
  logger: this.logger
3989
4001
  };
@@ -4006,12 +4018,12 @@ var init_stream_processor = __esm({
4006
4018
  }
4007
4019
  }
4008
4020
  }
4009
- if (this.shouldStopExecution) {
4021
+ if (this.executionHalted) {
4010
4022
  this.logger.info("Breaking from LLM stream due to gadget error");
4011
4023
  break;
4012
4024
  }
4013
4025
  }
4014
- if (!this.shouldStopExecution) {
4026
+ if (!this.executionHalted) {
4015
4027
  for (const event of this.parser.finalize()) {
4016
4028
  const processedEvents = await this.processEvent(event);
4017
4029
  outputs.push(...processedEvents);
@@ -4035,11 +4047,11 @@ var init_stream_processor = __esm({
4035
4047
  }
4036
4048
  }
4037
4049
  }
4038
- let finalMessage = this.accumulatedText;
4050
+ let finalMessage = this.responseText;
4039
4051
  if (this.hooks.interceptors?.interceptAssistantMessage) {
4040
4052
  const context = {
4041
4053
  iteration: this.iteration,
4042
- rawResponse: this.accumulatedText,
4054
+ rawResponse: this.responseText,
4043
4055
  logger: this.logger
4044
4056
  };
4045
4057
  finalMessage = this.hooks.interceptors.interceptAssistantMessage(finalMessage, context);
@@ -4050,7 +4062,7 @@ var init_stream_processor = __esm({
4050
4062
  didExecuteGadgets,
4051
4063
  finishReason,
4052
4064
  usage,
4053
- rawResponse: this.accumulatedText,
4065
+ rawResponse: this.responseText,
4054
4066
  finalMessage
4055
4067
  };
4056
4068
  }
@@ -4073,7 +4085,7 @@ var init_stream_processor = __esm({
4073
4085
  if (this.hooks.interceptors?.interceptTextChunk) {
4074
4086
  const context = {
4075
4087
  iteration: this.iteration,
4076
- accumulatedText: this.accumulatedText,
4088
+ accumulatedText: this.responseText,
4077
4089
  logger: this.logger
4078
4090
  };
4079
4091
  const intercepted = this.hooks.interceptors.interceptTextChunk(content, context);
@@ -4092,7 +4104,7 @@ var init_stream_processor = __esm({
4092
4104
  * After each execution, pending gadgets are checked to see if they can now run.
4093
4105
  */
4094
4106
  async processGadgetCall(call) {
4095
- if (this.shouldStopExecution) {
4107
+ if (this.executionHalted) {
4096
4108
  this.logger.debug("Skipping gadget execution due to previous error", {
4097
4109
  gadgetName: call.gadgetName
4098
4110
  });
@@ -4131,7 +4143,7 @@ var init_stream_processor = __esm({
4131
4143
  invocationId: call.invocationId,
4132
4144
  waitingOn: unsatisfied
4133
4145
  });
4134
- this.pendingGadgets.set(call.invocationId, call);
4146
+ this.gadgetsAwaitingDependencies.set(call.invocationId, call);
4135
4147
  return events;
4136
4148
  }
4137
4149
  }
@@ -4153,14 +4165,14 @@ var init_stream_processor = __esm({
4153
4165
  error: call.parseError,
4154
4166
  rawParameters: call.parametersRaw
4155
4167
  });
4156
- const shouldContinue = await this.checkContinueAfterError(
4168
+ const shouldContinue = await this.checkCanRecoverFromError(
4157
4169
  call.parseError,
4158
4170
  call.gadgetName,
4159
4171
  "parse",
4160
4172
  call.parameters
4161
4173
  );
4162
4174
  if (!shouldContinue) {
4163
- this.shouldStopExecution = true;
4175
+ this.executionHalted = true;
4164
4176
  }
4165
4177
  }
4166
4178
  let parameters = call.parameters ?? {};
@@ -4284,14 +4296,14 @@ var init_stream_processor = __esm({
4284
4296
  events.push({ type: "gadget_result", result });
4285
4297
  if (result.error) {
4286
4298
  const errorType = this.determineErrorType(call, result);
4287
- const shouldContinue = await this.checkContinueAfterError(
4299
+ const shouldContinue = await this.checkCanRecoverFromError(
4288
4300
  result.error,
4289
4301
  result.gadgetName,
4290
4302
  errorType,
4291
4303
  result.parameters
4292
4304
  );
4293
4305
  if (!shouldContinue) {
4294
- this.shouldStopExecution = true;
4306
+ this.executionHalted = true;
4295
4307
  }
4296
4308
  }
4297
4309
  return events;
@@ -4378,11 +4390,11 @@ var init_stream_processor = __esm({
4378
4390
  async processPendingGadgets() {
4379
4391
  const events = [];
4380
4392
  let progress = true;
4381
- while (progress && this.pendingGadgets.size > 0) {
4393
+ while (progress && this.gadgetsAwaitingDependencies.size > 0) {
4382
4394
  progress = false;
4383
4395
  const readyToExecute = [];
4384
4396
  const readyToSkip = [];
4385
- for (const [invocationId, call] of this.pendingGadgets) {
4397
+ for (const [invocationId, call] of this.gadgetsAwaitingDependencies) {
4386
4398
  const failedDep = call.dependencies.find((dep) => this.failedInvocations.has(dep));
4387
4399
  if (failedDep) {
4388
4400
  readyToSkip.push({ call, failedDep });
@@ -4394,7 +4406,7 @@ var init_stream_processor = __esm({
4394
4406
  }
4395
4407
  }
4396
4408
  for (const { call, failedDep } of readyToSkip) {
4397
- this.pendingGadgets.delete(call.invocationId);
4409
+ this.gadgetsAwaitingDependencies.delete(call.invocationId);
4398
4410
  const skipEvents = await this.handleFailedDependency(call, failedDep);
4399
4411
  events.push(...skipEvents);
4400
4412
  progress = true;
@@ -4405,7 +4417,7 @@ var init_stream_processor = __esm({
4405
4417
  invocationIds: readyToExecute.map((c) => c.invocationId)
4406
4418
  });
4407
4419
  for (const call of readyToExecute) {
4408
- this.pendingGadgets.delete(call.invocationId);
4420
+ this.gadgetsAwaitingDependencies.delete(call.invocationId);
4409
4421
  }
4410
4422
  const executePromises = readyToExecute.map((call) => this.executeGadgetWithHooks(call));
4411
4423
  const results = await Promise.all(executePromises);
@@ -4415,9 +4427,9 @@ var init_stream_processor = __esm({
4415
4427
  progress = true;
4416
4428
  }
4417
4429
  }
4418
- if (this.pendingGadgets.size > 0) {
4419
- const pendingIds = new Set(this.pendingGadgets.keys());
4420
- for (const [invocationId, call] of this.pendingGadgets) {
4430
+ if (this.gadgetsAwaitingDependencies.size > 0) {
4431
+ const pendingIds = new Set(this.gadgetsAwaitingDependencies.keys());
4432
+ for (const [invocationId, call] of this.gadgetsAwaitingDependencies) {
4421
4433
  const missingDeps = call.dependencies.filter((dep) => !this.completedResults.has(dep));
4422
4434
  const circularDeps = missingDeps.filter((dep) => pendingIds.has(dep));
4423
4435
  const trulyMissingDeps = missingDeps.filter((dep) => !pendingIds.has(dep));
@@ -4448,7 +4460,7 @@ var init_stream_processor = __esm({
4448
4460
  };
4449
4461
  events.push(skipEvent);
4450
4462
  }
4451
- this.pendingGadgets.clear();
4463
+ this.gadgetsAwaitingDependencies.clear();
4452
4464
  }
4453
4465
  return events;
4454
4466
  }
@@ -4478,19 +4490,19 @@ var init_stream_processor = __esm({
4478
4490
  );
4479
4491
  }
4480
4492
  /**
4481
- * Check if execution should continue after an error.
4493
+ * Check if execution can recover from an error.
4482
4494
  *
4483
4495
  * Returns true if we should continue processing subsequent gadgets, false if we should stop.
4484
4496
  *
4485
4497
  * Logic:
4486
- * - If custom shouldContinueAfterError is provided, use it
4498
+ * - If custom canRecoverFromGadgetError is provided, use it
4487
4499
  * - Otherwise, use stopOnGadgetError config:
4488
4500
  * - stopOnGadgetError=true → return false (stop execution)
4489
4501
  * - stopOnGadgetError=false → return true (continue execution)
4490
4502
  */
4491
- async checkContinueAfterError(error, gadgetName, errorType, parameters) {
4492
- if (this.shouldContinueAfterError) {
4493
- return await this.shouldContinueAfterError({
4503
+ async checkCanRecoverFromError(error, gadgetName, errorType, parameters) {
4504
+ if (this.canRecoverFromGadgetError) {
4505
+ return await this.canRecoverFromGadgetError({
4494
4506
  error,
4495
4507
  gadgetName,
4496
4508
  errorType,
@@ -4553,14 +4565,14 @@ var init_agent = __esm({
4553
4565
  gadgetStartPrefix;
4554
4566
  gadgetEndPrefix;
4555
4567
  gadgetArgPrefix;
4556
- onHumanInputRequired;
4568
+ requestHumanInput;
4557
4569
  textOnlyHandler;
4558
4570
  textWithGadgetsHandler;
4559
4571
  stopOnGadgetError;
4560
- shouldContinueAfterError;
4572
+ canRecoverFromGadgetError;
4561
4573
  defaultGadgetTimeoutMs;
4562
4574
  defaultMaxTokens;
4563
- userPromptProvided;
4575
+ hasUserPrompt;
4564
4576
  // Gadget output limiting
4565
4577
  outputStore;
4566
4578
  outputLimitEnabled;
@@ -4571,6 +4583,9 @@ var init_agent = __esm({
4571
4583
  mediaStore;
4572
4584
  // Cancellation
4573
4585
  signal;
4586
+ // Subagent configuration
4587
+ agentContextConfig;
4588
+ subagentConfig;
4574
4589
  /**
4575
4590
  * Creates a new Agent instance.
4576
4591
  * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.
@@ -4590,11 +4605,11 @@ var init_agent = __esm({
4590
4605
  this.gadgetStartPrefix = options.gadgetStartPrefix;
4591
4606
  this.gadgetEndPrefix = options.gadgetEndPrefix;
4592
4607
  this.gadgetArgPrefix = options.gadgetArgPrefix;
4593
- this.onHumanInputRequired = options.onHumanInputRequired;
4608
+ this.requestHumanInput = options.requestHumanInput;
4594
4609
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
4595
4610
  this.textWithGadgetsHandler = options.textWithGadgetsHandler;
4596
4611
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
4597
- this.shouldContinueAfterError = options.shouldContinueAfterError;
4612
+ this.canRecoverFromGadgetError = options.canRecoverFromGadgetError;
4598
4613
  this.defaultGadgetTimeoutMs = options.defaultGadgetTimeoutMs;
4599
4614
  this.defaultMaxTokens = this.resolveMaxTokensFromCatalog(options.model);
4600
4615
  this.outputLimitEnabled = options.gadgetOutputLimit ?? DEFAULT_GADGET_OUTPUT_LIMIT;
@@ -4610,7 +4625,7 @@ var init_agent = __esm({
4610
4625
  createGadgetOutputViewer(this.outputStore, this.outputLimitCharLimit)
4611
4626
  );
4612
4627
  }
4613
- this.hooks = this.mergeOutputLimiterHook(options.hooks);
4628
+ this.hooks = this.chainOutputLimiterWithUserHooks(options.hooks);
4614
4629
  const baseBuilder = new LLMMessageBuilder(options.promptConfig);
4615
4630
  if (options.systemPrompt) {
4616
4631
  baseBuilder.addSystem(options.systemPrompt);
@@ -4630,7 +4645,7 @@ var init_agent = __esm({
4630
4645
  endPrefix: options.gadgetEndPrefix,
4631
4646
  argPrefix: options.gadgetArgPrefix
4632
4647
  });
4633
- this.userPromptProvided = !!options.userPrompt;
4648
+ this.hasUserPrompt = !!options.userPrompt;
4634
4649
  if (options.userPrompt) {
4635
4650
  this.conversation.addUserMessage(options.userPrompt);
4636
4651
  }
@@ -4643,6 +4658,11 @@ var init_agent = __esm({
4643
4658
  );
4644
4659
  }
4645
4660
  this.signal = options.signal;
4661
+ this.agentContextConfig = {
4662
+ model: this.model,
4663
+ temperature: this.temperature
4664
+ };
4665
+ this.subagentConfig = options.subagentConfig;
4646
4666
  }
4647
4667
  /**
4648
4668
  * Get the gadget registry for this agent.
@@ -4749,7 +4769,7 @@ var init_agent = __esm({
4749
4769
  * @throws {Error} If no user prompt was provided (when using build() without ask())
4750
4770
  */
4751
4771
  async *run() {
4752
- if (!this.userPromptProvided) {
4772
+ if (!this.hasUserPrompt) {
4753
4773
  throw new Error(
4754
4774
  "No user prompt provided. Use .ask(prompt) instead of .build(), or call agent.run() after providing a prompt."
4755
4775
  );
@@ -4866,12 +4886,14 @@ var init_agent = __esm({
4866
4886
  gadgetArgPrefix: this.gadgetArgPrefix,
4867
4887
  hooks: this.hooks,
4868
4888
  logger: this.logger.getSubLogger({ name: "stream-processor" }),
4869
- onHumanInputRequired: this.onHumanInputRequired,
4889
+ requestHumanInput: this.requestHumanInput,
4870
4890
  stopOnGadgetError: this.stopOnGadgetError,
4871
- shouldContinueAfterError: this.shouldContinueAfterError,
4891
+ canRecoverFromGadgetError: this.canRecoverFromGadgetError,
4872
4892
  defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
4873
4893
  client: this.client,
4874
- mediaStore: this.mediaStore
4894
+ mediaStore: this.mediaStore,
4895
+ agentConfig: this.agentContextConfig,
4896
+ subagentConfig: this.subagentConfig
4875
4897
  });
4876
4898
  const result = await processor.process(stream2);
4877
4899
  for (const output of result.outputs) {
@@ -4924,9 +4946,9 @@ var init_agent = __esm({
4924
4946
  if (msg.role === "user") {
4925
4947
  this.conversation.addUserMessage(msg.content);
4926
4948
  } else if (msg.role === "assistant") {
4927
- this.conversation.addAssistantMessage(extractText(msg.content));
4949
+ this.conversation.addAssistantMessage(extractMessageText(msg.content));
4928
4950
  } else if (msg.role === "system") {
4929
- this.conversation.addUserMessage(`[System] ${extractText(msg.content)}`);
4951
+ this.conversation.addUserMessage(`[System] ${extractMessageText(msg.content)}`);
4930
4952
  }
4931
4953
  }
4932
4954
  }
@@ -4938,7 +4960,7 @@ var init_agent = __esm({
4938
4960
  ).map((output) => output.content).join("");
4939
4961
  if (textContent.trim()) {
4940
4962
  const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;
4941
- this.conversation.addGadgetCall(
4963
+ this.conversation.addGadgetCallResult(
4942
4964
  gadgetName,
4943
4965
  parameterMapping(textContent),
4944
4966
  resultMapping ? resultMapping(textContent) : textContent
@@ -4948,7 +4970,7 @@ var init_agent = __esm({
4948
4970
  for (const output of result.outputs) {
4949
4971
  if (output.type === "gadget_result") {
4950
4972
  const gadgetResult = output.result;
4951
- this.conversation.addGadgetCall(
4973
+ this.conversation.addGadgetCallResult(
4952
4974
  gadgetResult.gadgetName,
4953
4975
  gadgetResult.parameters,
4954
4976
  gadgetResult.error ?? gadgetResult.result ?? "",
@@ -4959,7 +4981,7 @@ var init_agent = __esm({
4959
4981
  }
4960
4982
  } else {
4961
4983
  if (finalMessage.trim()) {
4962
- this.conversation.addGadgetCall(
4984
+ this.conversation.addGadgetCallResult(
4963
4985
  "TellUser",
4964
4986
  { message: finalMessage, done: false, type: "info" },
4965
4987
  `\u2139\uFE0F ${finalMessage}`
@@ -5085,10 +5107,10 @@ var init_agent = __esm({
5085
5107
  return this.client.modelRegistry.getModelLimits(unprefixedModelId)?.maxOutputTokens;
5086
5108
  }
5087
5109
  /**
5088
- * Merge the output limiter interceptor into user-provided hooks.
5110
+ * Chain the output limiter interceptor with user-provided hooks.
5089
5111
  * The limiter runs first, then chains to any user interceptor.
5090
5112
  */
5091
- mergeOutputLimiterHook(userHooks) {
5113
+ chainOutputLimiterWithUserHooks(userHooks) {
5092
5114
  if (!this.outputLimitEnabled) {
5093
5115
  return userHooks ?? {};
5094
5116
  }
@@ -5442,9 +5464,9 @@ var init_base_provider = __esm({
5442
5464
  */
5443
5465
  async *stream(options, descriptor, spec) {
5444
5466
  const preparedMessages = this.prepareMessages(options.messages);
5445
- const payload = this.buildRequestPayload(options, descriptor, spec, preparedMessages);
5467
+ const payload = this.buildApiRequest(options, descriptor, spec, preparedMessages);
5446
5468
  const rawStream = await this.executeStreamRequest(payload, options.signal);
5447
- yield* this.wrapStream(rawStream);
5469
+ yield* this.normalizeProviderStream(rawStream);
5448
5470
  }
5449
5471
  /**
5450
5472
  * Prepare messages for the request.
@@ -5544,11 +5566,11 @@ var init_anthropic = __esm({
5544
5566
  "Anthropic does not support speech generation. Use OpenAI (TTS) or Google Gemini (TTS) instead."
5545
5567
  );
5546
5568
  }
5547
- buildRequestPayload(options, descriptor, spec, messages) {
5569
+ buildApiRequest(options, descriptor, spec, messages) {
5548
5570
  const systemMessages = messages.filter((message) => message.role === "system");
5549
5571
  const system = systemMessages.length > 0 ? systemMessages.map((m, index) => ({
5550
5572
  type: "text",
5551
- text: extractText(m.content),
5573
+ text: extractMessageText(m.content),
5552
5574
  // Add cache_control to the LAST system message block
5553
5575
  ...index === systemMessages.length - 1 ? { cache_control: { type: "ephemeral" } } : {}
5554
5576
  })) : void 0;
@@ -5585,7 +5607,7 @@ var init_anthropic = __esm({
5585
5607
  * Handles text, images (base64 only), and applies cache_control.
5586
5608
  */
5587
5609
  convertToAnthropicContent(content, addCacheControl) {
5588
- const parts = normalizeContent(content);
5610
+ const parts = normalizeMessageContent(content);
5589
5611
  return parts.map((part, index) => {
5590
5612
  const isLastPart = index === parts.length - 1;
5591
5613
  const cacheControl = addCacheControl && isLastPart ? { cache_control: { type: "ephemeral" } } : {};
@@ -5631,7 +5653,7 @@ var init_anthropic = __esm({
5631
5653
  const stream2 = await client.messages.create(payload, signal ? { signal } : void 0);
5632
5654
  return stream2;
5633
5655
  }
5634
- async *wrapStream(iterable) {
5656
+ async *normalizeProviderStream(iterable) {
5635
5657
  const stream2 = iterable;
5636
5658
  let inputTokens = 0;
5637
5659
  let cachedInputTokens = 0;
@@ -5708,7 +5730,7 @@ var init_anthropic = __esm({
5708
5730
  async countTokens(messages, descriptor, _spec) {
5709
5731
  const client = this.client;
5710
5732
  const systemMessages = messages.filter((message) => message.role === "system");
5711
- const system = systemMessages.length > 0 ? systemMessages.map((m) => extractText(m.content)).join("\n\n") : void 0;
5733
+ const system = systemMessages.length > 0 ? systemMessages.map((m) => extractMessageText(m.content)).join("\n\n") : void 0;
5712
5734
  const conversation = messages.filter(
5713
5735
  (message) => message.role !== "system"
5714
5736
  ).map((message) => ({
@@ -5730,7 +5752,7 @@ var init_anthropic = __esm({
5730
5752
  let totalChars = 0;
5731
5753
  let imageCount = 0;
5732
5754
  for (const msg of messages) {
5733
- const parts = normalizeContent(msg.content);
5755
+ const parts = normalizeMessageContent(msg.content);
5734
5756
  for (const part of parts) {
5735
5757
  if (part.type === "text") {
5736
5758
  totalChars += part.text.length;
@@ -6421,7 +6443,7 @@ var init_gemini = __esm({
6421
6443
  format: spec?.defaultFormat ?? "wav"
6422
6444
  };
6423
6445
  }
6424
- buildRequestPayload(options, descriptor, _spec, messages) {
6446
+ buildApiRequest(options, descriptor, _spec, messages) {
6425
6447
  const contents = this.convertMessagesToContents(messages);
6426
6448
  const generationConfig = this.buildGenerationConfig(options);
6427
6449
  const config = {
@@ -6473,7 +6495,7 @@ var init_gemini = __esm({
6473
6495
  if (message.role === "system") {
6474
6496
  expandedMessages.push({
6475
6497
  role: "user",
6476
- content: extractText(message.content)
6498
+ content: extractMessageText(message.content)
6477
6499
  });
6478
6500
  expandedMessages.push({
6479
6501
  role: "assistant",
@@ -6523,7 +6545,7 @@ var init_gemini = __esm({
6523
6545
  * Handles text, images, and audio (Gemini supports all three).
6524
6546
  */
6525
6547
  convertToGeminiParts(content) {
6526
- const parts = normalizeContent(content);
6548
+ const parts = normalizeMessageContent(content);
6527
6549
  return parts.map((part) => {
6528
6550
  if (part.type === "text") {
6529
6551
  return { text: part.text };
@@ -6568,10 +6590,10 @@ var init_gemini = __esm({
6568
6590
  }
6569
6591
  return Object.keys(config).length > 0 ? config : null;
6570
6592
  }
6571
- async *wrapStream(iterable) {
6593
+ async *normalizeProviderStream(iterable) {
6572
6594
  const stream2 = iterable;
6573
6595
  for await (const chunk of stream2) {
6574
- const text3 = this.extractText(chunk);
6596
+ const text3 = this.extractMessageText(chunk);
6575
6597
  if (text3) {
6576
6598
  yield { text: text3, rawEvent: chunk };
6577
6599
  }
@@ -6582,7 +6604,7 @@ var init_gemini = __esm({
6582
6604
  }
6583
6605
  }
6584
6606
  }
6585
- extractText(chunk) {
6607
+ extractMessageText(chunk) {
6586
6608
  if (!chunk?.candidates) {
6587
6609
  return "";
6588
6610
  }
@@ -6647,7 +6669,7 @@ var init_gemini = __esm({
6647
6669
  let totalChars = 0;
6648
6670
  let mediaCount = 0;
6649
6671
  for (const msg of messages) {
6650
- const parts = normalizeContent(msg.content);
6672
+ const parts = normalizeMessageContent(msg.content);
6651
6673
  for (const part of parts) {
6652
6674
  if (part.type === "text") {
6653
6675
  totalChars += part.text.length;
@@ -7393,7 +7415,7 @@ var init_openai = __esm({
7393
7415
  format
7394
7416
  };
7395
7417
  }
7396
- buildRequestPayload(options, descriptor, spec, messages) {
7418
+ buildApiRequest(options, descriptor, spec, messages) {
7397
7419
  const { maxTokens, temperature, topP, stopSequences, extra } = options;
7398
7420
  const supportsTemperature = spec?.metadata?.supportsTemperature !== false;
7399
7421
  const shouldIncludeTemperature = typeof temperature === "number" && supportsTemperature;
@@ -7428,7 +7450,7 @@ var init_openai = __esm({
7428
7450
  ...message.name ? { name: message.name } : {}
7429
7451
  };
7430
7452
  }
7431
- const textContent = typeof message.content === "string" ? message.content : extractText(message.content);
7453
+ const textContent = typeof message.content === "string" ? message.content : extractMessageText(message.content);
7432
7454
  if (role === "system") {
7433
7455
  return {
7434
7456
  role: "system",
@@ -7488,7 +7510,7 @@ var init_openai = __esm({
7488
7510
  const stream2 = await client.chat.completions.create(payload, signal ? { signal } : void 0);
7489
7511
  return stream2;
7490
7512
  }
7491
- async *wrapStream(iterable) {
7513
+ async *normalizeProviderStream(iterable) {
7492
7514
  const stream2 = iterable;
7493
7515
  for await (const chunk of stream2) {
7494
7516
  const text3 = chunk.choices.map((choice) => choice.delta?.content ?? "").join("");
@@ -7546,9 +7568,9 @@ var init_openai = __esm({
7546
7568
  tokenCount += OPENAI_MESSAGE_OVERHEAD_TOKENS;
7547
7569
  const roleText = ROLE_MAP[message.role];
7548
7570
  tokenCount += encoding.encode(roleText).length;
7549
- const textContent = extractText(message.content);
7571
+ const textContent = extractMessageText(message.content);
7550
7572
  tokenCount += encoding.encode(textContent).length;
7551
- const parts = normalizeContent(message.content);
7573
+ const parts = normalizeMessageContent(message.content);
7552
7574
  for (const part of parts) {
7553
7575
  if (part.type === "image") {
7554
7576
  imageCount++;
@@ -7573,7 +7595,7 @@ var init_openai = __esm({
7573
7595
  let totalChars = 0;
7574
7596
  let imageCount = 0;
7575
7597
  for (const msg of messages) {
7576
- const parts = normalizeContent(msg.content);
7598
+ const parts = normalizeMessageContent(msg.content);
7577
7599
  for (const part of parts) {
7578
7600
  if (part.type === "text") {
7579
7601
  totalChars += part.text.length;
@@ -8438,20 +8460,21 @@ var init_builder = __esm({
8438
8460
  promptConfig;
8439
8461
  gadgets = [];
8440
8462
  initialMessages = [];
8441
- onHumanInputRequired;
8463
+ requestHumanInput;
8442
8464
  gadgetStartPrefix;
8443
8465
  gadgetEndPrefix;
8444
8466
  gadgetArgPrefix;
8445
8467
  textOnlyHandler;
8446
8468
  textWithGadgetsHandler;
8447
8469
  stopOnGadgetError;
8448
- shouldContinueAfterError;
8470
+ canRecoverFromGadgetError;
8449
8471
  defaultGadgetTimeoutMs;
8450
8472
  gadgetOutputLimit;
8451
8473
  gadgetOutputLimitPercent;
8452
8474
  compactionConfig;
8453
8475
  signal;
8454
8476
  trailingMessage;
8477
+ subagentConfig;
8455
8478
  constructor(client) {
8456
8479
  this.client = client;
8457
8480
  }
@@ -8542,13 +8565,13 @@ var init_builder = __esm({
8542
8565
  *
8543
8566
  * @example
8544
8567
  * ```typescript
8545
- * .withPromptConfig({
8568
+ * .withPromptTemplateConfig({
8546
8569
  * mainInstruction: "Use the gadget markers below:",
8547
8570
  * rules: ["Always use markers", "Never use function calling"]
8548
8571
  * })
8549
8572
  * ```
8550
8573
  */
8551
- withPromptConfig(config) {
8574
+ withPromptTemplateConfig(config) {
8552
8575
  this.promptConfig = config;
8553
8576
  return this;
8554
8577
  }
@@ -8628,7 +8651,7 @@ var init_builder = __esm({
8628
8651
  * ```
8629
8652
  */
8630
8653
  onHumanInput(handler) {
8631
- this.onHumanInputRequired = handler;
8654
+ this.requestHumanInput = handler;
8632
8655
  return this;
8633
8656
  }
8634
8657
  /**
@@ -8763,9 +8786,9 @@ var init_builder = __esm({
8763
8786
  * Provides fine-grained control over whether to continue after different types of errors.
8764
8787
  * Overrides `stopOnGadgetError` when provided.
8765
8788
  *
8766
- * **Note:** This builder method configures the underlying `shouldContinueAfterError` option
8789
+ * **Note:** This builder method configures the underlying `canRecoverFromGadgetError` option
8767
8790
  * in `AgentOptions`. The method is named `withErrorHandler` for better developer experience,
8768
- * but maps to the `shouldContinueAfterError` property internally.
8791
+ * but maps to the `canRecoverFromGadgetError` property internally.
8769
8792
  *
8770
8793
  * @param handler - Function that decides whether to continue after an error.
8771
8794
  * Return `true` to continue execution, `false` to stop.
@@ -8786,7 +8809,7 @@ var init_builder = __esm({
8786
8809
  * ```
8787
8810
  */
8788
8811
  withErrorHandler(handler) {
8789
- this.shouldContinueAfterError = handler;
8812
+ this.canRecoverFromGadgetError = handler;
8790
8813
  return this;
8791
8814
  }
8792
8815
  /**
@@ -8927,6 +8950,27 @@ var init_builder = __esm({
8927
8950
  this.signal = signal;
8928
8951
  return this;
8929
8952
  }
8953
+ /**
8954
+ * Set subagent configuration overrides.
8955
+ *
8956
+ * Subagent gadgets (like BrowseWeb) can read these settings from ExecutionContext
8957
+ * to inherit model and other options from the CLI configuration.
8958
+ *
8959
+ * @param config - Subagent configuration map keyed by gadget name
8960
+ * @returns This builder for chaining
8961
+ *
8962
+ * @example
8963
+ * ```typescript
8964
+ * .withSubagentConfig({
8965
+ * BrowseWeb: { model: "inherit", maxIterations: 20, headless: true },
8966
+ * CodeAnalyzer: { model: "sonnet", maxIterations: 10 }
8967
+ * })
8968
+ * ```
8969
+ */
8970
+ withSubagentConfig(config) {
8971
+ this.subagentConfig = config;
8972
+ return this;
8973
+ }
8930
8974
  /**
8931
8975
  * Add an ephemeral trailing message that appears at the end of each LLM request.
8932
8976
  *
@@ -9091,19 +9135,20 @@ ${endPrefix}`
9091
9135
  hooks: this.composeHooks(),
9092
9136
  promptConfig: this.promptConfig,
9093
9137
  initialMessages: this.initialMessages,
9094
- onHumanInputRequired: this.onHumanInputRequired,
9138
+ requestHumanInput: this.requestHumanInput,
9095
9139
  gadgetStartPrefix: this.gadgetStartPrefix,
9096
9140
  gadgetEndPrefix: this.gadgetEndPrefix,
9097
9141
  gadgetArgPrefix: this.gadgetArgPrefix,
9098
9142
  textOnlyHandler: this.textOnlyHandler,
9099
9143
  textWithGadgetsHandler: this.textWithGadgetsHandler,
9100
9144
  stopOnGadgetError: this.stopOnGadgetError,
9101
- shouldContinueAfterError: this.shouldContinueAfterError,
9145
+ canRecoverFromGadgetError: this.canRecoverFromGadgetError,
9102
9146
  defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
9103
9147
  gadgetOutputLimit: this.gadgetOutputLimit,
9104
9148
  gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,
9105
9149
  compactionConfig: this.compactionConfig,
9106
- signal: this.signal
9150
+ signal: this.signal,
9151
+ subagentConfig: this.subagentConfig
9107
9152
  };
9108
9153
  }
9109
9154
  ask(userPrompt) {
@@ -9272,19 +9317,20 @@ ${endPrefix}`
9272
9317
  hooks: this.composeHooks(),
9273
9318
  promptConfig: this.promptConfig,
9274
9319
  initialMessages: this.initialMessages,
9275
- onHumanInputRequired: this.onHumanInputRequired,
9320
+ requestHumanInput: this.requestHumanInput,
9276
9321
  gadgetStartPrefix: this.gadgetStartPrefix,
9277
9322
  gadgetEndPrefix: this.gadgetEndPrefix,
9278
9323
  gadgetArgPrefix: this.gadgetArgPrefix,
9279
9324
  textOnlyHandler: this.textOnlyHandler,
9280
9325
  textWithGadgetsHandler: this.textWithGadgetsHandler,
9281
9326
  stopOnGadgetError: this.stopOnGadgetError,
9282
- shouldContinueAfterError: this.shouldContinueAfterError,
9327
+ canRecoverFromGadgetError: this.canRecoverFromGadgetError,
9283
9328
  defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
9284
9329
  gadgetOutputLimit: this.gadgetOutputLimit,
9285
9330
  gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,
9286
9331
  compactionConfig: this.compactionConfig,
9287
- signal: this.signal
9332
+ signal: this.signal,
9333
+ subagentConfig: this.subagentConfig
9288
9334
  };
9289
9335
  return new Agent(AGENT_INTERNAL_KEY, options);
9290
9336
  }
@@ -9295,11 +9341,10 @@ ${endPrefix}`
9295
9341
  // src/index.ts
9296
9342
  var index_exports = {};
9297
9343
  __export(index_exports, {
9298
- AbortError: () => AbortError,
9344
+ AbortException: () => AbortException,
9345
+ AbstractGadget: () => AbstractGadget,
9299
9346
  AgentBuilder: () => AgentBuilder,
9300
9347
  AnthropicMessagesProvider: () => AnthropicMessagesProvider,
9301
- BaseGadget: () => BaseGadget,
9302
- BreakLoopException: () => BreakLoopException,
9303
9348
  CompactionManager: () => CompactionManager,
9304
9349
  ConversationManager: () => ConversationManager,
9305
9350
  DEFAULT_COMPACTION_CONFIG: () => DEFAULT_COMPACTION_CONFIG,
@@ -9307,12 +9352,13 @@ __export(index_exports, {
9307
9352
  DEFAULT_PROMPTS: () => DEFAULT_PROMPTS,
9308
9353
  DEFAULT_SUMMARIZATION_PROMPT: () => DEFAULT_SUMMARIZATION_PROMPT,
9309
9354
  Gadget: () => Gadget,
9355
+ GadgetCallParser: () => GadgetCallParser,
9310
9356
  GadgetExecutor: () => GadgetExecutor,
9311
9357
  GadgetOutputStore: () => GadgetOutputStore,
9312
9358
  GadgetRegistry: () => GadgetRegistry,
9313
9359
  GeminiGenerativeProvider: () => GeminiGenerativeProvider,
9314
9360
  HookPresets: () => HookPresets,
9315
- HumanInputException: () => HumanInputException,
9361
+ HumanInputRequiredException: () => HumanInputRequiredException,
9316
9362
  HybridStrategy: () => HybridStrategy,
9317
9363
  LLMMessageBuilder: () => LLMMessageBuilder,
9318
9364
  LLMist: () => LLMist,
@@ -9325,9 +9371,10 @@ __export(index_exports, {
9325
9371
  ModelRegistry: () => ModelRegistry,
9326
9372
  OpenAIChatProvider: () => OpenAIChatProvider,
9327
9373
  SlidingWindowStrategy: () => SlidingWindowStrategy,
9328
- StreamParser: () => StreamParser,
9329
9374
  StreamProcessor: () => StreamProcessor,
9330
9375
  SummarizationStrategy: () => SummarizationStrategy,
9376
+ TaskCompletionSignal: () => TaskCompletionSignal,
9377
+ TimeoutException: () => TimeoutException,
9331
9378
  audioFromBase64: () => audioFromBase64,
9332
9379
  audioFromBuffer: () => audioFromBuffer,
9333
9380
  collectEvents: () => collectEvents,
@@ -9339,7 +9386,7 @@ __export(index_exports, {
9339
9386
  createGeminiProviderFromEnv: () => createGeminiProviderFromEnv,
9340
9387
  createHints: () => createHints,
9341
9388
  createLogger: () => createLogger,
9342
- createMedia: () => createMedia,
9389
+ createMediaOutput: () => createMediaOutput,
9343
9390
  createMockAdapter: () => createMockAdapter,
9344
9391
  createMockClient: () => createMockClient,
9345
9392
  createMockStream: () => createMockStream,
@@ -9349,7 +9396,7 @@ __export(index_exports, {
9349
9396
  detectAudioMimeType: () => detectAudioMimeType,
9350
9397
  detectImageMimeType: () => detectImageMimeType,
9351
9398
  discoverProviderAdapters: () => discoverProviderAdapters,
9352
- extractText: () => extractText,
9399
+ extractMessageText: () => extractMessageText,
9353
9400
  getMockManager: () => getMockManager,
9354
9401
  getModelId: () => getModelId,
9355
9402
  getProvider: () => getProvider,
@@ -9363,7 +9410,7 @@ __export(index_exports, {
9363
9410
  isTextPart: () => isTextPart,
9364
9411
  iterationProgressHint: () => iterationProgressHint,
9365
9412
  mockLLM: () => mockLLM,
9366
- normalizeContent: () => normalizeContent,
9413
+ normalizeMessageContent: () => normalizeMessageContent,
9367
9414
  parallelGadgetHint: () => parallelGadgetHint,
9368
9415
  parseDataUrl: () => parseDataUrl,
9369
9416
  resolveHintTemplate: () => resolveHintTemplate,
@@ -10293,7 +10340,7 @@ init_registry();
10293
10340
  // src/gadgets/typed-gadget.ts
10294
10341
  init_gadget();
10295
10342
  function Gadget(config) {
10296
- class GadgetBase extends BaseGadget {
10343
+ class GadgetBase extends AbstractGadget {
10297
10344
  description = config.description;
10298
10345
  parameterSchema = config.schema;
10299
10346
  name = config.name;
@@ -10313,7 +10360,7 @@ function Gadget(config) {
10313
10360
 
10314
10361
  // src/gadgets/helpers.ts
10315
10362
  init_input_content();
10316
- function createMedia(kind, data, mimeType, options) {
10363
+ function createMediaOutput(kind, data, mimeType, options) {
10317
10364
  const buffer = data instanceof Buffer ? data : Buffer.from(data);
10318
10365
  return {
10319
10366
  kind,
@@ -11017,7 +11064,7 @@ var MockBuilder = class {
11017
11064
  whenMessageContains(text3) {
11018
11065
  this.matchers.push(
11019
11066
  (ctx) => ctx.messages.some(
11020
- (msg) => extractText(msg.content).toLowerCase().includes(text3.toLowerCase())
11067
+ (msg) => extractMessageText(msg.content).toLowerCase().includes(text3.toLowerCase())
11021
11068
  )
11022
11069
  );
11023
11070
  return this;
@@ -11032,7 +11079,7 @@ var MockBuilder = class {
11032
11079
  this.matchers.push((ctx) => {
11033
11080
  const lastMsg = ctx.messages[ctx.messages.length - 1];
11034
11081
  if (!lastMsg) return false;
11035
- return extractText(lastMsg.content).toLowerCase().includes(text3.toLowerCase());
11082
+ return extractMessageText(lastMsg.content).toLowerCase().includes(text3.toLowerCase());
11036
11083
  });
11037
11084
  return this;
11038
11085
  }
@@ -11043,7 +11090,7 @@ var MockBuilder = class {
11043
11090
  * mockLLM().whenMessageMatches(/calculate \d+/)
11044
11091
  */
11045
11092
  whenMessageMatches(regex) {
11046
- this.matchers.push((ctx) => ctx.messages.some((msg) => regex.test(extractText(msg.content))));
11093
+ this.matchers.push((ctx) => ctx.messages.some((msg) => regex.test(extractMessageText(msg.content))));
11047
11094
  return this;
11048
11095
  }
11049
11096
  /**
@@ -11055,7 +11102,7 @@ var MockBuilder = class {
11055
11102
  whenRoleContains(role, text3) {
11056
11103
  this.matchers.push(
11057
11104
  (ctx) => ctx.messages.some(
11058
- (msg) => msg.role === role && extractText(msg.content).toLowerCase().includes(text3.toLowerCase())
11105
+ (msg) => msg.role === role && extractMessageText(msg.content).toLowerCase().includes(text3.toLowerCase())
11059
11106
  )
11060
11107
  );
11061
11108
  return this;
@@ -11460,11 +11507,10 @@ function createMockClient(options) {
11460
11507
  init_gadget();
11461
11508
  // Annotate the CommonJS export names for ESM import in node:
11462
11509
  0 && (module.exports = {
11463
- AbortError,
11510
+ AbortException,
11511
+ AbstractGadget,
11464
11512
  AgentBuilder,
11465
11513
  AnthropicMessagesProvider,
11466
- BaseGadget,
11467
- BreakLoopException,
11468
11514
  CompactionManager,
11469
11515
  ConversationManager,
11470
11516
  DEFAULT_COMPACTION_CONFIG,
@@ -11472,12 +11518,13 @@ init_gadget();
11472
11518
  DEFAULT_PROMPTS,
11473
11519
  DEFAULT_SUMMARIZATION_PROMPT,
11474
11520
  Gadget,
11521
+ GadgetCallParser,
11475
11522
  GadgetExecutor,
11476
11523
  GadgetOutputStore,
11477
11524
  GadgetRegistry,
11478
11525
  GeminiGenerativeProvider,
11479
11526
  HookPresets,
11480
- HumanInputException,
11527
+ HumanInputRequiredException,
11481
11528
  HybridStrategy,
11482
11529
  LLMMessageBuilder,
11483
11530
  LLMist,
@@ -11490,9 +11537,10 @@ init_gadget();
11490
11537
  ModelRegistry,
11491
11538
  OpenAIChatProvider,
11492
11539
  SlidingWindowStrategy,
11493
- StreamParser,
11494
11540
  StreamProcessor,
11495
11541
  SummarizationStrategy,
11542
+ TaskCompletionSignal,
11543
+ TimeoutException,
11496
11544
  audioFromBase64,
11497
11545
  audioFromBuffer,
11498
11546
  collectEvents,
@@ -11504,7 +11552,7 @@ init_gadget();
11504
11552
  createGeminiProviderFromEnv,
11505
11553
  createHints,
11506
11554
  createLogger,
11507
- createMedia,
11555
+ createMediaOutput,
11508
11556
  createMockAdapter,
11509
11557
  createMockClient,
11510
11558
  createMockStream,
@@ -11514,7 +11562,7 @@ init_gadget();
11514
11562
  detectAudioMimeType,
11515
11563
  detectImageMimeType,
11516
11564
  discoverProviderAdapters,
11517
- extractText,
11565
+ extractMessageText,
11518
11566
  getMockManager,
11519
11567
  getModelId,
11520
11568
  getProvider,
@@ -11528,7 +11576,7 @@ init_gadget();
11528
11576
  isTextPart,
11529
11577
  iterationProgressHint,
11530
11578
  mockLLM,
11531
- normalizeContent,
11579
+ normalizeMessageContent,
11532
11580
  parallelGadgetHint,
11533
11581
  parseDataUrl,
11534
11582
  resolveHintTemplate,