@mastra/core 0.21.2-alpha.0 → 0.22.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 (181) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/dist/agent/agent.d.ts +1 -0
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/index.cjs +13 -13
  5. package/dist/agent/index.js +2 -2
  6. package/dist/agent/input-processor/index.cjs +6 -6
  7. package/dist/agent/input-processor/index.js +1 -1
  8. package/dist/agent/message-list/index.d.ts +14 -1
  9. package/dist/agent/message-list/index.d.ts.map +1 -1
  10. package/dist/agent/test-utils.d.ts +1 -0
  11. package/dist/agent/test-utils.d.ts.map +1 -1
  12. package/dist/agent/types.d.ts +6 -1
  13. package/dist/agent/types.d.ts.map +1 -1
  14. package/dist/agent/utils.d.ts +1 -1
  15. package/dist/agent/utils.d.ts.map +1 -1
  16. package/dist/ai-tracing/chunk-tracing.d.ts +76 -0
  17. package/dist/ai-tracing/chunk-tracing.d.ts.map +1 -0
  18. package/dist/ai-tracing/exporters/base.d.ts +111 -0
  19. package/dist/ai-tracing/exporters/base.d.ts.map +1 -0
  20. package/dist/ai-tracing/exporters/cloud.d.ts +6 -8
  21. package/dist/ai-tracing/exporters/cloud.d.ts.map +1 -1
  22. package/dist/ai-tracing/exporters/console.d.ts +6 -6
  23. package/dist/ai-tracing/exporters/console.d.ts.map +1 -1
  24. package/dist/ai-tracing/exporters/index.d.ts +1 -0
  25. package/dist/ai-tracing/exporters/index.d.ts.map +1 -1
  26. package/dist/ai-tracing/index.cjs +48 -32
  27. package/dist/ai-tracing/index.d.ts +1 -0
  28. package/dist/ai-tracing/index.d.ts.map +1 -1
  29. package/dist/ai-tracing/index.js +1 -1
  30. package/dist/ai-tracing/spans/base.d.ts +4 -1
  31. package/dist/ai-tracing/spans/base.d.ts.map +1 -1
  32. package/dist/ai-tracing/spans/default.d.ts.map +1 -1
  33. package/dist/ai-tracing/tracers/base.d.ts +15 -1
  34. package/dist/ai-tracing/tracers/base.d.ts.map +1 -1
  35. package/dist/ai-tracing/types.d.ts +85 -11
  36. package/dist/ai-tracing/types.d.ts.map +1 -1
  37. package/dist/ai-tracing/utils.d.ts +14 -0
  38. package/dist/ai-tracing/utils.d.ts.map +1 -1
  39. package/dist/{chunk-D3IOLHNB.cjs → chunk-34L2Z6PH.cjs} +12 -12
  40. package/dist/{chunk-D3IOLHNB.cjs.map → chunk-34L2Z6PH.cjs.map} +1 -1
  41. package/dist/{chunk-BLVB2IJK.js → chunk-3CVE7NQC.js} +728 -267
  42. package/dist/chunk-3CVE7NQC.js.map +1 -0
  43. package/dist/{chunk-URQI7RJ3.cjs → chunk-5GIAZ3CH.cjs} +734 -269
  44. package/dist/chunk-5GIAZ3CH.cjs.map +1 -0
  45. package/dist/{chunk-XYNSPEJO.js → chunk-5NYWRAJN.js} +3 -3
  46. package/dist/{chunk-XYNSPEJO.js.map → chunk-5NYWRAJN.js.map} +1 -1
  47. package/dist/{chunk-URVM3Y4T.cjs → chunk-634YFL42.cjs} +44 -7
  48. package/dist/chunk-634YFL42.cjs.map +1 -0
  49. package/dist/{chunk-NIESGYOH.js → chunk-A3TQYIIR.js} +1392 -1416
  50. package/dist/chunk-A3TQYIIR.js.map +1 -0
  51. package/dist/{chunk-EGNHIPGJ.cjs → chunk-A4B6IAKN.cjs} +4 -4
  52. package/dist/{chunk-EGNHIPGJ.cjs.map → chunk-A4B6IAKN.cjs.map} +1 -1
  53. package/dist/{chunk-LMP5KMU3.js → chunk-AGD5B3FB.js} +43 -6
  54. package/dist/chunk-AGD5B3FB.js.map +1 -0
  55. package/dist/{chunk-V5WDWSQ5.cjs → chunk-CAZTWPDK.cjs} +11 -11
  56. package/dist/{chunk-V5WDWSQ5.cjs.map → chunk-CAZTWPDK.cjs.map} +1 -1
  57. package/dist/{chunk-N3ZSX5OS.js → chunk-F7OMDF5K.js} +72 -36
  58. package/dist/chunk-F7OMDF5K.js.map +1 -0
  59. package/dist/{chunk-ZMPSVDDO.cjs → chunk-FMNZ3BPT.cjs} +1393 -1417
  60. package/dist/chunk-FMNZ3BPT.cjs.map +1 -0
  61. package/dist/{chunk-4ZFVJA3A.js → chunk-HZIF7HQC.js} +3 -3
  62. package/dist/{chunk-4ZFVJA3A.js.map → chunk-HZIF7HQC.js.map} +1 -1
  63. package/dist/{chunk-KLWDUSBX.js → chunk-ITFEGBP2.js} +4 -4
  64. package/dist/{chunk-KLWDUSBX.js.map → chunk-ITFEGBP2.js.map} +1 -1
  65. package/dist/{chunk-GKTRUHKB.js → chunk-KQBF5ZEN.js} +5 -5
  66. package/dist/{chunk-GKTRUHKB.js.map → chunk-KQBF5ZEN.js.map} +1 -1
  67. package/dist/{chunk-R35PINKN.js → chunk-MHICZASQ.js} +5 -5
  68. package/dist/{chunk-R35PINKN.js.map → chunk-MHICZASQ.js.map} +1 -1
  69. package/dist/{chunk-H4KO46HZ.js → chunk-MKCC5K77.js} +3 -3
  70. package/dist/{chunk-H4KO46HZ.js.map → chunk-MKCC5K77.js.map} +1 -1
  71. package/dist/{chunk-UN653TND.cjs → chunk-O4KVF3MI.cjs} +4 -4
  72. package/dist/{chunk-UN653TND.cjs.map → chunk-O4KVF3MI.cjs.map} +1 -1
  73. package/dist/{chunk-WI2YMBNG.cjs → chunk-QBPTDMR7.cjs} +102 -64
  74. package/dist/chunk-QBPTDMR7.cjs.map +1 -0
  75. package/dist/{chunk-7P5FMQQK.cjs → chunk-RWWOJXMF.cjs} +6 -6
  76. package/dist/{chunk-7P5FMQQK.cjs.map → chunk-RWWOJXMF.cjs.map} +1 -1
  77. package/dist/{chunk-XBJP7THY.js → chunk-RXBG6UV2.js} +4 -4
  78. package/dist/chunk-RXBG6UV2.js.map +1 -0
  79. package/dist/{chunk-NL3P7IFI.js → chunk-SF75RENF.js} +3 -3
  80. package/dist/{chunk-NL3P7IFI.js.map → chunk-SF75RENF.js.map} +1 -1
  81. package/dist/{chunk-SE4PA467.cjs → chunk-VF676YCO.cjs} +2 -2
  82. package/dist/chunk-VF676YCO.cjs.map +1 -0
  83. package/dist/{chunk-6OLRLZJ3.js → chunk-WM4RO23J.js} +2 -2
  84. package/dist/chunk-WM4RO23J.js.map +1 -0
  85. package/dist/{chunk-MVVMHOAC.cjs → chunk-YOVX3R5U.cjs} +14 -14
  86. package/dist/chunk-YOVX3R5U.cjs.map +1 -0
  87. package/dist/{chunk-L5A4MRCK.cjs → chunk-ZABG3SZ2.cjs} +4 -4
  88. package/dist/{chunk-L5A4MRCK.cjs.map → chunk-ZABG3SZ2.cjs.map} +1 -1
  89. package/dist/{chunk-YKVVW65D.cjs → chunk-ZDW322JC.cjs} +8 -8
  90. package/dist/{chunk-YKVVW65D.cjs.map → chunk-ZDW322JC.cjs.map} +1 -1
  91. package/dist/index.cjs +53 -53
  92. package/dist/index.js +11 -11
  93. package/dist/integration/index.cjs +3 -3
  94. package/dist/integration/index.js +1 -1
  95. package/dist/llm/index.cjs +7 -7
  96. package/dist/llm/index.js +1 -1
  97. package/dist/llm/model/model.loop.d.ts.map +1 -1
  98. package/dist/llm/model/provider-types.generated.d.ts +585 -597
  99. package/dist/loop/index.cjs +2 -2
  100. package/dist/loop/index.js +1 -1
  101. package/dist/loop/loop.d.ts.map +1 -1
  102. package/dist/loop/test-utils/mock-server-response.d.ts +7 -2
  103. package/dist/loop/test-utils/mock-server-response.d.ts.map +1 -1
  104. package/dist/loop/test-utils/options.d.ts.map +1 -1
  105. package/dist/loop/types.d.ts +2 -1
  106. package/dist/loop/types.d.ts.map +1 -1
  107. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts.map +1 -1
  108. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts +1 -1
  109. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts.map +1 -1
  110. package/dist/mastra/index.cjs +2 -2
  111. package/dist/mastra/index.js +1 -1
  112. package/dist/memory/index.cjs +4 -4
  113. package/dist/memory/index.js +1 -1
  114. package/dist/memory/memory.d.ts +3 -2
  115. package/dist/memory/memory.d.ts.map +1 -1
  116. package/dist/processors/index.cjs +11 -11
  117. package/dist/processors/index.js +1 -1
  118. package/dist/provider-registry.json +1390 -1414
  119. package/dist/relevance/index.cjs +4 -4
  120. package/dist/relevance/index.js +1 -1
  121. package/dist/scores/index.cjs +9 -9
  122. package/dist/scores/index.js +2 -2
  123. package/dist/scores/scoreTraces/index.cjs +8 -8
  124. package/dist/scores/scoreTraces/index.js +3 -3
  125. package/dist/storage/index.cjs +3 -3
  126. package/dist/storage/index.js +1 -1
  127. package/dist/stream/RunOutput.d.ts +72 -0
  128. package/dist/stream/RunOutput.d.ts.map +1 -0
  129. package/dist/stream/aisdk/v5/output.d.ts +2 -2
  130. package/dist/stream/aisdk/v5/output.d.ts.map +1 -1
  131. package/dist/stream/base/base.d.ts +7 -0
  132. package/dist/stream/base/base.d.ts.map +1 -0
  133. package/dist/stream/base/consume-stream.d.ts +5 -0
  134. package/dist/stream/base/consume-stream.d.ts.map +1 -0
  135. package/dist/stream/base/output.d.ts.map +1 -1
  136. package/dist/stream/index.cjs +14 -10
  137. package/dist/stream/index.d.ts +2 -1
  138. package/dist/stream/index.d.ts.map +1 -1
  139. package/dist/stream/index.js +2 -2
  140. package/dist/stream/types.d.ts +1 -1
  141. package/dist/stream/types.d.ts.map +1 -1
  142. package/dist/test-utils/llm-mock.cjs +2 -2
  143. package/dist/test-utils/llm-mock.js +1 -1
  144. package/dist/tools/index.cjs +4 -4
  145. package/dist/tools/index.js +1 -1
  146. package/dist/tools/is-vercel-tool.cjs +2 -2
  147. package/dist/tools/is-vercel-tool.js +1 -1
  148. package/dist/tools/tool-builder/builder.d.ts +75 -2
  149. package/dist/tools/tool-builder/builder.d.ts.map +1 -1
  150. package/dist/tools/tool.d.ts +2 -2
  151. package/dist/tools/tool.d.ts.map +1 -1
  152. package/dist/tools/types.d.ts +17 -12
  153. package/dist/tools/types.d.ts.map +1 -1
  154. package/dist/utils.cjs +17 -17
  155. package/dist/utils.d.ts +1 -0
  156. package/dist/utils.d.ts.map +1 -1
  157. package/dist/utils.js +1 -1
  158. package/dist/workflows/evented/index.cjs +10 -10
  159. package/dist/workflows/evented/index.js +1 -1
  160. package/dist/workflows/evented/workflow.d.ts +5 -3
  161. package/dist/workflows/evented/workflow.d.ts.map +1 -1
  162. package/dist/workflows/index.cjs +12 -12
  163. package/dist/workflows/index.js +1 -1
  164. package/dist/workflows/legacy/index.cjs +22 -22
  165. package/dist/workflows/legacy/index.js +1 -1
  166. package/dist/workflows/workflow.d.ts +30 -23
  167. package/dist/workflows/workflow.d.ts.map +1 -1
  168. package/package.json +12 -10
  169. package/src/llm/model/provider-types.generated.d.ts +585 -597
  170. package/dist/chunk-6OLRLZJ3.js.map +0 -1
  171. package/dist/chunk-BLVB2IJK.js.map +0 -1
  172. package/dist/chunk-LMP5KMU3.js.map +0 -1
  173. package/dist/chunk-MVVMHOAC.cjs.map +0 -1
  174. package/dist/chunk-N3ZSX5OS.js.map +0 -1
  175. package/dist/chunk-NIESGYOH.js.map +0 -1
  176. package/dist/chunk-SE4PA467.cjs.map +0 -1
  177. package/dist/chunk-URQI7RJ3.cjs.map +0 -1
  178. package/dist/chunk-URVM3Y4T.cjs.map +0 -1
  179. package/dist/chunk-WI2YMBNG.cjs.map +0 -1
  180. package/dist/chunk-XBJP7THY.js.map +0 -1
  181. package/dist/chunk-ZMPSVDDO.cjs.map +0 -1
