@tanstack/ai 0.61.0 → 0.63.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.
Files changed (65) hide show
  1. package/README.md +1 -0
  2. package/dist/esm/activities/chat/agents/define-agent.d.ts +17 -5
  3. package/dist/esm/activities/chat/agents/define-agent.js.map +1 -1
  4. package/dist/esm/activities/chat/agents/spawn.d.ts +2 -0
  5. package/dist/esm/activities/chat/agents/spawn.js +8 -5
  6. package/dist/esm/activities/chat/agents/spawn.js.map +1 -1
  7. package/dist/esm/activities/chat/index.js +156 -57
  8. package/dist/esm/activities/chat/index.js.map +1 -1
  9. package/dist/esm/activities/chat/messages.js +30 -18
  10. package/dist/esm/activities/chat/messages.js.map +1 -1
  11. package/dist/esm/activities/chat/middleware/types.d.ts +1 -0
  12. package/dist/esm/activities/chat/middleware/types.js.map +1 -1
  13. package/dist/esm/activities/chat/stream/message-updaters.d.ts +2 -2
  14. package/dist/esm/activities/chat/stream/message-updaters.js +2 -1
  15. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  16. package/dist/esm/activities/chat/stream/processor.d.ts +11 -9
  17. package/dist/esm/activities/chat/stream/processor.js +38 -18
  18. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  19. package/dist/esm/activities/chat/tools/tool-calls.d.ts +16 -2
  20. package/dist/esm/activities/chat/tools/tool-calls.js +55 -16
  21. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  22. package/dist/esm/activities/chat/tools/tool-definition.d.ts +4 -0
  23. package/dist/esm/activities/chat/tools/tool-definition.js +4 -0
  24. package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
  25. package/dist/esm/activities/evaluate/adapter.d.ts +4 -0
  26. package/dist/esm/activities/evaluate/adapter.js.map +1 -1
  27. package/dist/esm/activities/evaluate/index.d.ts +4 -0
  28. package/dist/esm/activities/evaluate/index.js +3 -1
  29. package/dist/esm/activities/evaluate/index.js.map +1 -1
  30. package/dist/esm/client.d.ts +1 -1
  31. package/dist/esm/client.js.map +1 -1
  32. package/dist/esm/index.d.ts +1 -1
  33. package/dist/esm/index.js +2 -2
  34. package/dist/esm/interrupt-resume.js +29 -4
  35. package/dist/esm/interrupt-resume.js.map +1 -1
  36. package/dist/esm/middlewares/otel.d.ts +5 -2
  37. package/dist/esm/middlewares/otel.js +114 -0
  38. package/dist/esm/middlewares/otel.js.map +1 -1
  39. package/dist/esm/types.d.ts +42 -1
  40. package/dist/esm/utilities/ag-ui-wire.js +5 -3
  41. package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
  42. package/dist/esm/utilities/tool-result.d.ts +2 -1
  43. package/dist/esm/utilities/tool-result.js +4 -1
  44. package/dist/esm/utilities/tool-result.js.map +1 -1
  45. package/package.json +3 -3
  46. package/skills/ai-core/chat-experience/SKILL.md +120 -0
  47. package/skills/ai-core/tool-calling/SKILL.md +103 -0
  48. package/src/activities/chat/agents/define-agent.ts +20 -3
  49. package/src/activities/chat/agents/spawn.ts +20 -12
  50. package/src/activities/chat/index.ts +235 -62
  51. package/src/activities/chat/messages.ts +40 -5
  52. package/src/activities/chat/middleware/types.ts +1 -0
  53. package/src/activities/chat/stream/message-updaters.ts +3 -0
  54. package/src/activities/chat/stream/processor.ts +57 -27
  55. package/src/activities/chat/tools/tool-calls.ts +98 -9
  56. package/src/activities/chat/tools/tool-definition.ts +8 -0
  57. package/src/activities/evaluate/adapter.ts +4 -0
  58. package/src/activities/evaluate/index.ts +6 -0
  59. package/src/client.ts +1 -0
  60. package/src/index.ts +1 -0
  61. package/src/interrupt-resume.ts +55 -4
  62. package/src/middlewares/otel.ts +161 -3
  63. package/src/types.ts +38 -1
  64. package/src/utilities/ag-ui-wire.ts +12 -1
  65. package/src/utilities/tool-result.ts +7 -1
