@mastra/core 1.3.0 → 1.4.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 (274) hide show
  1. package/CHANGELOG.md +462 -0
  2. package/datasets.d.ts +1 -0
  3. package/dist/agent/agent.d.ts +1 -1
  4. package/dist/agent/index.cjs +13 -13
  5. package/dist/agent/index.js +2 -2
  6. package/dist/agent/message-list/adapters/AIV4Adapter.d.ts.map +1 -1
  7. package/dist/agent/message-list/adapters/AIV5Adapter.d.ts.map +1 -1
  8. package/dist/agent/message-list/conversion/output-converter.d.ts +2 -1
  9. package/dist/agent/message-list/conversion/output-converter.d.ts.map +1 -1
  10. package/dist/agent/message-list/index.cjs +18 -18
  11. package/dist/agent/message-list/index.js +1 -1
  12. package/dist/agent/workflows/prepare-stream/index.d.ts +1 -1
  13. package/dist/chunk-3JVFFAJX.cjs +1207 -0
  14. package/dist/chunk-3JVFFAJX.cjs.map +1 -0
  15. package/dist/{chunk-WL3AW3YA.js → chunk-3X3CZUXI.js} +4070 -3983
  16. package/dist/chunk-3X3CZUXI.js.map +1 -0
  17. package/dist/{chunk-2GWTJFVM.js → chunk-4EHGOATH.js} +46 -14
  18. package/dist/chunk-4EHGOATH.js.map +1 -0
  19. package/dist/{chunk-YNXIGRQE.cjs → chunk-4IJ4UDZX.cjs} +319 -83
  20. package/dist/chunk-4IJ4UDZX.cjs.map +1 -0
  21. package/dist/{chunk-CGPH7CMG.cjs → chunk-4KFEMXTV.cjs} +46 -14
  22. package/dist/chunk-4KFEMXTV.cjs.map +1 -0
  23. package/dist/{chunk-PHYJYZ32.js → chunk-4TQ4EBYX.js} +16 -8
  24. package/dist/chunk-4TQ4EBYX.js.map +1 -0
  25. package/dist/{chunk-SIZEIYNH.js → chunk-4XSAZPPS.js} +254 -18
  26. package/dist/chunk-4XSAZPPS.js.map +1 -0
  27. package/dist/{chunk-KUTU2YZF.js → chunk-5Q5Y34SS.js} +5 -5
  28. package/dist/{chunk-KUTU2YZF.js.map → chunk-5Q5Y34SS.js.map} +1 -1
  29. package/dist/{chunk-EH6SAGEO.cjs → chunk-64WGYTQK.cjs} +72 -53
  30. package/dist/{chunk-EH6SAGEO.cjs.map → chunk-64WGYTQK.cjs.map} +1 -1
  31. package/dist/{chunk-OOCEAC6U.cjs → chunk-65PHUUMF.cjs} +3 -3
  32. package/dist/{chunk-OOCEAC6U.cjs.map → chunk-65PHUUMF.cjs.map} +1 -1
  33. package/dist/{chunk-JNE2ABVB.js → chunk-7NKUSQEV.js} +1094 -10
  34. package/dist/chunk-7NKUSQEV.js.map +1 -0
  35. package/dist/{chunk-ZHFM7HCQ.js → chunk-AXHBJ4GX.js} +3 -3
  36. package/dist/{chunk-ZHFM7HCQ.js.map → chunk-AXHBJ4GX.js.map} +1 -1
  37. package/dist/{chunk-ILQXPZCD.js → chunk-AY6DBRS3.js} +37 -21
  38. package/dist/chunk-AY6DBRS3.js.map +1 -0
  39. package/dist/{chunk-TERSHTY5.cjs → chunk-BP7VYTOP.cjs} +1116 -21
  40. package/dist/chunk-BP7VYTOP.cjs.map +1 -0
  41. package/dist/{chunk-UE2G2LRP.cjs → chunk-CZ4NQANZ.cjs} +37 -21
  42. package/dist/chunk-CZ4NQANZ.cjs.map +1 -0
  43. package/dist/{chunk-NCC45KOB.cjs → chunk-DBSVT6AR.cjs} +7 -7
  44. package/dist/{chunk-NCC45KOB.cjs.map → chunk-DBSVT6AR.cjs.map} +1 -1
  45. package/dist/{chunk-BXLLXTT4.js → chunk-FLPEGTEK.js} +4 -4
  46. package/dist/{chunk-BXLLXTT4.js.map → chunk-FLPEGTEK.js.map} +1 -1
  47. package/dist/{chunk-ON2KVIUJ.cjs → chunk-HYRYTTMT.cjs} +7 -7
  48. package/dist/{chunk-ON2KVIUJ.cjs.map → chunk-HYRYTTMT.cjs.map} +1 -1
  49. package/dist/chunk-NJ7TL3LQ.js +1196 -0
  50. package/dist/chunk-NJ7TL3LQ.js.map +1 -0
  51. package/dist/{chunk-EUG4AON3.cjs → chunk-NKYWDNCI.cjs} +8 -7
  52. package/dist/{chunk-EUG4AON3.cjs.map → chunk-NKYWDNCI.cjs.map} +1 -1
  53. package/dist/{chunk-UHVG25VW.cjs → chunk-NZG2JAKS.cjs} +23 -15
  54. package/dist/chunk-NZG2JAKS.cjs.map +1 -0
  55. package/dist/{chunk-44SUGDBR.js → chunk-PS5ONCXY.js} +109 -5
  56. package/dist/chunk-PS5ONCXY.js.map +1 -0
  57. package/dist/{chunk-57QAF2ZQ.js → chunk-QTTWRCB5.js} +4 -4
  58. package/dist/{chunk-57QAF2ZQ.js.map → chunk-QTTWRCB5.js.map} +1 -1
  59. package/dist/{chunk-VM25PDSW.js → chunk-RZ4CIIZR.js} +4 -4
  60. package/dist/{chunk-VM25PDSW.js.map → chunk-RZ4CIIZR.js.map} +1 -1
  61. package/dist/{chunk-C3XU7ZDC.cjs → chunk-SU5APAM6.cjs} +123 -4
  62. package/dist/chunk-SU5APAM6.cjs.map +1 -0
  63. package/dist/{chunk-3MJCJLZS.js → chunk-U2HKJZCI.js} +24 -5
  64. package/dist/{chunk-3MJCJLZS.js.map → chunk-U2HKJZCI.js.map} +1 -1
  65. package/dist/{chunk-GCTAD6B7.cjs → chunk-VD5YA6RH.cjs} +12 -12
  66. package/dist/{chunk-GCTAD6B7.cjs.map → chunk-VD5YA6RH.cjs.map} +1 -1
  67. package/dist/{chunk-KAJNBNWP.cjs → chunk-YNNJLLFN.cjs} +4071 -3984
  68. package/dist/chunk-YNNJLLFN.cjs.map +1 -0
  69. package/dist/datasets/dataset.d.ts +153 -0
  70. package/dist/datasets/dataset.d.ts.map +1 -0
  71. package/dist/datasets/experiment/analytics/aggregate.d.ts +46 -0
  72. package/dist/datasets/experiment/analytics/aggregate.d.ts.map +1 -0
  73. package/dist/datasets/experiment/analytics/compare.d.ts +33 -0
  74. package/dist/datasets/experiment/analytics/compare.d.ts.map +1 -0
  75. package/dist/datasets/experiment/analytics/index.d.ts +9 -0
  76. package/dist/datasets/experiment/analytics/index.d.ts.map +1 -0
  77. package/dist/datasets/experiment/analytics/types.d.ts +103 -0
  78. package/dist/datasets/experiment/analytics/types.d.ts.map +1 -0
  79. package/dist/datasets/experiment/executor.d.ts +40 -0
  80. package/dist/datasets/experiment/executor.d.ts.map +1 -0
  81. package/dist/datasets/experiment/index.d.ts +31 -0
  82. package/dist/datasets/experiment/index.d.ts.map +1 -0
  83. package/dist/datasets/experiment/scorer.d.ts +21 -0
  84. package/dist/datasets/experiment/scorer.d.ts.map +1 -0
  85. package/dist/datasets/experiment/types.d.ts +140 -0
  86. package/dist/datasets/experiment/types.d.ts.map +1 -0
  87. package/dist/datasets/index.cjs +69 -0
  88. package/dist/datasets/index.cjs.map +1 -0
  89. package/dist/datasets/index.d.ts +6 -0
  90. package/dist/datasets/index.d.ts.map +1 -0
  91. package/dist/datasets/index.js +4 -0
  92. package/dist/datasets/index.js.map +1 -0
  93. package/dist/datasets/manager.d.ts +73 -0
  94. package/dist/datasets/manager.d.ts.map +1 -0
  95. package/dist/datasets/validation/errors.d.ts +44 -0
  96. package/dist/datasets/validation/errors.d.ts.map +1 -0
  97. package/dist/datasets/validation/index.d.ts +3 -0
  98. package/dist/datasets/validation/index.d.ts.map +1 -0
  99. package/dist/datasets/validation/validator.d.ts +24 -0
  100. package/dist/datasets/validation/validator.d.ts.map +1 -0
  101. package/dist/docs/SKILL.md +1 -3
  102. package/dist/docs/assets/SOURCE_MAP.json +436 -346
  103. package/dist/docs/references/docs-memory-observational-memory.md +86 -11
  104. package/dist/docs/references/docs-streaming-events.md +23 -0
  105. package/dist/docs/references/docs-workspace-filesystem.md +72 -1
  106. package/dist/docs/references/docs-workspace-overview.md +95 -12
  107. package/dist/docs/references/docs-workspace-sandbox.md +2 -0
  108. package/dist/docs/references/guides-agent-frameworks-ai-sdk.md +6 -2
  109. package/dist/docs/references/reference-ai-sdk-with-mastra.md +1 -1
  110. package/dist/docs/references/reference-memory-observational-memory.md +318 -9
  111. package/dist/docs/references/reference-streaming-workflows-stream.md +1 -0
  112. package/dist/docs/references/reference-workflows-workflow-methods-foreach.md +30 -0
  113. package/dist/docs/references/reference.md +3 -0
  114. package/dist/editor/index.d.ts +1 -1
  115. package/dist/editor/index.d.ts.map +1 -1
  116. package/dist/editor/types.d.ts +21 -3
  117. package/dist/editor/types.d.ts.map +1 -1
  118. package/dist/evals/index.cjs +20 -20
  119. package/dist/evals/index.js +3 -3
  120. package/dist/evals/scoreTraces/index.cjs +5 -5
  121. package/dist/evals/scoreTraces/index.js +2 -2
  122. package/dist/features/index.cjs +1 -1
  123. package/dist/features/index.cjs.map +1 -1
  124. package/dist/features/index.d.ts.map +1 -1
  125. package/dist/features/index.js +1 -1
  126. package/dist/features/index.js.map +1 -1
  127. package/dist/index.cjs +2 -7
  128. package/dist/index.d.ts +0 -9
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +1 -2
  131. package/dist/llm/index.cjs +10 -10
  132. package/dist/llm/index.js +2 -2
  133. package/dist/llm/model/provider-types.generated.d.ts +1694 -1659
  134. package/dist/loop/index.cjs +12 -12
  135. package/dist/loop/index.js +1 -1
  136. package/dist/loop/network/index.d.ts +1 -1
  137. package/dist/loop/workflows/agentic-execution/index.d.ts +1 -1
  138. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts.map +1 -1
  139. package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts.map +1 -1
  140. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts.map +1 -1
  141. package/dist/loop/workflows/agentic-loop/index.d.ts +1 -1
  142. package/dist/loop/workflows/errors.d.ts +4 -0
  143. package/dist/loop/workflows/errors.d.ts.map +1 -0
  144. package/dist/mastra/index.cjs +2 -2
  145. package/dist/mastra/index.d.ts +2 -0
  146. package/dist/mastra/index.d.ts.map +1 -1
  147. package/dist/mastra/index.js +1 -1
  148. package/dist/memory/index.cjs +14 -14
  149. package/dist/memory/index.js +1 -1
  150. package/dist/memory/memory.d.ts +5 -0
  151. package/dist/memory/memory.d.ts.map +1 -1
  152. package/dist/memory/types.d.ts +56 -0
  153. package/dist/memory/types.d.ts.map +1 -1
  154. package/dist/processors/index.cjs +41 -41
  155. package/dist/processors/index.js +1 -1
  156. package/dist/processors/processors/skills.d.ts +1 -1
  157. package/dist/processors/processors/skills.d.ts.map +1 -1
  158. package/dist/processors/runner.d.ts.map +1 -1
  159. package/dist/processors/trailing-assistant-guard.d.ts +34 -0
  160. package/dist/processors/trailing-assistant-guard.d.ts.map +1 -0
  161. package/dist/provider-registry-6LZAGQET.cjs +40 -0
  162. package/dist/{provider-registry-C6XCYX44.cjs.map → provider-registry-6LZAGQET.cjs.map} +1 -1
  163. package/dist/provider-registry-QUNT7S55.js +3 -0
  164. package/dist/{provider-registry-NWU4YFQW.js.map → provider-registry-QUNT7S55.js.map} +1 -1
  165. package/dist/provider-registry.json +4068 -3981
  166. package/dist/relevance/index.cjs +3 -3
  167. package/dist/relevance/index.js +1 -1
  168. package/dist/storage/base.d.ts +4 -1
  169. package/dist/storage/base.d.ts.map +1 -1
  170. package/dist/storage/constants.cjs +87 -27
  171. package/dist/storage/constants.d.ts +21 -2
  172. package/dist/storage/constants.d.ts.map +1 -1
  173. package/dist/storage/constants.js +1 -1
  174. package/dist/storage/domains/agents/inmemory.d.ts.map +1 -1
  175. package/dist/storage/domains/datasets/base.d.ts +83 -0
  176. package/dist/storage/domains/datasets/base.d.ts.map +1 -0
  177. package/dist/storage/domains/datasets/index.d.ts +3 -0
  178. package/dist/storage/domains/datasets/index.d.ts.map +1 -0
  179. package/dist/storage/domains/datasets/inmemory.d.ts +40 -0
  180. package/dist/storage/domains/datasets/inmemory.d.ts.map +1 -0
  181. package/dist/storage/domains/experiments/base.d.ts +28 -0
  182. package/dist/storage/domains/experiments/base.d.ts.map +1 -0
  183. package/dist/storage/domains/experiments/index.d.ts +3 -0
  184. package/dist/storage/domains/experiments/index.d.ts.map +1 -0
  185. package/dist/storage/domains/experiments/inmemory.d.ts +28 -0
  186. package/dist/storage/domains/experiments/inmemory.d.ts.map +1 -0
  187. package/dist/storage/domains/index.d.ts +3 -0
  188. package/dist/storage/domains/index.d.ts.map +1 -1
  189. package/dist/storage/domains/inmemory-db.d.ts +9 -1
  190. package/dist/storage/domains/inmemory-db.d.ts.map +1 -1
  191. package/dist/storage/domains/mcp-clients/base.d.ts +47 -0
  192. package/dist/storage/domains/mcp-clients/base.d.ts.map +1 -0
  193. package/dist/storage/domains/mcp-clients/index.d.ts +3 -0
  194. package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -0
  195. package/dist/storage/domains/mcp-clients/inmemory.d.ts +31 -0
  196. package/dist/storage/domains/mcp-clients/inmemory.d.ts.map +1 -0
  197. package/dist/storage/domains/operations/inmemory.d.ts.map +1 -1
  198. package/dist/storage/index.cjs +201 -117
  199. package/dist/storage/index.js +2 -2
  200. package/dist/storage/mock.d.ts.map +1 -1
  201. package/dist/storage/types.d.ts +338 -3
  202. package/dist/storage/types.d.ts.map +1 -1
  203. package/dist/stream/base/output.d.ts.map +1 -1
  204. package/dist/stream/index.cjs +11 -11
  205. package/dist/stream/index.js +2 -2
  206. package/dist/stream/types.d.ts +15 -0
  207. package/dist/stream/types.d.ts.map +1 -1
  208. package/dist/test-utils/llm-mock.cjs +4 -4
  209. package/dist/test-utils/llm-mock.js +1 -1
  210. package/dist/tool-loop-agent/index.cjs +4 -4
  211. package/dist/tool-loop-agent/index.js +1 -1
  212. package/dist/tool-provider/index.cjs +4 -0
  213. package/dist/tool-provider/index.cjs.map +1 -0
  214. package/dist/tool-provider/index.d.ts +2 -0
  215. package/dist/tool-provider/index.d.ts.map +1 -0
  216. package/dist/tool-provider/index.js +3 -0
  217. package/dist/tool-provider/index.js.map +1 -0
  218. package/dist/tool-provider/types.d.ts +113 -0
  219. package/dist/tool-provider/types.d.ts.map +1 -0
  220. package/dist/utils.cjs +23 -23
  221. package/dist/utils.d.ts +1 -1
  222. package/dist/utils.d.ts.map +1 -1
  223. package/dist/utils.js +1 -1
  224. package/dist/vector/index.cjs +7 -7
  225. package/dist/vector/index.js +1 -1
  226. package/dist/workflows/evented/index.cjs +10 -10
  227. package/dist/workflows/evented/index.js +1 -1
  228. package/dist/workflows/evented/workflow-event-processor/index.d.ts.map +1 -1
  229. package/dist/workflows/handlers/control-flow.d.ts.map +1 -1
  230. package/dist/workflows/index.cjs +25 -25
  231. package/dist/workflows/index.js +1 -1
  232. package/dist/workflows/workflow.d.ts +2 -2
  233. package/dist/workflows/workflow.d.ts.map +1 -1
  234. package/dist/workspace/filesystem/filesystem.d.ts +5 -15
  235. package/dist/workspace/filesystem/filesystem.d.ts.map +1 -1
  236. package/dist/workspace/filesystem/local-filesystem.d.ts +18 -2
  237. package/dist/workspace/filesystem/local-filesystem.d.ts.map +1 -1
  238. package/dist/workspace/filesystem/mastra-filesystem.d.ts +21 -1
  239. package/dist/workspace/filesystem/mastra-filesystem.d.ts.map +1 -1
  240. package/dist/workspace/index.cjs +41 -41
  241. package/dist/workspace/index.d.ts +1 -1
  242. package/dist/workspace/index.d.ts.map +1 -1
  243. package/dist/workspace/index.js +1 -1
  244. package/dist/workspace/lifecycle.d.ts +49 -53
  245. package/dist/workspace/lifecycle.d.ts.map +1 -1
  246. package/dist/workspace/sandbox/local-sandbox.d.ts +1 -1
  247. package/dist/workspace/sandbox/local-sandbox.d.ts.map +1 -1
  248. package/dist/workspace/sandbox/mastra-sandbox.d.ts +3 -2
  249. package/dist/workspace/sandbox/mastra-sandbox.d.ts.map +1 -1
  250. package/dist/workspace/sandbox/sandbox.d.ts +3 -4
  251. package/dist/workspace/sandbox/sandbox.d.ts.map +1 -1
  252. package/dist/workspace/workspace.d.ts +2 -15
  253. package/dist/workspace/workspace.d.ts.map +1 -1
  254. package/package.json +7 -7
  255. package/src/llm/model/provider-types.generated.d.ts +1694 -1659
  256. package/tool-provider.d.ts +1 -0
  257. package/dist/chunk-2GWTJFVM.js.map +0 -1
  258. package/dist/chunk-44SUGDBR.js.map +0 -1
  259. package/dist/chunk-C3XU7ZDC.cjs.map +0 -1
  260. package/dist/chunk-CGPH7CMG.cjs.map +0 -1
  261. package/dist/chunk-ILQXPZCD.js.map +0 -1
  262. package/dist/chunk-JNE2ABVB.js.map +0 -1
  263. package/dist/chunk-KAJNBNWP.cjs.map +0 -1
  264. package/dist/chunk-PHYJYZ32.js.map +0 -1
  265. package/dist/chunk-SIZEIYNH.js.map +0 -1
  266. package/dist/chunk-TERSHTY5.cjs.map +0 -1
  267. package/dist/chunk-UE2G2LRP.cjs.map +0 -1
  268. package/dist/chunk-UHVG25VW.cjs.map +0 -1
  269. package/dist/chunk-WL3AW3YA.js.map +0 -1
  270. package/dist/chunk-YNXIGRQE.cjs.map +0 -1
  271. package/dist/docs/references/reference-cli-mastra.md +0 -336
  272. package/dist/docs/references/reference-deployer-cloudflare.md +0 -56
  273. package/dist/provider-registry-C6XCYX44.cjs +0 -40
  274. package/dist/provider-registry-NWU4YFQW.js +0 -3