@@ -1,19 +1,21 @@
1
1
  import { RuntimeContext } from './chunk-HLRWYUFN.js';
2
2
  import { MastraError } from './chunk-T3JFFQH2.js';
3
3
  import { ToolStream } from './chunk-HGNRQ3OG.js';
4
- import { isVercelTool, validateToolInput } from './chunk-6OLRLZJ3.js';
4
+ import { isVercelTool, validateToolInput } from './chunk-WM4RO23J.js';
5
5
  import { MastraBase } from './chunk-VQASQG5D.js';
6
- import { RegisteredLogger, ConsoleLogger, LogLevel } from './chunk-UXG7PYML.js';
6
+ import { ConsoleLogger, LogLevel, RegisteredLogger } from './chunk-UXG7PYML.js';
7
7
  import { createHash } from 'crypto';
8
8
  import jsonSchemaToZod from 'json-schema-to-zod';
9
9
  import { z } from 'zod';
10
10
  import { convertZodSchemaToAISDKSchema, OpenAIReasoningSchemaCompatLayer, OpenAISchemaCompatLayer, GoogleSchemaCompatLayer, AnthropicSchemaCompatLayer, DeepSeekSchemaCompatLayer, MetaSchemaCompatLayer, applyCompatLayer } from '@mastra/schema-compat';
11
+ import { TransformStream } from 'stream/web';
11
12
 
12
13
  // src/ai-tracing/types.ts