@@ -163,8 +163,10 @@ var TextEngine = class {
163
163
  initialClientToolResults;
164
164
  resumeApprovals = /* @__PURE__ */ new Map();
165
165
  resumeClientToolResults = /* @__PURE__ */ new Map();
166
+ resumeClientToolErrors = /* @__PURE__ */ new Map();
166
167
  resumeDeniedToolResults = /* @__PURE__ */ new Map();
167
168
  resumeCancelledToolCallIds = /* @__PURE__ */ new Set();
169
+ resumeInputResponses = /* @__PURE__ */ new Map();
168
170
  resumeGenericInterrupts = /* @__PURE__ */ new Map();
169
171
  resumeGenericInterruptRequests = /* @__PURE__ */ new Map();
170
172
  threadId;
@@ -330,6 +332,33 @@ var TextEngine = class {
330
332
  getFinalizationError() {
331
333
  return this.finalizationError;
332
334
  }
335
+ async runTerminalHook() {
336
+ if (this.terminalHookCalled || this.isCancelled()) return;
337
+ this.terminalHookCalled = true;
338
+ if (this.finalizationError) {
339
+ const errForHook = new Error(this.finalizationError.message, this.finalizationError.cause !== void 0 ? { cause: this.finalizationError.cause } : void 0);
340
+ if (this.finalizationError.code !== void 0) Object.defineProperty(errForHook, "code", {
341
+ value: this.finalizationError.code,
342
+ enumerable: true
343
+ });
344
+ if (this.finalizationError.rawText !== void 0) Object.defineProperty(errForHook, "rawText", {
345
+ value: this.finalizationError.rawText,
346
+ enumerable: true
347
+ });
348
+ await this.middlewareRunner.runOnError(this.middlewareCtx, {
349
+ error: errForHook,
350
+ duration: Date.now() - this.streamStartTime
351
+ });
352
+ return;
353
+ }
354
+ this.addTerminalAssistantMessages();
355
+ await this.middlewareRunner.runOnFinish(this.middlewareCtx, {
356
+ finishReason: this.lastFinishReason,
357
+ duration: Date.now() - this.streamStartTime,
358
+ content: this.accumulatedContent,
359
+ usage: rebuildTokenUsage(this.finishedEvent?.usage, tanstackMetadata(this.finishedEvent ?? void 0)?.usage)
360
+ });
361
+ }
333
362
  async *run() {
334
363
  this.beforeRun();
335
364
  this.logger.agentLoop("run started", { threadId: this.middlewareCtx.threadId });
@@ -355,7 +384,11 @@ var TextEngine = class {
355
384
  }
356
385
  return;
357
386
  }
358
- if ((yield* this.checkForPendingToolCalls()) === "wait") return;
387
+ const pendingPhase = yield* this.checkForPendingToolCalls();
388
+ if (pendingPhase === "stop" || pendingPhase === "wait") {
389
+ await this.runTerminalHook();
390
+ return;
391
+ }
359
392
  if (!(!!this.finalStructuredOutput && this.tools.length === 0 && this.finalStructuredOutput.nativeCombined !== true)) do {
360
393
  if (this.earlyTermination) break;
361
394
  if (this.isCancelled()) return;
@@ -391,29 +424,7 @@ var TextEngine = class {
391
424
  if (!this.finalizationError && !this.isCancelled()) yield* this.flushDeferredModelRunFinishedChunks();
392
425
  } else yield* this.runStructuredFinalization();
393
426
  }
394
- if (!this.terminalHookCalled && this.toolPhase !== "wait" && !this.isCancelled()) {
395
- if (this.finalizationError) {
396
- this.terminalHookCalled = true;
397
- const errForHook = new Error(this.finalizationError.message, this.finalizationError.cause !== void 0 ? { cause: this.finalizationError.cause } : void 0);
398
- if (this.finalizationError.code !== void 0) Object.defineProperty(errForHook, "code", {
399
- value: this.finalizationError.code,
400
- enumerable: true
401
- });
402
- await this.middlewareRunner.runOnError(this.middlewareCtx, {
403
- error: errForHook,
404
- duration: Date.now() - this.streamStartTime
405
- });
406
- } else {
407
- this.addTerminalAssistantMessages();
408
- this.terminalHookCalled = true;
409
- await this.middlewareRunner.runOnFinish(this.middlewareCtx, {
410
- finishReason: this.lastFinishReason,
411
- duration: Date.now() - this.streamStartTime,
412
- content: this.accumulatedContent,
413
- usage: rebuildTokenUsage(this.finishedEvent?.usage, tanstackMetadata(this.finishedEvent ?? void 0)?.usage)
414
- });
415
- }
416
- }
427
+ await this.runTerminalHook();
417
428
  } catch (error) {
418
429
  if (error instanceof Error && error.name === "InterruptReplaySignal" && "continuationRunId" in error && typeof error.continuationRunId === "string") {
419
430
  this.terminalHookCalled = true;
@@ -885,8 +896,10 @@ var TextEngine = class {
885
896
  await this.middlewareRunner.runOnAfterToolCall(this.middlewareCtx, info);
886
897
  }
887
898
  }, this.middlewareCtx.context, this.toolAbortSignal, {
899
+ clientToolErrors: this.resumeClientToolErrors,
888
900
  deniedToolResults: this.resumeDeniedToolResults,
889
- cancelledToolCallIds: this.resumeCancelledToolCallIds
901
+ cancelledToolCallIds: this.resumeCancelledToolCallIds,
902
+ inputResponses: this.resumeInputResponses
890
903
  });
891
904
  const executionResult = yield* this.drainToolCallGenerator(generator);
892
905
  if (this.isMiddlewareAborted()) {
@@ -900,10 +913,10 @@ var TextEngine = class {
900
913
  needsApproval: executionResult.needsApproval,
901
914
  needsClientExecution: executionResult.needsClientExecution
902
915
  }));
