@tanstack/ai 0.26.1 → 0.28.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 -6
  2. package/dist/esm/activities/chat/index.js +78 -27
  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/middleware/types.d.ts +1 -4
  9. package/dist/esm/activities/chat/stream/message-updaters.js +20 -8
  10. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  11. package/dist/esm/activities/chat/tools/tool-calls.d.ts +1 -1
  12. package/dist/esm/activities/chat/tools/tool-calls.js +2 -1
  13. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  14. package/dist/esm/activities/summarize/chat-stream-summarize.js +62 -3
  15. package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
  16. package/dist/esm/extend-adapter.d.ts +22 -6
  17. package/dist/esm/extend-adapter.js.map +1 -1
  18. package/dist/esm/index.d.ts +2 -0
  19. package/dist/esm/index.js +2 -0
  20. package/dist/esm/index.js.map +1 -1
  21. package/dist/esm/logger/internal-logger.d.ts +8 -0
  22. package/dist/esm/logger/internal-logger.js +15 -0
  23. package/dist/esm/logger/internal-logger.js.map +1 -1
  24. package/dist/esm/middlewares/otel.js +30 -6
  25. package/dist/esm/middlewares/otel.js.map +1 -1
  26. package/dist/esm/types.d.ts +6 -35
  27. package/dist/esm/utilities/sampling-keys.d.ts +20 -0
  28. package/dist/esm/utilities/sampling-keys.js +20 -0
  29. package/dist/esm/utilities/sampling-keys.js.map +1 -0
  30. package/package.json +2 -2
  31. package/skills/ai-core/adapter-configuration/SKILL.md +67 -6
  32. package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +6 -3
  33. package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +3 -0
  34. package/skills/ai-core/adapter-configuration/references/ollama-adapter.md +10 -1
  35. package/skills/ai-core/adapter-configuration/references/openai-adapter.md +4 -0
  36. package/skills/ai-core/chat-experience/SKILL.md +95 -7
  37. package/skills/ai-core/middleware/SKILL.md +11 -0
  38. package/skills/ai-core/tool-calling/SKILL.md +287 -0
  39. package/src/activities/chat/index.ts +97 -35
  40. package/src/activities/chat/mcp/manager.ts +85 -0
  41. package/src/activities/chat/mcp/types.ts +66 -0
  42. package/src/activities/chat/middleware/types.ts +1 -4
  43. package/src/activities/chat/stream/message-updaters.ts +22 -9
  44. package/src/activities/chat/tools/tool-calls.ts +2 -0
  45. package/src/activities/summarize/chat-stream-summarize.ts +162 -3
  46. package/src/extend-adapter.ts +42 -24
  47. package/src/index.ts +10 -0
  48. package/src/logger/internal-logger.ts +18 -0
  49. package/src/middlewares/otel.ts +48 -6
  50. package/src/types.ts +6 -35
  51. package/src/utilities/sampling-keys.ts +28 -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,12 +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;
80
- /** Controls the randomness of the output. Higher values make output more random. Range: [0.0, 2.0] */
81
- temperature?: TextOptions['temperature'];
82
- /** Nucleus sampling parameter. The model considers tokens with topP probability mass. */
83
- topP?: TextOptions['topP'];
84
- /** The maximum number of tokens to generate in the response. */
85
- maxTokens?: TextOptions['maxTokens'];
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;
86
87
  /** Additional metadata to attach to the request. */
87
88
  metadata?: TextOptions['metadata'];
88
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,
@@ -297,11 +318,8 @@ class TextEngine {
297
318
  }
298
319
  beforeRun() {
299
320
  this.streamStartTime = Date.now();
300
- const { tools, temperature, topP, maxTokens, metadata } = this.params;
321
+ const { tools, metadata } = this.params;
301
322
  const options = {};
302
- if (temperature !== void 0) options.temperature = temperature;
303
- if (topP !== void 0) options.topP = topP;
304
- if (maxTokens !== void 0) options.maxTokens = maxTokens;
305
323
  if (metadata !== void 0) options.metadata = metadata;
306
324
  this.eventOptions = Object.keys(options).length > 0 ? options : void 0;
307
325
  this.eventToolNames = tools?.map((t) => t.name);
@@ -336,7 +354,7 @@ class TextEngine {
336
354
  });
337
355
  }
338
356
  async *streamModelResponse() {
339
- const { temperature, topP, maxTokens, metadata, modelOptions } = this.params;
357
+ const { metadata, modelOptions } = this.params;
340
358
  const tools = this.tools;
341
359
  const toolsWithJsonSchemas = tools.map((tool) => ({
342
360
  ...tool,
@@ -359,9 +377,6 @@ class TextEngine {
359
377
  model: this.params.model,
360
378
  messages: this.messages,
361
379
  tools: toolsWithJsonSchemas,
362
- temperature,
363
- topP,
364
- maxTokens,
365
380
  metadata,
366
381
  request: this.effectiveRequest,
367
382
  modelOptions,
@@ -569,7 +584,8 @@ class TextEngine {
569
584
  );
570
585
  }
571
586
  },
572
- this.middlewareCtx.context
587
+ this.middlewareCtx.context,
588
+ this.toolAbortSignal
573
589
  );
574
590
  const executionResult = yield* this.drainToolCallGenerator(generator);
575
591
  if (this.isMiddlewareAborted()) {
@@ -700,7 +716,8 @@ class TextEngine {
700
716
  );
701
717
  }
702
718
  },
703
- this.middlewareCtx.context
719
+ this.middlewareCtx.context,
720
+ this.toolAbortSignal
704
721
  );
