@tanstack/ai 0.27.0 → 0.29.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 (51) hide show
  1. package/dist/esm/activities/chat/index.d.ts +7 -0
  2. package/dist/esm/activities/chat/index.js +86 -20
  3. package/dist/esm/activities/chat/index.js.map +1 -1
  4. package/dist/esm/activities/chat/mcp/manager.d.ts +25 -0
  5. package/dist/esm/activities/chat/mcp/manager.js +71 -0
  6. package/dist/esm/activities/chat/mcp/manager.js.map +1 -0
  7. package/dist/esm/activities/chat/mcp/types.d.ts +56 -0
  8. package/dist/esm/activities/chat/messages.js +1 -1
  9. package/dist/esm/activities/chat/messages.js.map +1 -1
  10. package/dist/esm/activities/chat/stream/message-updaters.js +20 -8
  11. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  12. package/dist/esm/activities/chat/stream/processor.d.ts +6 -0
  13. package/dist/esm/activities/chat/stream/processor.js +18 -3
  14. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  15. package/dist/esm/activities/chat/tools/tool-calls.d.ts +1 -1
  16. package/dist/esm/activities/chat/tools/tool-calls.js +2 -1
  17. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  18. package/dist/esm/activities/generateVideo/index.d.ts +2 -1
  19. package/dist/esm/activities/generateVideo/index.js +12 -2
  20. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  21. package/dist/esm/extend-adapter.d.ts +22 -6
  22. package/dist/esm/extend-adapter.js.map +1 -1
  23. package/dist/esm/index.d.ts +2 -0
  24. package/dist/esm/index.js +2 -0
  25. package/dist/esm/index.js.map +1 -1
  26. package/dist/esm/logger/console-logger.d.ts +18 -0
  27. package/dist/esm/logger/console-logger.js +64 -8
  28. package/dist/esm/logger/console-logger.js.map +1 -1
  29. package/dist/esm/logger/types.d.ts +4 -4
  30. package/dist/esm/realtime/index.d.ts +1 -3
  31. package/dist/esm/realtime/index.js.map +1 -1
  32. package/dist/esm/types.d.ts +13 -1
  33. package/package.json +2 -2
  34. package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +2 -2
  35. package/skills/ai-core/chat-experience/SKILL.md +71 -0
  36. package/skills/ai-core/media-generation/SKILL.md +29 -1
  37. package/skills/ai-core/tool-calling/SKILL.md +287 -0
  38. package/src/activities/chat/index.ts +109 -25
  39. package/src/activities/chat/mcp/manager.ts +85 -0
  40. package/src/activities/chat/mcp/types.ts +66 -0
  41. package/src/activities/chat/messages.ts +1 -0
  42. package/src/activities/chat/stream/message-updaters.ts +22 -9
  43. package/src/activities/chat/stream/processor.ts +30 -3
  44. package/src/activities/chat/tools/tool-calls.ts +2 -0
  45. package/src/activities/generateVideo/index.ts +12 -0
  46. package/src/extend-adapter.ts +42 -24
  47. package/src/index.ts +10 -0
  48. package/src/logger/console-logger.ts +112 -17
  49. package/src/logger/types.ts +4 -4
  50. package/src/realtime/index.ts +1 -3
  51. package/src/types.ts +13 -0
@@ -5,6 +5,7 @@ import { SystemPrompt } from '../../system-prompts.js';
5
5
  import { DebugOption } from '../../logger/types.js';
6
6
  import { ProviderTool } from '../../tools/provider-tool.js';
7
7
  import { ContextFromMiddleware, ContextFromTool, DefinedContext, MergeContext, UnionToIntersection } from './runtime-context-types.js';
8
+ import { ChatMCPOptions } from './mcp/types.js';
8
9
  /** The adapter kind this activity handles */
9
10
  export declare const kind: "text";
10
11
  type AnyRuntimeTool = AnyTool;
@@ -77,6 +78,12 @@ export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema ex
77
78
  tools?: Array<(AnyRuntimeTool & {
78
79
  readonly '~toolKind'?: never;
79
80
  }) | ProviderTool<string, TAdapter['~types']['toolCapabilities'][number]>> | undefined;
81
+ /**
82
+ * Hand MCP clients/pools to chat(): their tools are discovered at run start
83
+ * and merged into the run; `connection` controls whether chat() closes them
84
+ * when the run ends. See docs/tools/mcp.md "Managing MCP clients with chat()".
85
+ */
86
+ mcp?: ChatMCPOptions;
80
87
  /** Additional metadata to attach to the request. */