903
- if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0 || executionResult.subagentInterrupts.length > 0) {
916
+ if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0 || executionResult.inputRequired.length > 0 || executionResult.subagentInterrupts.length > 0) {
904
917
  this.discardDeferredToolCallRunFinishedChunks();
905
918
  if (allResults.length > 0) for (const chunk of this.buildToolResultChunks(allResults, finishEvent)) yield* this.pipeThroughMiddleware(chunk);
906
- const emitted = yield* this.emitActionableInterruptBoundary(finishEvent, executionResult.needsApproval, executionResult.needsClientExecution, [], executionResult.subagentInterrupts);
919
+ const emitted = yield* this.emitActionableInterruptBoundary(finishEvent, executionResult.needsApproval, executionResult.needsClientExecution, [], executionResult.inputRequired, executionResult.subagentInterrupts);
907
920
  this.setToolPhase(emitted ? "wait" : "stop");
908
921
  return emitted ? "wait" : "stop";
909
922
  }
@@ -977,8 +990,10 @@ var TextEngine = class {
977
990
  await this.middlewareRunner.runOnAfterToolCall(this.middlewareCtx, info);
978
991
  }
979
992
  }, this.middlewareCtx.context, this.toolAbortSignal, {
993
+ clientToolErrors: this.resumeClientToolErrors,
980
994
  deniedToolResults: this.resumeDeniedToolResults,
981
- cancelledToolCallIds: this.resumeCancelledToolCallIds
995
+ cancelledToolCallIds: this.resumeCancelledToolCallIds,
996
+ inputResponses: this.resumeInputResponses
982
997
  });
983
998
  const executionResult = yield* this.drainToolCallGenerator(generator);
984
999
  this.middlewareCtx.phase = "afterTools";