705
722
  const executionResult = yield* this.drainToolCallGenerator(generator);
706
723
  this.middlewareCtx.phase = "afterTools";
@@ -1024,9 +1041,6 @@ class TextEngine {
1024
1041
  chatOptions: {
1025
1042
  model: this.params.model,
1026
1043
  messages: this.messages,
1027
- temperature: postOnConfig.temperature,
1028
- topP: postOnConfig.topP,
1029
- maxTokens: postOnConfig.maxTokens,
1030
1044
  metadata: postOnConfig.metadata,
1031
1045
  modelOptions: postOnConfig.modelOptions,
1032
1046
  systemPrompts: postOnConfig.systemPrompts,
@@ -1330,9 +1344,6 @@ class TextEngine {
1330
1344
  messages: this.messages,
1331
1345
  systemPrompts: [...this.systemPrompts],
1332
1346
  tools: [...this.tools],
1333
- temperature: this.params.temperature,
1334
- topP: this.params.topP,
1335
- maxTokens: this.params.maxTokens,
1336
1347
  metadata: this.params.metadata,
1337
1348
  modelOptions: this.params.modelOptions
1338
1349
  };
@@ -1343,9 +1354,6 @@ class TextEngine {
1343
1354
  this.tools = config.tools;
1344
1355
  this.params = {
1345
1356
  ...this.params,
1346
- temperature: config.temperature,
1347
- topP: config.topP,
1348
- maxTokens: config.maxTokens,
1349
1357
  metadata: config.metadata,
1350
1358
  modelOptions: config.modelOptions
1351
1359
  };
@@ -1426,9 +1434,14 @@ function chat(options) {
1426
1434
  });
1427
1435
  }
1428
1436
  async function* runStreamingText(options) {
1429
- const { adapter, middleware, context, debug, ...textOptions } = options;
1437
+ const { adapter, middleware, context, debug, mcp, ...textOptions } = options;
1430
1438
  const model = adapter.model;
1431
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
+ }
1432
1445
  const engine = new TextEngine(
1433
1446
  {
1434
1447
  adapter,
@@ -1438,8 +1451,12 @@ async function* runStreamingText(options) {
1438
1451
  },
1439
1452
  logger
1440
1453
  );
1441
- for await (const chunk of engine.run()) {
1442
- yield chunk;
1454
+ try {
1455
+ for await (const chunk of engine.run()) {
1456
+ yield chunk;
1457
+ }
1458
+ } finally {
1459
+ await mcpManager.dispose();
1443
1460
  }
1444
1461
  }
1445
1462
  function runNonStreamingText(options) {
@@ -1450,7 +1467,15 @@ function runNonStreamingText(options) {
1450
1467
  return streamToText(stream);
1451
1468
  }
1452
1469
  async function runAgenticStructuredOutput(options) {
1453
- 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;
1454
1479
  const model = adapter.model;
1455
1480
  const logger = resolveDebugOption(debug);
1456
1481
  if (!outputSchema) {
@@ -1464,6 +1489,11 @@ async function runAgenticStructuredOutput(options) {
1464
1489
  }
1465
1490
  const validate = isStandardSchema(outputSchema) ? (data) => parseWithStandardSchema(outputSchema, data) : void 0;
1466
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
+ }
1467
1497
  const engine = new TextEngine(
1468
1498
  {
1469
1499
  adapter,
@@ -1479,7 +1509,11 @@ async function runAgenticStructuredOutput(options) {
1479
1509
  },
1480
1510
  logger
1481
1511
  );
1482
- for await (const _chunk of engine.run()) {
1512
+ try {
1513
+ for await (const _chunk of engine.run()) {
1514
+ }
1515
+ } finally {
1516
+ await mcpManager.dispose();
1483
1517
  }
1484
1518
  const finalizationError = engine.getFinalizationError();
1485
1519
  if (finalizationError) {
@@ -1603,10 +1637,23 @@ function runStreamingStructuredOutput(options) {
1603
1637
  );
1604
1638
  }
1605
1639
  async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
1606
- 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;
1607
1649
  const model = adapter.model;
1608
1650
  const logger = resolveDebugOption(debug);
1609
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
+ }
1610
1657
  const engine = new TextEngine(
1611
1658
  {
1612
1659
  adapter,
@@ -1621,8 +1668,12 @@ async function* runStreamingStructuredOutputImpl(options, jsonSchema) {
1621
1668
  },
1622
1669
  logger
1623
1670
  );
1624
- for await (const chunk of engine.run()) {
1625
- yield chunk;
1671
+ try {
1672
+ for await (const chunk of engine.run()) {
1673
+ yield chunk;
1674
+ }
1675
+ } finally {
1676
+ await mcpManager.dispose();
1626
1677
  }
1627
1678
  }
1628
1679
  export {