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.
@@ -320,13 +320,13 @@ var init_prompt_config = __esm({
320
320
  });
321
321
 
322
322
  // src/core/messages.ts
323
- function normalizeContent(content) {
323
+ function normalizeMessageContent(content) {
324
324
  if (typeof content === "string") {
325
325
  return [{ type: "text", text: content }];
326
326
  }
327
327
  return content;
328
328
  }
329
- function extractText(content) {
329
+ function extractMessageText(content) {
330
330
  if (typeof content === "string") {
331
331
  return content;
332
332
  }
@@ -686,7 +686,17 @@ Produces: { "items": ["first", "second"] }`);
686
686
  this.messages.push({ role: "user", content: parts });
687
687
  return this;
688
688
  }
689
- addGadgetCall(gadget, parameters, result, media, mediaIds) {
689
+ /**
690
+ * Record a gadget execution result in the message history.
691
+ * Creates an assistant message with the gadget invocation and a user message with the result.
692
+ *
693
+ * @param gadget - Name of the gadget that was executed
694
+ * @param parameters - Parameters that were passed to the gadget
695
+ * @param result - Text result from the gadget execution
696
+ * @param media - Optional media outputs from the gadget
697
+ * @param mediaIds - Optional IDs for the media outputs
698
+ */
699
+ addGadgetCallResult(gadget, parameters, result, media, mediaIds) {
690
700
  const paramStr = this.formatBlockParameters(parameters, "");
691
701
  this.messages.push({
692
702
  role: "assistant",
@@ -1267,21 +1277,21 @@ var init_media_store = __esm({
1267
1277
  });
1268
1278
 
1269
1279
  // src/gadgets/exceptions.ts
1270
- var BreakLoopException, HumanInputException, TimeoutException, AbortError;
1280
+ var TaskCompletionSignal, HumanInputRequiredException, TimeoutException, AbortException;
1271
1281
  var init_exceptions = __esm({
1272
1282
  "src/gadgets/exceptions.ts"() {
1273
1283
  "use strict";
1274
- BreakLoopException = class extends Error {
1284
+ TaskCompletionSignal = class extends Error {
1275
1285
  constructor(message) {
1276
1286
  super(message ?? "Agent loop terminated by gadget");
1277
- this.name = "BreakLoopException";
1287
+ this.name = "TaskCompletionSignal";
1278
1288
  }
1279
1289
  };
1280
- HumanInputException = class extends Error {
1290
+ HumanInputRequiredException = class extends Error {
1281
1291
  question;
1282
1292
  constructor(question) {
1283
1293
  super(`Human input required: ${question}`);
1284
- this.name = "HumanInputException";
1294
+ this.name = "HumanInputRequiredException";
1285
1295
  this.question = question;
1286
1296
  }
1287
1297
  };
@@ -1295,10 +1305,10 @@ var init_exceptions = __esm({
1295
1305
  this.timeoutMs = timeoutMs;
1296
1306
  }
1297
1307
  };
1298
- AbortError = class extends Error {
1308
+ AbortException = class extends Error {
1299
1309
  constructor(message) {
1300
1310
  super(message || "Gadget execution was aborted");
1301
- this.name = "AbortError";
1311
+ this.name = "AbortException";
1302
1312
  }
1303
1313
  };
1304
1314
  }
@@ -1387,7 +1397,7 @@ var init_schema_to_json = __esm({
1387
1397
  });
1388
1398
 
1389
1399
  // src/gadgets/gadget.ts
1390
- function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
1400
+ function formatParamsForBlockExample(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
1391
1401
  const lines = [];
1392
1402
  for (const [key, value] of Object.entries(params)) {
1393
1403
  const fullPath = prefix ? `${prefix}/${key}` : key;
@@ -1395,14 +1405,14 @@ function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX)
1395
1405
  value.forEach((item, index) => {
1396
1406
  const itemPath = `${fullPath}/${index}`;
1397
1407
  if (typeof item === "object" && item !== null) {
1398
- lines.push(formatParamsAsBlock(item, itemPath, argPrefix));
1408
+ lines.push(formatParamsForBlockExample(item, itemPath, argPrefix));
1399
1409
  } else {
1400
1410
  lines.push(`${argPrefix}${itemPath}`);
1401
1411
  lines.push(String(item));
1402
1412
  }
1403
1413
  });
1404
1414
  } else if (typeof value === "object" && value !== null) {
1405
- lines.push(formatParamsAsBlock(value, fullPath, argPrefix));
1415
+ lines.push(formatParamsForBlockExample(value, fullPath, argPrefix));
1406
1416
  } else {
1407
1417
  lines.push(`${argPrefix}${fullPath}`);
1408
1418
  lines.push(String(value));
@@ -1491,7 +1501,7 @@ function formatSchemaAsPlainText(schema, indent = "", atRoot = true) {
1491
1501
  }
1492
1502
  return lines.join("\n");
1493
1503
  }
1494
- var BaseGadget;
1504
+ var AbstractGadget;
1495
1505
  var init_gadget = __esm({
1496
1506
  "src/gadgets/gadget.ts"() {
1497
1507
  "use strict";
@@ -1499,7 +1509,7 @@ var init_gadget = __esm({
1499
1509
  init_exceptions();
1500
1510
  init_schema_to_json();
1501
1511
  init_schema_validator();
1502
- BaseGadget = class {
1512
+ AbstractGadget = class {
1503
1513
  /**
1504
1514
  * The name of the gadget. Used for identification when LLM calls it.
1505
1515
  * If not provided, defaults to the class name.
@@ -1527,14 +1537,14 @@ var init_gadget = __esm({
1527
1537
  */
1528
1538
  examples;
1529
1539
  /**
1530
- * Throws an AbortError if the execution has been aborted.
1540
+ * Throws an AbortException if the execution has been aborted.
1531
1541
  *
1532
1542
  * Call this at key checkpoints in long-running gadgets to allow early exit
1533
1543
  * when the gadget has been cancelled (e.g., due to timeout). This enables
1534
1544
  * resource cleanup and prevents unnecessary work after cancellation.
1535
1545
  *
1536
1546
  * @param ctx - The execution context containing the abort signal
1537
- * @throws AbortError if ctx.signal.aborted is true
1547
+ * @throws AbortException if ctx.signal.aborted is true
1538
1548
  *
1539
1549
  * @example
1540
1550
  * ```typescript
@@ -1559,7 +1569,7 @@ var init_gadget = __esm({
1559
1569
  */
1560
1570
  throwIfAborted(ctx) {
1561
1571
  if (ctx?.signal?.aborted) {
1562
- throw new AbortError();
1572
+ throw new AbortException();
1563
1573
  }
1564
1574
  }
1565
1575
  /**
@@ -1701,7 +1711,7 @@ var init_gadget = __esm({
1701
1711
  }
1702
1712
  parts.push(`${effectiveStartPrefix}${gadgetName}`);
1703
1713
  parts.push(
1704
- formatParamsAsBlock(example.params, "", effectiveArgPrefix)
1714
+ formatParamsForBlockExample(example.params, "", effectiveArgPrefix)
1705
1715
  );
1706
1716
  parts.push(effectiveEndPrefix);
1707
1717
  if (example.output !== void 0) {
@@ -1719,7 +1729,7 @@ var init_gadget = __esm({
1719
1729
 
1720
1730
  // src/gadgets/create-gadget.ts
1721
1731
  function createGadget(config) {
1722
- class DynamicGadget extends BaseGadget {
1732
+ class DynamicGadget extends AbstractGadget {
1723
1733
  name = config.name;
1724
1734
  description = config.description;
1725
1735
  parameterSchema = config.schema;
@@ -2357,8 +2367,8 @@ var init_conversation_manager = __esm({
2357
2367
  addAssistantMessage(content) {
2358
2368
  this.historyBuilder.addAssistant(content);
2359
2369
  }
2360
- addGadgetCall(gadgetName, parameters, result, media, mediaIds) {
2361
- this.historyBuilder.addGadgetCall(gadgetName, parameters, result, media, mediaIds);
2370
+ addGadgetCallResult(gadgetName, parameters, result, media, mediaIds) {
2371
+ this.historyBuilder.addGadgetCallResult(gadgetName, parameters, result, media, mediaIds);
2362
2372
  }
2363
2373
  getMessages() {
2364
2374
  return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
@@ -2378,7 +2388,7 @@ var init_conversation_manager = __esm({
2378
2388
  if (msg.role === "user") {
2379
2389
  this.historyBuilder.addUser(msg.content);
2380
2390
  } else if (msg.role === "assistant") {
2381
- this.historyBuilder.addAssistant(extractText(msg.content));
2391
+ this.historyBuilder.addAssistant(extractMessageText(msg.content));
2382
2392
  }
2383
2393
  }
2384
2394
  }
@@ -3258,12 +3268,12 @@ var init_cost_reporting_client = __esm({
3258
3268
  });
3259
3269
 
3260
3270
  // src/gadgets/error-formatter.ts
3261
- var GadgetErrorFormatter;
3271
+ var GadgetExecutionErrorFormatter;
3262
3272
  var init_error_formatter = __esm({
3263
3273
  "src/gadgets/error-formatter.ts"() {
3264
3274
  "use strict";
3265
3275
  init_constants();
3266
- GadgetErrorFormatter = class {
3276
+ GadgetExecutionErrorFormatter = class {
3267
3277
  argPrefix;
3268
3278
  startPrefix;
3269
3279
  endPrefix;
@@ -3349,16 +3359,16 @@ function stripMarkdownFences(content) {
3349
3359
  cleaned = cleaned.replace(closingFence, "");
3350
3360
  return cleaned.trim();
3351
3361
  }
3352
- var globalInvocationCounter, StreamParser;
3362
+ var globalInvocationCounter, GadgetCallParser;
3353
3363
  var init_parser = __esm({
3354
3364
  "src/gadgets/parser.ts"() {
3355
3365
  "use strict";
3356
3366
  init_constants();
3357
3367
  init_block_params();
3358
3368
  globalInvocationCounter = 0;
3359
- StreamParser = class {
3369
+ GadgetCallParser = class {
3360
3370
  buffer = "";
3361
- lastReportedTextLength = 0;
3371
+ lastEmittedTextOffset = 0;
3362
3372
  startPrefix;
3363
3373
  endPrefix;
3364
3374
  argPrefix;
@@ -3367,16 +3377,20 @@ var init_parser = __esm({
3367
3377
  this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
3368
3378
  this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
3369
3379
  }
3370
- takeTextUntil(index) {
3371
- if (index <= this.lastReportedTextLength) {
3380
+ /**
3381
+ * Extract and consume text up to the given index.
3382
+ * Returns undefined if no meaningful text to emit.
3383
+ */
3384
+ extractTextSegment(index) {
3385
+ if (index <= this.lastEmittedTextOffset) {
3372
3386
  return void 0;
3373
3387
  }
3374
- const segment = this.buffer.slice(this.lastReportedTextLength, index);
3375
- this.lastReportedTextLength = index;
3388
+ const segment = this.buffer.slice(this.lastEmittedTextOffset, index);
3389
+ this.lastEmittedTextOffset = index;
3376
3390
  return segment.trim().length > 0 ? segment : void 0;
3377
3391
  }
3378
3392
  /**
3379
- * Parse gadget name with optional invocation ID and dependencies.
3393
+ * Parse gadget invocation metadata from the header line.
3380
3394
  *
3381
3395
  * Supported formats:
3382
3396
  * - `GadgetName` - Auto-generate ID, no dependencies
@@ -3385,24 +3399,24 @@ var init_parser = __esm({
3385
3399
  *
3386
3400
  * Dependencies must be comma-separated invocation IDs.
3387
3401
  */
3388
- parseGadgetName(gadgetName) {
3389
- const parts = gadgetName.split(":");
3402
+ parseInvocationMetadata(headerLine) {
3403
+ const parts = headerLine.split(":");
3390
3404
  if (parts.length === 1) {
3391
3405
  return {
3392
- actualName: parts[0],
3406
+ gadgetName: parts[0],
3393
3407
  invocationId: `gadget_${++globalInvocationCounter}`,
3394
3408
  dependencies: []
3395
3409
  };
3396
3410
  } else if (parts.length === 2) {
3397
3411
  return {
3398
- actualName: parts[0],
3412
+ gadgetName: parts[0],
3399
3413
  invocationId: parts[1].trim(),
3400
3414
  dependencies: []
3401
3415
  };
3402
3416
  } else {
3403
3417
  const deps = parts[2].split(",").map((d) => d.trim()).filter((d) => d.length > 0);
3404
3418
  return {
3405
- actualName: parts[0],
3419
+ gadgetName: parts[0],
3406
3420
  invocationId: parts[1].trim(),
3407
3421
  dependencies: deps
3408
3422
  };
@@ -3434,19 +3448,15 @@ var init_parser = __esm({
3434
3448
  while (true) {
3435
3449
  const partStartIndex = this.buffer.indexOf(this.startPrefix, startIndex);
3436
3450
  if (partStartIndex === -1) break;
3437
- const textBefore = this.takeTextUntil(partStartIndex);
3451
+ const textBefore = this.extractTextSegment(partStartIndex);
3438
3452
  if (textBefore !== void 0) {
3439
3453
  yield { type: "text", content: textBefore };
3440
3454
  }
3441
3455
  const metadataStartIndex = partStartIndex + this.startPrefix.length;
3442
3456
  const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
3443
3457
  if (metadataEndIndex === -1) break;
3444
- const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
3445
- const {
3446
- actualName: actualGadgetName,
3447
- invocationId,
3448
- dependencies
3449
- } = this.parseGadgetName(gadgetName);
3458
+ const headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
3459
+ const { gadgetName, invocationId, dependencies } = this.parseInvocationMetadata(headerLine);
3450
3460
  const contentStartIndex = metadataEndIndex + 1;
3451
3461
  let partEndIndex;
3452
3462
  let endMarkerLength = 0;
@@ -3466,7 +3476,7 @@ var init_parser = __esm({
3466
3476
  yield {
3467
3477
  type: "gadget_call",
3468
3478
  call: {
3469
- gadgetName: actualGadgetName,
3479
+ gadgetName,
3470
3480
  invocationId,
3471
3481
  parametersRaw,
3472
3482
  parameters,
@@ -3475,37 +3485,33 @@ var init_parser = __esm({
3475
3485
  }
3476
3486
  };
3477
3487
  startIndex = partEndIndex + endMarkerLength;
3478
- this.lastReportedTextLength = startIndex;
3488
+ this.lastEmittedTextOffset = startIndex;
3479
3489
  }
3480
3490
  if (startIndex > 0) {
3481
3491
  this.buffer = this.buffer.substring(startIndex);
3482
- this.lastReportedTextLength = 0;
3492
+ this.lastEmittedTextOffset = 0;
3483
3493
  }
3484
3494
  }
3485
3495
  // Finalize parsing and return remaining text or incomplete gadgets
3486
3496
  *finalize() {
3487
- const startIndex = this.buffer.indexOf(this.startPrefix, this.lastReportedTextLength);
3497
+ const startIndex = this.buffer.indexOf(this.startPrefix, this.lastEmittedTextOffset);
3488
3498
  if (startIndex !== -1) {
3489
- const textBefore = this.takeTextUntil(startIndex);
3499
+ const textBefore = this.extractTextSegment(startIndex);
3490
3500
  if (textBefore !== void 0) {
3491
3501
  yield { type: "text", content: textBefore };
3492
3502
  }
3493
3503
  const metadataStartIndex = startIndex + this.startPrefix.length;
3494
3504
  const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
3495
3505
  if (metadataEndIndex !== -1) {
3496
- const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
3497
- const {
3498
- actualName: actualGadgetName,
3499
- invocationId,
3500
- dependencies
3501
- } = this.parseGadgetName(gadgetName);
3506
+ const headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
3507
+ const { gadgetName, invocationId, dependencies } = this.parseInvocationMetadata(headerLine);
3502
3508
  const contentStartIndex = metadataEndIndex + 1;
3503
3509
  const parametersRaw = this.buffer.substring(contentStartIndex).trim();
3504
3510
  const { parameters, parseError } = this.parseParameters(parametersRaw);
3505
3511
  yield {
3506
3512
  type: "gadget_call",
3507
3513
  call: {
3508
- gadgetName: actualGadgetName,
3514
+ gadgetName,
3509
3515
  invocationId,
3510
3516
  parametersRaw,
3511
3517
  parameters,
@@ -3516,7 +3522,7 @@ var init_parser = __esm({
3516
3522
  return;
3517
3523
  }
3518
3524
  }
3519
- const remainingText = this.takeTextUntil(this.buffer.length);
3525
+ const remainingText = this.extractTextSegment(this.buffer.length);
3520
3526
  if (remainingText !== void 0) {
3521
3527
  yield { type: "text", content: remainingText };
3522
3528
  }
@@ -3524,7 +3530,7 @@ var init_parser = __esm({
3524
3530
  // Reset parser state (note: global invocation counter is NOT reset to ensure unique IDs)
3525
3531
  reset() {
3526
3532
  this.buffer = "";
3527
- this.lastReportedTextLength = 0;
3533
+ this.lastEmittedTextOffset = 0;
3528
3534
  }
3529
3535
  };
3530
3536
  }
@@ -3543,14 +3549,16 @@ var init_executor = __esm({
3543
3549
  init_exceptions();
3544
3550
  init_parser();
3545
3551
  GadgetExecutor = class {
3546
- constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs, errorFormatterOptions, client, mediaStore) {
3552
+ constructor(registry, requestHumanInput, logger, defaultGadgetTimeoutMs, errorFormatterOptions, client, mediaStore, agentConfig, subagentConfig) {
3547
3553
  this.registry = registry;
3548
- this.onHumanInputRequired = onHumanInputRequired;
3554
+ this.requestHumanInput = requestHumanInput;
3549
3555
  this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
3550
3556
  this.client = client;
3551
3557
  this.mediaStore = mediaStore;
3558
+ this.agentConfig = agentConfig;
3559
+ this.subagentConfig = subagentConfig;
3552
3560
  this.logger = logger ?? createLogger({ name: "llmist:executor" });
3553
- this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);
3561
+ this.errorFormatter = new GadgetExecutionErrorFormatter(errorFormatterOptions);
3554
3562
  this.argPrefix = errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;
3555
3563
  }
3556
3564
  logger;
@@ -3570,11 +3578,11 @@ var init_executor = __esm({
3570
3578
  });
3571
3579
  }
3572
3580
  /**
3573
- * Normalizes gadget execute result to consistent format.
3581
+ * Unify gadget execute result to consistent internal format.
3574
3582
  * Handles string returns (backwards compat), object returns with cost,
3575
3583
  * and object returns with media.
3576
3584
  */
3577
- normalizeExecuteResult(raw) {
3585
+ unifyExecuteResult(raw) {
3578
3586
  if (typeof raw === "string") {
3579
3587
  return { result: raw, cost: 0 };
3580
3588
  }
@@ -3692,7 +3700,9 @@ var init_executor = __esm({
3692
3700
  const ctx = {
3693
3701
  reportCost,
3694
3702
  llmist: this.client ? new CostReportingLLMistWrapper(this.client, reportCost) : void 0,
3695
- signal: abortController.signal
3703
+ signal: abortController.signal,
3704
+ agentConfig: this.agentConfig,
3705
+ subagentConfig: this.subagentConfig
3696
3706
  };
3697
3707
  let rawResult;
3698
3708
  if (timeoutMs && timeoutMs > 0) {
@@ -3707,7 +3717,7 @@ var init_executor = __esm({
3707
3717
  } else {
3708
3718
  rawResult = await Promise.resolve(gadget.execute(validatedParameters, ctx));
3709
3719
  }
3710
- const { result, media, cost: returnCost } = this.normalizeExecuteResult(rawResult);
3720
+ const { result, media, cost: returnCost } = this.unifyExecuteResult(rawResult);
3711
3721
  const totalCost = callbackCost + returnCost;
3712
3722
  let mediaIds;
3713
3723
  let storedMedia;
@@ -3753,7 +3763,7 @@ var init_executor = __esm({
3753
3763
  storedMedia
3754
3764
  };
3755
3765
  } catch (error) {
3756
- if (error instanceof BreakLoopException) {
3766
+ if (error instanceof TaskCompletionSignal) {
3757
3767
  this.logger.info("Gadget requested loop termination", {
3758
3768
  gadgetName: call.gadgetName,
3759
3769
  message: error.message
@@ -3781,7 +3791,7 @@ var init_executor = __esm({
3781
3791
  executionTimeMs: Date.now() - startTime
3782
3792
  };
3783
3793
  }
3784
- if (error instanceof AbortError) {
3794
+ if (error instanceof AbortException) {
3785
3795
  this.logger.info("Gadget execution was aborted", {
3786
3796
  gadgetName: call.gadgetName,
3787
3797
  executionTimeMs: Date.now() - startTime
@@ -3794,14 +3804,14 @@ var init_executor = __esm({
3794
3804
  executionTimeMs: Date.now() - startTime
3795
3805
  };
3796
3806
  }
3797
- if (error instanceof HumanInputException) {
3807
+ if (error instanceof HumanInputRequiredException) {
3798
3808
  this.logger.info("Gadget requested human input", {
3799
3809
  gadgetName: call.gadgetName,
3800
3810
  question: error.question
3801
3811
  });
3802
- if (this.onHumanInputRequired) {
3812
+ if (this.requestHumanInput) {
3803
3813
  try {
3804
- const answer = await this.onHumanInputRequired(error.question);
3814
+ const answer = await this.requestHumanInput(error.question);
3805
3815
  this.logger.debug("Human input received", {
3806
3816
  gadgetName: call.gadgetName,
3807
3817
  answerLength: answer.length
@@ -3899,13 +3909,13 @@ var init_stream_processor = __esm({
3899
3909
  parser;
3900
3910
  executor;
3901
3911
  stopOnGadgetError;
3902
- shouldContinueAfterError;
3903
- accumulatedText = "";
3904
- shouldStopExecution = false;
3912
+ canRecoverFromGadgetError;
3913
+ responseText = "";
3914
+ executionHalted = false;
3905
3915
  observerFailureCount = 0;
3906
3916
  // Dependency tracking for gadget execution DAG
3907
3917
  /** Gadgets waiting for their dependencies to complete */
3908
- pendingGadgets = /* @__PURE__ */ new Map();
3918
+ gadgetsAwaitingDependencies = /* @__PURE__ */ new Map();
3909
3919
  /** Completed gadget results, keyed by invocation ID */
3910
3920
  completedResults = /* @__PURE__ */ new Map();
3911
3921
  /** Invocation IDs of gadgets that have failed (error or skipped due to dependency) */
@@ -3916,20 +3926,22 @@ var init_stream_processor = __esm({
3916
3926
  this.hooks = options.hooks ?? {};
3917
3927
  this.logger = options.logger ?? createLogger({ name: "llmist:stream-processor" });
3918
3928
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
3919
- this.shouldContinueAfterError = options.shouldContinueAfterError;
3920
- this.parser = new StreamParser({
3929
+ this.canRecoverFromGadgetError = options.canRecoverFromGadgetError;
3930
+ this.parser = new GadgetCallParser({
3921
3931
  startPrefix: options.gadgetStartPrefix,
3922
3932
  endPrefix: options.gadgetEndPrefix,
3923
3933
  argPrefix: options.gadgetArgPrefix
3924
3934
  });
3925
3935
  this.executor = new GadgetExecutor(
3926
3936
  options.registry,
3927
- options.onHumanInputRequired,
3937
+ options.requestHumanInput,
3928
3938
  this.logger.getSubLogger({ name: "executor" }),
3929
3939
  options.defaultGadgetTimeoutMs,
3930
3940
  { argPrefix: options.gadgetArgPrefix },
3931
3941
  options.client,
3932
- options.mediaStore
3942
+ options.mediaStore,
3943
+ options.agentConfig,
3944
+ options.subagentConfig
3933
3945
  );
3934
3946
  }
3935
3947
  /**
@@ -3950,7 +3962,7 @@ var init_stream_processor = __esm({
3950
3962
  if (this.hooks.interceptors?.interceptRawChunk) {
3951
3963
  const context = {
3952
3964
  iteration: this.iteration,
3953
- accumulatedText: this.accumulatedText,
3965
+ accumulatedText: this.responseText,
3954
3966
  logger: this.logger
3955
3967
  };
3956
3968
  const intercepted = this.hooks.interceptors.interceptRawChunk(processedChunk, context);
@@ -3961,7 +3973,7 @@ var init_stream_processor = __esm({
3961
3973
  }
3962
3974
  }
3963
3975
  if (processedChunk) {
3964
- this.accumulatedText += processedChunk;
3976
+ this.responseText += processedChunk;
3965
3977
  }
3966
3978
  }
3967
3979
  if (this.hooks.observers?.onStreamChunk && (processedChunk || chunk.usage)) {
@@ -3970,7 +3982,7 @@ var init_stream_processor = __esm({
3970
3982
  const context = {
3971
3983
  iteration: this.iteration,
3972
3984
  rawChunk: processedChunk,
3973
- accumulatedText: this.accumulatedText,
3985
+ accumulatedText: this.responseText,
3974
3986
  usage,
3975
3987
  logger: this.logger
3976
3988
  };
@@ -3993,12 +4005,12 @@ var init_stream_processor = __esm({
3993
4005
  }
3994
4006
  }
3995
4007
  }
3996
- if (this.shouldStopExecution) {
4008
+ if (this.executionHalted) {
3997
4009
  this.logger.info("Breaking from LLM stream due to gadget error");
3998
4010
  break;
3999
4011
  }
4000
4012
  }
4001
- if (!this.shouldStopExecution) {
4013
+ if (!this.executionHalted) {
4002
4014
  for (const event of this.parser.finalize()) {
4003
4015
  const processedEvents = await this.processEvent(event);
4004
4016
  outputs.push(...processedEvents);
@@ -4022,11 +4034,11 @@ var init_stream_processor = __esm({
4022
4034
  }
4023
4035
  }
4024
4036
  }
4025
- let finalMessage = this.accumulatedText;
4037
+ let finalMessage = this.responseText;
4026
4038
  if (this.hooks.interceptors?.interceptAssistantMessage) {
4027
4039
  const context = {
4028
4040
  iteration: this.iteration,
4029
- rawResponse: this.accumulatedText,
4041
+ rawResponse: this.responseText,
4030
4042
  logger: this.logger
4031
4043
  };
4032
4044
  finalMessage = this.hooks.interceptors.interceptAssistantMessage(finalMessage, context);
@@ -4037,7 +4049,7 @@ var init_stream_processor = __esm({
4037
4049
  didExecuteGadgets,
4038
4050
  finishReason,
4039
4051
  usage,
4040
- rawResponse: this.accumulatedText,
4052
+ rawResponse: this.responseText,
4041
4053
  finalMessage
4042
4054
  };
4043
4055
  }
@@ -4060,7 +4072,7 @@ var init_stream_processor = __esm({
4060
4072
  if (this.hooks.interceptors?.interceptTextChunk) {
4061
4073
  const context = {
4062
4074
  iteration: this.iteration,
4063
- accumulatedText: this.accumulatedText,
4075
+ accumulatedText: this.responseText,
4064
4076
  logger: this.logger
4065
4077
  };
4066
4078
  const intercepted = this.hooks.interceptors.interceptTextChunk(content, context);
@@ -4079,7 +4091,7 @@ var init_stream_processor = __esm({
4079
4091
  * After each execution, pending gadgets are checked to see if they can now run.
4080
4092
  */
4081
4093
  async processGadgetCall(call) {
4082
- if (this.shouldStopExecution) {
4094
+ if (this.executionHalted) {
4083
4095
  this.logger.debug("Skipping gadget execution due to previous error", {
4084
4096
  gadgetName: call.gadgetName
4085
4097
  });
@@ -4118,7 +4130,7 @@ var init_stream_processor = __esm({
4118
4130
  invocationId: call.invocationId,
4119
4131
  waitingOn: unsatisfied
4120
4132
  });
4121
- this.pendingGadgets.set(call.invocationId, call);
4133
+ this.gadgetsAwaitingDependencies.set(call.invocationId, call);
4122
4134
  return events;
4123
4135
  }
4124
4136
  }
@@ -4140,14 +4152,14 @@ var init_stream_processor = __esm({
4140
4152
  error: call.parseError,
4141
4153
  rawParameters: call.parametersRaw
4142
4154
  });
4143
- const shouldContinue = await this.checkContinueAfterError(
4155
+ const shouldContinue = await this.checkCanRecoverFromError(
4144
4156
  call.parseError,
4145
4157
  call.gadgetName,
4146
4158
  "parse",
4147
4159
  call.parameters
4148
4160
  );
4149
4161
  if (!shouldContinue) {
4150
- this.shouldStopExecution = true;
4162
+ this.executionHalted = true;
4151
4163
  }
4152
4164
  }
4153
4165
  let parameters = call.parameters ?? {};
@@ -4271,14 +4283,14 @@ var init_stream_processor = __esm({
4271
4283
  events.push({ type: "gadget_result", result });
4272
4284
  if (result.error) {
4273
4285
  const errorType = this.determineErrorType(call, result);
4274
- const shouldContinue = await this.checkContinueAfterError(
4286
+ const shouldContinue = await this.checkCanRecoverFromError(
4275
4287
  result.error,
4276
4288
  result.gadgetName,
4277
4289
  errorType,
4278
4290
  result.parameters
4279
4291
  );
4280
4292
  if (!shouldContinue) {
4281
- this.shouldStopExecution = true;
4293
+ this.executionHalted = true;
4282
4294
  }
4283
4295
  }
4284
4296
  return events;
@@ -4365,11 +4377,11 @@ var init_stream_processor = __esm({
4365
4377
  async processPendingGadgets() {
4366
4378
  const events = [];
4367
4379
  let progress = true;
4368
- while (progress && this.pendingGadgets.size > 0) {
4380
+ while (progress && this.gadgetsAwaitingDependencies.size > 0) {
4369
4381
  progress = false;
4370
4382
  const readyToExecute = [];
4371
4383
  const readyToSkip = [];
4372
- for (const [invocationId, call] of this.pendingGadgets) {
4384
+ for (const [invocationId, call] of this.gadgetsAwaitingDependencies) {
4373
4385
  const failedDep = call.dependencies.find((dep) => this.failedInvocations.has(dep));
4374
4386
  if (failedDep) {
4375
4387
  readyToSkip.push({ call, failedDep });
@@ -4381,7 +4393,7 @@ var init_stream_processor = __esm({
4381
4393
  }
4382
4394
  }
4383
4395
  for (const { call, failedDep } of readyToSkip) {
4384
- this.pendingGadgets.delete(call.invocationId);
4396
+ this.gadgetsAwaitingDependencies.delete(call.invocationId);
4385
4397
  const skipEvents = await this.handleFailedDependency(call, failedDep);
4386
4398
  events.push(...skipEvents);
4387
4399
  progress = true;
@@ -4392,7 +4404,7 @@ var init_stream_processor = __esm({
4392
4404
  invocationIds: readyToExecute.map((c) => c.invocationId)
4393
4405
  });
4394
4406
  for (const call of readyToExecute) {
4395
- this.pendingGadgets.delete(call.invocationId);
4407
+ this.gadgetsAwaitingDependencies.delete(call.invocationId);
4396
4408
  }
4397
4409
  const executePromises = readyToExecute.map((call) => this.executeGadgetWithHooks(call));
4398
4410
  const results = await Promise.all(executePromises);
@@ -4402,9 +4414,9 @@ var init_stream_processor = __esm({
4402
4414
  progress = true;
4403
4415
  }
4404
4416
  }
4405
- if (this.pendingGadgets.size > 0) {
4406
- const pendingIds = new Set(this.pendingGadgets.keys());
4407
- for (const [invocationId, call] of this.pendingGadgets) {
4417
+ if (this.gadgetsAwaitingDependencies.size > 0) {
4418
+ const pendingIds = new Set(this.gadgetsAwaitingDependencies.keys());
4419
+ for (const [invocationId, call] of this.gadgetsAwaitingDependencies) {
4408
4420
  const missingDeps = call.dependencies.filter((dep) => !this.completedResults.has(dep));
4409
4421
  const circularDeps = missingDeps.filter((dep) => pendingIds.has(dep));
4410
4422
  const trulyMissingDeps = missingDeps.filter((dep) => !pendingIds.has(dep));
@@ -4435,7 +4447,7 @@ var init_stream_processor = __esm({
4435
4447
  };
4436
4448
  events.push(skipEvent);
4437
4449
  }
4438
- this.pendingGadgets.clear();
4450
+ this.gadgetsAwaitingDependencies.clear();
4439
4451
  }
4440
4452
  return events;
4441
4453
  }
@@ -4465,19 +4477,19 @@ var init_stream_processor = __esm({
4465
4477
  );
4466
4478
  }
4467
4479
  /**
4468
- * Check if execution should continue after an error.
4480
+ * Check if execution can recover from an error.
4469
4481
  *
4470
4482
  * Returns true if we should continue processing subsequent gadgets, false if we should stop.
4471
4483
  *
4472
4484
  * Logic:
4473
- * - If custom shouldContinueAfterError is provided, use it
4485
+ * - If custom canRecoverFromGadgetError is provided, use it
4474
4486
  * - Otherwise, use stopOnGadgetError config:
4475
4487
  * - stopOnGadgetError=true → return false (stop execution)
4476
4488
  * - stopOnGadgetError=false → return true (continue execution)
4477
4489
  */
4478
- async checkContinueAfterError(error, gadgetName, errorType, parameters) {
4479
- if (this.shouldContinueAfterError) {
4480
- return await this.shouldContinueAfterError({
4490
+ async checkCanRecoverFromError(error, gadgetName, errorType, parameters) {
4491
+ if (this.canRecoverFromGadgetError) {
4492
+ return await this.canRecoverFromGadgetError({
4481
4493
  error,
4482
4494
  gadgetName,
4483
4495
  errorType,
@@ -4540,14 +4552,14 @@ var init_agent = __esm({
4540
4552
  gadgetStartPrefix;
4541
4553
  gadgetEndPrefix;
4542
4554
  gadgetArgPrefix;
4543
- onHumanInputRequired;
4555
+ requestHumanInput;
4544
4556
  textOnlyHandler;
4545
4557
  textWithGadgetsHandler;
4546
4558
  stopOnGadgetError;
4547
- shouldContinueAfterError;
4559
+ canRecoverFromGadgetError;
4548
4560
  defaultGadgetTimeoutMs;
4549
4561
  defaultMaxTokens;
4550
- userPromptProvided;
4562
+ hasUserPrompt;
4551
4563
  // Gadget output limiting
4552
4564
  outputStore;
4553
4565
  outputLimitEnabled;
@@ -4558,6 +4570,9 @@ var init_agent = __esm({
4558
4570
  mediaStore;
4559
4571
  // Cancellation
4560
4572
  signal;
4573
+ // Subagent configuration
4574
+ agentContextConfig;
4575
+ subagentConfig;
4561
4576
  /**
4562
4577
  * Creates a new Agent instance.
4563
4578
  * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.
@@ -4577,11 +4592,11 @@ var init_agent = __esm({
4577
4592
  this.gadgetStartPrefix = options.gadgetStartPrefix;
4578
4593
  this.gadgetEndPrefix = options.gadgetEndPrefix;
4579
4594
  this.gadgetArgPrefix = options.gadgetArgPrefix;
4580
- this.onHumanInputRequired = options.onHumanInputRequired;
4595
+ this.requestHumanInput = options.requestHumanInput;
4581
4596
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
4582
4597
  this.textWithGadgetsHandler = options.textWithGadgetsHandler;
4583
4598
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
4584
- this.shouldContinueAfterError = options.shouldContinueAfterError;
4599
+ this.canRecoverFromGadgetError = options.canRecoverFromGadgetError;
4585
4600
  this.defaultGadgetTimeoutMs = options.defaultGadgetTimeoutMs;
4586
4601
  this.defaultMaxTokens = this.resolveMaxTokensFromCatalog(options.model);
4587
4602
  this.outputLimitEnabled = options.gadgetOutputLimit ?? DEFAULT_GADGET_OUTPUT_LIMIT;
@@ -4597,7 +4612,7 @@ var init_agent = __esm({
4597
4612
  createGadgetOutputViewer(this.outputStore, this.outputLimitCharLimit)
4598
4613
  );
4599
4614
  }
4600
- this.hooks = this.mergeOutputLimiterHook(options.hooks);
4615
+ this.hooks = this.chainOutputLimiterWithUserHooks(options.hooks);
4601
4616
  const baseBuilder = new LLMMessageBuilder(options.promptConfig);
4602
4617
  if (options.systemPrompt) {
4603
4618
  baseBuilder.addSystem(options.systemPrompt);
@@ -4617,7 +4632,7 @@ var init_agent = __esm({
4617
4632
  endPrefix: options.gadgetEndPrefix,
4618
4633
  argPrefix: options.gadgetArgPrefix
4619
4634
  });
4620
- this.userPromptProvided = !!options.userPrompt;
4635
+ this.hasUserPrompt = !!options.userPrompt;
4621
4636
  if (options.userPrompt) {
4622
4637
  this.conversation.addUserMessage(options.userPrompt);
4623
4638
  }
@@ -4630,6 +4645,11 @@ var init_agent = __esm({
4630
4645
  );
4631
4646
  }
4632
4647
  this.signal = options.signal;
4648
+ this.agentContextConfig = {
4649
+ model: this.model,
4650
+ temperature: this.temperature
4651
+ };
4652
+ this.subagentConfig = options.subagentConfig;
4633
4653
  }
4634
4654
  /**
4635
4655
  * Get the gadget registry for this agent.
@@ -4736,7 +4756,7 @@ var init_agent = __esm({
4736
4756
  * @throws {Error} If no user prompt was provided (when using build() without ask())
4737
4757
  */
4738
4758
  async *run() {
4739
- if (!this.userPromptProvided) {
4759
+ if (!this.hasUserPrompt) {
4740
4760
  throw new Error(
4741
4761
  "No user prompt provided. Use .ask(prompt) instead of .build(), or call agent.run() after providing a prompt."
4742
4762
  );
@@ -4853,12 +4873,14 @@ var init_agent = __esm({
4853
4873
  gadgetArgPrefix: this.gadgetArgPrefix,
4854
4874
  hooks: this.hooks,
4855
4875
  logger: this.logger.getSubLogger({ name: "stream-processor" }),
4856
- onHumanInputRequired: this.onHumanInputRequired,
4876
+ requestHumanInput: this.requestHumanInput,
4857
4877
  stopOnGadgetError: this.stopOnGadgetError,
4858
- shouldContinueAfterError: this.shouldContinueAfterError,
4878
+ canRecoverFromGadgetError: this.canRecoverFromGadgetError,
4859
4879
  defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
4860
4880
  client: this.client,
4861
- mediaStore: this.mediaStore
4881
+ mediaStore: this.mediaStore,
4882
+ agentConfig: this.agentContextConfig,
4883
+ subagentConfig: this.subagentConfig
4862
4884
  });
4863
4885
  const result = await processor.process(stream2);
4864
4886
  for (const output of result.outputs) {
@@ -4911,9 +4933,9 @@ var init_agent = __esm({
4911
4933
  if (msg.role === "user") {
4912
4934
  this.conversation.addUserMessage(msg.content);
4913
4935
  } else if (msg.role === "assistant") {
4914
- this.conversation.addAssistantMessage(extractText(msg.content));
4936
+ this.conversation.addAssistantMessage(extractMessageText(msg.content));
4915
4937
  } else if (msg.role === "system") {
4916
- this.conversation.addUserMessage(`[System] ${extractText(msg.content)}`);
4938
+ this.conversation.addUserMessage(`[System] ${extractMessageText(msg.content)}`);
4917
4939
  }
4918
4940
  }
4919
4941
  }
@@ -4925,7 +4947,7 @@ var init_agent = __esm({
4925
4947
  ).map((output) => output.content).join("");
4926
4948
  if (textContent.trim()) {
4927
4949
  const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;
4928
- this.conversation.addGadgetCall(
4950
+ this.conversation.addGadgetCallResult(
4929
4951
  gadgetName,
4930
4952
  parameterMapping(textContent),
4931
4953
  resultMapping ? resultMapping(textContent) : textContent
@@ -4935,7 +4957,7 @@ var init_agent = __esm({
4935
4957
  for (const output of result.outputs) {
4936
4958
  if (output.type === "gadget_result") {
4937
4959
  const gadgetResult = output.result;
4938
- this.conversation.addGadgetCall(
4960
+ this.conversation.addGadgetCallResult(
4939
4961
  gadgetResult.gadgetName,
4940
4962
  gadgetResult.parameters,
4941
4963
  gadgetResult.error ?? gadgetResult.result ?? "",
@@ -4946,7 +4968,7 @@ var init_agent = __esm({
4946
4968
  }
4947
4969
  } else {
4948
4970
  if (finalMessage.trim()) {
4949
- this.conversation.addGadgetCall(
4971
+ this.conversation.addGadgetCallResult(
4950
4972
  "TellUser",
4951
4973
  { message: finalMessage, done: false, type: "info" },
4952
4974
  `\u2139\uFE0F ${finalMessage}`
@@ -5072,10 +5094,10 @@ var init_agent = __esm({
5072
5094
  return this.client.modelRegistry.getModelLimits(unprefixedModelId)?.maxOutputTokens;
5073
5095
  }
5074
5096
  /**
5075
- * Merge the output limiter interceptor into user-provided hooks.
5097
+ * Chain the output limiter interceptor with user-provided hooks.
5076
5098
  * The limiter runs first, then chains to any user interceptor.
5077
5099
  */
5078
- mergeOutputLimiterHook(userHooks) {
5100
+ chainOutputLimiterWithUserHooks(userHooks) {
5079
5101
  if (!this.outputLimitEnabled) {
5080
5102
  return userHooks ?? {};
5081
5103
  }
@@ -5154,20 +5176,21 @@ var init_builder = __esm({
5154
5176
  promptConfig;
5155
5177
  gadgets = [];
5156
5178
  initialMessages = [];
5157
- onHumanInputRequired;
5179
+ requestHumanInput;
5158
5180
  gadgetStartPrefix;
5159
5181
  gadgetEndPrefix;
5160
5182
  gadgetArgPrefix;
5161
5183
  textOnlyHandler;
5162
5184
  textWithGadgetsHandler;
5163
5185
  stopOnGadgetError;
5164
- shouldContinueAfterError;
5186
+ canRecoverFromGadgetError;
5165
5187
  defaultGadgetTimeoutMs;
5166
5188
  gadgetOutputLimit;
5167
5189
  gadgetOutputLimitPercent;
5168
5190
  compactionConfig;
5169
5191
  signal;
5170
5192
  trailingMessage;
5193
+ subagentConfig;
5171
5194
  constructor(client) {
5172
5195
  this.client = client;
5173
5196
  }
@@ -5258,13 +5281,13 @@ var init_builder = __esm({
5258
5281
  *
5259
5282
  * @example
5260
5283
  * ```typescript
5261
- * .withPromptConfig({
5284
+ * .withPromptTemplateConfig({
5262
5285
  * mainInstruction: "Use the gadget markers below:",
5263
5286
  * rules: ["Always use markers", "Never use function calling"]
5264
5287
  * })
5265
5288
  * ```
5266
5289
  */
5267
- withPromptConfig(config) {
5290
+ withPromptTemplateConfig(config) {
5268
5291
  this.promptConfig = config;
5269
5292
  return this;
5270
5293
  }
@@ -5344,7 +5367,7 @@ var init_builder = __esm({
5344
5367
  * ```
5345
5368
  */
5346
5369
  onHumanInput(handler) {
5347
- this.onHumanInputRequired = handler;
5370
+ this.requestHumanInput = handler;
5348
5371
  return this;
5349
5372
  }
5350
5373
  /**
@@ -5479,9 +5502,9 @@ var init_builder = __esm({
5479
5502
  * Provides fine-grained control over whether to continue after different types of errors.
5480
5503
  * Overrides `stopOnGadgetError` when provided.
5481
5504
  *
5482
- * **Note:** This builder method configures the underlying `shouldContinueAfterError` option
5505
+ * **Note:** This builder method configures the underlying `canRecoverFromGadgetError` option
5483
5506
  * in `AgentOptions`. The method is named `withErrorHandler` for better developer experience,
5484
- * but maps to the `shouldContinueAfterError` property internally.
5507
+ * but maps to the `canRecoverFromGadgetError` property internally.
5485
5508
  *
5486
5509
  * @param handler - Function that decides whether to continue after an error.
5487
5510
  * Return `true` to continue execution, `false` to stop.
@@ -5502,7 +5525,7 @@ var init_builder = __esm({
5502
5525
  * ```
5503
5526
  */
5504
5527
  withErrorHandler(handler) {
5505
- this.shouldContinueAfterError = handler;
5528
+ this.canRecoverFromGadgetError = handler;
5506
5529
  return this;
5507
5530
  }
5508
5531
  /**
@@ -5643,6 +5666,27 @@ var init_builder = __esm({
5643
5666
  this.signal = signal;
5644
5667
  return this;
5645
5668
  }
5669
+ /**
5670
+ * Set subagent configuration overrides.
5671
+ *
5672
+ * Subagent gadgets (like BrowseWeb) can read these settings from ExecutionContext
5673
+ * to inherit model and other options from the CLI configuration.
5674
+ *
5675
+ * @param config - Subagent configuration map keyed by gadget name
5676
+ * @returns This builder for chaining
5677
+ *
5678
+ * @example
5679
+ * ```typescript
5680
+ * .withSubagentConfig({
5681
+ * BrowseWeb: { model: "inherit", maxIterations: 20, headless: true },
5682
+ * CodeAnalyzer: { model: "sonnet", maxIterations: 10 }
5683
+ * })
5684
+ * ```
5685
+ */
5686
+ withSubagentConfig(config) {
5687
+ this.subagentConfig = config;
5688
+ return this;
5689
+ }
5646
5690
  /**
5647
5691
  * Add an ephemeral trailing message that appears at the end of each LLM request.
5648
5692
  *
@@ -5807,19 +5851,20 @@ ${endPrefix}`
5807
5851
  hooks: this.composeHooks(),
5808
5852
  promptConfig: this.promptConfig,
5809
5853
  initialMessages: this.initialMessages,
5810
- onHumanInputRequired: this.onHumanInputRequired,
5854
+ requestHumanInput: this.requestHumanInput,
5811
5855
  gadgetStartPrefix: this.gadgetStartPrefix,
5812
5856
  gadgetEndPrefix: this.gadgetEndPrefix,
5813
5857
  gadgetArgPrefix: this.gadgetArgPrefix,
5814
5858
  textOnlyHandler: this.textOnlyHandler,
5815
5859
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5816
5860
  stopOnGadgetError: this.stopOnGadgetError,
5817
- shouldContinueAfterError: this.shouldContinueAfterError,
5861
+ canRecoverFromGadgetError: this.canRecoverFromGadgetError,
5818
5862
  defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
5819
5863
  gadgetOutputLimit: this.gadgetOutputLimit,
5820
5864
  gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,
5821
5865
  compactionConfig: this.compactionConfig,
5822
- signal: this.signal
5866
+ signal: this.signal,
5867
+ subagentConfig: this.subagentConfig
5823
5868
  };
5824
5869
  }
5825
5870
  ask(userPrompt) {
@@ -5988,19 +6033,20 @@ ${endPrefix}`
5988
6033
  hooks: this.composeHooks(),
5989
6034
  promptConfig: this.promptConfig,
5990
6035
  initialMessages: this.initialMessages,
5991
- onHumanInputRequired: this.onHumanInputRequired,
6036
+ requestHumanInput: this.requestHumanInput,
5992
6037
  gadgetStartPrefix: this.gadgetStartPrefix,
5993
6038
  gadgetEndPrefix: this.gadgetEndPrefix,
5994
6039
  gadgetArgPrefix: this.gadgetArgPrefix,
5995
6040
  textOnlyHandler: this.textOnlyHandler,
5996
6041
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5997
6042
  stopOnGadgetError: this.stopOnGadgetError,
5998
- shouldContinueAfterError: this.shouldContinueAfterError,
6043
+ canRecoverFromGadgetError: this.canRecoverFromGadgetError,
5999
6044
  defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,
6000
6045
  gadgetOutputLimit: this.gadgetOutputLimit,
6001
6046
  gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,
6002
6047
  compactionConfig: this.compactionConfig,
6003
- signal: this.signal
6048
+ signal: this.signal,
6049
+ subagentConfig: this.subagentConfig
6004
6050
  };
6005
6051
  return new Agent(AGENT_INTERNAL_KEY, options);
6006
6052
  }
@@ -6306,9 +6352,9 @@ var init_base_provider = __esm({
6306
6352
  */
6307
6353
  async *stream(options, descriptor, spec) {
6308
6354
  const preparedMessages = this.prepareMessages(options.messages);
6309
- const payload = this.buildRequestPayload(options, descriptor, spec, preparedMessages);
6355
+ const payload = this.buildApiRequest(options, descriptor, spec, preparedMessages);
6310
6356
  const rawStream = await this.executeStreamRequest(payload, options.signal);
6311
- yield* this.wrapStream(rawStream);
6357
+ yield* this.normalizeProviderStream(rawStream);
6312
6358
  }
6313
6359
  /**
6314
6360
  * Prepare messages for the request.
@@ -6408,11 +6454,11 @@ var init_anthropic = __esm({
6408
6454
  "Anthropic does not support speech generation. Use OpenAI (TTS) or Google Gemini (TTS) instead."
6409
6455
  );
6410
6456
  }
6411
- buildRequestPayload(options, descriptor, spec, messages) {
6457
+ buildApiRequest(options, descriptor, spec, messages) {
6412
6458
  const systemMessages = messages.filter((message) => message.role === "system");
6413
6459
  const system = systemMessages.length > 0 ? systemMessages.map((m, index) => ({
6414
6460
  type: "text",
6415
- text: extractText(m.content),
6461
+ text: extractMessageText(m.content),
6416
6462
  // Add cache_control to the LAST system message block
6417
6463
  ...index === systemMessages.length - 1 ? { cache_control: { type: "ephemeral" } } : {}
6418
6464
  })) : void 0;
@@ -6449,7 +6495,7 @@ var init_anthropic = __esm({
6449
6495
  * Handles text, images (base64 only), and applies cache_control.
6450
6496
  */
6451
6497
  convertToAnthropicContent(content, addCacheControl) {
6452
- const parts = normalizeContent(content);
6498
+ const parts = normalizeMessageContent(content);
6453
6499
  return parts.map((part, index) => {
6454
6500
  const isLastPart = index === parts.length - 1;
6455
6501
  const cacheControl = addCacheControl && isLastPart ? { cache_control: { type: "ephemeral" } } : {};
@@ -6495,7 +6541,7 @@ var init_anthropic = __esm({
6495
6541
  const stream2 = await client.messages.create(payload, signal ? { signal } : void 0);
6496
6542
  return stream2;
6497
6543
  }
6498
- async *wrapStream(iterable) {
6544
+ async *normalizeProviderStream(iterable) {
6499
6545
  const stream2 = iterable;
6500
6546
  let inputTokens = 0;
6501
6547
  let cachedInputTokens = 0;
@@ -6572,7 +6618,7 @@ var init_anthropic = __esm({
6572
6618
  async countTokens(messages, descriptor, _spec) {
6573
6619
  const client = this.client;
6574
6620
  const systemMessages = messages.filter((message) => message.role === "system");
6575
- const system = systemMessages.length > 0 ? systemMessages.map((m) => extractText(m.content)).join("\n\n") : void 0;
6621
+ const system = systemMessages.length > 0 ? systemMessages.map((m) => extractMessageText(m.content)).join("\n\n") : void 0;
6576
6622
  const conversation = messages.filter(
6577
6623
  (message) => message.role !== "system"
6578
6624
  ).map((message) => ({
@@ -6594,7 +6640,7 @@ var init_anthropic = __esm({
6594
6640
  let totalChars = 0;
6595
6641
  let imageCount = 0;
6596
6642
  for (const msg of messages) {
6597
- const parts = normalizeContent(msg.content);
6643
+ const parts = normalizeMessageContent(msg.content);
6598
6644
  for (const part of parts) {
6599
6645
  if (part.type === "text") {
6600
6646
  totalChars += part.text.length;
@@ -7285,7 +7331,7 @@ var init_gemini = __esm({
7285
7331
  format: spec?.defaultFormat ?? "wav"
7286
7332
  };
7287
7333
  }
7288
- buildRequestPayload(options, descriptor, _spec, messages) {
7334
+ buildApiRequest(options, descriptor, _spec, messages) {
7289
7335
  const contents = this.convertMessagesToContents(messages);
7290
7336
  const generationConfig = this.buildGenerationConfig(options);
7291
7337
  const config = {
@@ -7337,7 +7383,7 @@ var init_gemini = __esm({
7337
7383
  if (message.role === "system") {
7338
7384
  expandedMessages.push({
7339
7385
  role: "user",
7340
- content: extractText(message.content)
7386
+ content: extractMessageText(message.content)
7341
7387
  });
7342
7388
  expandedMessages.push({
7343
7389
  role: "assistant",
@@ -7387,7 +7433,7 @@ var init_gemini = __esm({
7387
7433
  * Handles text, images, and audio (Gemini supports all three).
7388
7434
  */
7389
7435
  convertToGeminiParts(content) {
7390
- const parts = normalizeContent(content);
7436
+ const parts = normalizeMessageContent(content);
7391
7437
  return parts.map((part) => {
7392
7438
  if (part.type === "text") {
7393
7439
  return { text: part.text };
@@ -7432,10 +7478,10 @@ var init_gemini = __esm({
7432
7478
  }
7433
7479
  return Object.keys(config).length > 0 ? config : null;
7434
7480
  }
7435
- async *wrapStream(iterable) {
7481
+ async *normalizeProviderStream(iterable) {
7436
7482
  const stream2 = iterable;
7437
7483
  for await (const chunk of stream2) {
7438
- const text3 = this.extractText(chunk);
7484
+ const text3 = this.extractMessageText(chunk);
7439
7485
  if (text3) {
7440
7486
  yield { text: text3, rawEvent: chunk };
7441
7487
  }
@@ -7446,7 +7492,7 @@ var init_gemini = __esm({
7446
7492
  }
7447
7493
  }
7448
7494
  }
7449
- extractText(chunk) {
7495
+ extractMessageText(chunk) {
7450
7496
  if (!chunk?.candidates) {
7451
7497
  return "";
7452
7498
  }
@@ -7511,7 +7557,7 @@ var init_gemini = __esm({
7511
7557
  let totalChars = 0;
7512
7558
  let mediaCount = 0;
7513
7559
  for (const msg of messages) {
7514
- const parts = normalizeContent(msg.content);
7560
+ const parts = normalizeMessageContent(msg.content);
7515
7561
  for (const part of parts) {
7516
7562
  if (part.type === "text") {
7517
7563
  totalChars += part.text.length;
@@ -8257,7 +8303,7 @@ var init_openai = __esm({
8257
8303
  format
8258
8304
  };
8259
8305
  }
8260
- buildRequestPayload(options, descriptor, spec, messages) {
8306
+ buildApiRequest(options, descriptor, spec, messages) {
8261
8307
  const { maxTokens, temperature, topP, stopSequences, extra } = options;
8262
8308
  const supportsTemperature = spec?.metadata?.supportsTemperature !== false;
8263
8309
  const shouldIncludeTemperature = typeof temperature === "number" && supportsTemperature;
@@ -8292,7 +8338,7 @@ var init_openai = __esm({
8292
8338
  ...message.name ? { name: message.name } : {}
8293
8339
  };
8294
8340
  }
8295
- const textContent = typeof message.content === "string" ? message.content : extractText(message.content);
8341
+ const textContent = typeof message.content === "string" ? message.content : extractMessageText(message.content);
8296
8342
  if (role === "system") {
8297
8343
  return {
8298
8344
  role: "system",
@@ -8352,7 +8398,7 @@ var init_openai = __esm({
8352
8398
  const stream2 = await client.chat.completions.create(payload, signal ? { signal } : void 0);
8353
8399
  return stream2;
8354
8400
  }
8355
- async *wrapStream(iterable) {
8401
+ async *normalizeProviderStream(iterable) {
8356
8402
  const stream2 = iterable;
8357
8403
  for await (const chunk of stream2) {
8358
8404
  const text3 = chunk.choices.map((choice) => choice.delta?.content ?? "").join("");
@@ -8410,9 +8456,9 @@ var init_openai = __esm({
8410
8456
  tokenCount += OPENAI_MESSAGE_OVERHEAD_TOKENS;
8411
8457
  const roleText = ROLE_MAP[message.role];
8412
8458
  tokenCount += encoding.encode(roleText).length;
8413
- const textContent = extractText(message.content);
8459
+ const textContent = extractMessageText(message.content);
8414
8460
  tokenCount += encoding.encode(textContent).length;
8415
- const parts = normalizeContent(message.content);
8461
+ const parts = normalizeMessageContent(message.content);
8416
8462
  for (const part of parts) {
8417
8463
  if (part.type === "image") {
8418
8464
  imageCount++;
@@ -8437,7 +8483,7 @@ var init_openai = __esm({
8437
8483
  let totalChars = 0;
8438
8484
  let imageCount = 0;
8439
8485
  for (const msg of messages) {
8440
- const parts = normalizeContent(msg.content);
8486
+ const parts = normalizeMessageContent(msg.content);
8441
8487
  for (const part of parts) {
8442
8488
  if (part.type === "text") {
8443
8489
  totalChars += part.text.length;
@@ -10125,7 +10171,7 @@ var MockBuilder = class {
10125
10171
  whenMessageContains(text3) {
10126
10172
  this.matchers.push(
10127
10173
  (ctx) => ctx.messages.some(
10128
- (msg) => extractText(msg.content).toLowerCase().includes(text3.toLowerCase())
10174
+ (msg) => extractMessageText(msg.content).toLowerCase().includes(text3.toLowerCase())
10129
10175
  )
10130
10176
  );
10131
10177
  return this;
@@ -10140,7 +10186,7 @@ var MockBuilder = class {
10140
10186
  this.matchers.push((ctx) => {
10141
10187
  const lastMsg = ctx.messages[ctx.messages.length - 1];
10142
10188
  if (!lastMsg) return false;
10143
- return extractText(lastMsg.content).toLowerCase().includes(text3.toLowerCase());
10189
+ return extractMessageText(lastMsg.content).toLowerCase().includes(text3.toLowerCase());
10144
10190
  });
10145
10191
  return this;
10146
10192
  }
@@ -10151,7 +10197,7 @@ var MockBuilder = class {
10151
10197
  * mockLLM().whenMessageMatches(/calculate \d+/)
10152
10198
  */
10153
10199
  whenMessageMatches(regex) {
10154
- this.matchers.push((ctx) => ctx.messages.some((msg) => regex.test(extractText(msg.content))));
10200
+ this.matchers.push((ctx) => ctx.messages.some((msg) => regex.test(extractMessageText(msg.content))));
10155
10201
  return this;
10156
10202
  }
10157
10203
  /**
@@ -10163,7 +10209,7 @@ var MockBuilder = class {
10163
10209
  whenRoleContains(role, text3) {
10164
10210
  this.matchers.push(
10165
10211
  (ctx) => ctx.messages.some(
10166
- (msg) => msg.role === role && extractText(msg.content).toLowerCase().includes(text3.toLowerCase())
10212
+ (msg) => msg.role === role && extractMessageText(msg.content).toLowerCase().includes(text3.toLowerCase())
10167
10213
  )
10168
10214
  );
10169
10215
  return this;
@@ -10585,7 +10631,7 @@ var MockConversationManager = class {
10585
10631
  this.history.push(msg);
10586
10632
  this.addedMessages.push(msg);
10587
10633
  }
10588
- addGadgetCall(gadgetName, parameters, result) {
10634
+ addGadgetCallResult(gadgetName, parameters, result) {
10589
10635
  const assistantMsg = {
10590
10636
  role: "assistant",
10591
10637
  content: `!!!GADGET_START:${gadgetName}
@@ -10695,7 +10741,7 @@ function createMockConversationManager(turnCount, baseMessages = []) {
10695
10741
 
10696
10742
  // src/testing/mock-gadget.ts
10697
10743
  init_gadget();
10698
- var MockGadgetImpl = class extends BaseGadget {
10744
+ var MockGadgetImpl = class extends AbstractGadget {
10699
10745
  name;
10700
10746
  description;
10701
10747
  parameterSchema;
@@ -10948,22 +10994,23 @@ export {
10948
10994
  resolveRulesTemplate,
10949
10995
  resolveHintTemplate,
10950
10996
  init_prompt_config,
10951
- normalizeContent,
10952
- extractText,
10997
+ normalizeMessageContent,
10998
+ extractMessageText,
10953
10999
  LLMMessageBuilder,
10954
11000
  init_messages,
10955
11001
  MediaStore,
10956
11002
  init_media_store,
10957
- BreakLoopException,
10958
- HumanInputException,
10959
- AbortError,
11003
+ TaskCompletionSignal,
11004
+ HumanInputRequiredException,
11005
+ TimeoutException,
11006
+ AbortException,
10960
11007
  init_exceptions,
10961
11008
  createLogger,
10962
11009
  defaultLogger,
10963
11010
  init_logger,
10964
11011
  schemaToJSONSchema,
10965
11012
  init_schema_to_json,
10966
- BaseGadget,
11013
+ AbstractGadget,
10967
11014
  init_gadget,
10968
11015
  createGadget,
10969
11016
  init_create_gadget,
@@ -10987,7 +11034,7 @@ export {
10987
11034
  init_event_handlers,
10988
11035
  GadgetOutputStore,
10989
11036
  init_gadget_output_store,
10990
- StreamParser,
11037
+ GadgetCallParser,
10991
11038
  init_parser,
10992
11039
  GadgetExecutor,
10993
11040
  init_executor,
@@ -11059,4 +11106,4 @@ export {
11059
11106
  createEmptyStream,
11060
11107
  createErrorStream
11061
11108
  };
11062
- //# sourceMappingURL=chunk-364PEMVT.js.map
11109
+ //# sourceMappingURL=chunk-67MMSOAT.js.map