@@ -997,13 +1012,13 @@ var TextEngine = class {
997
1012
  const afterToolRequests = yield* this.runWhileYielding(this.middlewareRunner.runOnInterruptBoundary(this.middlewareCtx));
998
1013
  if (afterToolRequests.length > 0) {
999
1014
  for (const chunk of afterToolBoundaryChunks) yield* this.pipeThroughMiddleware(chunk);
1000
- yield* this.emitBoundaryInterrupts("afterTools", finishEvent, toolCalls, afterToolRequests);
1015
+ yield* this.emitBoundaryInterrupts("afterTools", finishEvent, toolCalls, afterToolRequests, executionResult.inputRequired);
1001
1016
  this.setToolPhase("wait");
1002
1017
  return;
1003
1018
  }
1004
- if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0 || executionResult.subagentInterrupts.length > 0) {
1019
+ if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0 || executionResult.inputRequired.length > 0 || executionResult.subagentInterrupts.length > 0) {
1005
1020
  if (allResults.length > 0) for (const chunk of afterToolBoundaryChunks) yield* this.pipeThroughMiddleware(chunk);
1006
- const emitted = yield* this.emitActionableInterruptBoundary(finishEvent, executionResult.needsApproval, executionResult.needsClientExecution, [], executionResult.subagentInterrupts);
1021
+ const emitted = yield* this.emitActionableInterruptBoundary(finishEvent, executionResult.needsApproval, executionResult.needsClientExecution, [], executionResult.inputRequired, executionResult.subagentInterrupts);
1007
1022
  this.setToolPhase(emitted ? "wait" : "stop");
1008
1023
  return;
1009
1024
  }