81
88
  metadata?: TextOptions['metadata'];
82
89
  /** Model-specific provider options (type comes from adapter) */
@@ -9,11 +9,25 @@ import { convertSchemaToJsonSchema, isStandardSchema, parseWithStandardSchema }
9
9
  import { maxIterations } from "./agent-loop-strategies.js";
10
10
  import { convertMessagesToModelMessages, generateMessageId } from "./messages.js";
11
11
  import { MiddlewareRunner } from "./middleware/compose.js";
12
+ import { MCPManager } from "./mcp/manager.js";
12
13
  import { EventType } from "@ag-ui/core";
13
14
  const kind = "text";
14
15
  function createChatOptions(options) {
15
16
  return options;
16
17
  }
18
+ function combineAbortSignals(a, b) {
19
+ if (!a) return b;
20
+ if (!b) return a;
21
+ if (a.aborted) return a;
22
+ if (b.aborted) return b;
23
+ const controller = new AbortController();
24
+ const onAbort = (source) => () => {
25
+ controller.abort(source.reason);
26
+ };
27
+ a.addEventListener("abort", onAbort(a), { once: true });
28
+ b.addEventListener("abort", onAbort(b), { once: true });
29
+ return controller.signal;
30
+ }
17
31
  class TextEngine {
18
32
  adapter;
19
33
  params;
@@ -56,6 +70,9 @@ class TextEngine {
56
70
  deferredPromises = [];
57
71
  abortReason;
58
72
  middlewareAbortController;
73
+ // Combines the caller's signal with middleware abort() so running tools
74
+ // observe both cancellation sources via ctx.abortSignal.
75
+ toolAbortSignal;
59
76
  terminalHookCalled = false;
60
77
  logger;
61
78
  // Structured-output finalization state (populated by runStructuredFinalization)
@@ -111,6 +128,10 @@ class TextEngine {
111
128
  ];
112
129
  this.middlewareRunner = new MiddlewareRunner(allMiddleware, logger);
113
130
  this.middlewareAbortController = new AbortController();
131
+ this.toolAbortSignal = combineAbortSignals(
132
+ this.effectiveSignal,
133
+ this.middlewareAbortController.signal
134
+ );
114
135
  this.middlewareCtx = {
115
136
  requestId: this.requestId,
116
137
  streamId: this.streamId,
@@ -563,7 +584,8 @@ class TextEngine {
563
584
  );
564
585
  }
565
586
  },
566
- this.middlewareCtx.context
587
+ this.middlewareCtx.context,
588
+ this.toolAbortSignal
567
589
  );
568
590
  const executionResult = yield* this.drainToolCallGenerator(generator);
569
591
  if (this.isMiddlewareAborted()) {
@@ -694,7 +716,8 @@ class TextEngine {
694
716
  );
695
717
  }
696
718
  },
697
- this.middlewareCtx.context
719
+ this.middlewareCtx.context,
720
+ this.toolAbortSignal
698
721
  );
699
722
  const executionResult = yield* this.drainToolCallGenerator(generator);
700
723
  this.middlewareCtx.phase = "afterTools";
@@ -873,17 +896,17 @@ class TextEngine {
873
896
  delta: args,
874
897
  args
875
898
  });
899
+ chunks.push({
900
+ type: "TOOL_CALL_END",
901
+ timestamp: Date.now(),
902
+ model: finishEvent.model,
903
+ toolCallId: result.toolCallId,
904
+ toolCallName: result.toolName,
905
+ toolName: result.toolName,
906
+ result: wireContent,
907
+ ...result.state !== void 0 && { state: result.state }
908
+ });
876
909
  }
877
- chunks.push({
878
- type: "TOOL_CALL_END",
879
- timestamp: Date.now(),
880
- model: finishEvent.model,
881
- toolCallId: result.toolCallId,
882
- toolCallName: result.toolName,
883
- toolName: result.toolName,
884
- result: wireContent,
885
- ...result.state !== void 0 && { state: result.state }
886
- });
887
910
  chunks.push({
888
911
  type: "TOOL_CALL_RESULT",
889
912
  timestamp: Date.now(),
@@ -1411,9 +1434,14 @@ function chat(options) {
1411
1434
  });
1412
1435
  }