13
14
  var AISpanType = /* @__PURE__ */ ((AISpanType2) => {
14
15
  AISpanType2["AGENT_RUN"] = "agent_run";
15
16
  AISpanType2["GENERIC"] = "generic";
16
17
  AISpanType2["LLM_GENERATION"] = "llm_generation";
18
+ AISpanType2["LLM_STEP"] = "llm_step";
17
19
  AISpanType2["LLM_CHUNK"] = "llm_chunk";
18
20
  AISpanType2["MCP_TOOL_CALL"] = "mcp_tool_call";
19
21
  AISpanType2["PROCESSOR_RUN"] = "processor_run";
@@ -76,6 +78,7 @@ function isSpanInternal(spanType, flags) {
76
78
  return (flags & 4 /* TOOL */) !== 0;
77
79
  // LLM-related spans
78
80
  case "llm_generation" /* LLM_GENERATION */:
81
+ case "llm_step" /* LLM_STEP */:
79
82
  case "llm_chunk" /* LLM_CHUNK */:
80
83
  return (flags & 8 /* LLM */) !== 0;
81
84
  // Default: never internal
@@ -97,6 +100,9 @@ var BaseAISpan = class {
97
100
  output;
98
101
  errorInfo;
99
102
  metadata;
103
+ traceState;
104
+ /** Parent span ID (for root spans that are children of external spans) */
105
+ parentSpanId;
100
106
  constructor(options, aiTracing) {
101
107
  this.name = options.name;
102
108
  this.type = options.type;
@@ -107,6 +113,7 @@ var BaseAISpan = class {
107
113
  this.aiTracing = aiTracing;
108
114
  this.isEvent = options.isEvent ?? false;
109
115
  this.isInternal = isSpanInternal(this.type, options.tracingPolicy?.internal);
116
+ this.traceState = options.traceState;
110
117
  if (this.isEvent) {
111
118
  this.output = deepClean(options.output);
112
119
  } else {
@@ -125,7 +132,9 @@ var BaseAISpan = class {
125
132
  }
126
133
  /** Get the closest parent spanId that isn't an internal span */
127
134
  getParentSpanId(includeInternalSpans) {
128
- if (!this.parent) return void 0;
135
+ if (!this.parent) {
136
+ return this.parentSpanId;
137
+ }
129
138
  if (includeInternalSpans) return this.parent.id;
130
139
  if (this.parent.isInternal) return this.parent.getParentSpanId(includeInternalSpans);
131
140
  return this.parent.id;
@@ -209,10 +218,28 @@ var DefaultAISpan = class extends BaseAISpan {
209
218
  constructor(options, aiTracing) {
210
219
  super(options, aiTracing);
211
220
  this.id = generateSpanId();
212
- if (!options.parent) {
213
- this.traceId = generateTraceId();
214
- } else {
221
+ if (options.parent) {
215
222
  this.traceId = options.parent.traceId;
223
+ } else if (options.traceId) {
224
+ if (isValidTraceId(options.traceId)) {
225
+ this.traceId = options.traceId;
226
+ } else {
227
+ console.error(
228
+ `[Mastra Tracing] Invalid traceId: must be 1-32 hexadecimal characters, got "${options.traceId}". Generating new trace ID.`
229
+ );
230
+ this.traceId = generateTraceId();
231
+ }
232
+ } else {
233
+ this.traceId = generateTraceId();
234
+ }
235
+ if (!options.parent && options.parentSpanId) {
236
+ if (isValidSpanId(options.parentSpanId)) {
237
+ this.parentSpanId = options.parentSpanId;
238
+ } else {
239
+ console.error(
240
+ `[Mastra Tracing] Invalid parentSpanId: must be 1-16 hexadecimal characters, got "${options.parentSpanId}". Ignoring parent span ID.`
241
+ );
242
+ }
216
243
  }
217
244
  }
218
245
  end(options) {
@@ -309,6 +336,12 @@ function generateTraceId() {
309
336
  }
310
337
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
311
338
  }
339
+ function isValidTraceId(traceId) {
340
+ return /^[0-9a-f]{1,32}$/i.test(traceId);
341
+ }
342
+ function isValidSpanId(spanId) {
343
+ return /^[0-9a-f]{1,16}$/i.test(spanId);
344
+ }
312
345
 
313
346
  // src/ai-tracing/spans/no-op.ts
314
347
  var NoOpAISpan = class extends BaseAISpan {
@@ -330,247 +363,72 @@ var NoOpAISpan = class extends BaseAISpan {
330
363
  }
331
364
  };
332
365
 
333
- // src/ai-tracing/tracers/base.ts
334
- var BaseAITracing = class extends MastraBase {
335
- config;
336
- constructor(config) {
337
- super({ component: RegisteredLogger.AI_TRACING, name: config.serviceName });
338
- this.config = {
339
- serviceName: config.serviceName,
340
- name: config.name,
341
- sampling: config.sampling ?? { type: "always" /* ALWAYS */ },
342
- exporters: config.exporters ?? [],
343
- processors: config.processors ?? [],
344
- includeInternalSpans: config.includeInternalSpans ?? false
345
- };
346
- }
347
- /**
348
- * Override setLogger to add AI tracing specific initialization log
349
- */
350
- __setLogger(logger) {
351
- super.__setLogger(logger);
352
- this.logger.debug(
353
- `[AI Tracing] Initialized [service=${this.config.serviceName}] [instance=${this.config.name}] [sampling=${this.config.sampling.type}]`
354
- );
355
- }
356
- // ============================================================================
357
- // Protected getters for clean config access
358
- // ============================================================================
359
- get exporters() {
360
- return this.config.exporters || [];
361
- }
362
- get processors() {
363
- return this.config.processors || [];
364
- }
365
- // ============================================================================
366
- // Public API - Single type-safe span creation method
367
- // ============================================================================
368
- /**
369
- * Start a new span of a specific AISpanType
370
- */
371
- startSpan(options) {
372
- const { customSamplerOptions, ...createSpanOptions } = options;
373
- if (!this.shouldSample(customSamplerOptions)) {
374
- return new NoOpAISpan(createSpanOptions, this);
375
- }
376
- const span = this.createSpan(createSpanOptions);
377
- if (span.isEvent) {
378
- this.emitSpanEnded(span);
379
- } else {
380
- this.wireSpanLifecycle(span);
381
- this.emitSpanStarted(span);
382
- }
383
- return span;
384
- }
385
- // ============================================================================
386
- // Configuration Management
387
- // ============================================================================
388
- /**
389
- * Get current configuration
390
- */
391
- getConfig() {
392
- return { ...this.config };
393
- }
394
- // ============================================================================
395
- // Plugin Access
396
- // ============================================================================
397
- /**
398
- * Get all exporters
399
- */
400
- getExporters() {
401
- return [...this.exporters];
402
- }
366
+ // src/ai-tracing/exporters/base.ts
367
+ var BaseExporter = class {
368
+ /** Mastra logger instance */
369
+ logger;
370
+ /** Whether this exporter is disabled */
371
+ isDisabled = false;
403
372
  /**
404
- * Get all processors
373
+ * Initialize the base exporter with logger
405
374
  */
406
- getProcessors() {
407
- return [...this.processors];
375
+ constructor(config = {}) {
376
+ const logLevel = this.resolveLogLevel(config.logLevel);
377
+ this.logger = config.logger ?? new ConsoleLogger({ level: logLevel, name: this.constructor.name });
408
378
  }
409
379
  /**
410
- * Get the logger instance (for exporters and other components)
380
+ * Set the logger for the exporter (called by Mastra/AITracing during initialization)
411
381
  */
412
- getLogger() {
413
- return this.logger;
382
+ __setLogger(logger) {
383
+ this.logger = logger;
384
+ this.logger.debug(`Logger updated for exporter [name=${this.name}]`);
414
385
  }
415
- // ============================================================================
416
- // Span Lifecycle Management
417
- // ============================================================================
418
386
  /**
419
- * Automatically wires up AI tracing lifecycle events for any span
420
- * This ensures all spans emit events regardless of implementation
387
+ * Convert string log level to LogLevel enum
421
388
  */
422
- wireSpanLifecycle(span) {
423
- if (!this.config.includeInternalSpans && span.isInternal) {
424
- return;
425
- }
426
- const originalEnd = span.end.bind(span);
427
- const originalUpdate = span.update.bind(span);
428
- span.end = (options) => {
429
- if (span.isEvent) {
430
- this.logger.warn(`End event is not available on event spans`);
431
- return;
432
- }
433
- originalEnd(options);
434
- this.emitSpanEnded(span);
435
- };
436
- span.update = (options) => {
437
- if (span.isEvent) {
438
- this.logger.warn(`Update() is not available on event spans`);
439
- return;
440
- }
441
- originalUpdate(options);
442
- this.emitSpanUpdated(span);
389
+ resolveLogLevel(logLevel) {
390
+ if (!logLevel) {
391
+ return LogLevel.INFO;
392
+ }
393
+ if (typeof logLevel === "number") {
394
+ return logLevel;
395
+ }
396
+ const logLevelMap = {
397
+ debug: LogLevel.DEBUG,
398
+ info: LogLevel.INFO,
399
+ warn: LogLevel.WARN,
400
+ error: LogLevel.ERROR
443
401
  };
444
- }
445
- // ============================================================================
446
- // Utility Methods
447
- // ============================================================================
448
- /**
449
- * Check if an AI trace should be sampled
450
- */
451
- shouldSample(options) {
452
- const { sampling } = this.config;
453
- switch (sampling.type) {
454
- case "always" /* ALWAYS */:
455
- return true;
456
- case "never" /* NEVER */:
457
- return false;
458
- case "ratio" /* RATIO */:
459
- if (sampling.probability === void 0 || sampling.probability < 0 || sampling.probability > 1) {
460
- this.logger.warn(
461
- `Invalid sampling probability: ${sampling.probability}. Expected value between 0 and 1. Defaulting to no sampling.`
462
- );
463
- return false;
464
- }
465
- return Math.random() < sampling.probability;
466
- case "custom" /* CUSTOM */:
467
- return sampling.sampler(options);
468
- default:
469
- throw new Error(`Sampling strategy type not implemented: ${sampling.type}`);
470
- }
471
- }
472
- /**
473
- * Process a span through all processors
474
- */
475
- processSpan(span) {
476
- for (const processor of this.processors) {
477
- if (!span) {
478
- break;
479
- }
480
- try {
481
- span = processor.process(span);
482
- } catch (error) {
483
- this.logger.error(`[AI Tracing] Processor error [name=${processor.name}]`, error);
484
- }
485
- }
486
- return span;
487
- }
488
- // ============================================================================
489
- // Event-driven Export Methods
490
- // ============================================================================
491
- getSpanForExport(span) {
492
- if (!span.isValid) return void 0;
493
- if (span.isInternal && !this.config.includeInternalSpans) return void 0;
494
- const processedSpan = this.processSpan(span);
495
- return processedSpan?.exportSpan(this.config.includeInternalSpans);
496
- }
497
- /**
498
- * Emit a span started event
499
- */
500
- emitSpanStarted(span) {
501
- const exportedSpan = this.getSpanForExport(span);
502
- if (exportedSpan) {
503
- this.exportEvent({ type: "span_started" /* SPAN_STARTED */, exportedSpan }).catch((error) => {
504
- this.logger.error("[AI Tracing] Failed to export span_started event", error);
505
- });
506
- }
507
- }
508
- /**
509
- * Emit a span ended event (called automatically when spans end)
510
- */
511
- emitSpanEnded(span) {
512
- const exportedSpan = this.getSpanForExport(span);
513
- if (exportedSpan) {
514
- this.exportEvent({ type: "span_ended" /* SPAN_ENDED */, exportedSpan }).catch((error) => {
515
- this.logger.error("[AI Tracing] Failed to export span_ended event", error);
516
- });
517
- }
402
+ return logLevelMap[logLevel] ?? LogLevel.INFO;
518
403
  }
519
404
  /**
520
- * Emit a span updated event
405
+ * Mark the exporter as disabled and log a message
406
+ *
407
+ * @param reason - Reason why the exporter is disabled
521
408
  */
522
- emitSpanUpdated(span) {
523
- const exportedSpan = this.getSpanForExport(span);
524
- if (exportedSpan) {
525
- this.exportEvent({ type: "span_updated" /* SPAN_UPDATED */, exportedSpan }).catch((error) => {
526
- this.logger.error("[AI Tracing] Failed to export span_updated event", error);
527
- });
528
- }
409
+ setDisabled(reason) {
410
+ this.isDisabled = true;
411
+ this.logger.warn(`${this.name} disabled: ${reason}`);
529
412
  }
530
413
  /**
531
- * Export tracing event through all exporters (realtime mode)
414
+ * Export a tracing event
415
+ *
416
+ * This method checks if the exporter is disabled before calling _exportEvent.
417
+ * Subclasses should implement _exportEvent instead of overriding this method.
532
418
  */
533
419
  async exportEvent(event) {
534
- const exportPromises = this.exporters.map(async (exporter) => {
535
- try {
536
- if (exporter.exportEvent) {
537
- await exporter.exportEvent(event);
538
- this.logger.debug(`[AI Tracing] Event exported [exporter=${exporter.name}] [type=${event.type}]`);
539
- }
540
- } catch (error) {
541
- this.logger.error(`[AI Tracing] Export error [exporter=${exporter.name}]`, error);
542
- }
543
- });
544
- await Promise.allSettled(exportPromises);
545
- }
546
- // ============================================================================
547
- // Lifecycle Management
548
- // ============================================================================
549
- /**
550
- * Initialize AI tracing (called by Mastra during component registration)
551
- */
552
- init() {
553
- this.logger.debug(`[AI Tracing] Initialization started [name=${this.name}]`);
554
- this.logger.info(`[AI Tracing] Initialized successfully [name=${this.name}]`);
420
+ if (this.isDisabled) {
421
+ return;
422
+ }
423
+ await this._exportEvent(event);
555
424
  }
556
425
  /**
557
- * Shutdown AI tracing and clean up resources
426
+ * Shutdown the exporter and clean up resources
427
+ *
428
+ * Default implementation just logs. Override to add custom cleanup.
558
429
  */
559
430
  async shutdown() {
560
- this.logger.debug(`[AI Tracing] Shutdown started [name=${this.name}]`);
561
- const shutdownPromises = [...this.exporters.map((e) => e.shutdown()), ...this.processors.map((p) => p.shutdown())];
562
- await Promise.allSettled(shutdownPromises);
563
- this.logger.info(`[AI Tracing] Shutdown completed [name=${this.name}]`);
564
- }
565
- };
566
-
567
- // src/ai-tracing/tracers/default.ts
568
- var DefaultAITracing = class extends BaseAITracing {
569
- constructor(config) {
570
- super(config);
571
- }
572
- createSpan(options) {
573
- return new DefaultAISpan(options, this);
431
+ this.logger.info(`${this.name} shutdown complete`);
574
432
  }
575
433
  };
576
434
  var CoreToolBuilder = class extends MastraBase {
@@ -586,12 +444,26 @@ var CoreToolBuilder = class extends MastraBase {
586
444
  // Helper to get parameters based on tool type
587
445
  getParameters = () => {
588
446
  if (isVercelTool(this.originalTool)) {
589
- return this.originalTool.parameters ?? z.object({});
447
+ let schema2 = this.originalTool.parameters ?? ("inputSchema" in this.originalTool ? this.originalTool.inputSchema : void 0) ?? z.object({});
448
+ if (typeof schema2 === "function") {
449
+ schema2 = schema2();
450
+ }
451
+ return schema2;
590
452
  }
591
- return this.originalTool.inputSchema ?? z.object({});
453
+ let schema = this.originalTool.inputSchema ?? z.object({});
454
+ if (typeof schema === "function") {
455
+ schema = schema();
456
+ }
457
+ return schema;
592
458
  };
593
459
  getOutputSchema = () => {
594
- if ("outputSchema" in this.originalTool) return this.originalTool.outputSchema;
460
+ if ("outputSchema" in this.originalTool) {
461
+ let schema = this.originalTool.outputSchema;
462
+ if (typeof schema === "function") {
463
+ schema = schema();
464
+ }
465
+ return schema;
466
+ }
595
467
  return null;
596
468
  };
597
469
  // For provider-defined tools, we need to include all required properties
@@ -604,8 +476,8 @@ var CoreToolBuilder = class extends MastraBase {
604
476
  id: tool.id,
605
477
  args: "args" in this.originalTool ? this.originalTool.args : {},
606
478
  description: tool.description,
607
- parameters: convertZodSchemaToAISDKSchema(parameters),
608
- ...outputSchema ? { outputSchema: convertZodSchemaToAISDKSchema(outputSchema) } : {},
479
+ parameters: parameters.jsonSchema ? parameters : convertZodSchemaToAISDKSchema(parameters),
480
+ ...outputSchema ? { outputSchema: outputSchema.jsonSchema ? outputSchema : convertZodSchemaToAISDKSchema(outputSchema) } : {},
609
481
  execute: this.originalTool.execute ? this.createExecute(
610
482
  this.originalTool,
611
483
  { ...this.options, description: this.originalTool.description },
@@ -642,7 +514,8 @@ var CoreToolBuilder = class extends MastraBase {
642
514
  type: logType
643
515
  });
644
516
  const execFunction = async (args, execOptions) => {
645
- const toolSpan = options.tracingContext?.currentSpan?.createChildSpan({
517
+ const tracingContext = execOptions.tracingContext || options.tracingContext;
518
+ const toolSpan = tracingContext?.currentSpan?.createChildSpan({
646
519
  type: "tool_call" /* TOOL_CALL */,
647
520
  name: `tool: '${options.name}'`,
648
521
  input: args,
@@ -739,13 +612,25 @@ var CoreToolBuilder = class extends MastraBase {
739
612
  if (!builtTool.parameters) {
740
613
  throw new Error("Tool parameters are required");
741
614
  }
742
- return {
615
+ const base = {
743
616
  ...builtTool,
744
617
  inputSchema: builtTool.parameters,
745
618
  onInputStart: "onInputStart" in this.originalTool ? this.originalTool.onInputStart : void 0,
746
619
  onInputDelta: "onInputDelta" in this.originalTool ? this.originalTool.onInputDelta : void 0,
747
620
  onInputAvailable: "onInputAvailable" in this.originalTool ? this.originalTool.onInputAvailable : void 0
748
621
  };
622
+ if (builtTool.type === "provider-defined") {
623
+ const { execute, parameters, ...rest } = base;
624
+ const name = builtTool.id.split(".")[1] || builtTool.id;
625
+ return {
626
+ ...rest,
627
+ type: builtTool.type,
628
+ id: builtTool.id,
629
+ name,
630
+ args: builtTool.args
631
+ };
632
+ }
633
+ return base;
749
634
  }
750
635
  build() {
751
636
  const providerTool = this.buildProviderTool(this.originalTool);
@@ -926,7 +811,7 @@ function createDeterministicId(input) {
926
811
  return createHash("sha256").update(input).digest("hex").slice(0, 8);
927
812
  }
928
813
  function setVercelToolProperties(tool) {
929
- const inputSchema = convertVercelToolParameters(tool);
814
+ const inputSchema = "inputSchema" in tool ? tool.inputSchema : convertVercelToolParameters(tool);
930
815
  const toolId = !("id" in tool) ? tool.description ? `tool-${createDeterministicId(tool.description)}` : `tool-${Math.random().toString(36).substring(2, 9)}` : tool.id;
931
816
  return {
932
817
  ...tool,
@@ -949,7 +834,10 @@ function ensureToolProperties(tools) {
949
834
  return toolsWithProperties;
950
835
  }
951
836
  function convertVercelToolParameters(tool) {
952
- const schema = tool.parameters ?? z.object({});
837
+ let schema = tool.parameters ?? z.object({});
838
+ if (typeof schema === "function") {
839
+ schema = schema();
840
+ }
953
841
  return isZodType(schema) ? schema : resolveSerializedZodOutput(jsonSchemaToZod(schema));
954
842
  }
955
843
  function makeCoreTool(originalTool, options, logType) {
@@ -1094,42 +982,36 @@ async function fetchWithRetry(url, options = {}, maxRetries = 3) {
1094
982
  }
1095
983
 
1096
984
  // src/ai-tracing/exporters/cloud.ts
1097
- var CloudExporter = class {
985
+ var CloudExporter = class extends BaseExporter {
1098
986
  name = "mastra-cloud-ai-tracing-exporter";
1099
987
  config;
1100
988
  buffer;
1101
989
  flushTimer = null;
1102
- logger;
1103
- isDisabled = false;
1104
990
  constructor(config = {}) {
1105
- this.logger = config.logger ?? new ConsoleLogger({ level: LogLevel.INFO });
991
+ super(config);
1106
992
  const accessToken = config.accessToken ?? process.env.MASTRA_CLOUD_ACCESS_TOKEN;
1107
993
  if (!accessToken) {
1108
- this.logger.debug(
1109
- "CloudExporter disabled: MASTRA_CLOUD_ACCESS_TOKEN environment variable not set. \u{1F680} Sign up for Mastra Cloud at https://cloud.mastra.ai to see your AI traces online and obtain your access token."
994
+ this.setDisabled(
995
+ "MASTRA_CLOUD_ACCESS_TOKEN environment variable not set. \u{1F680} Sign up for Mastra Cloud at https://cloud.mastra.ai to see your AI traces online and obtain your access token."
1110
996
  );
1111
- this.isDisabled = true;
1112
997
  }
1113
998
  const endpoint = config.endpoint ?? process.env.MASTRA_CLOUD_AI_TRACES_ENDPOINT ?? "https://api.mastra.ai/ai/spans/publish";
1114
999
  this.config = {
1000
+ logger: this.logger,
1001
+ logLevel: config.logLevel ?? LogLevel.INFO,
1115
1002
  maxBatchSize: config.maxBatchSize ?? 1e3,
1116
1003
  maxBatchWaitMs: config.maxBatchWaitMs ?? 5e3,
1117
1004
  maxRetries: config.maxRetries ?? 3,
1118
1005
  accessToken: accessToken || "",
1119
- // Empty string if no token
1120
- endpoint,
1121
- logger: this.logger
1006
+ endpoint
1122
1007
  };
1123
1008
  this.buffer = {
1124
1009
  spans: [],
1125
1010
  totalSize: 0
1126
1011
  };
1127
1012
  }
1128
- async exportEvent(event) {
1129
- if (this.isDisabled) {
1130
- return;
1131
- }
1132
- if (event.type !== "span_ended" /* SPAN_ENDED */) {
1013
+ async _exportEvent(event) {
1014
+ if (event.type !== "span_ended" /* SPAN_ENDED */) {
1133
1015
  return;
1134
1016
  }
1135
1017
  this.addToBuffer(event);
@@ -1242,7 +1124,6 @@ var CloudExporter = class {
1242
1124
  * Uploads spans to cloud API using fetchWithRetry for all retry logic
1243
1125
  */
1244
1126
  async batchUpload(spans) {
1245
- const url = `${this.config.endpoint}`;
1246
1127
  const headers = {
1247
1128
  Authorization: `Bearer ${this.config.accessToken}`,
1248
1129
  "Content-Type": "application/json"
@@ -1252,7 +1133,7 @@ var CloudExporter = class {
1252
1133
  headers,
1253
1134
  body: JSON.stringify({ spans })
1254
1135
  };
1255
- await fetchWithRetry(url, options, this.config.maxRetries);
1136
+ await fetchWithRetry(this.config.endpoint, options, this.config.maxRetries);
1256
1137
  }
1257
1138
  resetBuffer() {
1258
1139
  this.buffer.spans = [];
@@ -1294,17 +1175,12 @@ var CloudExporter = class {
1294
1175
  };
1295
1176
 
1296
1177
  // src/ai-tracing/exporters/console.ts
1297
- var ConsoleExporter = class {
1178
+ var ConsoleExporter = class extends BaseExporter {
1298
1179
  name = "tracing-console-exporter";
1299
- logger;
1300
- constructor(logger) {
1301
- if (logger) {
1302
- this.logger = logger;
1303
- } else {
1304
- this.logger = new ConsoleLogger({ level: LogLevel.INFO });
1305
- }
1180
+ constructor(config = {}) {
1181
+ super(config);
1306
1182
  }
1307
- async exportEvent(event) {
1183
+ async _exportEvent(event) {
1308
1184
  const span = event.exportedSpan;
1309
1185
  const formatAttributes = (attributes) => {
1310
1186
  try {
@@ -2191,10 +2067,10 @@ function getValidTraceId(span) {
2191
2067
  return span?.isValid ? span.traceId : void 0;
2192
2068
  }
2193
2069
  function getOrCreateSpan(options) {
2194
- const { type, attributes, tracingContext, runtimeContext, ...rest } = options;
2070
+ const { type, attributes, tracingContext, runtimeContext, tracingOptions, ...rest } = options;
2195
2071
  const metadata = {
2196
2072
  ...rest.metadata ?? {},
2197
- ...rest.tracingOptions?.metadata ?? {}
2073
+ ...tracingOptions?.metadata ?? {}
2198
2074
  };
2199
2075
  if (tracingContext?.currentSpan) {
2200
2076
  return tracingContext.currentSpan.createChildSpan({
@@ -2212,6 +2088,10 @@ function getOrCreateSpan(options) {
2212
2088
  attributes,
2213
2089
  ...rest,
2214
2090
  metadata,
2091
+ runtimeContext,
2092
+ tracingOptions,
2093
+ traceId: tracingOptions?.traceId,
2094
+ parentSpanId: tracingOptions?.parentSpanId,
2215
2095
  customSamplerOptions: {
2216
2096
  runtimeContext,
2217
2097
  metadata
@@ -2219,6 +2099,322 @@ function getOrCreateSpan(options) {
2219
2099
  });
2220
2100
  }
2221
2101
 
2102
+ // src/ai-tracing/tracers/base.ts
2103
+ var BaseAITracing = class extends MastraBase {
2104
+ config;
2105
+ constructor(config) {
2106
+ super({ component: RegisteredLogger.AI_TRACING, name: config.serviceName });
2107
+ this.config = {
2108
+ serviceName: config.serviceName,
2109
+ name: config.name,
2110
+ sampling: config.sampling ?? { type: "always" /* ALWAYS */ },
2111
+ exporters: config.exporters ?? [],
2112
+ processors: config.processors ?? [],
2113
+ includeInternalSpans: config.includeInternalSpans ?? false,
2114
+ runtimeContextKeys: config.runtimeContextKeys ?? []
2115
+ };
2116
+ }
2117
+ /**
2118
+ * Override setLogger to add AI tracing specific initialization log
2119
+ * and propagate logger to exporters
2120
+ */
2121
+ __setLogger(logger) {
2122
+ super.__setLogger(logger);
2123
+ this.exporters.forEach((exporter) => {
2124
+ if (typeof exporter.__setLogger === "function") {
2125
+ exporter.__setLogger(logger);
2126
+ }
2127
+ });
2128
+ this.logger.debug(
2129
+ `[AI Tracing] Initialized [service=${this.config.serviceName}] [instance=${this.config.name}] [sampling=${this.config.sampling.type}]`
2130
+ );
2131
+ }
2132
+ // ============================================================================
2133
+ // Protected getters for clean config access
2134
+ // ============================================================================
2135
+ get exporters() {
2136
+ return this.config.exporters || [];
2137
+ }
2138
+ get processors() {
2139
+ return this.config.processors || [];
2140
+ }
2141
+ // ============================================================================
2142
+ // Public API - Single type-safe span creation method
2143
+ // ============================================================================
2144
+ /**
2145
+ * Start a new span of a specific AISpanType
2146
+ */
2147
+ startSpan(options) {
2148
+ const { customSamplerOptions, runtimeContext, metadata, tracingOptions, ...rest } = options;
2149
+ if (!this.shouldSample(customSamplerOptions)) {
2150
+ return new NoOpAISpan({ ...rest, metadata }, this);
2151
+ }
2152
+ let traceState;
2153
+ if (options.parent) {
2154
+ traceState = options.parent.traceState;
2155
+ } else {
2156
+ traceState = this.computeTraceState(tracingOptions);
2157
+ }
2158
+ const enrichedMetadata = this.extractMetadataFromRuntimeContext(runtimeContext, metadata, traceState);
2159
+ const span = this.createSpan({
2160
+ ...rest,
2161
+ metadata: enrichedMetadata,
2162
+ traceState
2163
+ });
2164
+ if (span.isEvent) {
2165
+ this.emitSpanEnded(span);
2166
+ } else {
2167
+ this.wireSpanLifecycle(span);
2168
+ this.emitSpanStarted(span);
2169
+ }
2170
+ return span;
2171
+ }
2172
+ // ============================================================================
2173
+ // Configuration Management
2174
+ // ============================================================================
2175
+ /**
2176
+ * Get current configuration
2177
+ */
2178
+ getConfig() {
2179
+ return { ...this.config };
2180
+ }
2181
+ // ============================================================================
2182
+ // Plugin Access
2183
+ // ============================================================================
2184
+ /**
2185
+ * Get all exporters
2186
+ */
2187
+ getExporters() {
2188
+ return [...this.exporters];
2189
+ }
2190
+ /**
2191
+ * Get all processors
2192
+ */
2193
+ getProcessors() {
2194
+ return [...this.processors];
2195
+ }
2196
+ /**
2197
+ * Get the logger instance (for exporters and other components)
2198
+ */
2199
+ getLogger() {
2200
+ return this.logger;
2201
+ }
2202
+ // ============================================================================
2203
+ // Span Lifecycle Management
2204
+ // ============================================================================
2205
+ /**
2206
+ * Automatically wires up AI tracing lifecycle events for any span
2207
+ * This ensures all spans emit events regardless of implementation
2208
+ */
2209
+ wireSpanLifecycle(span) {
2210
+ if (!this.config.includeInternalSpans && span.isInternal) {
2211
+ return;
2212
+ }
2213
+ const originalEnd = span.end.bind(span);
2214
+ const originalUpdate = span.update.bind(span);
2215
+ span.end = (options) => {
2216
+ if (span.isEvent) {
2217
+ this.logger.warn(`End event is not available on event spans`);
2218
+ return;
2219
+ }
2220
+ originalEnd(options);
2221
+ this.emitSpanEnded(span);
2222
+ };
2223
+ span.update = (options) => {
2224
+ if (span.isEvent) {
2225
+ this.logger.warn(`Update() is not available on event spans`);
2226
+ return;
2227
+ }
2228
+ originalUpdate(options);
2229
+ this.emitSpanUpdated(span);
2230
+ };
2231
+ }
2232
+ // ============================================================================
2233
+ // Utility Methods
2234
+ // ============================================================================
2235
+ /**
2236
+ * Check if an AI trace should be sampled
2237
+ */
2238
+ shouldSample(options) {
2239
+ const { sampling } = this.config;
2240
+ switch (sampling.type) {
2241
+ case "always" /* ALWAYS */:
2242
+ return true;
2243
+ case "never" /* NEVER */:
2244
+ return false;
2245
+ case "ratio" /* RATIO */:
2246
+ if (sampling.probability === void 0 || sampling.probability < 0 || sampling.probability > 1) {
2247
+ this.logger.warn(
2248
+ `Invalid sampling probability: ${sampling.probability}. Expected value between 0 and 1. Defaulting to no sampling.`
2249
+ );
2250
+ return false;
2251
+ }
2252
+ return Math.random() < sampling.probability;
2253
+ case "custom" /* CUSTOM */:
2254
+ return sampling.sampler(options);
2255
+ default:
2256
+ throw new Error(`Sampling strategy type not implemented: ${sampling.type}`);
2257
+ }
2258
+ }
2259
+ /**
2260
+ * Compute TraceState for a new trace based on configured and per-request keys
2261
+ */
2262
+ computeTraceState(tracingOptions) {
2263
+ const configuredKeys = this.config.runtimeContextKeys ?? [];
2264
+ const additionalKeys = tracingOptions?.runtimeContextKeys ?? [];
2265
+ const allKeys = [...configuredKeys, ...additionalKeys];
2266
+ if (allKeys.length === 0) {
2267
+ return void 0;
2268
+ }
2269
+ return {
2270
+ runtimeContextKeys: allKeys
2271
+ };
2272
+ }
2273
+ /**
2274
+ * Extract metadata from RuntimeContext using TraceState
2275
+ */
2276
+ extractMetadataFromRuntimeContext(runtimeContext, explicitMetadata, traceState) {
2277
+ if (!runtimeContext || !traceState || traceState.runtimeContextKeys.length === 0) {
2278
+ return explicitMetadata;
2279
+ }
2280
+ const extracted = this.extractKeys(runtimeContext, traceState.runtimeContextKeys);
2281
+ if (Object.keys(extracted).length === 0 && !explicitMetadata) {
2282
+ return void 0;
2283
+ }
2284
+ return {
2285
+ ...extracted,
2286
+ ...explicitMetadata
2287
+ // Explicit metadata always wins
2288
+ };
2289
+ }
2290
+ /**
2291
+ * Extract specific keys from RuntimeContext
2292
+ */
2293
+ extractKeys(runtimeContext, keys) {
2294
+ const result = {};
2295
+ for (const key of keys) {
2296
+ const parts = key.split(".");
2297
+ const rootKey = parts[0];
2298
+ const value = runtimeContext.get(rootKey);
2299
+ if (value !== void 0) {
2300
+ if (parts.length > 1) {
2301
+ const nestedPath = parts.slice(1).join(".");
2302
+ const nestedValue = getNestedValue(value, nestedPath);
2303
+ if (nestedValue !== void 0) {
2304
+ setNestedValue(result, key, nestedValue);
2305
+ }
2306
+ } else {
2307
+ setNestedValue(result, key, value);
2308
+ }
2309
+ }
2310
+ }
2311
+ return result;
2312
+ }
2313
+ /**
2314
+ * Process a span through all processors
2315
+ */
2316
+ processSpan(span) {
2317
+ for (const processor of this.processors) {
2318
+ if (!span) {
2319
+ break;
2320
+ }
2321
+ try {
2322
+ span = processor.process(span);
2323
+ } catch (error) {
2324
+ this.logger.error(`[AI Tracing] Processor error [name=${processor.name}]`, error);
2325
+ }
2326
+ }
2327
+ return span;
2328
+ }
2329
+ // ============================================================================
2330
+ // Event-driven Export Methods
2331
+ // ============================================================================
2332
+ getSpanForExport(span) {
2333
+ if (!span.isValid) return void 0;
2334
+ if (span.isInternal && !this.config.includeInternalSpans) return void 0;
2335
+ const processedSpan = this.processSpan(span);
2336
+ return processedSpan?.exportSpan(this.config.includeInternalSpans);
2337
+ }
2338
+ /**
2339
+ * Emit a span started event
2340
+ */
2341
+ emitSpanStarted(span) {
2342
+ const exportedSpan = this.getSpanForExport(span);
2343
+ if (exportedSpan) {
2344
+ this.exportEvent({ type: "span_started" /* SPAN_STARTED */, exportedSpan }).catch((error) => {
2345
+ this.logger.error("[AI Tracing] Failed to export span_started event", error);
2346
+ });
2347
+ }
2348
+ }
2349
+ /**
2350
+ * Emit a span ended event (called automatically when spans end)
2351
+ */
2352
+ emitSpanEnded(span) {
2353
+ const exportedSpan = this.getSpanForExport(span);
2354
+ if (exportedSpan) {
2355
+ this.exportEvent({ type: "span_ended" /* SPAN_ENDED */, exportedSpan }).catch((error) => {
2356
+ this.logger.error("[AI Tracing] Failed to export span_ended event", error);
2357
+ });
2358
+ }
2359
+ }
2360
+ /**
2361
+ * Emit a span updated event
2362
+ */
2363
+ emitSpanUpdated(span) {
2364
+ const exportedSpan = this.getSpanForExport(span);
2365
+ if (exportedSpan) {
2366
+ this.exportEvent({ type: "span_updated" /* SPAN_UPDATED */, exportedSpan }).catch((error) => {
2367
+ this.logger.error("[AI Tracing] Failed to export span_updated event", error);
2368
+ });
2369
+ }
2370
+ }
2371
+ /**
2372
+ * Export tracing event through all exporters (realtime mode)
2373
+ */
2374
+ async exportEvent(event) {
2375
+ const exportPromises = this.exporters.map(async (exporter) => {
2376
+ try {
2377
+ if (exporter.exportEvent) {
2378
+ await exporter.exportEvent(event);
2379
+ this.logger.debug(`[AI Tracing] Event exported [exporter=${exporter.name}] [type=${event.type}]`);
2380
+ }
2381
+ } catch (error) {
2382
+ this.logger.error(`[AI Tracing] Export error [exporter=${exporter.name}]`, error);
2383
+ }
2384
+ });
2385
+ await Promise.allSettled(exportPromises);
2386
+ }
2387
+ // ============================================================================
2388
+ // Lifecycle Management
2389
+ // ============================================================================
2390
+ /**
2391
+ * Initialize AI tracing (called by Mastra during component registration)
2392
+ */
2393
+ init() {
2394
+ this.logger.debug(`[AI Tracing] Initialization started [name=${this.name}]`);
2395
+ this.logger.info(`[AI Tracing] Initialized successfully [name=${this.name}]`);
2396
+ }
2397
+ /**
2398
+ * Shutdown AI tracing and clean up resources
2399
+ */
2400
+ async shutdown() {
2401
+ this.logger.debug(`[AI Tracing] Shutdown started [name=${this.name}]`);
2402
+ const shutdownPromises = [...this.exporters.map((e) => e.shutdown()), ...this.processors.map((p) => p.shutdown())];
2403
+ await Promise.allSettled(shutdownPromises);
2404
+ this.logger.info(`[AI Tracing] Shutdown completed [name=${this.name}]`);
2405
+ }
2406
+ };
2407
+
2408
+ // src/ai-tracing/tracers/default.ts
2409
+ var DefaultAITracing = class extends BaseAITracing {
2410
+ constructor(config) {
2411
+ super(config);
2412
+ }
2413
+ createSpan(options) {
2414
+ return new DefaultAISpan(options, this);
2415
+ }
2416
+ };
2417
+
2222
2418
  // src/ai-tracing/context.ts
2223
2419
  var AGENT_GETTERS = ["getAgent", "getAgentById"];
2224
2420
  var AGENT_METHODS_TO_WRAP = ["generate", "stream", "generateLegacy", "streamLegacy"];
@@ -2365,7 +2561,272 @@ function wrapRun(run, tracingContext) {
2365
2561
  return run;
2366
2562
  }
2367
2563
  }
2564
+ var ModelSpanTracker = class {
2565
+ modelSpan;
2566
+ currentStepSpan;
2567
+ currentChunkSpan;
2568
+ accumulator = {};
2569
+ stepIndex = 0;
2570
+ chunkSequence = 0;
2571
+ constructor(modelSpan) {
2572
+ this.modelSpan = modelSpan;
2573
+ }
2574
+ /**
2575
+ * Start a new Model execution step
2576
+ */
2577
+ startStepSpan(payload) {
2578
+ this.currentStepSpan = this.modelSpan?.createChildSpan({
2579
+ name: `step: ${this.stepIndex}`,
2580
+ type: "llm_step" /* LLM_STEP */,
2581
+ attributes: {
2582
+ stepIndex: this.stepIndex,
2583
+ ...payload?.messageId ? { messageId: payload.messageId } : {},
2584
+ ...payload?.warnings?.length ? { warnings: payload.warnings } : {}
2585
+ },
2586
+ input: payload?.request
2587
+ });
2588
+ this.chunkSequence = 0;
2589
+ }
2590
+ /**
2591
+ * End the current Model execution step with token usage, finish reason, output, and metadata
2592
+ */
2593
+ endStepSpan(payload) {
2594
+ if (!this.currentStepSpan) return;
2595
+ const output = payload.output;
2596
+ const { usage, ...otherOutput } = output;
2597
+ const stepResult = payload.stepResult;
2598
+ const metadata = payload.metadata;
2599
+ const cleanMetadata = metadata ? { ...metadata } : void 0;
2600
+ if (cleanMetadata?.request) {
2601
+ delete cleanMetadata.request;
2602
+ }
2603
+ this.currentStepSpan.end({
2604
+ output: otherOutput,
2605
+ attributes: {
2606
+ usage,
2607
+ isContinued: stepResult.isContinued,
2608
+ finishReason: stepResult.reason,
2609
+ warnings: stepResult.warnings
2610
+ },
2611
+ metadata: {
2612
+ ...cleanMetadata
2613
+ }
2614
+ });
2615
+ this.currentStepSpan = void 0;
2616
+ this.stepIndex++;
2617
+ }
2618
+ /**
2619
+ * Create a new chunk span (for multi-part chunks like text-start/delta/end)
2620
+ */
2621
+ startChunkSpan(chunkType, initialData) {
2622
+ if (!this.currentStepSpan) {
2623
+ this.startStepSpan();
2624
+ }
2625
+ this.currentChunkSpan = this.currentStepSpan?.createChildSpan({
2626
+ name: `chunk: '${chunkType}'`,
2627
+ type: "llm_chunk" /* LLM_CHUNK */,
2628
+ attributes: {
2629
+ chunkType,
2630
+ sequenceNumber: this.chunkSequence
2631
+ }
2632
+ });
2633
+ this.accumulator = initialData || {};
2634
+ }
2635
+ /**
2636
+ * Append string content to a specific field in the accumulator
2637
+ */
2638
+ appendToAccumulator(field, text) {
2639
+ if (this.accumulator[field] === void 0) {
2640
+ this.accumulator[field] = text;
2641
+ } else {
2642
+ this.accumulator[field] += text;
2643
+ }
2644
+ }
2645
+ /**
2646
+ * End the current chunk span.
2647
+ * Safe to call multiple times - will no-op if span already ended.
2648
+ */
2649
+ endChunkSpan(output) {
2650
+ if (!this.currentChunkSpan) return;
2651
+ this.currentChunkSpan.end({
2652
+ output: output !== void 0 ? output : this.accumulator
2653
+ });
2654
+ this.currentChunkSpan = void 0;
2655
+ this.accumulator = {};
2656
+ this.chunkSequence++;
2657
+ }
2658
+ /**
2659
+ * Create an event span (for single chunks like tool-call)
2660
+ */
2661
+ createEventSpan(chunkType, output) {
2662
+ if (!this.currentStepSpan) {
2663
+ this.startStepSpan();
2664
+ }
2665
+ const span = this.currentStepSpan?.createEventSpan({
2666
+ name: `chunk: '${chunkType}'`,
2667
+ type: "llm_chunk" /* LLM_CHUNK */,
2668
+ attributes: {
2669
+ chunkType,
2670
+ sequenceNumber: this.chunkSequence
2671
+ },
2672
+ output
2673
+ });
2674
+ if (span) {
2675
+ this.chunkSequence++;
2676
+ }
2677
+ }
2678
+ /**
2679
+ * Check if there is currently an active chunk span
2680
+ */
2681
+ hasActiveChunkSpan() {
2682
+ return !!this.currentChunkSpan;
2683
+ }
2684
+ /**
2685
+ * Get the current accumulator value
2686
+ */
2687
+ getAccumulator() {
2688
+ return this.accumulator;
2689
+ }
2690
+ /**
2691
+ * Get the current step span (for making tool calls children of steps)
2692
+ */
2693
+ getCurrentStepSpan() {
2694
+ return this.currentStepSpan;
2695
+ }
2696
+ /**
2697
+ * Wraps a stream with model tracing transform to track LLM_STEP and LLM_CHUNK spans.
2698
+ *
2699
+ * This should be added to the stream pipeline to automatically
2700
+ * create LLM_STEP and LLM_CHUNK spans for each semantic unit in the stream.
2701
+ */
2702
+ wrapStream(stream) {
2703
+ const tracker = this;
2704
+ return stream.pipeThrough(
2705
+ new TransformStream({
2706
+ transform(chunk, controller) {
2707
+ controller.enqueue(chunk);
2708
+ switch (chunk.type) {
2709
+ case "text-start":
2710
+ case "text-delta":
2711
+ case "text-end":
2712
+ handleTextChunk(chunk, tracker);
2713
+ break;
2714
+ case "tool-call-input-streaming-start":
2715
+ case "tool-call-delta":
2716
+ case "tool-call-input-streaming-end":
2717
+ case "tool-call":
2718
+ handleToolCallChunk(chunk, tracker);
2719
+ break;
2720
+ case "reasoning-start":
2721
+ case "reasoning-delta":
2722
+ case "reasoning-end":
2723
+ handleReasoningChunk(chunk, tracker);
2724
+ break;
2725
+ case "object":
2726
+ case "object-result":
2727
+ handleObjectChunk(chunk, tracker);
2728
+ break;
2729
+ case "step-start":
2730
+ tracker.startStepSpan(chunk.payload);
2731
+ break;
2732
+ case "step-finish":
2733
+ tracker.endStepSpan(chunk.payload);
2734
+ break;
2735
+ case "raw":
2736
+ // Skip raw chunks as they're redundant
2737
+ case "start":
2738
+ case "finish":
2739
+ break;
2740
+ // Default: auto-create event span for all other chunk types
2741
+ default: {
2742
+ let outputPayload = chunk.payload;
2743
+ if (outputPayload && typeof outputPayload === "object" && "data" in outputPayload) {
2744
+ const typedPayload = outputPayload;
2745
+ outputPayload = { ...typedPayload };
2746
+ if (typedPayload.data) {
2747
+ outputPayload.size = typeof typedPayload.data === "string" ? typedPayload.data.length : typedPayload.data instanceof Uint8Array ? typedPayload.data.length : void 0;
2748
+ delete outputPayload.data;
2749
+ }
2750
+ }
2751
+ tracker.createEventSpan(chunk.type, outputPayload);
2752
+ break;
2753
+ }
2754
+ }
2755
+ }
2756
+ })
2757
+ );
2758
+ }
2759
+ };
2760
+ function handleTextChunk(chunk, tracker) {
2761
+ switch (chunk.type) {
2762
+ case "text-start":
2763
+ tracker.startChunkSpan("text");
2764
+ break;
2765
+ case "text-delta":
2766
+ tracker.appendToAccumulator("text", chunk.payload.text);
2767
+ break;
2768
+ case "text-end": {
2769
+ tracker.endChunkSpan();
2770
+ break;
2771
+ }
2772
+ }
2773
+ }
2774
+ function handleReasoningChunk(chunk, tracker) {
2775
+ switch (chunk.type) {
2776
+ case "reasoning-start":
2777
+ tracker.startChunkSpan("reasoning");
2778
+ break;
2779
+ case "reasoning-delta":
2780
+ tracker.appendToAccumulator("text", chunk.payload.text);
2781
+ break;
2782
+ case "reasoning-end": {
2783
+ tracker.endChunkSpan();
2784
+ break;
2785
+ }
2786
+ }
2787
+ }
2788
+ function handleToolCallChunk(chunk, tracker) {
2789
+ switch (chunk.type) {
2790
+ case "tool-call-input-streaming-start":
2791
+ tracker.startChunkSpan("tool-call", {
2792
+ toolName: chunk.payload.toolName,
2793
+ toolCallId: chunk.payload.toolCallId
2794
+ });
2795
+ break;
2796
+ case "tool-call-delta":
2797
+ tracker.appendToAccumulator("toolInput", chunk.payload.argsTextDelta);
2798
+ break;
2799
+ case "tool-call-input-streaming-end":
2800
+ case "tool-call": {
2801
+ const acc = tracker.getAccumulator();
2802
+ let toolInput;
2803
+ try {
2804
+ toolInput = acc.toolInput ? JSON.parse(acc.toolInput) : {};
2805
+ } catch {
2806
+ toolInput = acc.toolInput;
2807
+ }
2808
+ tracker.endChunkSpan({
2809
+ toolName: acc.toolName,
2810
+ toolCallId: acc.toolCallId,
2811
+ toolInput
2812
+ });
2813
+ break;
2814
+ }
2815
+ }
2816
+ }
2817
+ function handleObjectChunk(chunk, tracker) {
2818
+ switch (chunk.type) {
2819
+ case "object":
2820
+ if (!tracker.hasActiveChunkSpan()) {
2821
+ tracker.startChunkSpan("object");
2822
+ }
2823
+ break;
2824
+ case "object-result":
2825
+ tracker.endChunkSpan(chunk.object);
2826
+ break;
2827
+ }
2828
+ }
2368
2829
 
2369
- export { AISpanType, AITracingEventType, BaseAISpan, BaseAITracing, CloudExporter, ConsoleExporter, DefaultAISpan, DefaultAITracing, DefaultExporter, InternalSpans, NoOpAISpan, SamplingStrategyType, SensitiveDataFilter, checkEvalStorageFields, clearAITracingRegistry, createMastraProxy, deepClean, deepMerge, delay, ensureToolProperties, fetchWithRetry, generateEmptyFromSchema, getAITracing, getAllAITracing, getDefaultAITracing, getOrCreateSpan, getSelectedAITracing, getValidTraceId, hasAITracing, isCoreMessage, isMastra, isUiMessage, isZodType, makeCoreTool, makeCoreToolV5, maskStreamTags, omitKeys, parseFieldKey, parseSqlIdentifier, registerAITracing, resolveSerializedZodOutput, selectFields, setSelector, setupAITracing, shutdownAITracingRegistry, unregisterAITracing, wrapMastra };
2370
- //# sourceMappingURL=chunk-BLVB2IJK.js.map
2371
- //# sourceMappingURL=chunk-BLVB2IJK.js.map
2830
+ export { AISpanType, AITracingEventType, BaseAISpan, BaseAITracing, BaseExporter, CloudExporter, ConsoleExporter, DefaultAISpan, DefaultAITracing, DefaultExporter, InternalSpans, ModelSpanTracker, NoOpAISpan, SamplingStrategyType, SensitiveDataFilter, checkEvalStorageFields, clearAITracingRegistry, createMastraProxy, deepClean, deepMerge, delay, ensureToolProperties, fetchWithRetry, generateEmptyFromSchema, getAITracing, getAllAITracing, getDefaultAITracing, getNestedValue, getOrCreateSpan, getSelectedAITracing, getValidTraceId, hasAITracing, isCoreMessage, isMastra, isUiMessage, isZodType, makeCoreTool, makeCoreToolV5, maskStreamTags, omitKeys, parseFieldKey, parseSqlIdentifier, registerAITracing, resolveSerializedZodOutput, selectFields, setNestedValue, setSelector, setupAITracing, shutdownAITracingRegistry, unregisterAITracing, wrapMastra };
2831
+ //# sourceMappingURL=chunk-3CVE7NQC.js.map
2832
+ //# sourceMappingURL=chunk-3CVE7NQC.js.map