@@ -1230,7 +1245,7 @@ var TextEngine = class {
1230
1245
  genericInterruptId() {
1231
1246
  return this.createId("interrupt");
1232
1247
  }
1233
- buildActionableInterrupts(approvals, clientRequests, genericRequests = [], genericInterruptIds = [], childInterrupts = []) {
1248
+ buildActionableInterrupts(approvals, clientRequests, genericRequests = [], genericInterruptIds = [], inputRequired = [], childInterrupts = []) {
1234
1249
  const interrupts = [];
1235
1250
  for (const approval of approvals) {
1236
1251
  const tool = this.tools.find((candidate) => candidate.name === approval.toolName);
@@ -1311,6 +1326,27 @@ var TextEngine = class {
1311
1326
  }
1312
1327
  });
1313
1328
  }
1329
+ for (const pendingInput of inputRequired) {
1330
+ const id = `mcp_input_${pendingInput.toolCallId}`;
1331
+ interrupts.push({
1332
+ id,
1333
+ reason: "mcp_input",
1334
+ message: `Input required to run ${pendingInput.toolName}`,
1335
+ toolCallId: pendingInput.toolCallId,
1336
+ metadata: {
1337
+ toolName: pendingInput.toolName,
1338
+ [interruptBindingMetadataKey]: {
1339
+ v: 1,
1340
+ kind: "generic",
1341
+ interruptId: id
1342
+ },
1343
+ [INTERRUPT_PAYLOAD_METADATA_KEY]: {
1344
+ kind: pendingInput.kind,
1345
+ request: pendingInput.request
1346
+ }
1347
+ }
1348
+ });
1349
+ }
1314
1350
  interrupts.push(...childInterrupts);
1315
1351
  const ids = /* @__PURE__ */ new Set();
1316
1352
  for (const interrupt of interrupts) {
@@ -1319,13 +1355,13 @@ var TextEngine = class {
1319
1355
  }
1320
1356
  return interrupts;
1321
1357
  }
1322
- buildInterruptFinishedChunk(finishEvent, approvals, clientRequests, genericRequests = [], genericInterruptIds, childInterrupts) {
1358
+ buildInterruptFinishedChunk(finishEvent, approvals, clientRequests, genericRequests = [], genericInterruptIds, inputRequired = [], childInterrupts) {
1323
1359
  return {
1324
1360
  ...finishEvent,
1325
1361
  timestamp: Date.now(),
1326
1362
  outcome: {
1327
1363
  type: "interrupt",
1328
- interrupts: this.buildActionableInterrupts(approvals, clientRequests, genericRequests, genericInterruptIds, childInterrupts)
1364
+ interrupts: this.buildActionableInterrupts(approvals, clientRequests, genericRequests, genericInterruptIds, inputRequired, childInterrupts)
1329
1365
  }
1330
1366
  };
1331
1367
  }
@@ -1419,10 +1455,10 @@ var TextEngine = class {
1419
1455
  };
1420
1456
  yield* this.pipeThroughMiddleware(this.buildInterruptRunErrorChunk(error));
1421
1457
  }
1422
- async *emitActionableInterruptBoundary(finishEvent, approvals, clientRequests, genericRequests = [], childInterrupts = []) {
1458
+ async *emitActionableInterruptBoundary(finishEvent, approvals, clientRequests, genericRequests = [], inputRequired = [], childInterrupts = []) {
1423
1459
  yield* this.emitSyntheticRunStarted(finishEvent);
1424
1460
  const genericInterruptIds = genericRequests.map(() => this.genericInterruptId());
1425
- const terminal = this.completeEphemeralInterruptBindings(this.buildInterruptFinishedChunk(finishEvent, approvals, clientRequests, genericRequests, genericInterruptIds, childInterrupts));
1461
+ const terminal = this.completeEphemeralInterruptBindings(this.buildInterruptFinishedChunk(finishEvent, approvals, clientRequests, genericRequests, genericInterruptIds, inputRequired, childInterrupts));
1426
1462
  let terminalOutputs;
1427
1463
  try {
1428
1464
  terminalOutputs = [...this.emitPublicChunks(await this.middlewareRunner.runOnChunk(this.middlewareCtx, terminal))];
@@ -1439,7 +1475,7 @@ var TextEngine = class {
1439
1475
  for (const output of terminalOutputs) yield this.publicInterruptTerminal(output);
1440
1476
  return true;
1441
1477
  }
1442
- async *emitBoundaryInterrupts(phase, finishEvent, toolCalls = [], requests) {
1478
+ async *emitBoundaryInterrupts(phase, finishEvent, toolCalls = [], requests, inputRequired = []) {
1443
1479
  this.middlewareCtx.phase = phase;
1444
1480
  const boundaryRequests = requests ?? (yield* this.runWhileYielding(this.middlewareRunner.runOnInterruptBoundary(this.middlewareCtx)));
1445
1481
  if (boundaryRequests.length === 0) return false;
@@ -1449,7 +1485,7 @@ var TextEngine = class {
1449
1485
  else this.addAssistantTextMessageForInterrupt();
1450
1486
  }
1451
1487
  const actionable = this.getBoundaryActionableToolRequests(toolCalls);
1452
- yield* this.emitActionableInterruptBoundary(finishEvent, actionable.approvals, actionable.clientRequests, boundaryRequests);
1488
+ yield* this.emitActionableInterruptBoundary(finishEvent, actionable.approvals, actionable.clientRequests, boundaryRequests, inputRequired);
1453
1489
  return true;
1454
1490
  }
1455
1491
  addAssistantTextMessageForInterrupt() {
@@ -1482,7 +1518,7 @@ var TextEngine = class {
1482
1518
  input,
1483
1519
  approvalId
1484
1520
  });
1485
- else if (!tool.execute && !clientToolResults.has(toolCall.id) && !this.resumeCancelledToolCallIds.has(toolCall.id)) clientRequests.push({
1521
+ else if (!tool.execute && !clientToolResults.has(toolCall.id) && !this.resumeClientToolErrors.has(toolCall.id) && !this.resumeCancelledToolCallIds.has(toolCall.id)) clientRequests.push({
1486
1522
  toolCallId: toolCall.id,
1487
1523
  toolName: toolCall.function.name,
1488
1524
  input
@@ -1553,7 +1589,10 @@ var TextEngine = class {
1553
1589
  content: wireContent,
1554
1590
  role: "tool"
1555
1591
  };
1556
- chunks.push(result.state === "output-error" ? withTanstackMetadata(resultChunk, { state: result.state }) : resultChunk);
1592
+ chunks.push(result.state === "output-error" ? withTanstackMetadata(resultChunk, {
1593
+ state: result.state,
1594
+ ...result.outcome !== void 0 && { toolResultOutcome: result.outcome }
1595
+ }) : resultChunk);
1557
1596
  const placeholderIdx = this.messages.findIndex((m) => {
1558
1597
  if (m.role !== "tool" || m.toolCallId !== result.toolCallId) return false;
1559
1598
  if (typeof m.content !== "string") return false;
@@ -1563,18 +1602,31 @@ var TextEngine = class {
1563
1602
  return false;
1564
1603
  }
1565
1604
  });
1566
- const newToolMessage = {
1605
+ const isDeniedResult = result.outcome === "denied";
1606
+ const existingToolResultIdx = isDeniedResult ? this.messages.findIndex((message) => message.role === "tool" && message.toolCallId === result.toolCallId) : -1;
1607
+ const resultMessageIdx = existingToolResultIdx >= 0 ? existingToolResultIdx : placeholderIdx;
1608
+ const existingToolMessage = existingToolResultIdx >= 0 ? this.messages[existingToolResultIdx] : void 0;
1609
+ const errorField = result.state === "output-error" && { error: toolResultErrorText(parseToolOutput(wireContent)) };
1610
+ const replacementMessage = existingToolMessage?.role === "tool" ? {
1611
+ ...existingToolMessage,
1612
+ content,
1613
+ toolCallId: result.toolCallId,
1614
+ ...errorField
1615
+ } : {
1567
1616
  role: "tool",
1568
1617
  content,
1569
1618
  toolCallId: result.toolCallId,
1570
- ...result.state === "output-error" && { error: toolResultErrorText(parseToolOutput(wireContent)) }
1619
+ ...errorField
1571
1620
  };
1572
- if (placeholderIdx >= 0) this.messages = [
1573
- ...this.messages.slice(0, placeholderIdx),
1574
- newToolMessage,
1575
- ...this.messages.slice(placeholderIdx + 1)
1576
- ];
1577
- else this.messages = [...this.messages, newToolMessage];
1621
+ const newToolMessage = result.outcome !== void 0 ? withTanstackMetadata(replacementMessage, { toolResultOutcome: result.outcome }) : replacementMessage;
1622
+ if (resultMessageIdx >= 0) {
1623
+ const replacedMessages = [
1624
+ ...this.messages.slice(0, resultMessageIdx),
1625
+ newToolMessage,
1626
+ ...this.messages.slice(resultMessageIdx + 1)
1627
+ ];
1628
+ this.messages = isDeniedResult ? replacedMessages.filter((message, index) => index === resultMessageIdx || !(message.role === "tool" && message.toolCallId === result.toolCallId)) : replacedMessages;
1629
+ } else this.messages = [...this.messages, newToolMessage];
1578
1630
  this.middlewareCtx.messages = this.messages;
1579
1631
  }
1580
1632
  return chunks;
@@ -1586,7 +1638,7 @@ var TextEngine = class {
1586
1638
  if (typeof message.content === "string") try {
1587
1639
  if (JSON.parse(message.content).pendingExecution === true) hasPendingExecution = true;
1588
1640
  } catch {}
1589
- if (!hasPendingExecution) completedToolIds.add(message.toolCallId);
1641
+ if (!hasPendingExecution && !this.resumeDeniedToolResults.has(message.toolCallId)) completedToolIds.add(message.toolCallId);
1590
1642
  }
1591
1643
  const pending = [];
1592
1644
  for (const message of this.messages) if (message.role === "assistant" && message.toolCalls) for (const toolCall of message.toolCalls) {
@@ -1828,6 +1880,7 @@ var TextEngine = class {
1828
1880
  };
1829
1881
  const runChunkMiddleware = (synthChunk) => this.middlewareRunner.runOnChunk(this.middlewareCtx, synthChunk);
1830
1882
  let runErrorYielded = false;
1883
+ let rawText = "";
1831
1884
  for await (const raw of providerStream) {
1832
1885
  if (this.isCancelled()) break;
1833
1886
  {
@@ -1873,11 +1926,16 @@ var TextEngine = class {
1873
1926
  }
1874
1927
  }
1875
1928
  if (chunk.type === EventType.RUN_FINISHED) await this.runOnUsageFromChunk(chunk);
1876
- if (chunk.type === EventType.RUN_ERROR) this.finalizationError = {
1877
- message: chunk.message,
1878
- ...chunk.code ? { code: chunk.code } : {},
1879
- ...fallbackAdapterError !== void 0 ? { cause: fallbackAdapterError } : {}
1880
- };
1929
+ if (chunk.type === EventType.TEXT_MESSAGE_CONTENT) rawText += chunk.delta;
1930
+ if (chunk.type === EventType.RUN_ERROR) {
1931
+ const cause = fallbackAdapterError ?? chunk.rawEvent;
1932
+ this.finalizationError = {
1933
+ message: chunk.message,
1934
+ ...chunk.code ? { code: chunk.code } : {},
1935
+ ...cause !== void 0 ? { cause } : {},
1936
+ ...rawText ? { rawText } : {}
1937
+ };
1938
+ }
1881
1939
  const outputChunks = await this.middlewareRunner.runOnChunk(this.middlewareCtx, outboundChunk);
1882
1940
  if (this.finalStructuredOutput.yieldChunks) for (const spec of this.emitPublicChunks(outputChunks)) {
1883
1941
  if (spec.type === EventType.RUN_ERROR) runErrorYielded = true;
@@ -1967,7 +2025,8 @@ var TextEngine = class {
1967
2025
  this.finalizationError = {
1968
2026
  message: `Failed to parse structured output as JSON. Content: ${detail}`,
1969
2027
  code: "structured-output-parse-failed",
1970
- cause: err
2028
+ cause: err,
2029
+ rawText
1971
2030
  };
1972
2031
  }
1973
2032
  }
@@ -2029,6 +2088,7 @@ var TextEngine = class {
2029
2088
  resumeToolState: {
2030
2089
  approvals: this.resumeApprovals,
2031
2090
  clientToolResults: this.resumeClientToolResults,
2091
+ clientToolErrors: this.resumeClientToolErrors,
2032
2092
  deniedToolResults: this.resumeDeniedToolResults,
2033
2093
  cancelledToolCallIds: this.resumeCancelledToolCallIds
2034
2094
  },
@@ -2108,6 +2168,24 @@ var TextEngine = class {
2108
2168
  }] : [];
2109
2169
  });
2110
2170
  pending.push(...genericPending);
2171
+ const mcpInputCallIds = /* @__PURE__ */ new Map();
2172
+ for (const toolCall of pendingToolCalls) {
2173
+ const interruptId = `mcp_input_${toolCall.id}`;
2174
+ if (!resumeInterruptIds.has(interruptId)) continue;
2175
+ if (!toolsByCallId.get(toolCall.id)?.execute) continue;
2176
+ mcpInputCallIds.set(interruptId, toolCall.id);
2177
+ pending.push({
2178
+ interruptId,
2179
+ payload: { id: interruptId },
2180
+ binding: {
2181
+ v: 1,
2182
+ kind: "generic",
2183
+ interruptId,
2184
+ interruptedRunId,
2185
+ generation: 0
2186
+ }
2187
+ });
2188
+ }
2111
2189
  const validated = await validateInterruptResumeBatch({
2112
2190
  threadId: this.threadId,
2113
2191
  interruptedRunId,
@@ -2124,6 +2202,14 @@ var TextEngine = class {
2124
2202
  approvals
2125
2203
  });
2126
2204
  const genericResolutions = validated.resumeToolState.genericInterrupts;
2205
+ for (const [interruptId, toolCallId] of mcpInputCallIds) {
2206
+ const resolution = genericResolutions?.get(interruptId);
2207
+ if (!resolution) continue;
2208
+ this.resumeInputResponses.set(toolCallId, resolution.status === "resolved" ? {
2209
+ status: "resolved",
2210
+ payload: resolution.payload
2211
+ } : { status: "cancelled" });
2212
+ }
2127
2213
  if (genericPending.length > 0 && genericResolutions) {
2128
2214
  const resolutions = genericPending.sort((left, right) => {
2129
2215
  return (left.binding.kind === "generic" ? left.binding.batchIndex ?? 0 : 0) - (right.binding.kind === "generic" ? right.binding.batchIndex ?? 0 : 0);
@@ -2144,7 +2230,10 @@ var TextEngine = class {
2144
2230
  all: (...definitions) => definitions.length === 0 ? resolutions : resolutions.filter((resolution) => definitions.includes(resolution.request.definition))
2145
2231
  });
2146
2232
  if (policy.toolResume === "stop") this.earlyTermination = true;
2147
- else if (policy.toolResume === "cancel") for (const request of pendingToolCalls) this.resumeCancelledToolCallIds.add(request.id);
2233
+ else if (policy.toolResume === "cancel") for (const request of pendingToolCalls) {
2234
+ if (this.resumeDeniedToolResults.has(request.id)) continue;
2235
+ this.resumeCancelledToolCallIds.add(request.id);
2236
+ }
2148
2237
  }
2149
2238
  }
2150
2239
  getGenericContinuationPending(interruptedRunId) {
@@ -2216,6 +2305,7 @@ var TextEngine = class {
2216
2305
  applyResumeToolState(state) {
2217
2306
  if (state?.approvals) for (const [approvalId, resolution] of state.approvals) this.resumeApprovals.set(approvalId, resolution);
2218
2307
  if (state?.clientToolResults) for (const [toolCallId, result] of state.clientToolResults) this.resumeClientToolResults.set(toolCallId, result);
2308
+ if (state?.clientToolErrors) for (const [toolCallId, errorText] of state.clientToolErrors) this.resumeClientToolErrors.set(toolCallId, errorText);
2219
2309
  if (state?.deniedToolResults) for (const [toolCallId, result] of state.deniedToolResults) this.resumeDeniedToolResults.set(toolCallId, result);
2220
2310
  if (state?.cancelledToolCallIds) for (const toolCallId of state.cancelledToolCallIds) this.resumeCancelledToolCallIds.add(toolCallId);
2221
2311
  if (state?.genericInterrupts) for (const [interruptId, resolution] of state.genericInterrupts) this.resumeGenericInterrupts.set(interruptId, resolution);
@@ -2240,7 +2330,10 @@ var TextEngine = class {
2240
2330
  all: (...definitions) => definitions.length === 0 ? resolutions : resolutions.filter((resolution) => definitions.includes(resolution.request.definition))
2241
2331
  });
2242
2332
  if (policy.toolResume === "stop") this.earlyTermination = true;
2243
- else if (policy.toolResume === "cancel") for (const toolCall of this.getPendingToolCallsFromMessages()) this.resumeCancelledToolCallIds.add(toolCall.id);
2333
+ else if (policy.toolResume === "cancel") for (const toolCall of this.getPendingToolCallsFromMessages()) {
2334
+ if (this.resumeDeniedToolResults.has(toolCall.id)) continue;
2335
+ this.resumeCancelledToolCallIds.add(toolCall.id);
2336
+ }
2244
2337
  }
2245
2338
  applyMiddlewareConfig(config) {
2246
2339
  this.applyResumeToolState(config.resumeToolState);
@@ -2577,6 +2670,8 @@ async function* runRoutedSubagents(options, engineRef) {
2577
2670
  yield* runChatEngine(options, engineRef);
2578
2671
  return;
2579
2672
  }
2673
+ const withInput = bag.agents.find((agent) => agent.inputSchema !== void 0);
2674
+ if (withInput) throw new Error(`Subagent "${withInput.name}" has an inputSchema. inputSchema needs tool mode: remove subagents.router so the model writes the input.`);
2580
2675
  const threadId = options.threadId ?? `thread-${Date.now()}`;
2581
2676
  const runId = options.runId ?? `run-${Date.now()}`;
2582
2677
  const messages = options.messages ?? [];
@@ -2889,6 +2984,10 @@ async function runAgenticStructuredOutput(options) {
2889
2984
  value: finalizationError.code,
2890
2985
  enumerable: true
2891
2986
  });
2987
+ if (finalizationError.rawText !== void 0) Object.defineProperty(err, "rawText", {
2988
+ value: finalizationError.rawText,
2989
+ enumerable: true
2990
+ });
2892
2991
  throw err;
2893
2992
  }
2894
2993
  const validated = engine.getValidatedStructuredOutput();