@@ -0,0 +1,1196 @@
1
+ import { validateAndSaveScore } from './chunk-5Q5Y34SS.js';
2
+ import { isSupportedLanguageModel } from './chunk-4XSAZPPS.js';
3
+ import { MastraError } from './chunk-FJEVLHJT.js';
4
+ import { isZodType } from '@mastra/schema-compat';
5
+ import { zodToJsonSchema } from '@mastra/schema-compat/zod-to-json';
6
+
7
+ // src/datasets/experiment/executor.ts
8
+ async function executeScorer(scorer, item) {
9
+ try {
10
+ const result = await scorer.run(item.input);
11
+ const score = typeof result.score === "number" && !isNaN(result.score) ? result.score : null;
12
+ if (score === null && result.score !== void 0) {
13
+ console.warn(`Scorer ${scorer.id} returned invalid score: ${result.score}`);
14
+ }
15
+ return {
16
+ output: {
17
+ score,
18
+ reason: typeof result.reason === "string" ? result.reason : null
19
+ },
20
+ error: null,
21
+ traceId: null
22
+ // Scorers don't produce traces
23
+ };
24
+ } catch (error) {
25
+ return {
26
+ output: null,
27
+ error: {
28
+ message: error instanceof Error ? error.message : String(error),
29
+ stack: error instanceof Error ? error.stack : void 0
30
+ },
31
+ traceId: null
32
+ };
33
+ }
34
+ }
35
+ async function executeTarget(target, targetType, item, options) {
36
+ try {
37
+ const signal = options?.signal;
38
+ if (signal?.aborted) {
39
+ throw signal.reason ?? new DOMException("The operation was aborted.", "AbortError");
40
+ }
41
+ let executionPromise;
42
+ switch (targetType) {
43
+ case "agent":
44
+ executionPromise = executeAgent(target, item, signal);
45
+ break;
46
+ case "workflow":
47
+ executionPromise = executeWorkflow(target, item);
48
+ break;
49
+ case "scorer":
50
+ executionPromise = executeScorer(target, item);
51
+ break;
52
+ case "processor":
53
+ throw new Error(`Target type '${targetType}' not yet supported.`);
54
+ default:
55
+ throw new Error(`Unknown target type: ${targetType}`);
56
+ }
57
+ if (signal) {
58
+ return await raceWithSignal(executionPromise, signal);
59
+ }
60
+ return await executionPromise;
61
+ } catch (error) {
62
+ return {
63
+ output: null,
64
+ error: {
65
+ message: error instanceof Error ? error.message : String(error),
66
+ stack: error instanceof Error ? error.stack : void 0
67
+ },
68
+ traceId: null
69
+ };
70
+ }
71
+ }
72
+ function raceWithSignal(promise, signal) {
73
+ if (signal.aborted) {
74
+ return Promise.reject(signal.reason ?? new DOMException("The operation was aborted.", "AbortError"));
75
+ }
76
+ return new Promise((resolve, reject) => {
77
+ const onAbort = () => {
78
+ reject(signal.reason ?? new DOMException("The operation was aborted.", "AbortError"));
79
+ };
80
+ signal.addEventListener("abort", onAbort, { once: true });
81
+ promise.then(
82
+ (value) => {
83
+ signal.removeEventListener("abort", onAbort);
84
+ resolve(value);
85
+ },
86
+ (err) => {
87
+ signal.removeEventListener("abort", onAbort);
88
+ reject(err);
89
+ }
90
+ );
91
+ });
92
+ }
93
+ async function executeAgent(agent, item, signal) {
94
+ const model = await agent.getModel();
95
+ const result = isSupportedLanguageModel(model) ? await agent.generate(item.input, {
96
+ scorers: {},
97
+ returnScorerData: true,
98
+ abortSignal: signal
99
+ }) : await agent.generateLegacy?.(item.input, {
100
+ scorers: {},
101
+ returnScorerData: true
102
+ });
103
+ if (result == null) {
104
+ throw new Error(`Agent "${agent.name}" does not support generateLegacy for this model type`);
105
+ }
106
+ const traceId = result?.traceId ?? null;
107
+ const scoringData = result?.scoringData;
108
+ return {
109
+ output: result,
110
+ error: null,
111
+ traceId,
112
+ scorerInput: scoringData?.input,
113
+ scorerOutput: scoringData?.output
114
+ };
115
+ }
116
+ async function executeWorkflow(workflow, item) {
117
+ const run = await workflow.createRun({ disableScorers: true });
118
+ const result = await run.start({
119
+ inputData: item.input
120
+ });
121
+ const traceId = result?.traceId ?? null;
122
+ if (result.status === "success") {
123
+ return { output: result.result, error: null, traceId };
124
+ }
125
+ if (result.status === "failed") {
126
+ return {
127
+ output: null,
128
+ error: { message: result.error?.message ?? "Workflow failed", stack: result.error?.stack },
129
+ traceId
130
+ };
131
+ }
132
+ if (result.status === "tripwire") {
133
+ return {
134
+ output: null,
135
+ error: { message: `Workflow tripwire: ${result.tripwire?.reason ?? "Unknown reason"}` },
136
+ traceId
137
+ };
138
+ }
139
+ if (result.status === "suspended") {
140
+ return {
141
+ output: null,
142
+ error: { message: "Workflow suspended - not yet supported in dataset experiments" },
143
+ traceId
144
+ };
145
+ }
146
+ if (result.status === "paused") {
147
+ return { output: null, error: { message: "Workflow paused - not yet supported in dataset experiments" }, traceId };
148
+ }
149
+ const _exhaustiveCheck = result;
150
+ return {
151
+ output: null,
152
+ error: { message: `Workflow ended with unexpected status: ${_exhaustiveCheck.status}` },
153
+ traceId
154
+ };
155
+ }
156
+
157
+ // src/datasets/experiment/scorer.ts
158
+ function resolveScorers(mastra, scorers) {
159
+ if (!scorers || scorers.length === 0) return [];
160
+ return scorers.map((scorer) => {
161
+ if (typeof scorer === "string") {
162
+ const resolved = mastra.getScorerById(scorer);
163
+ if (!resolved) {
164
+ console.warn(`Scorer not found: ${scorer}`);
165
+ return null;
166
+ }
167
+ return resolved;
168
+ }
169
+ return scorer;
170
+ }).filter((s) => s !== null);
171
+ }
172
+ async function runScorersForItem(scorers, item, output, storage, runId, targetType, targetId, itemId, scorerInput, scorerOutput) {
173
+ if (scorers.length === 0) return [];
174
+ const settled = await Promise.allSettled(
175
+ scorers.map(async (scorer) => {
176
+ const result = await runScorerSafe(scorer, item, output, scorerInput, scorerOutput);
177
+ if (storage && result.score !== null) {
178
+ try {
179
+ await validateAndSaveScore(storage, {
180
+ scorerId: scorer.id,
181
+ score: result.score,
182
+ reason: result.reason ?? void 0,
183
+ input: item.input,
184
+ output,
185
+ additionalContext: item.metadata,
186
+ entityType: targetType.toUpperCase(),
187
+ entityId: itemId,
188
+ source: "TEST",
189
+ runId,
190
+ scorer: {
191
+ id: scorer.id,
192
+ name: scorer.name,
193
+ description: scorer.description ?? ""
194
+ },
195
+ entity: {
196
+ id: targetId,
197
+ name: targetId
198
+ }
199
+ });
200
+ } catch (saveError) {
201
+ console.warn(`Failed to save score for scorer ${scorer.id}:`, saveError);
202
+ }
203
+ }
204
+ return result;
205
+ })
206
+ );
207
+ return settled.map(
208
+ (s, i) => s.status === "fulfilled" ? s.value : { scorerId: scorers[i].id, scorerName: scorers[i].name, score: null, reason: null, error: String(s.reason) }
209
+ );
210
+ }
211
+ async function runScorerSafe(scorer, item, output, scorerInput, scorerOutput) {
212
+ try {
213
+ const scoreResult = await scorer.run({
214
+ input: scorerInput ?? item.input,
215
+ output: scorerOutput ?? output,
216
+ groundTruth: item.groundTruth
217
+ });
218
+ const score = scoreResult.score;
219
+ const reason = scoreResult.reason;
220
+ return {
221
+ scorerId: scorer.id,
222
+ scorerName: scorer.name,
223
+ score: typeof score === "number" ? score : null,
224
+ reason: typeof reason === "string" ? reason : null,
225
+ error: null
226
+ };
227
+ } catch (error) {
228
+ return {
229
+ scorerId: scorer.id,
230
+ scorerName: scorer.name,
231
+ score: null,
232
+ reason: null,
233
+ error: error instanceof Error ? error.message : String(error)
234
+ };
235
+ }
236
+ }
237
+
238
+ // src/datasets/experiment/analytics/aggregate.ts
239
+ function computeMean(values) {
240
+ if (values.length === 0) {
241
+ return 0;
242
+ }
243
+ const sum = values.reduce((acc, val) => acc + val, 0);
244
+ return sum / values.length;
245
+ }
246
+ function computeScorerStats(scores, passThreshold = 0.5) {
247
+ const totalItems = scores.length;
248
+ if (totalItems === 0) {
249
+ return {
250
+ errorRate: 0,
251
+ errorCount: 0,
252
+ passRate: 0,
253
+ passCount: 0,
254
+ avgScore: 0,
255
+ scoreCount: 0,
256
+ totalItems: 0
257
+ };
258
+ }
259
+ const validScores = [];
260
+ let errorCount = 0;
261
+ for (const score of scores) {
262
+ if (score.score === null || score.score === void 0) {
263
+ errorCount++;
264
+ } else {
265
+ validScores.push(score.score);
266
+ }
267
+ }
268
+ const scoreCount = validScores.length;
269
+ const errorRate = errorCount / totalItems;
270
+ const passCount = validScores.filter((s) => s >= passThreshold).length;
271
+ const passRate = scoreCount > 0 ? passCount / scoreCount : 0;
272
+ const avgScore = computeMean(validScores);
273
+ return {
274
+ errorRate,
275
+ errorCount,
276
+ passRate,
277
+ passCount,
278
+ avgScore,
279
+ scoreCount,
280
+ totalItems
281
+ };
282
+ }
283
+ function isRegression(delta, threshold, direction = "higher-is-better") {
284
+ if (direction === "higher-is-better") {
285
+ return delta < -threshold;
286
+ } else {
287
+ return delta > threshold;
288
+ }
289
+ }
290
+
291
+ // src/datasets/experiment/analytics/compare.ts
292
+ var DEFAULT_THRESHOLD = {
293
+ value: 0,
294
+ direction: "higher-is-better"
295
+ };
296
+ var DEFAULT_PASS_THRESHOLD = 0.5;
297
+ async function compareExperiments(mastra, config) {
298
+ const { experimentIdA, experimentIdB, thresholds = {} } = config;
299
+ const warnings = [];
300
+ const storage = mastra.getStorage();
301
+ if (!storage) {
302
+ throw new Error("Storage not configured. Configure storage in Mastra instance.");
303
+ }
304
+ const experimentsStore = await storage.getStore("experiments");
305
+ const scoresStore = await storage.getStore("scores");
306
+ if (!experimentsStore) {
307
+ throw new Error("ExperimentsStorage not configured.");
308
+ }
309
+ if (!scoresStore) {
310
+ throw new Error("ScoresStorage not configured.");
311
+ }
312
+ const [experimentA, experimentB] = await Promise.all([
313
+ experimentsStore.getExperimentById({ id: experimentIdA }),
314
+ experimentsStore.getExperimentById({ id: experimentIdB })
315
+ ]);
316
+ if (!experimentA) {
317
+ throw new Error(`Experiment not found: ${experimentIdA}`);
318
+ }
319
+ if (!experimentB) {
320
+ throw new Error(`Experiment not found: ${experimentIdB}`);
321
+ }
322
+ const versionMismatch = experimentA.datasetVersion !== experimentB.datasetVersion;
323
+ if (versionMismatch) {
324
+ warnings.push(
325
+ `Experiments have different dataset versions: ${experimentA.datasetVersion} vs ${experimentB.datasetVersion}`
326
+ );
327
+ }
328
+ const [resultsA, resultsB] = await Promise.all([
329
+ experimentsStore.listExperimentResults({ experimentId: experimentIdA, pagination: { page: 0, perPage: false } }),
330
+ experimentsStore.listExperimentResults({ experimentId: experimentIdB, pagination: { page: 0, perPage: false } })
331
+ ]);
332
+ const [scoresA, scoresB] = await Promise.all([
333
+ scoresStore.listScoresByRunId({ runId: experimentIdA, pagination: { page: 0, perPage: false } }),
334
+ scoresStore.listScoresByRunId({ runId: experimentIdB, pagination: { page: 0, perPage: false } })
335
+ ]);
336
+ if (resultsA.results.length === 0 && resultsB.results.length === 0) {
337
+ warnings.push("Both experiments have no results.");
338
+ return buildEmptyResult(experimentA, experimentB, versionMismatch, warnings);
339
+ }
340
+ if (resultsA.results.length === 0) {
341
+ warnings.push("Experiment A has no results.");
342
+ }
343
+ if (resultsB.results.length === 0) {
344
+ warnings.push("Experiment B has no results.");
345
+ }
346
+ const itemIdsA = new Set(resultsA.results.map((r) => r.itemId));
347
+ const itemIdsB = new Set(resultsB.results.map((r) => r.itemId));
348
+ const overlappingItemIds = [...itemIdsA].filter((id) => itemIdsB.has(id));
349
+ if (overlappingItemIds.length === 0) {
350
+ warnings.push("No overlapping items between experiments.");
351
+ }
352
+ const scoresMapA = groupScoresByScorerAndItem(scoresA.scores);
353
+ const scoresMapB = groupScoresByScorerAndItem(scoresB.scores);
354
+ const allScorerIds = /* @__PURE__ */ new Set([...Object.keys(scoresMapA), ...Object.keys(scoresMapB)]);
355
+ const scorers = {};
356
+ let hasRegression = false;
357
+ for (const scorerId of allScorerIds) {
358
+ const scorerScoresA = scoresMapA[scorerId] ?? {};
359
+ const scorerScoresB = scoresMapB[scorerId] ?? {};
360
+ const scoresArrayA = Object.values(scorerScoresA);
361
+ const scoresArrayB = Object.values(scorerScoresB);
362
+ const thresholdConfig = thresholds[scorerId] ?? DEFAULT_THRESHOLD;
363
+ const threshold = thresholdConfig.value;
364
+ const direction = thresholdConfig.direction ?? "higher-is-better";
365
+ const statsA = computeScorerStats(scoresArrayA, DEFAULT_PASS_THRESHOLD);
366
+ const statsB = computeScorerStats(scoresArrayB, DEFAULT_PASS_THRESHOLD);
367
+ const delta = statsB.avgScore - statsA.avgScore;
368
+ const regressed = isRegression(delta, threshold, direction);
369
+ if (regressed) {
370
+ hasRegression = true;
371
+ }
372
+ scorers[scorerId] = {
373
+ statsA,
374
+ statsB,
375
+ delta,
376
+ regressed,
377
+ threshold
378
+ };
379
+ }
380
+ const allItemIds = /* @__PURE__ */ new Set([...itemIdsA, ...itemIdsB]);
381
+ const items = [];
382
+ for (const itemId of allItemIds) {
383
+ const inBothExperiments = itemIdsA.has(itemId) && itemIdsB.has(itemId);
384
+ const itemScoresA = {};
385
+ const itemScoresB = {};
386
+ for (const scorerId of allScorerIds) {
387
+ const scoreA = scoresMapA[scorerId]?.[itemId];
388
+ const scoreB = scoresMapB[scorerId]?.[itemId];
389
+ itemScoresA[scorerId] = scoreA?.score ?? null;
390
+ itemScoresB[scorerId] = scoreB?.score ?? null;
391
+ }
392
+ items.push({
393
+ itemId,
394
+ inBothExperiments,
395
+ scoresA: itemScoresA,
396
+ scoresB: itemScoresB
397
+ });
398
+ }
399
+ return {
400
+ experimentA: {
401
+ id: experimentA.id,
402
+ datasetVersion: experimentA.datasetVersion
403
+ },
404
+ experimentB: {
405
+ id: experimentB.id,
406
+ datasetVersion: experimentB.datasetVersion
407
+ },
408
+ versionMismatch,
409
+ hasRegression,
410
+ scorers,
411
+ items,
412
+ warnings
413
+ };
414
+ }
415
+ function groupScoresByScorerAndItem(scores) {
416
+ const result = {};
417
+ for (const score of scores) {
418
+ const scorerId = score.scorerId;
419
+ const itemId = score.entityId;
420
+ if (!result[scorerId]) {
421
+ result[scorerId] = {};
422
+ }
423
+ result[scorerId][itemId] = score;
424
+ }
425
+ return result;
426
+ }
427
+ function buildEmptyResult(experimentA, experimentB, versionMismatch, warnings) {
428
+ return {
429
+ experimentA: {
430
+ id: experimentA.id,
431
+ datasetVersion: experimentA.datasetVersion
432
+ },
433
+ experimentB: {
434
+ id: experimentB.id,
435
+ datasetVersion: experimentB.datasetVersion
436
+ },
437
+ versionMismatch,
438
+ hasRegression: false,
439
+ scorers: {},
440
+ items: [],
441
+ warnings
442
+ };
443
+ }
444
+
445
+ // src/datasets/experiment/index.ts
446
+ async function runExperiment(mastra, config) {
447
+ const {
448
+ datasetId,
449
+ targetType,
450
+ targetId,
451
+ scorers: scorerInput,
452
+ version,
453
+ maxConcurrency = 5,
454
+ signal,
455
+ itemTimeout,
456
+ maxRetries = 0,
457
+ experimentId: providedExperimentId,
458
+ name,
459
+ description,
460
+ metadata
461
+ } = config;
462
+ const startedAt = /* @__PURE__ */ new Date();
463
+ const experimentId = providedExperimentId ?? crypto.randomUUID();
464
+ const storage = mastra.getStorage();
465
+ const datasetsStore = await storage?.getStore("datasets");
466
+ const experimentsStore = await storage?.getStore("experiments");
467
+ let items;
468
+ let datasetVersion;
469
+ if (config.data) {
470
+ const rawData = typeof config.data === "function" ? await config.data() : config.data;
471
+ items = rawData.map((dataItem) => {
472
+ const id = dataItem.id ?? crypto.randomUUID();
473
+ return {
474
+ id,
475
+ datasetVersion: null,
476
+ input: dataItem.input,
477
+ groundTruth: dataItem.groundTruth,
478
+ metadata: dataItem.metadata
479
+ };
480
+ });
481
+ datasetVersion = null;
482
+ } else if (datasetId) {
483
+ if (!datasetsStore) {
484
+ throw new Error("DatasetsStorage not configured. Configure storage in Mastra instance.");
485
+ }
486
+ const dataset = await datasetsStore.getDatasetById({ id: datasetId });
487
+ if (!dataset) {
488
+ throw new Error(`Dataset not found: ${datasetId}`);
489
+ }
490
+ datasetVersion = version ?? dataset.version;
491
+ const versionItems = await datasetsStore.getItemsByVersion({
492
+ datasetId,
493
+ version: datasetVersion
494
+ });
495
+ if (versionItems.length === 0) {
496
+ throw new Error(`No items in dataset ${datasetId} at version ${datasetVersion}`);
497
+ }
498
+ items = versionItems.map((v) => ({
499
+ id: v.id,
500
+ datasetVersion: v.datasetVersion,
501
+ input: v.input,
502
+ groundTruth: v.groundTruth,
503
+ metadata: v.metadata
504
+ }));
505
+ } else {
506
+ throw new Error("No data source: provide datasetId or data");
507
+ }
508
+ let execFn;
509
+ if (config.task) {
510
+ const taskFn = config.task;
511
+ execFn = async (item, itemSignal) => {
512
+ try {
513
+ const result = await taskFn({
514
+ input: item.input,
515
+ mastra,
516
+ groundTruth: item.groundTruth,
517
+ metadata: item.metadata,
518
+ signal: itemSignal
519
+ });
520
+ return { output: result, error: null, traceId: null };
521
+ } catch (err) {
522
+ return {
523
+ output: null,
524
+ error: {
525
+ message: err instanceof Error ? err.message : String(err),
526
+ stack: err instanceof Error ? err.stack : void 0
527
+ },
528
+ traceId: null
529
+ };
530
+ }
531
+ };
532
+ } else if (targetType && targetId) {
533
+ const target = resolveTarget(mastra, targetType, targetId);
534
+ if (!target) {
535
+ throw new Error(`Target not found: ${targetType}/${targetId}`);
536
+ }
537
+ execFn = (item, itemSignal) => executeTarget(target, targetType, item, { signal: itemSignal });
538
+ } else {
539
+ throw new Error("No task: provide targetType+targetId or task");
540
+ }
541
+ const scorers = resolveScorers(mastra, scorerInput);
542
+ if (experimentsStore) {
543
+ if (!providedExperimentId) {
544
+ await experimentsStore.createExperiment({
545
+ id: experimentId,
546
+ name,
547
+ description,
548
+ metadata,
549
+ datasetId: datasetId ?? null,
550
+ datasetVersion,
551
+ targetType: targetType ?? "agent",
552
+ targetId: targetId ?? "inline",
553
+ totalItems: items.length
554
+ });
555
+ }
556
+ await experimentsStore.updateExperiment({
557
+ id: experimentId,
558
+ status: "running",
559
+ startedAt
560
+ });
561
+ }
562
+ let succeededCount = 0;
563
+ let failedCount = 0;
564
+ const results = new Array(items.length);
565
+ const PROGRESS_UPDATE_INTERVAL = 2e3;
566
+ let lastProgressUpdate = 0;
567
+ try {
568
+ const pMap = (await import('p-map')).default;
569
+ await pMap(
570
+ items.map((item, idx) => ({ item, idx })),
571
+ async ({ item, idx }) => {
572
+ if (signal?.aborted) {
573
+ throw new DOMException("Aborted", "AbortError");
574
+ }
575
+ const itemStartedAt = /* @__PURE__ */ new Date();
576
+ let itemSignal = signal;
577
+ if (itemTimeout) {
578
+ const timeoutSignal = AbortSignal.timeout(itemTimeout);
579
+ itemSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
580
+ }
581
+ let retryCount = 0;
582
+ let execResult = await execFn(item, itemSignal);
583
+ while (execResult.error && retryCount < maxRetries) {
584
+ if (execResult.error.message.toLowerCase().includes("abort")) break;
585
+ retryCount++;
586
+ const delay = Math.min(1e3 * Math.pow(2, retryCount - 1), 3e4);
587
+ const jitter = delay * 0.2 * Math.random();
588
+ await new Promise((r) => setTimeout(r, delay + jitter));
589
+ if (signal?.aborted) {
590
+ throw new DOMException("Aborted", "AbortError");
591
+ }
592
+ execResult = await execFn(item, itemSignal);
593
+ }
594
+ const itemCompletedAt = /* @__PURE__ */ new Date();
595
+ if (execResult.error) {
596
+ failedCount++;
597
+ } else {
598
+ succeededCount++;
599
+ }
600
+ const itemResult = {
601
+ itemId: item.id,
602
+ itemVersion: item.datasetVersion ?? 0,
603
+ input: item.input,
604
+ output: execResult.output,
605
+ groundTruth: item.groundTruth ?? null,
606
+ error: execResult.error,
607
+ startedAt: itemStartedAt,
608
+ completedAt: itemCompletedAt,
609
+ retryCount
610
+ };
611
+ const itemScores = await runScorersForItem(
612
+ scorers,
613
+ item,
614
+ execResult.output,
615
+ storage ?? null,
616
+ experimentId,
617
+ targetType ?? "agent",
618
+ targetId ?? "inline",
619
+ item.id,
620
+ execResult.scorerInput,
621
+ execResult.scorerOutput
622
+ );
623
+ if (experimentsStore) {
624
+ try {
625
+ await experimentsStore.addExperimentResult({
626
+ experimentId,
627
+ itemId: item.id,
628
+ itemDatasetVersion: item.datasetVersion,
629
+ input: item.input,
630
+ output: execResult.output,
631
+ groundTruth: item.groundTruth ?? null,
632
+ error: execResult.error,
633
+ startedAt: itemStartedAt,
634
+ completedAt: itemCompletedAt,
635
+ retryCount,
636
+ traceId: execResult.traceId
637
+ });
638
+ } catch (persistError) {
639
+ console.warn(`Failed to persist result for item ${item.id}:`, persistError);
640
+ }
641
+ const now = Date.now();
642
+ if (now - lastProgressUpdate >= PROGRESS_UPDATE_INTERVAL) {
643
+ lastProgressUpdate = now;
644
+ try {
645
+ await experimentsStore.updateExperiment({
646
+ id: experimentId,
647
+ succeededCount,
648
+ failedCount
649
+ });
650
+ } catch {
651
+ }
652
+ }
653
+ }
654
+ results[idx] = {
655
+ ...itemResult,
656
+ scores: itemScores
657
+ };
658
+ },
659
+ { concurrency: maxConcurrency }
660
+ );
661
+ } catch {
662
+ const completedAt2 = /* @__PURE__ */ new Date();
663
+ const skippedCount2 = items.length - succeededCount - failedCount;
664
+ if (experimentsStore) {
665
+ await experimentsStore.updateExperiment({
666
+ id: experimentId,
667
+ status: "failed",
668
+ succeededCount,
669
+ failedCount,
670
+ skippedCount: skippedCount2,
671
+ completedAt: completedAt2
672
+ });
673
+ }
674
+ return {
675
+ experimentId,
676
+ status: "failed",
677
+ totalItems: items.length,
678
+ succeededCount,
679
+ failedCount,
680
+ skippedCount: skippedCount2,
681
+ completedWithErrors: false,
682
+ startedAt,
683
+ completedAt: completedAt2,
684
+ results: results.filter(Boolean)
685
+ };
686
+ }
687
+ const completedAt = /* @__PURE__ */ new Date();
688
+ const status = failedCount === items.length ? "failed" : "completed";
689
+ const completedWithErrors = status === "completed" && failedCount > 0;
690
+ const skippedCount = items.length - succeededCount - failedCount;
691
+ if (experimentsStore) {
692
+ await experimentsStore.updateExperiment({
693
+ id: experimentId,
694
+ status,
695
+ succeededCount,
696
+ failedCount,
697
+ skippedCount,
698
+ completedAt
699
+ });
700
+ }
701
+ return {
702
+ experimentId,
703
+ status,
704
+ totalItems: items.length,
705
+ succeededCount,
706
+ failedCount,
707
+ skippedCount,
708
+ completedWithErrors,
709
+ startedAt,
710
+ completedAt,
711
+ results
712
+ };
713
+ }
714
+ function resolveTarget(mastra, targetType, targetId) {
715
+ switch (targetType) {
716
+ case "agent":
717
+ try {
718
+ return mastra.getAgentById(targetId);
719
+ } catch {
720
+ try {
721
+ return mastra.getAgent(targetId);
722
+ } catch {
723
+ return null;
724
+ }
725
+ }
726
+ case "workflow":
727
+ try {
728
+ return mastra.getWorkflowById(targetId);
729
+ } catch {
730
+ try {
731
+ return mastra.getWorkflow(targetId);
732
+ } catch {
733
+ return null;
734
+ }
735
+ }
736
+ case "scorer":
737
+ try {
738
+ return mastra.getScorerById(targetId) ?? null;
739
+ } catch {
740
+ return null;
741
+ }
742
+ case "processor":
743
+ return null;
744
+ default:
745
+ return null;
746
+ }
747
+ }
748
+ var Dataset = class {
749
+ id;
750
+ #mastra;
751
+ #datasetsStore;
752
+ #experimentsStore;
753
+ constructor(id, mastra) {
754
+ this.id = id;
755
+ this.#mastra = mastra;
756
+ }
757
+ // ---------------------------------------------------------------------------
758
+ // Lazy storage resolution
759
+ // ---------------------------------------------------------------------------
760
+ async #getDatasetsStore() {
761
+ if (this.#datasetsStore) return this.#datasetsStore;
762
+ const storage = this.#mastra.getStorage();
763
+ if (!storage) {
764
+ throw new MastraError({
765
+ id: "DATASETS_STORAGE_NOT_CONFIGURED",
766
+ text: "Storage not configured. Configure storage in Mastra instance.",
767
+ domain: "STORAGE",
768
+ category: "USER"
769
+ });
770
+ }
771
+ const store = await storage.getStore("datasets");
772
+ if (!store) {
773
+ throw new MastraError({
774
+ id: "DATASETS_STORE_NOT_AVAILABLE",
775
+ text: "Datasets store not available. Ensure your storage adapter provides a datasets domain.",
776
+ domain: "STORAGE",
777
+ category: "USER"
778
+ });
779
+ }
780
+ this.#datasetsStore = store;
781
+ return store;
782
+ }
783
+ async #getExperimentsStore() {
784
+ if (this.#experimentsStore) return this.#experimentsStore;
785
+ const storage = this.#mastra.getStorage();
786
+ if (!storage) {
787
+ throw new MastraError({
788
+ id: "DATASETS_STORAGE_NOT_CONFIGURED",
789
+ text: "Storage not configured. Configure storage in Mastra instance.",
790
+ domain: "STORAGE",
791
+ category: "USER"
792
+ });
793
+ }
794
+ const store = await storage.getStore("experiments");
795
+ if (!store) {
796
+ throw new MastraError({
797
+ id: "EXPERIMENTS_STORE_NOT_AVAILABLE",
798
+ text: "Experiments store not available. Ensure your storage adapter provides an experiments domain.",
799
+ domain: "STORAGE",
800
+ category: "USER"
801
+ });
802
+ }
803
+ this.#experimentsStore = store;
804
+ return store;
805
+ }
806
+ // ---------------------------------------------------------------------------
807
+ // Dataset metadata
808
+ // ---------------------------------------------------------------------------
809
+ /**
810
+ * Get the full dataset record from storage.
811
+ */
812
+ async getDetails() {
813
+ const store = await this.#getDatasetsStore();
814
+ const record = await store.getDatasetById({ id: this.id });
815
+ if (!record) {
816
+ throw new MastraError({
817
+ id: "DATASET_NOT_FOUND",
818
+ text: `Dataset not found: ${this.id}`,
819
+ domain: "STORAGE",
820
+ category: "USER"
821
+ });
822
+ }
823
+ return record;
824
+ }
825
+ /**
826
+ * Update dataset metadata and/or schemas.
827
+ * Zod schemas are automatically converted to JSON Schema.
828
+ */
829
+ async update(input) {
830
+ const store = await this.#getDatasetsStore();
831
+ let { inputSchema, groundTruthSchema, ...rest } = input;
832
+ if (inputSchema !== void 0 && isZodType(inputSchema)) {
833
+ inputSchema = zodToJsonSchema(inputSchema);
834
+ }
835
+ if (groundTruthSchema !== void 0 && isZodType(groundTruthSchema)) {
836
+ groundTruthSchema = zodToJsonSchema(groundTruthSchema);
837
+ }
838
+ return store.updateDataset({
839
+ id: this.id,
840
+ ...rest,
841
+ inputSchema,
842
+ groundTruthSchema
843
+ });
844
+ }
845
+ // ---------------------------------------------------------------------------
846
+ // Item CRUD
847
+ // ---------------------------------------------------------------------------
848
+ /**
849
+ * Add a single item to the dataset.
850
+ */
851
+ async addItem(input) {
852
+ const store = await this.#getDatasetsStore();
853
+ return store.addItem({
854
+ datasetId: this.id,
855
+ input: input.input,
856
+ groundTruth: input.groundTruth,
857
+ metadata: input.metadata
858
+ });
859
+ }
860
+ /**
861
+ * Add multiple items to the dataset in bulk.
862
+ */
863
+ async addItems(input) {
864
+ const store = await this.#getDatasetsStore();
865
+ return store.batchInsertItems({
866
+ datasetId: this.id,
867
+ items: input.items
868
+ });
869
+ }
870
+ /**
871
+ * Get a single item by ID, optionally at a specific version.
872
+ */
873
+ async getItem(args) {
874
+ const store = await this.#getDatasetsStore();
875
+ return store.getItemById({ id: args.itemId, datasetVersion: args.version });
876
+ }
877
+ /**
878
+ * List items in the dataset, optionally at a specific version.
879
+ */
880
+ async listItems(args) {
881
+ const store = await this.#getDatasetsStore();
882
+ if (args?.version) {
883
+ return store.getItemsByVersion({ datasetId: this.id, version: args.version });
884
+ }
885
+ return store.listItems({
886
+ datasetId: this.id,
887
+ search: args?.search,
888
+ pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 }
889
+ });
890
+ }
891
+ /**
892
+ * Update an existing item in the dataset.
893
+ */
894
+ async updateItem(input) {
895
+ const store = await this.#getDatasetsStore();
896
+ return store.updateItem({
897
+ id: input.itemId,
898
+ datasetId: this.id,
899
+ input: input.input,
900
+ groundTruth: input.groundTruth,
901
+ metadata: input.metadata
902
+ });
903
+ }
904
+ /**
905
+ * Delete a single item from the dataset.
906
+ */
907
+ async deleteItem(args) {
908
+ const store = await this.#getDatasetsStore();
909
+ return store.deleteItem({ id: args.itemId, datasetId: this.id });
910
+ }
911
+ /**
912
+ * Delete multiple items from the dataset in bulk.
913
+ */
914
+ async deleteItems(args) {
915
+ const store = await this.#getDatasetsStore();
916
+ return store.batchDeleteItems({ datasetId: this.id, itemIds: args.itemIds });
917
+ }
918
+ // ---------------------------------------------------------------------------
919
+ // Versioning
920
+ // ---------------------------------------------------------------------------
921
+ /**
922
+ * List all versions of this dataset.
923
+ */
924
+ async listVersions(args) {
925
+ const store = await this.#getDatasetsStore();
926
+ return store.listDatasetVersions({
927
+ datasetId: this.id,
928
+ pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 }
929
+ });
930
+ }
931
+ /**
932
+ * Get full SCD-2 history of a specific item across all dataset versions.
933
+ */
934
+ async getItemHistory(args) {
935
+ const store = await this.#getDatasetsStore();
936
+ return store.getItemHistory(args.itemId);
937
+ }
938
+ // ---------------------------------------------------------------------------
939
+ // Experiments
940
+ // ---------------------------------------------------------------------------
941
+ /**
942
+ * Run an experiment on this dataset and wait for completion.
943
+ */
944
+ async startExperiment(config) {
945
+ return runExperiment(this.#mastra, { datasetId: this.id, ...config });
946
+ }
947
+ /**
948
+ * Start an experiment asynchronously (fire-and-forget).
949
+ * Returns immediately with the experiment ID and pending status.
950
+ */
951
+ async startExperimentAsync(config) {
952
+ const experimentsStore = await this.#getExperimentsStore();
953
+ const datasetsStore = await this.#getDatasetsStore();
954
+ const dataset = await datasetsStore.getDatasetById({ id: this.id });
955
+ if (!dataset) {
956
+ throw new MastraError({
957
+ id: "DATASET_NOT_FOUND",
958
+ text: `Dataset not found: ${this.id}`,
959
+ domain: "STORAGE",
960
+ category: "USER"
961
+ });
962
+ }
963
+ const run = await experimentsStore.createExperiment({
964
+ datasetId: this.id,
965
+ datasetVersion: dataset.version,
966
+ targetType: config.targetType ?? "agent",
967
+ targetId: config.targetId ?? "inline",
968
+ totalItems: 0,
969
+ name: config.name,
970
+ description: config.description,
971
+ metadata: config.metadata
972
+ });
973
+ const experimentId = run.id;
974
+ void runExperiment(this.#mastra, {
975
+ datasetId: this.id,
976
+ experimentId,
977
+ ...config
978
+ }).catch(() => {
979
+ });
980
+ return { experimentId, status: "pending" };
981
+ }
982
+ /**
983
+ * List all experiments (runs) for this dataset.
984
+ */
985
+ async listExperiments(args) {
986
+ const experimentsStore = await this.#getExperimentsStore();
987
+ return experimentsStore.listExperiments({
988
+ datasetId: this.id,
989
+ pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 }
990
+ });
991
+ }
992
+ /**
993
+ * Get a specific experiment (run) by ID.
994
+ */
995
+ async getExperiment(args) {
996
+ const experimentsStore = await this.#getExperimentsStore();
997
+ return experimentsStore.getExperimentById({ id: args.experimentId });
998
+ }
999
+ /**
1000
+ * List results for a specific experiment.
1001
+ */
1002
+ async listExperimentResults(args) {
1003
+ const experimentsStore = await this.#getExperimentsStore();
1004
+ return experimentsStore.listExperimentResults({
1005
+ experimentId: args.experimentId,
1006
+ pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 }
1007
+ });
1008
+ }
1009
+ /**
1010
+ * Delete an experiment (run) by ID.
1011
+ */
1012
+ async deleteExperiment(args) {
1013
+ const experimentsStore = await this.#getExperimentsStore();
1014
+ return experimentsStore.deleteExperiment({ id: args.experimentId });
1015
+ }
1016
+ };
1017
+ var DatasetsManager = class {
1018
+ #mastra;
1019
+ #datasetsStore;
1020
+ #experimentsStore;
1021
+ constructor(mastra) {
1022
+ this.#mastra = mastra;
1023
+ }
1024
+ // ---------------------------------------------------------------------------
1025
+ // Lazy storage resolution
1026
+ // ---------------------------------------------------------------------------
1027
+ async #getDatasetsStore() {
1028
+ if (this.#datasetsStore) return this.#datasetsStore;
1029
+ const storage = this.#mastra.getStorage();
1030
+ if (!storage) {
1031
+ throw new MastraError({
1032
+ id: "DATASETS_STORAGE_NOT_CONFIGURED",
1033
+ text: "Storage not configured. Configure storage in Mastra instance.",
1034
+ domain: "STORAGE",
1035
+ category: "USER"
1036
+ });
1037
+ }
1038
+ const store = await storage.getStore("datasets");
1039
+ if (!store) {
1040
+ throw new MastraError({
1041
+ id: "DATASETS_STORE_NOT_AVAILABLE",
1042
+ text: "Datasets store not available. Ensure your storage adapter provides a datasets domain.",
1043
+ domain: "STORAGE",
1044
+ category: "USER"
1045
+ });
1046
+ }
1047
+ this.#datasetsStore = store;
1048
+ return store;
1049
+ }
1050
+ async #getExperimentsStore() {
1051
+ if (this.#experimentsStore) return this.#experimentsStore;
1052
+ const storage = this.#mastra.getStorage();
1053
+ if (!storage) {
1054
+ throw new MastraError({
1055
+ id: "DATASETS_STORAGE_NOT_CONFIGURED",
1056
+ text: "Storage not configured. Configure storage in Mastra instance.",
1057
+ domain: "STORAGE",
1058
+ category: "USER"
1059
+ });
1060
+ }
1061
+ const store = await storage.getStore("experiments");
1062
+ if (!store) {
1063
+ throw new MastraError({
1064
+ id: "EXPERIMENTS_STORE_NOT_AVAILABLE",
1065
+ text: "Experiments store not available. Ensure your storage adapter provides an experiments domain.",
1066
+ domain: "STORAGE",
1067
+ category: "USER"
1068
+ });
1069
+ }
1070
+ this.#experimentsStore = store;
1071
+ return store;
1072
+ }
1073
+ // ---------------------------------------------------------------------------
1074
+ // Dataset CRUD
1075
+ // ---------------------------------------------------------------------------
1076
+ /**
1077
+ * Create a new dataset.
1078
+ * Zod schemas are automatically converted to JSON Schema.
1079
+ */
1080
+ async create(input) {
1081
+ const store = await this.#getDatasetsStore();
1082
+ let { inputSchema, groundTruthSchema, ...rest } = input;
1083
+ if (inputSchema !== void 0 && isZodType(inputSchema)) {
1084
+ inputSchema = zodToJsonSchema(inputSchema);
1085
+ }
1086
+ if (groundTruthSchema !== void 0 && isZodType(groundTruthSchema)) {
1087
+ groundTruthSchema = zodToJsonSchema(groundTruthSchema);
1088
+ }
1089
+ const result = await store.createDataset({
1090
+ ...rest,
1091
+ inputSchema,
1092
+ groundTruthSchema
1093
+ });
1094
+ return new Dataset(result.id, this.#mastra);
1095
+ }
1096
+ /**
1097
+ * Get an existing dataset by ID.
1098
+ * Throws if the dataset does not exist.
1099
+ */
1100
+ async get(args) {
1101
+ const store = await this.#getDatasetsStore();
1102
+ const record = await store.getDatasetById({ id: args.id });
1103
+ if (!record) {
1104
+ throw new MastraError({
1105
+ id: "DATASET_NOT_FOUND",
1106
+ text: "Dataset not found",
1107
+ domain: "STORAGE",
1108
+ category: "USER"
1109
+ });
1110
+ }
1111
+ return new Dataset(args.id, this.#mastra);
1112
+ }
1113
+ /**
1114
+ * List all datasets with pagination.
1115
+ */
1116
+ async list(args) {
1117
+ const store = await this.#getDatasetsStore();
1118
+ return store.listDatasets({
1119
+ pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 }
1120
+ });
1121
+ }
1122
+ /**
1123
+ * Delete a dataset by ID.
1124
+ */
1125
+ async delete(args) {
1126
+ const store = await this.#getDatasetsStore();
1127
+ return store.deleteDataset({ id: args.id });
1128
+ }
1129
+ // ---------------------------------------------------------------------------
1130
+ // Cross-dataset experiment operations
1131
+ // ---------------------------------------------------------------------------
1132
+ /**
1133
+ * Get a specific experiment (run) by ID.
1134
+ */
1135
+ async getExperiment(args) {
1136
+ const experimentsStore = await this.#getExperimentsStore();
1137
+ return experimentsStore.getExperimentById({ id: args.experimentId });
1138
+ }
1139
+ /**
1140
+ * Compare two or more experiments.
1141
+ *
1142
+ * Uses the internal `compareExperiments` function for pairwise comparison,
1143
+ * then enriches results with per-item input/groundTruth/output data.
1144
+ */
1145
+ async compareExperiments(args) {
1146
+ const { experimentIds, baselineId } = args;
1147
+ if (experimentIds.length < 2) {
1148
+ throw new MastraError({
1149
+ id: "COMPARE_INVALID_INPUT",
1150
+ text: "compareExperiments requires at least 2 experiment IDs.",
1151
+ domain: "STORAGE",
1152
+ category: "USER"
1153
+ });
1154
+ }
1155
+ const resolvedBaseline = baselineId ?? experimentIds[0];
1156
+ const otherExperimentId = experimentIds.find((id) => id !== resolvedBaseline) ?? experimentIds[1];
1157
+ const internal = await compareExperiments(this.#mastra, {
1158
+ experimentIdA: resolvedBaseline,
1159
+ experimentIdB: otherExperimentId
1160
+ });
1161
+ const experimentsStore = await this.#getExperimentsStore();
1162
+ const [resultsA, resultsB] = await Promise.all([
1163
+ experimentsStore.listExperimentResults({
1164
+ experimentId: resolvedBaseline,
1165
+ pagination: { page: 0, perPage: false }
1166
+ }),
1167
+ experimentsStore.listExperimentResults({
1168
+ experimentId: otherExperimentId,
1169
+ pagination: { page: 0, perPage: false }
1170
+ })
1171
+ ]);
1172
+ const resultsMapA = new Map(resultsA.results.map((r) => [r.itemId, r]));
1173
+ const resultsMapB = new Map(resultsB.results.map((r) => [r.itemId, r]));
1174
+ const items = internal.items.map((item) => {
1175
+ const resultA = resultsMapA.get(item.itemId);
1176
+ const resultB = resultsMapB.get(item.itemId);
1177
+ return {
1178
+ itemId: item.itemId,
1179
+ input: resultA?.input ?? resultB?.input ?? null,
1180
+ groundTruth: resultA?.groundTruth ?? resultB?.groundTruth ?? null,
1181
+ results: {
1182
+ [resolvedBaseline]: resultA ? { output: resultA.output, scores: item.scoresA } : null,
1183
+ [otherExperimentId]: resultB ? { output: resultB.output, scores: item.scoresB } : null
1184
+ }
1185
+ };
1186
+ });
1187
+ return {
1188
+ baselineId: resolvedBaseline,
1189
+ items
1190
+ };
1191
+ }
1192
+ };
1193
+
1194
+ export { Dataset, DatasetsManager, compareExperiments, computeMean, computeScorerStats, executeTarget, isRegression, resolveScorers, runExperiment, runScorersForItem };
1195
+ //# sourceMappingURL=chunk-NJ7TL3LQ.js.map
1196
+ //# sourceMappingURL=chunk-NJ7TL3LQ.js.map