1413
1436
  async function* runStreamingText(options) {
1414
- const { adapter, middleware, context, debug, ...textOptions } = options;
1437
+ const { adapter, middleware, context, debug, mcp, ...textOptions } = options;
1415
1438
  const model = adapter.model;
1416
1439
  const logger = resolveDebugOption(debug);
1440
+ const mcpManager = MCPManager.from(mcp);
1441
+ const mcpTools = await mcpManager.discover();
1442
+ if (mcpTools.length > 0) {
1443
+ textOptions.tools = [...textOptions.tools ?? [], ...mcpTools];
1444
+ }
1417
1445
  const engine = new TextEngine(
1418
1446
  {
1419
1447
  adapter,
@@ -1423,8 +1451,12 @@ async function* runStreamingText(options) {
1423
1451
  },
1424
1452
  logger
1425
1453
  );
1426
- for await (const chunk of engine.run()) {
1427
- yield chunk;
1454
+ try {
1455
+ for await (const chunk of engine.run()) {
1456
+ yield chunk;
1457
+ }
1458
+ } finally {
1459
+ await mcpManager.dispose();
1428
1460
  }
1429
1461
  }
1430
1462
  function runNonStreamingText(options) {
@@ -1435,7 +1467,15 @@ function runNonStreamingText(options) {
1435
1467
  return streamToText(stream);
1436
1468
  }
1437
1469
  async function runAgenticStructuredOutput(options) {
1438
- const { adapter, outputSchema, middleware, context, debug, ...textOptions } = options;
1470
+ const {
1471
+ adapter,
1472
+ outputSchema,
1473
+ middleware,
1474
+ context,
1475
+ debug,
1476
+ mcp,
1477
+ ...textOptions
1478
+ } = options;
1439
1479
  const model = adapter.model;
1440
1480
  const logger = resolveDebugOption(debug);
1441
1481
  if (!outputSchema) {
@@ -1449,6 +1489,11 @@ async function runAgenticStructuredOutput(options) {
1449
1489
  }
1450
1490
  const validate = isStandardSchema(outputSchema) ? (data) => parseWithStandardSchema(outputSchema, data) : void 0;
1451
1491
  const nativeCombined = adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true;
1492
+ const mcpManager = MCPManager.from(mcp);
1493
+ const mcpTools = await mcpManager.discover();
1494
+ if (mcpTools.length > 0) {
1495
+ textOptions.tools = [...textOptions.tools ?? [], ...mcpTools];
1496
+ }
1452
1497
  const engine = new TextEngine(
1453
1498
  {
1454
1499
  adapter,
@@ -1464,7 +1509,11 @@ async function runAgenticStructuredOutput(options) {
1464
1509
  },
1465
1510
  logger
1466
1511
  );
1467
- for await (const _chunk of engine.run()) {
1512
+ try {
1513
+ for await (const _chunk of engine.run()) {
1514
+ }
1515
+ } finally {
1516
+ await mcpManager.dispose();
1468
1517
  }
1469
1518
  const finalizationError = engine.getFinalizationError();
1470
1519
  if (finalizationError) {
@@ -1588,10 +1637,23 @@ function runStreamingStructuredOutput(options) {
1588
1637
  );
1589
1638
  }
1590
1639
  async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
1591
- const { adapter, outputSchema, middleware, context, debug, ...textOptions } = options;
1640
+ const {
1641
+ adapter,
1642
+ outputSchema,
1643
+ middleware,
1644
+ context,
1645
+ debug,
1646
+ mcp,
1647
+ ...textOptions
1648
+ } = options;
1592
1649
  const model = adapter.model;
1593
1650
  const logger = resolveDebugOption(debug);
1594
1651
  const nativeCombined = adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true;
1652
+ const mcpManager = MCPManager.from(mcp);
1653
+ const mcpTools = await mcpManager.discover();
1654
+ if (mcpTools.length > 0) {
1655
+ textOptions.tools = [...textOptions.tools ?? [], ...mcpTools];
1656
+ }
1595
1657
  const engine = new TextEngine(
1596
1658
  {
1597
1659
  adapter,
@@ -1606,8 +1668,12 @@ async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
1606
1668
  },
1607
1669
  logger
1608
1670
  );
1609
- for await (const chunk of engine.run()) {
1610
- yield chunk;
1671
+ try {
1672
+ for await (const chunk of engine.run()) {
1673
+ yield chunk;
1674
+ }
1675
+ } finally {
1676
+ await mcpManager.dispose();
1611
1677
  }
1612
1678
  }
1613
1679
  export {