@mastra/core 1.55.0-alpha.2 → 1.55.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.
- package/CHANGELOG.md +86 -0
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/durable/index.cjs +1 -1
- package/dist/agent/durable/index.js +1 -1
- package/dist/agent/index.cjs +2 -2
- package/dist/agent/index.js +2 -2
- package/dist/{agent-BvRfRKIt.js → agent-0y2cApTZ.js} +57 -82
- package/dist/agent-0y2cApTZ.js.map +1 -0
- package/dist/agent-builder/ee/index.cjs +1 -1
- package/dist/agent-builder/ee/index.js +1 -1
- package/dist/agent-controller/index.cjs +1 -1
- package/dist/agent-controller/index.js +1 -1
- package/dist/{agent-controller-CM6tQSMj.js → agent-controller-ByW51eCC.js} +5 -5
- package/dist/{agent-controller-CM6tQSMj.js.map → agent-controller-ByW51eCC.js.map} +1 -1
- package/dist/{agent-controller-C75dc544.cjs → agent-controller-DahKlMET.cjs} +5 -5
- package/dist/{agent-controller-C75dc544.cjs.map → agent-controller-DahKlMET.cjs.map} +1 -1
- package/dist/{agent-CwUYflGG.cjs → agent-um2LJs-0.cjs} +57 -82
- package/dist/agent-um2LJs-0.cjs.map +1 -0
- package/dist/background-tasks/index.cjs +1 -1
- package/dist/background-tasks/index.js +1 -1
- package/dist/{background-tasks-AKlv5tIo.js → background-tasks-CM94BIj8.js} +2 -2
- package/dist/{background-tasks-AKlv5tIo.js.map → background-tasks-CM94BIj8.js.map} +1 -1
- package/dist/{background-tasks-Chpan7PB.cjs → background-tasks-CobPW4Z3.cjs} +2 -2
- package/dist/{background-tasks-Chpan7PB.cjs.map → background-tasks-CobPW4Z3.cjs.map} +1 -1
- package/dist/browser/index.cjs +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/channels/index.cjs +2 -2
- package/dist/channels/index.js +2 -2
- package/dist/{channels-BW52ccH_.cjs → channels-BgbloDjB.cjs} +2 -2
- package/dist/{channels-BW52ccH_.cjs.map → channels-BgbloDjB.cjs.map} +1 -1
- package/dist/{channels-Da9lEAi1.js → channels-MegO_4KL.js} +2 -2
- package/dist/{channels-Da9lEAi1.js.map → channels-MegO_4KL.js.map} +1 -1
- package/dist/coding-agent/index.cjs +1 -1
- package/dist/coding-agent/index.js +1 -1
- package/dist/{create-durable-agent-DmTTvoGi.cjs → create-durable-agent-ChmjQwzE.cjs} +8 -8
- package/dist/{create-durable-agent-DmTTvoGi.cjs.map → create-durable-agent-ChmjQwzE.cjs.map} +1 -1
- package/dist/{create-durable-agent-Bd4Bm5FV.js → create-durable-agent-DH_dWTMR.js} +8 -8
- package/dist/{create-durable-agent-Bd4Bm5FV.js.map → create-durable-agent-DH_dWTMR.js.map} +1 -1
- package/dist/datasets/index.cjs +1 -1
- package/dist/datasets/index.js +1 -1
- package/dist/{dist-C077BlAN.js → dist-BZBxELZo.js} +2 -2
- package/dist/{dist-C077BlAN.js.map → dist-BZBxELZo.js.map} +1 -1
- package/dist/{dist-CsR_D1uk.cjs → dist-ftJxyNRx.cjs} +2 -2
- package/dist/{dist-CsR_D1uk.cjs.map → dist-ftJxyNRx.cjs.map} +1 -1
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/evals/index.cjs +1 -1
- package/dist/evals/index.js +1 -1
- package/dist/evals/scoreTraces/index.cjs +1 -1
- package/dist/evals/scoreTraces/index.js +1 -1
- package/dist/harness/index.cjs +1 -1
- package/dist/harness/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/llm/index.cjs +5 -5
- package/dist/llm/index.js +5 -5
- package/dist/{llm-DlVyw1cX.js → llm-DGuYy_Nx.js} +5 -5
- package/dist/{llm-DlVyw1cX.js.map → llm-DGuYy_Nx.js.map} +1 -1
- package/dist/{llm-Bjt2hZ3f.cjs → llm-DmAhSSgh.cjs} +5 -5
- package/dist/{llm-Bjt2hZ3f.cjs.map → llm-DmAhSSgh.cjs.map} +1 -1
- package/dist/loop/index.cjs +1 -1
- package/dist/loop/index.js +1 -1
- package/dist/{manager-CYGpXJfK.js → manager-DDRcONBK.js} +3 -3
- package/dist/{manager-CYGpXJfK.js.map → manager-DDRcONBK.js.map} +1 -1
- package/dist/{manager-BjrFnt_A.cjs → manager-DqHiikx1.cjs} +3 -3
- package/dist/{manager-BjrFnt_A.cjs.map → manager-DqHiikx1.cjs.map} +1 -1
- package/dist/mastra/index.cjs +1 -1
- package/dist/mastra/index.js +1 -1
- package/dist/{mastra-CVLF1dWt.js → mastra-B6CffFOC.js} +9 -9
- package/dist/{mastra-CVLF1dWt.js.map → mastra-B6CffFOC.js.map} +1 -1
- package/dist/{mastra-Bxx9WPf6.cjs → mastra-BlT9srQJ.cjs} +9 -9
- package/dist/{mastra-Bxx9WPf6.cjs.map → mastra-BlT9srQJ.cjs.map} +1 -1
- package/dist/memory/index.cjs +1 -1
- package/dist/memory/index.js +1 -1
- package/dist/{model-CA0WLISt.js → model-DQzxkQqM.js} +2 -2
- package/dist/{model-CA0WLISt.js.map → model-DQzxkQqM.js.map} +1 -1
- package/dist/{model-DMVq6nAS.cjs → model-Iow-mV9i.cjs} +2 -2
- package/dist/{model-DMVq6nAS.cjs.map → model-Iow-mV9i.cjs.map} +1 -1
- package/dist/{models-dev-Cbus1Uh2.js → models-dev-BFOUCgyS.js} +2 -2
- package/dist/{models-dev-Cbus1Uh2.js.map → models-dev-BFOUCgyS.js.map} +1 -1
- package/dist/{models-dev-D_X4VMSu.cjs → models-dev-BUEaCBxL.cjs} +2 -2
- package/dist/{models-dev-D_X4VMSu.cjs.map → models-dev-BUEaCBxL.cjs.map} +1 -1
- package/dist/{netlify-C-nnPVSj.js → netlify-7eHXUkln.js} +2 -2
- package/dist/{netlify-C-nnPVSj.js.map → netlify-7eHXUkln.js.map} +1 -1
- package/dist/{netlify-CUuCnmtd.cjs → netlify-Db5icdAJ.cjs} +2 -2
- package/dist/{netlify-CUuCnmtd.cjs.map → netlify-Db5icdAJ.cjs.map} +1 -1
- package/dist/processor-provider/index.cjs +1 -1
- package/dist/processor-provider/index.js +1 -1
- package/dist/processors/index.cjs +2 -2
- package/dist/processors/index.js +2 -2
- package/dist/processors/processors/index.d.ts +1 -1
- package/dist/processors/processors/index.d.ts.map +1 -1
- package/dist/processors/tool-result-reminder.d.ts +23 -0
- package/dist/processors/tool-result-reminder.d.ts.map +1 -1
- package/dist/{provider-registry-BFknh6Fu.cjs → provider-registry-DRJihW5_.cjs} +6 -6
- package/dist/{provider-registry-BFknh6Fu.cjs.map → provider-registry-DRJihW5_.cjs.map} +1 -1
- package/dist/{provider-registry-DIbls44Z.js → provider-registry-DzSSAz1R.js} +6 -6
- package/dist/{provider-registry-DIbls44Z.js.map → provider-registry-DzSSAz1R.js.map} +1 -1
- package/dist/relevance/index.cjs +2 -2
- package/dist/relevance/index.js +2 -2
- package/dist/stream/index.cjs +3 -3
- package/dist/stream/index.js +3 -3
- package/dist/{stream-tlVjYkAO.cjs → stream-D-cHV05r.cjs} +3 -3
- package/dist/{stream-tlVjYkAO.cjs.map → stream-D-cHV05r.cjs.map} +1 -1
- package/dist/{stream-Cd_isEZJ.js → stream-DJaosaeO.js} +3 -3
- package/dist/{stream-Cd_isEZJ.js.map → stream-DJaosaeO.js.map} +1 -1
- package/dist/test-utils/llm-mock.cjs +1 -1
- package/dist/test-utils/llm-mock.js +1 -1
- package/dist/tool-loop-agent/index.cjs +1 -1
- package/dist/tool-loop-agent/index.js +1 -1
- package/dist/{tool-loop-agent-th9L-ls9.cjs → tool-loop-agent-ByrutV2Q.cjs} +4 -4
- package/dist/{tool-loop-agent-th9L-ls9.cjs.map → tool-loop-agent-ByrutV2Q.cjs.map} +1 -1
- package/dist/{tool-loop-agent-CcT-TTcT.js → tool-loop-agent-BzHXZDL3.js} +4 -4
- package/dist/{tool-loop-agent-CcT-TTcT.js.map → tool-loop-agent-BzHXZDL3.js.map} +1 -1
- package/dist/{trip-wire-Cj0cJivR.js → trip-wire-DxpTS3jV.js} +2 -2
- package/dist/{trip-wire-Cj0cJivR.js.map → trip-wire-DxpTS3jV.js.map} +1 -1
- package/dist/{trip-wire-BNzxirr0.cjs → trip-wire-utCESgMt.cjs} +2 -2
- package/dist/{trip-wire-BNzxirr0.cjs.map → trip-wire-utCESgMt.cjs.map} +1 -1
- package/dist/{utils-BoQofieM.cjs → utils-CPUQn5dX.cjs} +2 -2
- package/dist/{utils-BoQofieM.cjs.map → utils-CPUQn5dX.cjs.map} +1 -1
- package/dist/{utils-DUfAZ4gr.js → utils-CrKEOVUo.js} +2 -2
- package/dist/{utils-DUfAZ4gr.js.map → utils-CrKEOVUo.js.map} +1 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +1 -1
- package/dist/worker/index.cjs +1 -1
- package/dist/worker/index.js +1 -1
- package/dist/{worker-DwlyX5l8.js → worker-Ciya6mfo.js} +3 -3
- package/dist/{worker-DwlyX5l8.js.map → worker-Ciya6mfo.js.map} +1 -1
- package/dist/{worker-CsbZPhWb.cjs → worker-YT_pMttZ.cjs} +3 -3
- package/dist/{worker-CsbZPhWb.cjs.map → worker-YT_pMttZ.cjs.map} +1 -1
- package/dist/{workflow-BR5D6ij_.cjs → workflow-DcS_0R0Z.cjs} +3 -3
- package/dist/{workflow-BR5D6ij_.cjs.map → workflow-DcS_0R0Z.cjs.map} +1 -1
- package/dist/{workflow-OjZRiiCG.js → workflow-k6s0ESOR.js} +3 -3
- package/dist/{workflow-OjZRiiCG.js.map → workflow-k6s0ESOR.js.map} +1 -1
- package/dist/workflows/evented/index.cjs +1 -1
- package/dist/workflows/evented/index.js +1 -1
- package/dist/workflows/index.cjs +1 -1
- package/dist/workflows/index.js +1 -1
- package/package.json +12 -12
- package/dist/agent-BvRfRKIt.js.map +0 -1
- package/dist/agent-CwUYflGG.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager-CYGpXJfK.js","names":["#entries","#served","#liveCalls","#failure","#mastra","#scope","#getDatasetsStore","#datasetsStore","#getExperimentsStore","#experimentsStore","#assertScope","#ownsChild","#assertExperimentOwnership","#mastra","#getDatasetsStore","#datasetsStore","#getExperimentsStore","#experimentsStore","compareExperimentsInternal"],"sources":["../src/datasets/experiment/tool-mocks.ts","../src/datasets/experiment/executor.ts","../src/datasets/experiment/scorer.ts","../src/datasets/experiment/analytics/aggregate.ts","../src/datasets/experiment/analytics/compare.ts","../src/datasets/experiment/index.ts","../src/datasets/dataset.ts","../src/datasets/manager.ts"],"sourcesContent":["import { deepEqual } from '../../utils';\n\n/**\n * A single static tool mock authored on a dataset item.\n *\n * v1 is output-only: when matched, `output` is served to the agent in place of\n * executing the real tool. Error mocks are intentionally not supported in v1\n * (the agent `beforeToolCall` hook can only short-circuit with an output).\n *\n * Tool mocks only apply to experiments with `targetType: 'agent'`. They are\n * ignored for `task`, `workflow`, and `scorer` targets (the experiment logs a\n * warning if a dataset carrying `toolMocks` is run against a non-agent target).\n */\n/**\n * How a mock's `args` are matched against the agent's tool call.\n * - `strict` (default): deep-equality on `args` (key order ignored, array order\n * significant, no coercion).\n * - `ignore`: match on `toolName` only; `args` are not compared. Useful for\n * tools whose arguments are noisy or LLM-authored — notably sub-agent\n * delegation calls (`agent-*`), whose `prompt` is free text.\n */\nexport type ToolMockMatchArgs = 'strict' | 'ignore';\n\nexport interface ItemToolMock {\n /** Name of the tool this mock applies to. */\n toolName: string;\n /**\n * Arguments to match against the agent's tool call. Compared with deep\n * equality when `matchArgs` is `strict`; ignored when `matchArgs` is `ignore`.\n */\n args: Record<string, unknown>;\n /** Output served to the agent when this mock is matched and consumed. */\n output: unknown;\n /**\n * Argument matching mode for this mock. Defaults to `strict`.\n *\n * @example\n * // strict (default): served only when args deep-equal the call\n * { toolName: 'getWeather', args: { city: 'Seattle' }, output: { tempF: 52 }, matchArgs: 'strict' }\n * // ignore: served for any args to `getWeather` (tool-name-only match)\n * { toolName: 'getWeather', args: {}, output: { tempF: 52 }, matchArgs: 'ignore' }\n */\n matchArgs?: ToolMockMatchArgs;\n}\n\n/** Deterministic failure codes surfaced via `ExecutionResult.error.code`. */\nexport const TOOL_MOCK_MISMATCH = 'TOOL_MOCK_MISMATCH';\nexport const TOOL_MOCK_EXHAUSTED = 'TOOL_MOCK_EXHAUSTED';\n\nexport type ToolMockFailureCode = typeof TOOL_MOCK_MISMATCH | typeof TOOL_MOCK_EXHAUSTED;\n\n/** Diagnostic receipt produced for a single item run. Persisted on experiment results. */\nexport interface ToolMockReport {\n /** Mocks that were matched and served, in consumption order. */\n served: { mockIndex: number; toolName: string; args: unknown }[];\n /** Mocks declared on the item that the agent never consumed (report-only — does NOT fail the item). */\n unconsumed: { mockIndex: number; toolName: string; args: unknown }[];\n /** Unmocked tools that ran live — flags that the item was not fully deterministic. */\n liveCalls: { toolName: string; args: unknown }[];\n /** Present when a mocked tool was mis-called and the item failed. */\n failure?: { code: ToolMockFailureCode; toolName: string; args: unknown };\n}\n\n/** Result of attempting to resolve a single tool call against the item's mocks. */\nexport type ToolMockResolution =\n | { kind: 'serve'; output: unknown }\n | { kind: 'live' }\n | { kind: 'fail'; code: ToolMockFailureCode };\n\ninterface MockEntry {\n mockIndex: number;\n toolName: string;\n args: Record<string, unknown>;\n output: unknown;\n matchArgs: ToolMockMatchArgs;\n consumed: boolean;\n}\n\n/**\n * Per-item mock matcher. Built fresh for each item run; consumption is tracked\n * in local state so repeated `(toolName, args)` mocks are served top-to-bottom.\n *\n * Tool execution must be forced sequential while an item has mocks so that\n * ordered consumption is deterministic (the matcher itself is order-sensitive).\n */\nexport class ToolMockMatcher {\n readonly #entries: MockEntry[];\n readonly #served: ToolMockReport['served'] = [];\n readonly #liveCalls: ToolMockReport['liveCalls'] = [];\n #failure: ToolMockReport['failure'];\n\n constructor(mocks: ItemToolMock[] | undefined) {\n this.#entries = (mocks ?? []).map((mock, mockIndex) => ({\n mockIndex,\n toolName: mock.toolName,\n args: mock.args,\n output: mock.output,\n matchArgs: mock.matchArgs ?? 'strict',\n consumed: false,\n }));\n }\n\n /** True when the item declares at least one mock (tool execution should run sequentially). */\n get hasMocks(): boolean {\n return this.#entries.length > 0;\n }\n\n /**\n * Resolve a single tool call:\n * - no mock for this tool → `live`\n * - unconsumed mock whose args match (deep-equal for `strict`, always for\n * `ignore`) → `serve`\n * - tool is mocked but no unconsumed entry matches → `fail`\n * (`TOOL_MOCK_EXHAUSTED` if args matched but all consumed, else `TOOL_MOCK_MISMATCH`)\n */\n resolve(toolName: string, args: unknown): ToolMockResolution {\n // Once any mock has failed, the item is already doomed and being aborted.\n // Fail every subsequent resolution so no further tool runs live/serves\n // during the abort-propagation race.\n if (this.#failure) {\n return { kind: 'fail', code: this.#failure.code };\n }\n\n const candidates = this.#entries.filter(entry => entry.toolName === toolName);\n\n if (candidates.length === 0) {\n this.#liveCalls.push({ toolName, args });\n return { kind: 'live' };\n }\n\n const argsMatch = (entry: MockEntry): boolean => entry.matchArgs === 'ignore' || deepEqual(entry.args, args);\n\n const next = candidates.find(entry => !entry.consumed && argsMatch(entry));\n if (next) {\n next.consumed = true;\n this.#served.push({ mockIndex: next.mockIndex, toolName, args });\n return { kind: 'serve', output: next.output };\n }\n\n const argsMatchedButConsumed = candidates.some(entry => argsMatch(entry));\n const code: ToolMockFailureCode = argsMatchedButConsumed ? TOOL_MOCK_EXHAUSTED : TOOL_MOCK_MISMATCH;\n // Record only the first failure — the item fails on it and stops.\n this.#failure ??= { code, toolName, args };\n return { kind: 'fail', code };\n }\n\n /** Build the diagnostic report for this item run. */\n report(): ToolMockReport {\n const unconsumed = this.#entries\n .filter(entry => !entry.consumed)\n .map(entry => ({ mockIndex: entry.mockIndex, toolName: entry.toolName, args: entry.args }));\n\n return {\n served: this.#served,\n unconsumed,\n liveCalls: this.#liveCalls,\n ...(this.#failure ? { failure: this.#failure } : {}),\n };\n }\n}\n","import type { Agent } from '../../agent';\nimport { isSupportedLanguageModel } from '../../agent';\nimport type { MessageListInput } from '../../agent/message-list';\nimport type { MastraScorer } from '../../evals/base';\nimport type { ScorerRunInputForAgent, ScorerRunOutputForAgent } from '../../evals/types';\nimport type { ScoringData } from '../../llm/model/base.types';\nimport type { VersionOverrides } from '../../mastra/types';\nimport { resolveObservabilityContext } from '../../observability';\nimport { RequestContext } from '../../request-context';\nimport type { TargetType } from '../../storage/types';\nimport type { ToolHooks } from '../../tools/types';\nimport type { StepResult, Workflow } from '../../workflows';\nimport type { ItemToolMock, ToolMockReport } from './tool-mocks';\nimport { ToolMockMatcher } from './tool-mocks';\n\n/**\n * Common fields extracted from both FullOutput (v2/v3) and GenerateTextResult/GenerateObjectResult (v1).\n * Used to type the agent result uniformly without coupling to the full return types.\n */\ninterface AgentGenerateResult {\n text?: string;\n object?: unknown;\n toolCalls?: unknown[];\n toolResults?: unknown[];\n sources?: unknown[];\n files?: unknown[];\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n reasoningText?: string;\n traceId?: string;\n error?: Error;\n scoringData?: ScoringData;\n}\n\n/**\n * Target types supported for dataset execution.\n * Agent and Workflow are Phase 2; scorer and processor are Phase 4.\n */\nexport type Target = Agent | Workflow | MastraScorer<any, any, any, any>;\n\n/**\n * Result from executing a target against a dataset item.\n */\nexport interface ExecutionResult {\n /** Output from the target (null if failed) */\n output: unknown;\n /** Structured error if execution failed */\n error: { message: string; stack?: string; code?: string } | null;\n /** Trace ID from agent/workflow execution (null for scorers or errors) */\n traceId: string | null;\n /** Root span ID from agent/workflow execution (null when not traced) */\n spanId?: string | null;\n /** Structured input for scorers (extracted from agent scoring data) */\n scorerInput?: ScorerRunInputForAgent;\n /** Structured output for scorers (extracted from agent scoring data) */\n scorerOutput?: ScorerRunOutputForAgent;\n /** Per-step results from a workflow run, keyed by step ID */\n stepResults?: Record<string, StepResult<any, any, any, any>>;\n /** Order in which workflow steps actually executed */\n stepExecutionPath?: string[];\n /** Diagnostic receipt for item-level tool mocks (agent targets only) */\n toolMockReport?: ToolMockReport;\n}\n\n/**\n * Execute a dataset item against a scorer (LLM-as-judge calibration).\n * item.input should contain exactly what the scorer expects - direct passthrough.\n * For calibration: item.input = { input, output, groundTruth } (user structures it)\n */\nasync function executeScorer(\n scorer: MastraScorer<any, any, any, any>,\n item: { input: unknown; groundTruth?: unknown },\n): Promise<ExecutionResult> {\n try {\n // Direct passthrough - scorer receives item.input exactly as provided\n // User structures item.input to match scorer's expected shape (e.g., { input, output, groundTruth })\n const result = await scorer.run(item.input as any);\n\n // Validate score is a number\n const score = typeof result.score === 'number' && !isNaN(result.score) ? result.score : null;\n\n if (score === null && result.score !== undefined) {\n console.warn(`Scorer ${scorer.id} returned invalid score: ${result.score}`);\n }\n\n return {\n output: {\n score,\n reason: typeof result.reason === 'string' ? result.reason : null,\n },\n error: null,\n traceId: null, // Scorers don't produce traces\n };\n } catch (error) {\n return {\n output: null,\n error: {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n traceId: null,\n };\n }\n}\n\n/** Maximum number of suspend/resume cycles to prevent infinite loops */\nconst MAX_RESUME_CYCLES = 10;\n\n/**\n * Execute a dataset item against a target (agent, workflow, scorer, processor).\n * Phase 2: agent/workflow. Phase 4: scorer. Processor deferred.\n */\nexport async function executeTarget(\n target: Target,\n targetType: TargetType,\n item: {\n input: unknown;\n groundTruth?: unknown;\n metadata?: Record<string, unknown>;\n resumeSteps?: Record<string, unknown>;\n resumeData?: unknown;\n },\n options?: {\n signal?: AbortSignal;\n requestContext?: Record<string, unknown>;\n experimentId?: string;\n versions?: VersionOverrides;\n /** Item-level static tool mocks (agent targets only). */\n toolMocks?: ItemToolMock[];\n },\n): Promise<ExecutionResult> {\n try {\n const signal = options?.signal;\n\n // Check if already aborted before starting\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException('The operation was aborted.', 'AbortError');\n }\n\n let executionPromise: Promise<ExecutionResult>;\n switch (targetType) {\n case 'agent':\n executionPromise = executeAgent(\n target as Agent,\n item,\n signal,\n options?.requestContext,\n options?.experimentId,\n options?.versions,\n options?.toolMocks,\n );\n break;\n case 'workflow':\n executionPromise = executeWorkflow(target as Workflow, item, options?.requestContext);\n break;\n case 'scorer':\n executionPromise = executeScorer(target as MastraScorer<any, any, any, any>, item);\n break;\n case 'processor':\n // Processor targets dropped from roadmap - not a core use case\n throw new Error(`Target type '${targetType}' not yet supported.`);\n default:\n throw new Error(`Unknown target type: ${targetType}`);\n }\n\n // Race execution against signal abort (ensures timeout works even if target ignores signal)\n if (signal) {\n return await raceWithSignal(executionPromise, signal);\n }\n\n return await executionPromise;\n } catch (error) {\n return {\n output: null,\n error: {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n traceId: null,\n };\n }\n}\n\n/**\n * Race a promise against an AbortSignal. Rejects with the signal's reason when aborted.\n */\nfunction raceWithSignal<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) {\n return Promise.reject(signal.reason ?? new DOMException('The operation was aborted.', 'AbortError'));\n }\n\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason ?? new DOMException('The operation was aborted.', 'AbortError'));\n };\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n promise.then(\n value => {\n signal.removeEventListener('abort', onAbort);\n resolve(value);\n },\n err => {\n signal.removeEventListener('abort', onAbort);\n reject(err);\n },\n );\n });\n}\n\n/**\n * Execute a dataset item against an agent.\n * Uses generate() for both v1 and v2 models.\n */\nasync function executeAgent(\n agent: Agent,\n item: { input: unknown; groundTruth?: unknown },\n signal?: AbortSignal,\n requestContext?: Record<string, unknown>,\n experimentId?: string,\n versions?: VersionOverrides,\n toolMocks?: ItemToolMock[],\n): Promise<ExecutionResult> {\n const model = await agent.getModel();\n\n // Both generate() and generateLegacy() return different types (FullOutput vs GenerateTextResult)\n // but share the fields we extract. Cast input to MessageListInput at the boundary.\n const input = item.input as MessageListInput;\n\n const reqCtx: RequestContext | undefined = requestContext\n ? new RequestContext(Object.entries(requestContext))\n : undefined;\n\n // Pass experimentId as tracing metadata so it appears on the AGENT_RUN span\n const tracingOptions = experimentId ? { metadata: { experimentId } } : undefined;\n\n // Build a fresh matcher per item run so ordered consumption is deterministic and\n // not leaked across retries. Compose with the agent's configured hooks.\n const matcher = new ToolMockMatcher(toolMocks);\n\n // When the item declares mocks, abort the whole run the instant a mocked tool is\n // mis-called so the model cannot go on to invoke later (possibly side-effecting,\n // unmocked) tools live. The mock-abort signal is combined with the outer signal.\n const mockAbort = matcher.hasMocks ? new AbortController() : undefined;\n const mockHooks = matcher.hasMocks ? buildToolMockHooks(agent, matcher, mockAbort!) : undefined;\n const generateSignal =\n mockAbort && signal ? AbortSignal.any([signal, mockAbort.signal]) : (mockAbort?.signal ?? signal);\n\n // Force sequential tool execution when mocks exist so the provider's tool-call\n // order equals the execution (and consumption) order — deterministic ordered\n // consumption of repeated (toolName, args) mocks. No cost for mock-free runs.\n const mockConcurrency = matcher.hasMocks ? { toolCallConcurrency: 1 } : undefined;\n\n let rawResult: unknown;\n try {\n rawResult = isSupportedLanguageModel(model)\n ? await agent.generate(input, {\n scorers: {},\n returnScorerData: true,\n abortSignal: generateSignal,\n ...(reqCtx ? { requestContext: reqCtx } : {}),\n ...(tracingOptions ? { tracingOptions } : {}),\n ...(versions ? { versions } : {}),\n ...(mockHooks ? { hooks: mockHooks } : {}),\n ...(mockConcurrency ?? {}),\n })\n : await agent.generateLegacy(input, {\n scorers: {},\n returnScorerData: true,\n abortSignal: generateSignal,\n ...(reqCtx ? { requestContext: reqCtx } : {}),\n ...(tracingOptions ? { tracingOptions } : {}),\n ...(mockHooks ? { hooks: mockHooks } : {}),\n ...(mockConcurrency ?? {}),\n });\n } catch (error) {\n // A mock failure aborts the run mid-flight: surface the deterministic coded\n // error instead of the raw abort. Any other error rethrows unchanged.\n const mockReport = matcher.hasMocks ? matcher.report() : undefined;\n if (mockReport?.failure) {\n return toolMockFailureResult(mockReport, null);\n }\n throw error;\n }\n\n // Narrow to the common fields we need — both v1 and v2 results share these\n const result = rawResult as AgentGenerateResult;\n\n const traceId = result.traceId ?? null;\n const scoringData = result.scoringData;\n\n const toolMockReport = matcher.hasMocks ? matcher.report() : undefined;\n\n // Fallback for the race where the model finishes a step before the abort\n // propagates: the matcher still recorded the first failure, so fail the item\n // deterministically with the coded error. The mis-called tool never ran live.\n if (toolMockReport?.failure) {\n return toolMockFailureResult(toolMockReport, traceId);\n }\n\n // Only persist fields relevant to experiment evaluation — drop provider metadata,\n // duplicate messages, steps trace, and other debugging internals\n const trimmedOutput = {\n text: result.text,\n object: result.object,\n toolCalls: result.toolCalls,\n toolResults: result.toolResults,\n sources: result.sources,\n files: result.files,\n usage: result.usage,\n reasoningText: result.reasoningText,\n traceId,\n error: result.error ?? null,\n };\n\n return {\n output: trimmedOutput,\n error: null,\n traceId,\n scorerInput: scoringData?.input,\n scorerOutput: scoringData?.output,\n ...(toolMockReport ? { toolMockReport } : {}),\n };\n}\n\n/** Build the deterministic, non-retryable failure result for a mis-called mock. */\nfunction toolMockFailureResult(report: ToolMockReport, traceId: string | null): ExecutionResult {\n const failure = report.failure!;\n return {\n output: null,\n error: {\n message: `Mocked tool \"${failure.toolName}\" was called with arguments that did not match an available mock (${failure.code}).`,\n code: failure.code,\n },\n traceId,\n toolMockReport: report,\n };\n}\n\n/**\n * Compose item-level tool mocks with the agent's configured tool hooks into a\n * single set of run-level hooks.\n *\n * Composition order (per spec):\n * 1. User `beforeToolCall` (if `{ proceed: false }`, short-circuit — the mock is\n * left unconsumed and reported as such; user `afterToolCall` is NOT called,\n * matching the agent's own short-circuit behavior).\n * 2. Mock matcher — `serve` returns the mocked output; `fail` aborts the run so\n * the model cannot call any further (possibly unmocked, side-effecting) tools\n * live; `live` falls through to the real tool.\n * 3. User `afterToolCall` runs for served mocks (the agent skips its own on\n * short-circuit, so it is invoked here to honor the documented composition).\n *\n * Ordered consumption of repeated `(toolName, args)` mocks is deterministic because\n * the caller forces `toolCallConcurrency: 1` when mocks exist, so tool calls arrive\n * (and consume) in the provider's call order — no mutex needed.\n */\nfunction buildToolMockHooks(agent: Agent, matcher: ToolMockMatcher, mockAbort: AbortController): ToolHooks {\n const userHooks = agent.getConfiguredToolHooks();\n\n return {\n beforeToolCall: async context => {\n // 1. User hook first — a short-circuit leaves the mock unconsumed.\n const userResult = await userHooks?.beforeToolCall?.(context);\n if (userResult?.proceed === false) {\n return userResult;\n }\n\n // 2. Mock matcher.\n const resolution = matcher.resolve(context.toolName, context.input);\n if (resolution.kind === 'serve') {\n await userHooks?.afterToolCall?.({ ...context, output: resolution.output });\n return { proceed: false, output: resolution.output };\n }\n if (resolution.kind === 'fail') {\n // Abort the whole run immediately. The matcher recorded the first failure;\n // the item fails deterministically via the catch path. Short-circuit the\n // tool here too so the mis-called tool never runs live even before the\n // abort propagates.\n mockAbort.abort(new Error(`Tool mock failure for \"${context.toolName}\" (${resolution.code})`));\n return { proceed: false, output: { error: resolution.code } };\n }\n\n // 3. `live` — fall through to the real tool.\n return undefined;\n },\n // Pass the user's afterToolCall through as-is (preserving undefined) so the\n // agent skips a no-op call when the user configured no afterToolCall. Served\n // mocks invoke it manually above, since they short-circuit the real tool.\n afterToolCall: userHooks?.afterToolCall,\n };\n}\n\n/**\n * Extract resume data from item fields and metadata.\n *\n * Checks top-level `resumeSteps`/`resumeData` first (inline data path),\n * then falls back to `metadata.resumeSteps`/`metadata.resumeData` (storage-backed path).\n *\n * Supports two shapes:\n * 1. Keyed by step ID: `resumeSteps: { \"step-id\": <payload> }`\n * Used when the workflow may suspend on multiple steps and each needs distinct data.\n * 2. Flat payload: `resumeData: <payload>`\n * Used when the workflow has a single suspended step (auto-detected).\n */\nfunction extractResumeData(item: {\n metadata?: Record<string, unknown>;\n resumeSteps?: Record<string, unknown>;\n resumeData?: unknown;\n}): {\n perStep?: Record<string, unknown>;\n flat?: unknown;\n} {\n // Top-level fields (from inline DataItem) take precedence.\n // Use explicit `undefined` checks rather than `??` so that falsy values\n // like `null`, `false`, `0`, `\"\"` are treated as valid resume payloads.\n const perStep =\n item.resumeSteps !== undefined\n ? item.resumeSteps\n : (item.metadata?.resumeSteps as Record<string, unknown> | undefined);\n const flat = item.resumeData !== undefined ? item.resumeData : item.metadata?.resumeData;\n return { perStep, flat };\n}\n\n/**\n * Execute a dataset item against a workflow.\n * Creates a run with scorers disabled to avoid double-scoring.\n *\n * When the workflow suspends, checks for resume data in `item.metadata`\n * (via `resumeSteps` keyed by step ID or `resumeData` for single-step workflows)\n * and automatically resumes. Loops through multiple suspend/resume cycles up to\n * MAX_RESUME_CYCLES to support multi-step suspend workflows.\n *\n * Mirrors `executeWorkflow` in evals/run so dataset experiments and runEvals\n * produce the same observability spans and scoring data for workflow targets.\n */\nasync function executeWorkflow(\n workflow: Workflow,\n item: {\n input: unknown;\n groundTruth?: unknown;\n metadata?: Record<string, unknown>;\n resumeSteps?: Record<string, unknown>;\n resumeData?: unknown;\n },\n requestContext?: Record<string, unknown>,\n): Promise<ExecutionResult> {\n const reqCtx: RequestContext | undefined = requestContext\n ? new RequestContext(Object.entries(requestContext))\n : undefined;\n const observabilityContext = resolveObservabilityContext({});\n\n const run = await workflow.createRun({ disableScorers: true });\n let result = await run.start({\n inputData: item.input,\n ...(reqCtx ? { requestContext: reqCtx } : {}),\n ...observabilityContext,\n });\n\n // Auto-resume loop: if the workflow suspends and resume data is provided,\n // resume the workflow automatically. Cap iterations to prevent infinite loops.\n const { perStep, flat } = extractResumeData(item);\n const hasResumeData = perStep !== undefined || flat !== undefined;\n\n if (hasResumeData) {\n let cycle = 0;\n while (result.status === 'suspended' && cycle < MAX_RESUME_CYCLES) {\n cycle++;\n\n // Determine which steps are suspended\n const suspendedPaths: string[][] = result.suspended ?? [];\n if (suspendedPaths.length === 0) break;\n\n // For each suspended step, look up resume data\n const firstSuspendedStep = suspendedPaths[0]?.[0];\n if (!firstSuspendedStep) break;\n\n // Resolve resume data: per-step map takes precedence, then flat fallback.\n // Use explicit undefined check so falsy values (null, false, 0) are forwarded.\n const perStepValue = perStep?.[firstSuspendedStep];\n const stepResumeData = perStepValue !== undefined ? perStepValue : flat;\n if (stepResumeData === undefined) break; // No data for this step, stop resuming\n\n result = await run.resume({\n resumeData: stepResumeData,\n step: firstSuspendedStep,\n ...(reqCtx ? { requestContext: reqCtx } : {}),\n ...observabilityContext,\n });\n }\n }\n\n return handleWorkflowResult(result);\n}\n\n/**\n * Map a terminal WorkflowResult to an ExecutionResult.\n * Uses a loose `result: any` parameter because WorkflowResult is heavily generic;\n * status-narrowing guards below keep accesses safe.\n */\n\nfunction handleWorkflowResult(result: any): ExecutionResult {\n // TracingProperties is intersected on every WorkflowResult variant\n const traceId = result.traceId ?? null;\n const spanId = result.spanId ?? null;\n\n if (result.status === 'success') {\n return {\n output: result.result,\n error: null,\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n if (result.status === 'failed') {\n return {\n output: null,\n error: { message: result.error?.message ?? 'Workflow failed', stack: result.error?.stack },\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n if (result.status === 'tripwire') {\n return {\n output: null,\n error: { message: `Workflow tripwire: ${result.tripwire?.reason ?? 'Unknown reason'}` },\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n if (result.status === 'suspended') {\n // Workflow suspended but no resume data was provided (or exhausted).\n // Return partial results with suspend payload for debugging.\n return {\n output: result.suspendPayload ?? null,\n error: {\n message:\n 'Workflow suspended — provide resume data via item.resumeSteps/item.resumeData (or metadata.resumeSteps/metadata.resumeData) to auto-resume',\n },\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n if (result.status === 'paused') {\n return {\n output: null,\n error: { message: 'Workflow paused - not yet supported in dataset experiments' },\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n // Catch-all for any other status\n return {\n output: null,\n error: { message: `Workflow ended with unexpected status: ${result.status}` },\n traceId,\n spanId,\n };\n}\n","import type { MastraScorer } from '../../evals/base';\nimport { extractTrajectory, extractTrajectoryFromTrace } from '../../evals/types';\nimport type { ScorerRunInputForAgent, ScorerRunOutputForAgent, Trajectory } from '../../evals/types';\nimport type { Mastra } from '../../mastra';\nimport { validateAndSaveScore } from '../../mastra/hooks';\nimport { EntityType } from '../../observability';\nimport type { CorrelationContext } from '../../observability';\nimport type { MastraCompositeStore } from '../../storage/base';\nimport type { TargetType } from '../../storage/types';\nimport type { StepResult } from '../../workflows';\nimport type { ScorerResult } from './types';\n\nfunction toScorerTargetEntityType(targetType?: TargetType): EntityType | undefined {\n switch (targetType) {\n case 'agent':\n return EntityType.AGENT;\n case 'workflow':\n return EntityType.WORKFLOW_RUN;\n case 'scorer':\n return EntityType.SCORER;\n default:\n return undefined;\n }\n}\n\n/**\n * Resolve scorers from mixed array of instances and string IDs.\n * String IDs are looked up from Mastra's scorer registry.\n */\nexport function resolveScorers(\n mastra: Mastra,\n scorers?: (MastraScorer<any, any, any, any> | string)[],\n): MastraScorer<any, any, any, any>[] {\n if (!scorers || scorers.length === 0) return [];\n\n return scorers\n .map(scorer => {\n if (typeof scorer === 'string') {\n const resolved = mastra.getScorerById(scorer);\n if (!resolved) {\n console.warn(`Scorer not found: ${scorer}`);\n return null;\n }\n return resolved;\n }\n return scorer;\n })\n .filter((s): s is MastraScorer<any, any, any, any> => s !== null);\n}\n\n/**\n * Attempt to extract a Trajectory from the observability trace store.\n * Falls back to undefined if storage is unavailable or the trace has no spans.\n */\nasync function extractTrajectoryFromStorage(\n storage: MastraCompositeStore | null,\n traceId?: string,\n): Promise<Trajectory | undefined> {\n if (!storage || !traceId) return undefined;\n try {\n const observabilityStore = await storage.getStore('observability');\n if (!observabilityStore) return undefined;\n const trace = await observabilityStore.getTrace({ traceId });\n if (!trace?.spans?.length) return undefined;\n return extractTrajectoryFromTrace(trace.spans);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Workflow-specific data forwarded to scorers so they can inspect step-level\n * input/output and the executed step path. Surfaced via `targetMetadata` on\n * the scorer run so existing scorer signatures stay unchanged.\n */\nexport interface WorkflowScorerData {\n stepResults?: Record<string, StepResult<any, any, any, any>>;\n stepExecutionPath?: string[];\n spanId?: string | null;\n}\n\n/**\n * Run all scorers for a single item result.\n * Errors are isolated per scorer - one failing scorer doesn't affect others.\n * Trajectory scorers (scorer.type === 'trajectory') receive a pre-extracted\n * Trajectory as their output, mirroring the dispatch runEvals performs.\n */\nexport async function runScorersForItem(\n scorers: MastraScorer<any, any, any, any>[],\n item: { input: unknown; groundTruth?: unknown; metadata?: Record<string, unknown> },\n output: unknown,\n storage: MastraCompositeStore | null,\n runId: string,\n targetType: TargetType,\n targetId: string,\n itemId: string,\n scorerInput?: ScorerRunInputForAgent,\n scorerOutput?: ScorerRunOutputForAgent,\n traceId?: string,\n workflowData?: WorkflowScorerData,\n): Promise<ScorerResult[]> {\n if (scorers.length === 0) return [];\n\n // Pre-extract trajectory once for all trajectory scorers in this batch.\n // Try the trace store first (requires observability storage + traceId), then\n // fall back to extracting from the raw MastraDBMessage[] scoring output.\n const hasTrajectoryScorer = scorers.some(s => s.type === 'trajectory');\n let trajectoryOutput: Trajectory | undefined;\n if (hasTrajectoryScorer) {\n const traceTrajectory = await extractTrajectoryFromStorage(storage, traceId);\n trajectoryOutput = traceTrajectory ?? (scorerOutput ? extractTrajectory(scorerOutput) : { steps: [] });\n }\n\n // Build correlation context so scorers can emit scores with full experiment context\n const targetCorrelationContext: CorrelationContext = {\n ...(traceId ? { traceId } : {}),\n entityType: toScorerTargetEntityType(targetType),\n entityId: targetId,\n entityName: targetId,\n experimentId: runId,\n };\n\n const settled = await Promise.allSettled(\n scorers.map(async scorer => {\n const { result, promptMetadata } = await runScorerSafe(\n scorer,\n item,\n output,\n scorerInput,\n scorerOutput,\n targetType,\n traceId,\n targetCorrelationContext,\n scorer.type === 'trajectory' ? trajectoryOutput : undefined,\n workflowData,\n );\n\n // Persist score if storage available and score was computed\n if (storage && result.score !== null) {\n try {\n // Legacy score-store emission. This path is being deprecated.\n await validateAndSaveScore(storage, {\n scorerId: scorer.id,\n score: result.score,\n reason: result.reason ?? undefined,\n input: item.input,\n output,\n additionalContext: item.metadata,\n entityType: targetType.toUpperCase(),\n entityId: itemId,\n source: 'TEST',\n runId,\n traceId,\n scorer: {\n id: scorer.id,\n name: scorer.name,\n description: scorer.description ?? '',\n hasJudge: !!scorer.judge,\n },\n entity: {\n id: targetId,\n name: targetId,\n },\n ...promptMetadata,\n });\n } catch (saveError) {\n // TODO: Remove this warning path once the old scores storage is deprecated.\n // Log but don't fail - score persistence is best-effort\n console.warn(`Failed to save score for scorer ${scorer.id}:`, saveError);\n }\n }\n\n return result;\n }),\n );\n\n return settled.map((s, i) => {\n if (s.status === 'fulfilled') return s.value;\n const scorer = scorers[i]!;\n return {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: String(s.reason),\n targetScope: scorer.type === 'trajectory' ? 'trajectory' : 'span',\n };\n });\n}\n\n/** Prompt/step metadata returned by scorer.run() for DB persistence. */\ninterface ScorerPromptMetadata {\n generateScorePrompt?: string;\n generateReasonPrompt?: string;\n preprocessStepResult?: Record<string, unknown>;\n preprocessPrompt?: string;\n analyzeStepResult?: Record<string, unknown>;\n analyzePrompt?: string;\n}\n\n/**\n * Run a single scorer safely, catching any errors.\n * Returns both the ScorerResult and prompt metadata for DB persistence.\n * When trajectoryOutput is provided the scorer receives it as run.output,\n * honoring the type: 'trajectory' contract.\n */\nasync function runScorerSafe(\n scorer: MastraScorer<any, any, any, any>,\n item: { input: unknown; groundTruth?: unknown; metadata?: Record<string, unknown> },\n output: unknown,\n scorerInput?: ScorerRunInputForAgent,\n scorerOutput?: ScorerRunOutputForAgent,\n targetType?: TargetType,\n targetTraceId?: string,\n targetCorrelationContext?: CorrelationContext,\n trajectoryOutput?: Trajectory,\n workflowData?: WorkflowScorerData,\n): Promise<{ result: ScorerResult; promptMetadata: ScorerPromptMetadata }> {\n try {\n const effectiveOutput = trajectoryOutput ?? scorerOutput ?? output;\n const effectiveScope = trajectoryOutput ? 'trajectory' : 'span';\n\n // Surface step-level data via targetMetadata so workflow scorers can\n // inspect per-step input/output without changing the scorer signature.\n // Trajectory scorers already receive the Trajectory as their output, so\n // the step metadata is only relevant for non-trajectory workflow scorers.\n const targetMetadata: Record<string, unknown> | undefined =\n !trajectoryOutput && workflowData && (workflowData.stepResults || workflowData.stepExecutionPath)\n ? {\n ...(workflowData.stepResults ? { stepResults: workflowData.stepResults } : {}),\n ...(workflowData.stepExecutionPath ? { stepExecutionPath: workflowData.stepExecutionPath } : {}),\n }\n : undefined;\n\n const scoreResult: unknown = await scorer.run({\n input: scorerInput ?? item.input,\n output: effectiveOutput,\n groundTruth: item.groundTruth,\n scoreSource: 'experiment',\n targetScope: effectiveScope,\n targetEntityType: toScorerTargetEntityType(targetType),\n targetTraceId,\n ...(workflowData?.spanId ? { targetSpanId: workflowData.spanId } : {}),\n ...(targetCorrelationContext ? { targetCorrelationContext } : {}),\n ...(targetMetadata ? { targetMetadata } : {}),\n });\n\n // Extract fields with typeof guards — scorer run result types use complex\n // conditional generics that don't resolve cleanly with MastraScorer<any,…>.\n if (typeof scoreResult !== 'object' || scoreResult === null) {\n return {\n result: {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: `Scorer ${scorer.name} (${scorer.id}) returned invalid result: expected object, got ${scoreResult === null ? 'null' : typeof scoreResult} (${String(scoreResult)})`,\n },\n promptMetadata: {},\n };\n }\n\n const fields = scoreResult as Record<string, unknown>;\n const score = typeof fields.score === 'number' ? fields.score : null;\n const reason = typeof fields.reason === 'string' ? fields.reason : null;\n\n const str = (key: string): string | undefined =>\n typeof fields[key] === 'string' ? (fields[key] as string) : undefined;\n const obj = (key: string): Record<string, unknown> | undefined => {\n const val = fields[key];\n return typeof val === 'object' && val !== null ? (val as Record<string, unknown>) : undefined;\n };\n\n return {\n result: {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score,\n reason,\n error: null,\n targetScope: effectiveScope,\n },\n promptMetadata: {\n generateScorePrompt: str('generateScorePrompt'),\n generateReasonPrompt: str('generateReasonPrompt'),\n preprocessStepResult: obj('preprocessStepResult'),\n preprocessPrompt: str('preprocessPrompt'),\n analyzeStepResult: obj('analyzeStepResult'),\n analyzePrompt: str('analyzePrompt'),\n },\n };\n } catch (error) {\n return {\n result: {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: error instanceof Error ? error.message : String(error),\n targetScope: trajectoryOutput ? 'trajectory' : 'span',\n },\n promptMetadata: {},\n };\n }\n}\n\n/**\n * Resolve step-scoped scorers from a `Record<stepId, (MastraScorer | string)[]>`.\n * String IDs are looked up from Mastra's scorer registry; missing IDs are skipped\n * with a warning (matching `resolveScorers`).\n */\nexport function resolveStepScorers(\n mastra: Mastra,\n stepsConfig?: Record<string, (MastraScorer<any, any, any, any> | string)[]>,\n): Record<string, MastraScorer<any, any, any, any>[]> {\n if (!stepsConfig) return {};\n const resolved: Record<string, MastraScorer<any, any, any, any>[]> = {};\n for (const [stepId, scorers] of Object.entries(stepsConfig)) {\n const stepScorers = resolveScorers(mastra, scorers);\n if (stepScorers.length > 0) resolved[stepId] = stepScorers;\n }\n return resolved;\n}\n\n/**\n * Run step-scoped scorers for a single workflow item. Mirrors the per-step\n * dispatch in `runEvals`: each scorer runs against `stepResult.payload` and\n * `stepResult.output`, with `targetScope: 'span'` and\n * `targetEntityType: WORKFLOW_STEP`. The returned `ScorerResult` carries the\n * originating `stepId` so callers can disambiguate per-step results in the\n * flat `scores` array. Steps whose result is missing or did not succeed\n * surface as an error `ScorerResult` rather than disappearing silently.\n *\n * Errors are isolated per scorer (consistent with `runScorersForItem`); a\n * failing scorer produces a `ScorerResult` with `error` set, not a throw.\n */\nexport async function runStepScorersForItem(\n stepScorers: Record<string, MastraScorer<any, any, any, any>[]>,\n item: { input: unknown; groundTruth?: unknown; metadata?: Record<string, unknown> },\n workflowData: WorkflowScorerData | undefined,\n storage: MastraCompositeStore | null,\n runId: string,\n targetType: TargetType,\n targetId: string,\n itemId: string,\n traceId?: string,\n): Promise<ScorerResult[]> {\n const stepIds = Object.keys(stepScorers);\n if (stepIds.length === 0) return [];\n\n const results: ScorerResult[] = [];\n const stepResults = workflowData?.stepResults;\n\n for (const stepId of stepIds) {\n const scorers = stepScorers[stepId]!;\n const stepResult = stepResults?.[stepId];\n\n // Skip silently when the step didn't run or didn't succeed — matches runEvals.\n // Surface this as an \"error\" ScorerResult so consumers can see the skip in the\n // flat results array (rather than disappear without a trace).\n if (!stepResult || stepResult.status !== 'success' || stepResult.output === undefined) {\n for (const scorer of scorers) {\n results.push({\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: `Step \"${stepId}\" did not produce a successful output (status: ${stepResult?.status ?? 'missing'})`,\n targetScope: 'span',\n stepId,\n });\n }\n continue;\n }\n\n const stepInput = stepResult.payload !== undefined ? stepResult.payload : item.input;\n const stepOutput = stepResult.output;\n\n const targetCorrelationContext: CorrelationContext = {\n ...(traceId ? { traceId } : {}),\n entityType: EntityType.WORKFLOW_STEP,\n entityId: stepId,\n entityName: stepId,\n experimentId: runId,\n };\n\n const settled = await Promise.allSettled(\n scorers.map(async scorer => {\n try {\n const scoreResult: unknown = await scorer.run({\n input: stepInput,\n output: stepOutput,\n groundTruth: item.groundTruth,\n scoreSource: 'experiment',\n targetScope: 'span',\n targetEntityType: EntityType.WORKFLOW_STEP,\n targetTraceId: traceId,\n ...(targetCorrelationContext ? { targetCorrelationContext } : {}),\n });\n\n if (typeof scoreResult !== 'object' || scoreResult === null) {\n return {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: `Scorer ${scorer.name} (${scorer.id}) returned invalid result on step ${stepId}`,\n targetScope: 'span' as const,\n stepId,\n };\n }\n const fields = scoreResult as Record<string, unknown>;\n const score = typeof fields.score === 'number' ? fields.score : null;\n const reason = typeof fields.reason === 'string' ? fields.reason : null;\n\n // Persist score (best-effort, mirrors runScorersForItem)\n if (storage && score !== null) {\n try {\n await validateAndSaveScore(storage, {\n scorerId: scorer.id,\n score,\n reason: reason ?? undefined,\n input: stepInput,\n output: stepOutput,\n additionalContext: { ...item.metadata, stepId },\n entityType: 'WORKFLOW_STEP',\n entityId: itemId,\n source: 'TEST',\n runId,\n traceId,\n scorer: {\n id: scorer.id,\n name: scorer.name,\n description: scorer.description ?? '',\n hasJudge: !!scorer.judge,\n },\n entity: {\n id: targetId,\n name: targetId,\n },\n });\n } catch (saveError) {\n console.warn(`Failed to save score for step scorer ${scorer.id} on ${stepId}:`, saveError);\n }\n }\n\n return {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score,\n reason,\n error: null,\n targetScope: 'span' as const,\n stepId,\n };\n } catch (error) {\n return {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: error instanceof Error ? error.message : String(error),\n targetScope: 'span' as const,\n stepId,\n };\n }\n }),\n );\n\n for (let i = 0; i < settled.length; i++) {\n const s = settled[i]!;\n if (s.status === 'fulfilled') {\n results.push(s.value);\n } else {\n const scorer = scorers[i]!;\n results.push({\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: String(s.reason),\n targetScope: 'span',\n stepId,\n });\n }\n }\n }\n\n // targetType/targetId are intentionally accepted but only used for persistence\n // entity context; the dispatch itself is workflow-step scoped.\n void targetType;\n return results;\n}\n","/**\n * Experiment Analytics Aggregation Helpers\n *\n * Pure functions for computing statistics from raw score data.\n * Used by compareExperiments to build ScorerStats and detect regressions.\n */\n\nimport type { ScoreRowData } from '../../../evals/types';\nimport type { ScorerStats } from './types';\n\n/**\n * Compute the arithmetic mean of an array of numbers.\n *\n * @param values - Array of numbers to average\n * @returns Mean value, or 0 if array is empty\n */\nexport function computeMean(values: number[]): number {\n if (values.length === 0) {\n return 0;\n }\n const sum = values.reduce((acc, val) => acc + val, 0);\n return sum / values.length;\n}\n\n/**\n * Compute aggregate statistics for a set of scores.\n *\n * Metrics:\n * - errorRate: proportion of items with null scores (errors)\n * - passRate: proportion of scored items meeting threshold\n * - avgScore: mean of non-null scores\n *\n * @param scores - Score records from storage\n * @param passThreshold - Absolute threshold for pass (score >= threshold)\n * @returns ScorerStats with all computed metrics\n */\nexport function computeScorerStats(scores: ScoreRowData[], passThreshold: number = 0.5): ScorerStats {\n const totalItems = scores.length;\n\n if (totalItems === 0) {\n return {\n errorRate: 0,\n errorCount: 0,\n passRate: 0,\n passCount: 0,\n avgScore: 0,\n scoreCount: 0,\n totalItems: 0,\n };\n }\n\n // Separate null scores (errors) from valid scores\n const validScores: number[] = [];\n let errorCount = 0;\n\n for (const score of scores) {\n if (score.score === null || score.score === undefined) {\n errorCount++;\n } else {\n validScores.push(score.score);\n }\n }\n\n const scoreCount = validScores.length;\n const errorRate = errorCount / totalItems;\n\n // Pass rate is computed over items with valid scores only\n const passCount = validScores.filter(s => s >= passThreshold).length;\n const passRate = scoreCount > 0 ? passCount / scoreCount : 0;\n\n // Average score excludes errors\n const avgScore = computeMean(validScores);\n\n return {\n errorRate,\n errorCount,\n passRate,\n passCount,\n avgScore,\n scoreCount,\n totalItems,\n };\n}\n\n/**\n * Determine if a score delta represents a regression.\n *\n * @param delta - Score difference (experiment B - experiment A)\n * @param threshold - Absolute threshold for regression detection\n * @param direction - Score direction ('higher-is-better' or 'lower-is-better')\n * @returns True if delta represents a regression\n *\n * @example\n * // Higher is better (default): negative delta is bad\n * isRegression(-0.1, 0.05, 'higher-is-better') // true (dropped more than 0.05)\n * isRegression(-0.01, 0.05, 'higher-is-better') // false (within tolerance)\n *\n * // Lower is better: positive delta is bad\n * isRegression(0.1, 0.05, 'lower-is-better') // true (increased more than 0.05)\n */\nexport function isRegression(\n delta: number,\n threshold: number,\n direction: 'higher-is-better' | 'lower-is-better' = 'higher-is-better',\n): boolean {\n if (direction === 'higher-is-better') {\n // Regression if score dropped below threshold\n // delta < -threshold means score dropped by more than threshold\n return delta < -threshold;\n } else {\n // Regression if score increased above threshold\n // delta > threshold means score increased by more than threshold\n return delta > threshold;\n }\n}\n","/**\n * Experiment Comparison\n *\n * Compare two experiments to detect score regressions.\n * Returns per-scorer deltas and per-item score diffs.\n */\n\nimport type { ScoreRowData } from '../../../evals/types';\nimport type { Mastra } from '../../../mastra';\nimport { computeScorerStats, isRegression } from './aggregate';\nimport type {\n CompareExperimentsConfig,\n ComparisonResult,\n ItemComparison,\n ScorerComparison,\n ScorerThreshold,\n} from './types';\n\n/**\n * Default threshold when not specified: no tolerance for regression.\n */\nconst DEFAULT_THRESHOLD: ScorerThreshold = {\n value: 0,\n direction: 'higher-is-better',\n};\n\n/**\n * Default pass threshold for computing pass rate.\n */\nconst DEFAULT_PASS_THRESHOLD = 0.5;\n\n/**\n * Compare two experiments to detect score regressions.\n *\n * @param mastra - Mastra instance for storage access\n * @param config - Comparison configuration\n * @returns ComparisonResult with per-scorer and per-item comparisons\n *\n * @example\n * ```typescript\n * const result = await compareExperiments(mastra, {\n * experimentIdA: 'baseline-experiment-id',\n * experimentIdB: 'candidate-experiment-id',\n * thresholds: {\n * 'accuracy': { value: 0.05, direction: 'higher-is-better' },\n * 'latency': { value: 100, direction: 'lower-is-better' },\n * },\n * });\n *\n * if (result.hasRegression) {\n * console.log('Quality regression detected!');\n * }\n * ```\n */\nexport async function compareExperiments(mastra: Mastra, config: CompareExperimentsConfig): Promise<ComparisonResult> {\n const { experimentIdA, experimentIdB, thresholds = {} } = config;\n const warnings: string[] = [];\n\n // 1. Get storage\n const storage = mastra.getStorage();\n if (!storage) {\n throw new Error('Storage not configured. Configure storage in Mastra instance.');\n }\n\n const experimentsStore = await storage.getStore('experiments');\n const scoresStore = await storage.getStore('scores');\n\n if (!experimentsStore) {\n throw new Error('ExperimentsStorage not configured.');\n }\n if (!scoresStore) {\n throw new Error('ScoresStorage not configured.');\n }\n\n // 2. Load both experiments\n const [experimentA, experimentB] = await Promise.all([\n experimentsStore.getExperimentById({ id: experimentIdA }),\n experimentsStore.getExperimentById({ id: experimentIdB }),\n ]);\n\n if (!experimentA) {\n throw new Error(`Experiment not found: ${experimentIdA}`);\n }\n if (!experimentB) {\n throw new Error(`Experiment not found: ${experimentIdB}`);\n }\n\n // 3. Check version mismatch\n const versionMismatch = experimentA.datasetVersion !== experimentB.datasetVersion;\n if (versionMismatch) {\n warnings.push(\n `Experiments have different dataset versions: ${experimentA.datasetVersion} vs ${experimentB.datasetVersion}`,\n );\n }\n\n // 4. Load results for both experiments\n const [resultsA, resultsB] = await Promise.all([\n experimentsStore.listExperimentResults({ experimentId: experimentIdA, pagination: { page: 0, perPage: false } }),\n experimentsStore.listExperimentResults({ experimentId: experimentIdB, pagination: { page: 0, perPage: false } }),\n ]);\n\n // 5. Load scores for both experiments\n const [scoresA, scoresB] = await Promise.all([\n scoresStore.listScoresByRunId({ runId: experimentIdA, pagination: { page: 0, perPage: false } }),\n scoresStore.listScoresByRunId({ runId: experimentIdB, pagination: { page: 0, perPage: false } }),\n ]);\n\n // 6. Handle empty experiments\n if (resultsA.results.length === 0 && resultsB.results.length === 0) {\n warnings.push('Both experiments have no results.');\n return buildEmptyResult(experimentA, experimentB, versionMismatch, warnings);\n }\n if (resultsA.results.length === 0) {\n warnings.push('Experiment A has no results.');\n }\n if (resultsB.results.length === 0) {\n warnings.push('Experiment B has no results.');\n }\n\n // 7. Find overlapping items\n const itemIdsA = new Set(resultsA.results.map(r => r.itemId));\n const itemIdsB = new Set(resultsB.results.map(r => r.itemId));\n const overlappingItemIds = [...itemIdsA].filter(id => itemIdsB.has(id));\n\n if (overlappingItemIds.length === 0) {\n warnings.push('No overlapping items between experiments.');\n }\n\n // 8. Group scores by scorer and item\n const scoresMapA = groupScoresByScorerAndItem(scoresA.scores);\n const scoresMapB = groupScoresByScorerAndItem(scoresB.scores);\n\n // 9. Find all unique scorers\n const allScorerIds = new Set([...Object.keys(scoresMapA), ...Object.keys(scoresMapB)]);\n\n // 10. Build per-scorer comparison\n const scorers: Record<string, ScorerComparison> = {};\n let hasRegression = false;\n\n for (const scorerId of allScorerIds) {\n const scorerScoresA = scoresMapA[scorerId] ?? {};\n const scorerScoresB = scoresMapB[scorerId] ?? {};\n\n // Get scores as arrays for stats computation\n const scoresArrayA = Object.values(scorerScoresA);\n const scoresArrayB = Object.values(scorerScoresB);\n\n // Get threshold config for this scorer\n const thresholdConfig = thresholds[scorerId] ?? DEFAULT_THRESHOLD;\n const threshold = thresholdConfig.value;\n const direction = thresholdConfig.direction ?? 'higher-is-better';\n\n // Compute stats\n const statsA = computeScorerStats(scoresArrayA, DEFAULT_PASS_THRESHOLD);\n const statsB = computeScorerStats(scoresArrayB, DEFAULT_PASS_THRESHOLD);\n\n // Compute delta and check regression\n const delta = statsB.avgScore - statsA.avgScore;\n const regressed = isRegression(delta, threshold, direction);\n\n if (regressed) {\n hasRegression = true;\n }\n\n scorers[scorerId] = {\n statsA,\n statsB,\n delta,\n regressed,\n threshold,\n };\n }\n\n // 11. Build per-item comparison\n const allItemIds = new Set([...itemIdsA, ...itemIdsB]);\n const items: ItemComparison[] = [];\n\n for (const itemId of allItemIds) {\n const inBothExperiments = itemIdsA.has(itemId) && itemIdsB.has(itemId);\n\n // Build scores for this item\n const itemScoresA: Record<string, number | null> = {};\n const itemScoresB: Record<string, number | null> = {};\n\n for (const scorerId of allScorerIds) {\n const scoreA = scoresMapA[scorerId]?.[itemId];\n const scoreB = scoresMapB[scorerId]?.[itemId];\n\n itemScoresA[scorerId] = scoreA?.score ?? null;\n itemScoresB[scorerId] = scoreB?.score ?? null;\n }\n\n items.push({\n itemId,\n inBothExperiments,\n scoresA: itemScoresA,\n scoresB: itemScoresB,\n });\n }\n\n return {\n experimentA: {\n id: experimentA.id,\n datasetVersion: experimentA.datasetVersion,\n },\n experimentB: {\n id: experimentB.id,\n datasetVersion: experimentB.datasetVersion,\n },\n versionMismatch,\n hasRegression,\n scorers,\n items,\n warnings,\n };\n}\n\n/**\n * Group scores by scorer ID, then by item ID.\n */\nfunction groupScoresByScorerAndItem(scores: ScoreRowData[]): Record<string, Record<string, ScoreRowData>> {\n const result: Record<string, Record<string, ScoreRowData>> = {};\n\n for (const score of scores) {\n const scorerId = score.scorerId;\n const itemId = score.entityId; // entityId is the item ID for experiment scores\n\n if (!result[scorerId]) {\n result[scorerId] = {};\n }\n result[scorerId][itemId] = score;\n }\n\n return result;\n}\n\n/**\n * Build an empty comparison result for edge cases.\n */\nfunction buildEmptyResult(\n experimentA: { id: string; datasetVersion: number | null },\n experimentB: { id: string; datasetVersion: number | null },\n versionMismatch: boolean,\n warnings: string[],\n): ComparisonResult {\n return {\n experimentA: {\n id: experimentA.id,\n datasetVersion: experimentA.datasetVersion,\n },\n experimentB: {\n id: experimentB.id,\n datasetVersion: experimentB.datasetVersion,\n },\n versionMismatch,\n hasRegression: false,\n scorers: {},\n items: [],\n warnings,\n };\n}\n","import { MastraError } from '../../error/index.js';\nimport type { MastraScorer } from '../../evals/base';\nimport type { Mastra } from '../../mastra';\nimport type { DatasetRecord } from '../../storage/types';\nimport { executeTarget } from './executor';\nimport type { Target, ExecutionResult } from './executor';\nimport { resolveScorers, resolveStepScorers, runScorersForItem, runStepScorersForItem } from './scorer';\nimport { TOOL_MOCK_MISMATCH, TOOL_MOCK_EXHAUSTED } from './tool-mocks';\nimport type { ItemToolMock } from './tool-mocks';\nimport type { ExperimentConfig, ExperimentSummary, ItemWithScores, ItemResult } from './types';\n\n/** Unified item shape used within experiment execution (bridges inline + versioned data) */\ntype ExperimentItem = {\n id: string; // item id (or generated for inline)\n datasetVersion: number | null; // null for inline experiments\n input: unknown;\n groundTruth?: unknown;\n requestContext?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n /** Resume data for suspended workflow steps, keyed by step ID */\n resumeSteps?: Record<string, unknown>;\n /** Flat resume data for single-step suspend workflows */\n resumeData?: unknown;\n /** Item-level static tool mocks (agent targets only) */\n toolMocks?: ItemToolMock[];\n};\n\n// Re-export types and helpers\nexport type {\n DataItem,\n ExperimentConfig,\n ExperimentSummary,\n ItemWithScores,\n ItemResult,\n ScorerResult,\n StartExperimentConfig,\n} from './types';\nexport { executeTarget, type Target, type ExecutionResult } from './executor';\nexport { resolveScorers, runScorersForItem } from './scorer';\nexport {\n ToolMockMatcher,\n TOOL_MOCK_MISMATCH,\n TOOL_MOCK_EXHAUSTED,\n type ItemToolMock,\n type ToolMockMatchArgs,\n type ToolMockReport,\n type ToolMockResolution,\n type ToolMockFailureCode,\n} from './tool-mocks';\n\n// Re-export analytics\nexport * from './analytics';\n\n/**\n * Run a dataset experiment against a target with optional scoring.\n *\n * Executes all items in the dataset concurrently (up to maxConcurrency) against\n * the specified target (agent or workflow). Optionally applies scorers to each\n * result and persists both results and scores to storage.\n *\n * @param mastra - Mastra instance for storage and target resolution\n * @param config - Experiment configuration\n * @returns ExperimentSummary with results and scores\n *\n * @example\n * ```typescript\n * const summary = await runExperiment(mastra, {\n * datasetId: 'my-dataset',\n * targetType: 'agent',\n * targetId: 'my-agent',\n * scorers: [accuracyScorer, latencyScorer],\n * maxConcurrency: 10,\n * });\n * console.log(`${summary.succeededCount}/${summary.totalItems} succeeded`);\n * ```\n */\nexport async function runExperiment(mastra: Mastra, config: ExperimentConfig): Promise<ExperimentSummary> {\n const {\n datasetId,\n targetType,\n targetId,\n scorers: scorerInput,\n version,\n maxConcurrency = 5,\n signal,\n itemTimeout,\n maxRetries = 0,\n experimentId: providedExperimentId,\n name,\n description,\n metadata,\n requestContext: globalRequestContext,\n agentVersion,\n versions,\n } = config;\n\n const startedAt = new Date();\n // Use provided experimentId (async trigger) or generate new one\n const experimentId = providedExperimentId ?? crypto.randomUUID();\n\n // 1. Get storage and resolve components\n const storage = mastra.getStorage();\n const datasetsStore = await storage?.getStore('datasets');\n const experimentsStore = await storage?.getStore('experiments');\n\n // Helper: if the experiment record was pre-created (async path) and we fail\n // during setup (Phase A/B), mark the experiment as failed so it doesn't stay stuck in 'pending'.\n const markFailedOnSetupError = async (err: unknown) => {\n if (providedExperimentId && experimentsStore) {\n try {\n await experimentsStore.updateExperiment({\n id: experimentId,\n status: 'failed',\n completedAt: new Date(),\n });\n } catch (updateErr) {\n mastra.getLogger()?.error(`Failed to mark experiment ${experimentId} as failed: ${updateErr}`);\n }\n }\n throw err;\n };\n\n // Phase A — Resolve items\n let items: ExperimentItem[];\n let datasetVersion: number | null;\n let datasetRecord: DatasetRecord | null | undefined;\n\n try {\n if (config.data) {\n // Inline data path — array or factory function\n const rawData = typeof config.data === 'function' ? await config.data() : config.data;\n items = rawData.map(dataItem => {\n const id = dataItem.id ?? crypto.randomUUID();\n return {\n id,\n datasetVersion: null,\n input: dataItem.input,\n groundTruth: dataItem.groundTruth,\n requestContext: dataItem.requestContext,\n metadata: dataItem.metadata,\n resumeSteps: dataItem.resumeSteps,\n resumeData: dataItem.resumeData,\n toolMocks: dataItem.toolMocks,\n };\n });\n datasetVersion = null;\n } else if (datasetId) {\n // Storage-backed data path (existing)\n if (!datasetsStore) {\n throw new Error('DatasetsStorage not configured. Configure storage in Mastra instance.');\n }\n\n datasetRecord = await datasetsStore.getDatasetById({ id: datasetId, filters: config.filters });\n if (!datasetRecord) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: `Dataset not found: ${datasetId}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n datasetVersion = version ?? datasetRecord.version;\n const versionItems = await datasetsStore.getItemsByVersion({\n datasetId,\n version: datasetVersion,\n });\n\n if (versionItems.length === 0) {\n throw new MastraError({\n id: 'EXPERIMENT_NO_ITEMS',\n text: `No items in dataset ${datasetId} at version ${datasetVersion}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n items = versionItems.map(v => ({\n id: v.id,\n datasetVersion: v.datasetVersion,\n input: v.input,\n groundTruth: v.groundTruth,\n requestContext: v.requestContext,\n metadata: v.metadata,\n toolMocks: v.toolMocks,\n }));\n } else {\n throw new Error('No data source: provide datasetId or data');\n }\n } catch (err) {\n await markFailedOnSetupError(err);\n throw err; // unreachable, but satisfies TS control flow\n }\n\n // Phase B — Resolve task function\n let execFn: (item: ExperimentItem, signal?: AbortSignal) => Promise<ExecutionResult>;\n\n try {\n if (config.task) {\n // Inline task path\n const taskFn = config.task;\n execFn = async (item, itemSignal) => {\n try {\n const result = await taskFn({\n input: item.input,\n mastra,\n groundTruth: item.groundTruth,\n metadata: item.metadata,\n signal: itemSignal,\n });\n return { output: result, error: null, traceId: null };\n } catch (err: unknown) {\n return {\n output: null,\n error: {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n },\n traceId: null,\n };\n }\n };\n } else if (targetType && targetId) {\n // Registry-based target path (existing)\n const resolved = await resolveTarget(mastra, targetType, targetId, agentVersion);\n if (!resolved) {\n throw new Error(`Target not found: ${targetType}/${targetId}`);\n }\n const { target } = resolved;\n execFn = (item, itemSignal) => {\n // Merge global request context with per-item request context (item takes precedence)\n const mergedRequestContext =\n globalRequestContext || item.requestContext ? { ...globalRequestContext, ...item.requestContext } : undefined;\n return executeTarget(target, targetType, item, {\n signal: itemSignal,\n requestContext: mergedRequestContext,\n experimentId,\n versions,\n toolMocks: targetType === 'agent' ? item.toolMocks : undefined,\n });\n };\n } else {\n throw new Error('No task: provide targetType+targetId or task');\n }\n } catch (err) {\n await markFailedOnSetupError(err);\n throw err; // unreachable, but satisfies TS control flow\n }\n\n // Tool mocks only apply to agent targets. If a dataset carrying toolMocks is reused\n // against a task/workflow/scorer target, the mocks are silently ignored — warn once\n // (not per item) so the misconfiguration is visible without log spam.\n const itemsWithToolMocks = items.filter(item => item.toolMocks?.length).length;\n if (targetType !== 'agent' && itemsWithToolMocks > 0) {\n mastra\n .getLogger()\n ?.warn(\n `Experiment target is \"${config.task ? 'task' : targetType}\" but ${itemsWithToolMocks} of ${items.length} dataset items declare toolMocks. ` +\n `Tool mocks only apply to agent targets and will be ignored.`,\n );\n }\n\n // Normalize categorized scorer config (AgentScorerConfig | WorkflowScorerConfig) to a flat\n // array so the existing merge/dedup/resolve logic below is unchanged.\n // Trajectory dispatch is handled per-scorer in runScorerSafe based on scorer.type.\n // Step scorers are kept separate (keyed by step ID) and dispatched per-step\n // after the flat scorers run, mirroring runEvals.\n let stepsConfigInput: Record<string, (MastraScorer<any, any, any, any> | string)[]> | undefined;\n const flatScorerInput: (MastraScorer<any, any, any, any> | string)[] | undefined = (() => {\n if (!scorerInput) return undefined;\n if (Array.isArray(scorerInput)) return scorerInput;\n // Categorized shape — flatten flat-style buckets into one array, keep steps separate\n const flat: (MastraScorer<any, any, any, any> | string)[] = [];\n if ('agent' in scorerInput && scorerInput.agent) flat.push(...scorerInput.agent);\n if ('workflow' in scorerInput && scorerInput.workflow) flat.push(...scorerInput.workflow);\n if ('trajectory' in scorerInput && scorerInput.trajectory) flat.push(...scorerInput.trajectory);\n if ('steps' in scorerInput && scorerInput.steps) {\n stepsConfigInput = scorerInput.steps;\n }\n return flat;\n })();\n\n // Merge dataset-attached scorers with explicitly provided scorers, then deduplicate\n let mergedScorerInput = flatScorerInput;\n const datasetScorerIds = datasetRecord?.scorerIds ?? [];\n if (datasetScorerIds.length > 0) {\n mergedScorerInput = [...(flatScorerInput ?? []), ...datasetScorerIds];\n }\n if (mergedScorerInput && mergedScorerInput.length > 0) {\n const seen = new Set<string>();\n mergedScorerInput = mergedScorerInput.filter(entry => {\n if (typeof entry === 'string') {\n if (seen.has(entry)) return false;\n seen.add(entry);\n return true;\n }\n // Keep all scorer instances — they are resolved by reference, not by ID\n return true;\n });\n }\n\n // Resolve scorers\n const scorers = resolveScorers(mastra, mergedScorerInput);\n // Resolve per-step scorers (keyed by step ID) for workflow targets\n const stepScorers = resolveStepScorers(mastra, stepsConfigInput);\n\n // 5. Create experiment record (if storage available and not pre-created)\n if (experimentsStore) {\n if (!providedExperimentId) {\n // Create new experiment record (sync trigger path)\n await experimentsStore.createExperiment({\n id: experimentId,\n name,\n description,\n metadata,\n datasetId: datasetId ?? null,\n datasetVersion,\n targetType: targetType ?? 'agent',\n targetId: targetId ?? 'inline',\n totalItems: items.length,\n agentVersion,\n organizationId: datasetRecord?.organizationId ?? null,\n projectId: datasetRecord?.projectId ?? null,\n });\n }\n // Update status to running (both sync and async paths)\n // Also set totalItems — needed for the async path where the experiment\n // was created with totalItems: 0 before items were resolved.\n await experimentsStore.updateExperiment({\n id: experimentId,\n status: 'running',\n totalItems: items.length,\n startedAt,\n });\n }\n\n // 6. Execute items with p-map\n let succeededCount = 0;\n let failedCount = 0;\n // Rows whose target run completed but whose persistence to\n // `mastra_experiment_results` failed. Surfaced on the summary so callers\n // can detect the DB being out of sync with the returned results.\n let persistenceFailures = 0;\n // Pre-allocate for deterministic ordering (results[i] matches items[i])\n const results: ItemWithScores[] = new Array(items.length);\n\n // Throttled progress updates\n const PROGRESS_UPDATE_INTERVAL = 2000;\n let lastProgressUpdate = 0;\n\n try {\n const pMap = (await import('p-map')).default;\n\n await pMap(\n items.map((item, idx) => ({ item, idx })),\n async ({ item, idx }) => {\n // Check for cancellation\n if (signal?.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n const itemStartedAt = new Date();\n // Compose per-item signal (timeout + run-level abort)\n let itemSignal: AbortSignal | undefined = signal;\n if (itemTimeout) {\n const timeoutSignal = AbortSignal.timeout(itemTimeout);\n itemSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;\n }\n\n // Retry loop\n let retryCount = 0;\n let execResult = await execFn(item, itemSignal);\n\n while (execResult.error && retryCount < maxRetries) {\n // Don't retry abort errors\n if (execResult.error.message.toLowerCase().includes('abort')) break;\n\n // Don't retry deterministic tool-mock failures — the matcher state cannot\n // change between attempts, so retrying would always fail identically.\n if (execResult.error.code === TOOL_MOCK_MISMATCH || execResult.error.code === TOOL_MOCK_EXHAUSTED) {\n break;\n }\n\n retryCount++;\n const delay = Math.min(1000 * Math.pow(2, retryCount - 1), 30000);\n const jitter = delay * 0.2 * Math.random();\n await new Promise(r => setTimeout(r, delay + jitter));\n\n // Re-check cancellation before retry\n if (signal?.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n execResult = await execFn(item, itemSignal);\n }\n\n const itemCompletedAt = new Date();\n\n // Track success/failure\n if (execResult.error) {\n failedCount++;\n } else {\n succeededCount++;\n }\n\n // Build item result. `persistenceError` starts null and is set below\n // if `addExperimentResult` throws so callers can detect rows that\n // never landed in storage.\n const itemResult: ItemResult = {\n itemId: item.id,\n itemVersion: item.datasetVersion ?? 0,\n input: item.input,\n output: execResult.output,\n groundTruth: item.groundTruth ?? null,\n error: execResult.error,\n startedAt: itemStartedAt,\n completedAt: itemCompletedAt,\n retryCount,\n persistenceError: null,\n ...(execResult.toolMockReport ? { toolMockReport: execResult.toolMockReport } : {}),\n };\n\n // Run scorers (inline, after target completes)\n const workflowData =\n execResult.stepResults || execResult.stepExecutionPath\n ? {\n stepResults: execResult.stepResults,\n stepExecutionPath: execResult.stepExecutionPath,\n spanId: execResult.spanId,\n }\n : undefined;\n\n const flatScores = await runScorersForItem(\n scorers,\n item,\n execResult.output,\n storage ?? null,\n experimentId,\n targetType ?? 'agent',\n targetId ?? 'inline',\n item.id,\n execResult.scorerInput,\n execResult.scorerOutput,\n execResult.traceId ?? undefined,\n workflowData,\n );\n\n // Per-step scorer dispatch (mirrors runEvals). Only meaningful for workflow\n // targets; for non-workflow targets stepScorers will be empty.\n const stepScores = await runStepScorersForItem(\n stepScorers,\n item,\n workflowData,\n storage ?? null,\n experimentId,\n targetType ?? 'agent',\n targetId ?? 'inline',\n item.id,\n execResult.traceId ?? undefined,\n );\n\n const itemScores = [...flatScores, ...stepScores];\n\n // Persist result with scores (if storage available). A throw here does\n // NOT abort the run — persistence is best-effort and the target run's\n // outcome is already recorded in `itemResult`. Instead we surface the\n // failure on the item (`persistenceError`) and bump the run-level\n // `persistenceFailures` counter so callers can detect rows that never\n // landed in `mastra_experiment_results`.\n if (experimentsStore) {\n try {\n await experimentsStore.addExperimentResult({\n experimentId,\n itemId: item.id,\n itemDatasetVersion: item.datasetVersion,\n input: item.input,\n output: execResult.output,\n groundTruth: item.groundTruth ?? null,\n error: execResult.error,\n startedAt: itemStartedAt,\n completedAt: itemCompletedAt,\n retryCount,\n traceId: execResult.traceId,\n organizationId: datasetRecord?.organizationId ?? null,\n projectId: datasetRecord?.projectId ?? null,\n ...(execResult.toolMockReport ? { toolMockReport: execResult.toolMockReport } : {}),\n });\n } catch (persistError) {\n persistenceFailures++;\n itemResult.persistenceError = {\n message: persistError instanceof Error ? persistError.message : String(persistError),\n };\n // Log the raw error (including stack) internally, but do NOT attach the\n // stack to the returned `persistenceError` — the summary can cross a\n // trust boundary (e.g. UIs, API responses) and stacks leak internal paths.\n mastra\n .getLogger()\n ?.error(\n `Failed to persist experiment result for item ${item.id} in experiment ${experimentId}: ${itemResult.persistenceError.message}`,\n { error: persistError },\n );\n }\n\n // Throttled progress update\n const now = Date.now();\n if (now - lastProgressUpdate >= PROGRESS_UPDATE_INTERVAL) {\n lastProgressUpdate = now;\n try {\n await experimentsStore.updateExperiment({\n id: experimentId,\n succeededCount,\n failedCount,\n });\n } catch {\n // Non-fatal — progress updates are best-effort\n }\n }\n }\n\n // Store at original index for deterministic ordering\n results[idx] = {\n ...itemResult,\n scores: itemScores,\n };\n },\n { concurrency: maxConcurrency },\n );\n } catch {\n // Handle abort or other fatal errors — return partial summary instead of throwing\n const completedAt = new Date();\n const skippedCount = items.length - succeededCount - failedCount;\n\n if (experimentsStore) {\n await experimentsStore.updateExperiment({\n id: experimentId,\n status: 'failed',\n succeededCount,\n failedCount,\n skippedCount,\n completedAt,\n });\n }\n\n return {\n experimentId,\n status: 'failed' as const,\n totalItems: items.length,\n succeededCount,\n failedCount,\n skippedCount,\n persistenceFailures,\n completedWithErrors: false,\n startedAt,\n completedAt,\n results: results.filter(Boolean),\n };\n }\n\n // 7. Finalize experiment record\n const completedAt = new Date();\n const status = failedCount === items.length ? 'failed' : 'completed';\n const completedWithErrors = status === 'completed' && failedCount > 0;\n\n const skippedCount = items.length - succeededCount - failedCount;\n if (experimentsStore) {\n await experimentsStore.updateExperiment({\n id: experimentId,\n status,\n succeededCount,\n failedCount,\n skippedCount,\n completedAt,\n });\n }\n\n return {\n experimentId,\n status,\n totalItems: items.length,\n succeededCount,\n failedCount,\n skippedCount,\n persistenceFailures,\n completedWithErrors,\n startedAt,\n completedAt,\n results,\n };\n}\n\n/**\n * Resolve a target from Mastra's registries by type and ID.\n * When `agentVersion` is provided for an agent target, the returned agent\n * will have the versioned config applied (via `applyStoredOverrides`).\n *\n * The result is wrapped in `{ target }` because `Workflow` has a `.then`\n * method for step chaining, which makes it thenable. Returning a thenable\n * from an async function causes the Promise machinery to attempt to unwrap\n * it, which hangs forever since the builder `.then` never invokes its\n * callbacks. Wrapping in a plain object avoids the unwrap.\n */\nasync function resolveTarget(\n mastra: Mastra,\n targetType: string,\n targetId: string,\n agentVersion?: string,\n): Promise<{ target: Target } | null> {\n let resolved: Target | null = null;\n\n switch (targetType) {\n case 'agent':\n try {\n if (agentVersion) {\n resolved = await mastra.getAgentById(targetId, { versionId: agentVersion });\n } else {\n resolved = mastra.getAgentById(targetId);\n }\n } catch {\n // Try by name if ID lookup fails\n try {\n if (agentVersion) {\n resolved = await mastra.getAgent(targetId, { versionId: agentVersion });\n } else {\n resolved = mastra.getAgent(targetId);\n }\n } catch {\n // leave null\n }\n }\n break;\n case 'workflow':\n try {\n resolved = mastra.getWorkflowById(targetId);\n } catch {\n // Try by name if ID lookup fails\n try {\n resolved = mastra.getWorkflow(targetId);\n } catch {\n // leave null\n }\n }\n break;\n case 'scorer':\n try {\n resolved = mastra.getScorerById(targetId) ?? null;\n } catch {\n // leave null\n }\n break;\n case 'processor':\n // Processors not yet in registry - Phase 4\n break;\n default:\n break;\n }\n\n return resolved ? { target: resolved } : null;\n}\n","import { isZodType } from '@mastra/schema-compat';\nimport { zodToJsonSchema } from '@mastra/schema-compat/zod-to-json';\nimport { MastraError } from '../error/index.js';\nimport type { Mastra } from '../mastra/index.js';\nimport type { DatasetsStorage } from '../storage/domains/datasets/base.js';\nimport type { ExperimentsStorage } from '../storage/domains/experiments/base.js';\nimport type {\n DatasetRecord,\n DatasetItem,\n DatasetItemPayload,\n DatasetItemRow,\n DatasetTenancyFilters,\n DatasetVersion,\n ExperimentResultStatus,\n ExperimentStatus,\n ExperimentTenancyFilters,\n ListDatasetItemsOutput,\n ListExperimentResultsOutput,\n ListExperimentsOutput,\n TargetType,\n UpdateDatasetInput,\n UpdateExperimentResultInput,\n} from '../storage/types.js';\nimport { runExperiment } from './experiment/index.js';\nimport type { ExperimentConfig, StartExperimentConfig, ExperimentSummary } from './experiment/types.js';\n\n/**\n * Public API for interacting with a single dataset.\n *\n * Provides methods for item CRUD, versioning, and experiment management.\n * Obtained via `DatasetsManager.get()` or `DatasetsManager.create()`.\n */\nexport class Dataset {\n readonly id: string;\n #mastra: Mastra;\n #datasetsStore?: DatasetsStorage;\n #experimentsStore?: ExperimentsStorage;\n /**\n * Tenancy read-scope carried by the handle. When set, all internal reads\n * ({@link Dataset.getDetails}, {@link Dataset.startExperimentAsync}) and item\n * mutations forward these filters to storage so cross-tenant reads/mutations\n * over a leaked dataset id are rejected as NOT_FOUND (or silent no-op for\n * deletes) rather than succeeding.\n */\n #scope?: DatasetTenancyFilters;\n\n constructor(id: string, mastra: Mastra, scope?: DatasetTenancyFilters) {\n this.id = id;\n this.#mastra = mastra;\n this.#scope = scope;\n }\n\n // ---------------------------------------------------------------------------\n // Lazy storage resolution\n // ---------------------------------------------------------------------------\n\n async #getDatasetsStore(): Promise<DatasetsStorage> {\n if (this.#datasetsStore) return this.#datasetsStore;\n\n const storage = this.#mastra.getStorage();\n if (!storage) {\n throw new MastraError({\n id: 'DATASETS_STORAGE_NOT_CONFIGURED',\n text: 'Storage not configured. Configure storage in Mastra instance.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const store = await storage.getStore('datasets');\n if (!store) {\n throw new MastraError({\n id: 'DATASETS_STORE_NOT_AVAILABLE',\n text: 'Datasets store not available. Ensure your storage adapter provides a datasets domain.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n this.#datasetsStore = store;\n return store;\n }\n\n async #getExperimentsStore(): Promise<ExperimentsStorage> {\n if (this.#experimentsStore) return this.#experimentsStore;\n\n const storage = this.#mastra.getStorage();\n if (!storage) {\n throw new MastraError({\n id: 'DATASETS_STORAGE_NOT_CONFIGURED',\n text: 'Storage not configured. Configure storage in Mastra instance.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const store = await storage.getStore('experiments');\n if (!store) {\n throw new MastraError({\n id: 'EXPERIMENTS_STORE_NOT_AVAILABLE',\n text: 'Experiments store not available. Ensure your storage adapter provides an experiments domain.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n this.#experimentsStore = store;\n return store;\n }\n\n /**\n * Preflight tenancy gate for storage APIs whose signatures don't accept\n * `filters`. When the handle has a `#scope`, a scoped `getDatasetById` is\n * used to prove the dataset exists in the caller's tenancy; on miss we\n * throw NOT_FOUND, mirroring {@link Dataset.getDetails}. Callers that must\n * return a non-throwing empty result (e.g. list endpoints) should catch and\n * translate.\n */\n async #assertScope(): Promise<void> {\n if (!this.#scope) return;\n const store = await this.#getDatasetsStore();\n const record = await store.getDatasetById({ id: this.id, filters: this.#scope });\n if (!record) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: `Dataset not found: ${this.id}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n }\n\n /**\n * Ownership gate: verifies a child record's `datasetId` matches `this.id`.\n * Prevents a valid scoped handle from reading/mutating child records\n * (items, experiments, results) that live under a different dataset — even\n * one in the same tenant. Returns `null` when the record is missing or\n * belongs to a different dataset, so callers can either return null or\n * translate to NOT_FOUND depending on their contract.\n */\n #ownsChild<T extends { datasetId?: string | null }>(record: T | null | undefined): T | null {\n if (!record) return null;\n if (record.datasetId !== this.id) return null;\n return record;\n }\n\n // ---------------------------------------------------------------------------\n // Dataset metadata\n // ---------------------------------------------------------------------------\n\n /**\n * Get the full dataset record from storage.\n */\n async getDetails(): Promise<DatasetRecord> {\n const store = await this.#getDatasetsStore();\n const record = await store.getDatasetById({ id: this.id, filters: this.#scope });\n if (!record) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: `Dataset not found: ${this.id}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n return record;\n }\n\n /**\n * Update dataset metadata and/or schemas.\n *\n * Accepts Zod schemas for `inputSchema` / `groundTruthSchema` (widened to\n * `unknown`); they are normalized to JSON Schema before being forwarded to\n * the storage-canonical {@link UpdateDatasetInput} shape. All other fields\n * mirror {@link UpdateDatasetInput} exactly (minus `id`, which is supplied\n * from `this.id`).\n */\n async update(\n input: Omit<UpdateDatasetInput, 'id' | 'inputSchema' | 'groundTruthSchema'> & {\n inputSchema?: unknown;\n groundTruthSchema?: unknown;\n },\n ): Promise<DatasetRecord> {\n const store = await this.#getDatasetsStore();\n\n let { inputSchema, groundTruthSchema, ...rest } = input;\n\n if (inputSchema !== undefined && inputSchema !== null && isZodType(inputSchema)) {\n inputSchema = zodToJsonSchema(inputSchema);\n }\n if (groundTruthSchema !== undefined && groundTruthSchema !== null && isZodType(groundTruthSchema)) {\n groundTruthSchema = zodToJsonSchema(groundTruthSchema);\n }\n\n return store.updateDataset({\n id: this.id,\n ...rest,\n inputSchema: inputSchema as Record<string, unknown> | null | undefined,\n groundTruthSchema: groundTruthSchema as Record<string, unknown> | null | undefined,\n filters: this.#scope,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Item CRUD\n // ---------------------------------------------------------------------------\n\n /**\n * Add a single item to the dataset.\n */\n async addItem(input: DatasetItemPayload): Promise<DatasetItem> {\n const store = await this.#getDatasetsStore();\n return store.addItem({ datasetId: this.id, ...input, filters: this.#scope });\n }\n\n /**\n * Add multiple items to the dataset in bulk.\n */\n async addItems(input: { items: DatasetItemPayload[] }): Promise<DatasetItem[]> {\n const store = await this.#getDatasetsStore();\n return store.batchInsertItems({\n datasetId: this.id,\n items: input.items,\n filters: this.#scope,\n });\n }\n\n /**\n * Get a single item by ID, optionally at a specific version.\n */\n async getItem(args: { itemId: string; version?: number }): Promise<DatasetItem | null> {\n await this.#assertScope();\n const store = await this.#getDatasetsStore();\n const item = await store.getItemById({ id: args.itemId, datasetVersion: args.version });\n return this.#ownsChild(item);\n }\n\n /**\n * List items in the dataset, optionally at a specific version, with\n * optional substring search and pagination.\n *\n * Return shape depends on the arguments:\n *\n * - When `version` is the only argument provided (no `search`, `page`, or\n * `perPage`), returns a bare `DatasetItem[]` snapshot of every item at\n * that version. This shape is retained for callers that predate\n * server-side pagination on the versioned path; new code should pass\n * `page` / `perPage` (or `search`) to opt into the paginated shape.\n * - In all other cases (no arguments, or `search` / `page` / `perPage`\n * provided with or without `version`), returns the paginated\n * `{ items, pagination }` shape.\n *\n * @deprecated The `DatasetItem[]` branch of the return type is retained\n * for backwards compatibility with the `version`-only call form; pass\n * `page` / `perPage` (or `search`) to always receive the paginated\n * `{ items, pagination }` shape.\n */\n async listItems(args?: {\n version?: number;\n page?: number;\n perPage?: number;\n search?: string;\n }): Promise<DatasetItem[] | ListDatasetItemsOutput> {\n const store = await this.#getDatasetsStore();\n\n const onlyVersion =\n args?.version !== undefined && args.search === undefined && args.page === undefined && args.perPage === undefined;\n\n if (onlyVersion) {\n // getItemsByVersion is keyed by datasetId — gate via scoped parent existence\n await this.#assertScope();\n return store.getItemsByVersion({ datasetId: this.id, version: args.version! });\n }\n\n return store.listItems({\n datasetId: this.id,\n ...(args?.version !== undefined ? { version: args.version } : {}),\n ...(args?.search ? { search: args.search } : {}),\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n filters: this.#scope,\n });\n }\n\n /**\n * Update an existing item in the dataset. Only the provided payload fields\n * are patched.\n */\n async updateItem(input: { itemId: string } & Partial<Omit<DatasetItemPayload, 'externalId'>>): Promise<DatasetItem> {\n const store = await this.#getDatasetsStore();\n const { itemId, ...rest } = input;\n return store.updateItem({ id: itemId, datasetId: this.id, ...rest, filters: this.#scope });\n }\n\n /**\n * Delete a single item from the dataset.\n */\n async deleteItem(args: { itemId: string }): Promise<void> {\n const store = await this.#getDatasetsStore();\n return store.deleteItem({ id: args.itemId, datasetId: this.id, filters: this.#scope });\n }\n\n /**\n * Delete multiple items from the dataset in bulk.\n */\n async deleteItems(args: { itemIds: string[] }): Promise<void> {\n const store = await this.#getDatasetsStore();\n return store.batchDeleteItems({ datasetId: this.id, itemIds: args.itemIds, filters: this.#scope });\n }\n\n // ---------------------------------------------------------------------------\n // Versioning\n // ---------------------------------------------------------------------------\n\n /**\n * List all versions of this dataset.\n */\n async listVersions(args?: { page?: number; perPage?: number }): Promise<{\n versions: DatasetVersion[];\n pagination: { total: number; page: number; perPage: number | false; hasMore: boolean };\n }> {\n await this.#assertScope();\n const store = await this.#getDatasetsStore();\n return store.listDatasetVersions({\n datasetId: this.id,\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n });\n }\n\n /**\n * Get full SCD-2 history of a specific item across all dataset versions.\n */\n async getItemHistory(args: { itemId: string }): Promise<DatasetItemRow[]> {\n await this.#assertScope();\n const store = await this.#getDatasetsStore();\n const rows = await store.getItemHistory(args.itemId);\n // Ownership gate: SCD-2 history is keyed only by item id — filter out any\n // rows that don't belong to this dataset so a known cross-dataset item id\n // cannot leak history through a valid scoped handle.\n return rows.filter(row => row.datasetId === this.id);\n }\n\n // ---------------------------------------------------------------------------\n // Experiments\n // ---------------------------------------------------------------------------\n\n /**\n * Run an experiment on this dataset and wait for completion.\n */\n async startExperiment<I = unknown, O = unknown, E = unknown>(\n config: StartExperimentConfig<I, O, E>,\n ): Promise<ExperimentSummary> {\n return runExperiment(this.#mastra, {\n datasetId: this.id,\n ...config,\n filters: this.#scope,\n } as ExperimentConfig);\n }\n\n /**\n * Start an experiment asynchronously (fire-and-forget).\n * Returns immediately with the experiment ID and pending status.\n */\n async startExperimentAsync<I = unknown, O = unknown, E = unknown>(\n config: StartExperimentConfig<I, O, E>,\n ): Promise<{ experimentId: string; status: 'pending'; totalItems: number }> {\n const experimentsStore = await this.#getExperimentsStore();\n const datasetsStore = await this.#getDatasetsStore();\n\n const dataset = await datasetsStore.getDatasetById({ id: this.id, filters: this.#scope });\n if (!dataset) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: `Dataset not found: ${this.id}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n // Validate that dataset has items before creating experiment record\n const targetVersion = config.version ?? dataset.version;\n const items = await datasetsStore.getItemsByVersion({\n datasetId: this.id,\n version: targetVersion,\n });\n if (items.length === 0) {\n throw new MastraError({\n id: 'EXPERIMENT_NO_ITEMS',\n text: `Cannot run experiment: dataset \"${this.id}\" has no items at version ${targetVersion}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const run = await experimentsStore.createExperiment({\n datasetId: this.id,\n datasetVersion: targetVersion,\n targetType: config.targetType ?? 'agent',\n targetId: config.targetId ?? 'inline',\n totalItems: items.length,\n name: config.name,\n description: config.description,\n metadata: config.metadata,\n agentVersion: config.agentVersion,\n organizationId: dataset.organizationId ?? null,\n projectId: dataset.projectId ?? null,\n });\n\n const experimentId = run.id;\n\n // Fire-and-forget — runExperiment merges dataset-attached scorers automatically\n void runExperiment(this.#mastra, {\n datasetId: this.id,\n experimentId,\n ...config,\n version: targetVersion,\n filters: this.#scope,\n } as ExperimentConfig).catch(async err => {\n await experimentsStore\n .updateExperiment({\n id: experimentId,\n status: 'failed',\n completedAt: new Date(),\n })\n .catch(() => {});\n this.#mastra.getLogger()?.error(`Experiment ${experimentId} failed: ${err?.message ?? err}`);\n });\n\n return { experimentId, status: 'pending' as const, totalItems: items.length };\n }\n\n /**\n * List experiments (runs) for this dataset, with optional filters and\n * pagination. All filters are pushed to the storage layer.\n *\n * @param args.targetType Restrict to a specific target type (e.g. `agent`).\n * @param args.targetId Restrict to a specific target ID.\n * @param args.agentVersion Restrict to a specific agent version — useful for\n * baseline vs variant read patterns.\n * @param args.status Restrict to a specific experiment status.\n * @param args.filters Multi-tenant scoping filters (organization/project).\n * @param args.page Page number. Defaults to `0`.\n * @param args.perPage Page size. Defaults to `20`.\n */\n async listExperiments(args?: {\n targetType?: TargetType;\n targetId?: string;\n agentVersion?: string;\n status?: ExperimentStatus;\n filters?: ExperimentTenancyFilters;\n page?: number;\n perPage?: number;\n }): Promise<ListExperimentsOutput> {\n await this.#assertScope();\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.listExperiments({\n datasetId: this.id,\n ...(args?.targetType !== undefined ? { targetType: args.targetType } : {}),\n ...(args?.targetId !== undefined ? { targetId: args.targetId } : {}),\n ...(args?.agentVersion !== undefined ? { agentVersion: args.agentVersion } : {}),\n ...(args?.status !== undefined ? { status: args.status } : {}),\n ...(args?.filters !== undefined ? { filters: args.filters } : {}),\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n });\n }\n\n /**\n * Verify the experiment belongs to this dataset (and, by extension, to the\n * handle's tenancy scope which was enforced when the handle was minted).\n * Throws NOT_FOUND on missing or cross-dataset experiments so cross-tenant\n * mutation via a valid scoped handle + a known foreign experimentId is\n * rejected.\n */\n async #assertExperimentOwnership(experimentId: string): Promise<void> {\n await this.#assertScope();\n const experimentsStore = await this.#getExperimentsStore();\n const experiment = await experimentsStore.getExperimentById({\n id: experimentId,\n filters: this.#scope,\n });\n if (!experiment || experiment.datasetId !== this.id) {\n throw new MastraError({\n id: 'EXPERIMENT_NOT_FOUND',\n text: `Experiment not found: ${experimentId}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n }\n\n /**\n * Get a specific experiment (run) by ID.\n */\n async getExperiment(args: { experimentId: string }) {\n await this.#assertScope();\n const experimentsStore = await this.#getExperimentsStore();\n const experiment = await experimentsStore.getExperimentById({\n id: args.experimentId,\n filters: this.#scope,\n });\n if (!experiment || experiment.datasetId !== this.id) return null;\n return experiment;\n }\n\n /**\n * List results for a specific experiment, with optional filters and\n * pagination. All filters are pushed to the storage layer.\n *\n * @param args.experimentId The experiment whose results to list.\n * @param args.traceId Restrict to results linked to a specific trace.\n * @param args.status Restrict to a specific per-result review status.\n * @param args.filters Multi-tenant scoping filters (organization/project).\n * @param args.page Page number. Defaults to `0`.\n * @param args.perPage Page size. Defaults to `20`.\n */\n async listExperimentResults(args: {\n experimentId: string;\n traceId?: string;\n status?: ExperimentResultStatus;\n filters?: ExperimentTenancyFilters;\n page?: number;\n perPage?: number;\n }): Promise<ListExperimentResultsOutput> {\n await this.#assertExperimentOwnership(args.experimentId);\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.listExperimentResults({\n experimentId: args.experimentId,\n ...(args.traceId !== undefined ? { traceId: args.traceId } : {}),\n ...(args.status !== undefined ? { status: args.status } : {}),\n ...(args.filters !== undefined ? { filters: args.filters } : {}),\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n });\n }\n\n /**\n * Update an experiment result's status or tags.\n */\n async updateExperimentResult(input: UpdateExperimentResultInput & { experimentId: string }) {\n // The result's parent experiment must belong to this dataset. If the\n // caller supplied `experimentId`, verify ownership on that; otherwise we\n // cannot bind the update to this dataset and must reject.\n if (!input.experimentId) {\n throw new MastraError({\n id: 'EXPERIMENT_RESULT_MISSING_EXPERIMENT_ID',\n text: 'updateExperimentResult requires experimentId when called via a Dataset handle',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n await this.#assertExperimentOwnership(input.experimentId);\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.updateExperimentResult(input);\n }\n\n /**\n * Delete an experiment (run) by ID.\n *\n * The ownership check above already refuses cross-tenant / cross-dataset\n * requests, but we still forward `this.#scope` to storage so the delete\n * is defense-in-depth: a leaked handle or race that skipped the assertion\n * still cannot delete another tenant's experiment (storage silently no-ops\n * on tenancy mismatch).\n */\n async deleteExperiment(args: { experimentId: string }) {\n await this.#assertExperimentOwnership(args.experimentId);\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.deleteExperiment({ id: args.experimentId, filters: this.#scope });\n }\n}\n","import { isZodType } from '@mastra/schema-compat';\nimport { zodToJsonSchema } from '@mastra/schema-compat/zod-to-json';\nimport { MastraError } from '../error/index.js';\nimport type { Mastra } from '../mastra/index.js';\nimport type { DatasetsStorage } from '../storage/domains/datasets/base.js';\nimport type { ExperimentsStorage } from '../storage/domains/experiments/base.js';\nimport type { DatasetTenancyFilters, TargetType } from '../storage/types.js';\nimport { Dataset } from './dataset.js';\nimport { compareExperiments as compareExperimentsInternal } from './experiment/analytics/compare.js';\n\n/**\n * Build a {@link DatasetTenancyFilters} from public manager args. Returns\n * `undefined` when neither field is set (preserves legacy unscoped behavior).\n * Null values are coerced away — `DatasetTenancyFilters` is `string | undefined`\n * only, matching the existing `listDatasets` filter contract.\n */\nfunction scopeFromArgs(args: {\n organizationId?: string | null;\n projectId?: string | null;\n}): DatasetTenancyFilters | undefined {\n const scope: DatasetTenancyFilters = {};\n if (typeof args.organizationId === 'string') scope.organizationId = args.organizationId;\n if (typeof args.projectId === 'string') scope.projectId = args.projectId;\n return scope.organizationId === undefined && scope.projectId === undefined ? undefined : scope;\n}\n\n/**\n * Public API for managing datasets.\n *\n * Provides methods for dataset CRUD and cross-dataset experiment operations.\n * Typically accessed via `mastra.datasets` (Phase 4).\n */\nexport class DatasetsManager {\n #mastra: Mastra;\n #datasetsStore?: DatasetsStorage;\n #experimentsStore?: ExperimentsStorage;\n\n constructor(mastra: Mastra) {\n this.#mastra = mastra;\n }\n\n // ---------------------------------------------------------------------------\n // Lazy storage resolution\n // ---------------------------------------------------------------------------\n\n async #getDatasetsStore(): Promise<DatasetsStorage> {\n if (this.#datasetsStore) return this.#datasetsStore;\n\n const storage = this.#mastra.getStorage();\n if (!storage) {\n throw new MastraError({\n id: 'DATASETS_STORAGE_NOT_CONFIGURED',\n text: 'Storage not configured. Configure storage in Mastra instance.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const store = await storage.getStore('datasets');\n if (!store) {\n throw new MastraError({\n id: 'DATASETS_STORE_NOT_AVAILABLE',\n text: 'Datasets store not available. Ensure your storage adapter provides a datasets domain.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n this.#datasetsStore = store;\n return store;\n }\n\n async #getExperimentsStore(): Promise<ExperimentsStorage> {\n if (this.#experimentsStore) return this.#experimentsStore;\n\n const storage = this.#mastra.getStorage();\n if (!storage) {\n throw new MastraError({\n id: 'DATASETS_STORAGE_NOT_CONFIGURED',\n text: 'Storage not configured. Configure storage in Mastra instance.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const store = await storage.getStore('experiments');\n if (!store) {\n throw new MastraError({\n id: 'EXPERIMENTS_STORE_NOT_AVAILABLE',\n text: 'Experiments store not available. Ensure your storage adapter provides an experiments domain.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n this.#experimentsStore = store;\n return store;\n }\n\n // ---------------------------------------------------------------------------\n // Dataset CRUD\n // ---------------------------------------------------------------------------\n\n /**\n * Create a new dataset.\n *\n * Accepts Zod schemas for `inputSchema` / `groundTruthSchema` (typed as\n * `unknown` here); they are normalized to JSON Schema via `zodToJsonSchema`\n * before being forwarded to the storage-canonical\n * {@link import('../storage/types.js').CreateDatasetInput} shape. All other\n * fields mirror `CreateDatasetInput` exactly.\n */\n async create(input: {\n id?: string;\n name: string;\n description?: string;\n inputSchema?: unknown;\n groundTruthSchema?: unknown;\n requestContextSchema?: Record<string, unknown> | null;\n metadata?: Record<string, unknown>;\n targetType?: TargetType;\n targetIds?: string[];\n scorerIds?: string[];\n organizationId?: string | null;\n projectId?: string | null;\n candidateKey?: string | null;\n candidateId?: string | null;\n }): Promise<Dataset> {\n const store = await this.#getDatasetsStore();\n\n let { inputSchema, groundTruthSchema, ...rest } = input;\n\n if (inputSchema !== undefined && isZodType(inputSchema)) {\n inputSchema = zodToJsonSchema(inputSchema);\n }\n if (groundTruthSchema !== undefined && isZodType(groundTruthSchema)) {\n groundTruthSchema = zodToJsonSchema(groundTruthSchema);\n }\n\n const result = await store.createDataset({\n ...rest,\n inputSchema: inputSchema as Record<string, unknown> | undefined,\n groundTruthSchema: groundTruthSchema as Record<string, unknown> | undefined,\n });\n\n // Preserve the tenancy the caller created the dataset under so subsequent\n // reads/updates on the returned handle stay bound to the same tenant.\n const createScope = scopeFromArgs(input);\n return new Dataset(result.id, this.#mastra, createScope);\n }\n\n /**\n * Get an existing dataset by ID, optionally scoped to a tenant.\n *\n * When `organizationId` / `projectId` are provided, the read is scoped to\n * that tenancy: a dataset row that exists but belongs to a different tenant\n * returns NOT_FOUND (same 404 as a truly missing row) rather than leaking\n * cross-tenant existence. The returned {@link Dataset} handle carries the\n * scope forward on all subsequent reads and item mutations.\n */\n async get(args: { id: string; organizationId?: string; projectId?: string }): Promise<Dataset> {\n const store = await this.#getDatasetsStore();\n const scope = scopeFromArgs(args);\n const record = await store.getDatasetById({ id: args.id, filters: scope });\n if (!record) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: 'Dataset not found',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n return new Dataset(args.id, this.#mastra, scope);\n }\n\n /**\n * List all datasets with pagination.\n *\n * Supports optional tenancy and candidate-identity filters. When omitted, all\n * datasets visible to the configured storage instance are returned.\n */\n async list(args?: {\n page?: number;\n perPage?: number;\n filters?: {\n organizationId?: string;\n projectId?: string;\n candidateKey?: string;\n candidateId?: string;\n /** Filter by dataset target type. */\n targetType?: TargetType;\n /**\n * Filter to datasets whose `targetIds` intersect this list (any overlap matches).\n */\n targetIds?: string[];\n /** Substring match on dataset `name`, case-insensitive. */\n name?: string;\n };\n }) {\n const store = await this.#getDatasetsStore();\n return store.listDatasets({\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n ...(args?.filters ? { filters: args.filters } : {}),\n });\n }\n\n /**\n * Delete a dataset by ID, optionally scoped to a tenant.\n *\n * When `organizationId` / `projectId` are provided, the delete is scoped to\n * that tenancy: a dataset row in another tenant is a silent no-op (no error)\n * so cross-tenant existence is not leaked via error timing/text.\n */\n async delete(args: { id: string; organizationId?: string; projectId?: string }) {\n const store = await this.#getDatasetsStore();\n return store.deleteDataset({ id: args.id, filters: scopeFromArgs(args) });\n }\n\n // ---------------------------------------------------------------------------\n // Cross-dataset experiment operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get a specific experiment (run) by ID, optionally scoped to a tenant.\n *\n * When `organizationId` / `projectId` are provided, the read is scoped to\n * that tenancy: an experiment row that exists but belongs to a different\n * tenant returns `null` (same as a truly missing row) rather than leaking\n * cross-tenant existence via error timing/text.\n */\n async getExperiment(args: { experimentId: string; organizationId?: string; projectId?: string }) {\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.getExperimentById({\n id: args.experimentId,\n filters: scopeFromArgs(args),\n });\n }\n\n /**\n * Compare two or more experiments.\n *\n * Uses the internal `compareExperiments` function for pairwise comparison,\n * then enriches results with per-item input/groundTruth/output data.\n */\n async compareExperiments(args: { experimentIds: string[]; baselineId?: string }) {\n const { experimentIds, baselineId } = args;\n\n if (experimentIds.length < 2) {\n throw new MastraError({\n id: 'COMPARE_INVALID_INPUT',\n text: 'compareExperiments requires at least 2 experiment IDs.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const resolvedBaseline = baselineId ?? experimentIds[0]!;\n const otherExperimentId = experimentIds.find(id => id !== resolvedBaseline) ?? experimentIds[1]!;\n\n const internal = await compareExperimentsInternal(this.#mastra, {\n experimentIdA: resolvedBaseline,\n experimentIdB: otherExperimentId,\n });\n\n // Load results for both runs to get input/groundTruth/output\n const experimentsStore = await this.#getExperimentsStore();\n const [resultsA, resultsB] = await Promise.all([\n experimentsStore.listExperimentResults({\n experimentId: resolvedBaseline,\n pagination: { page: 0, perPage: false },\n }),\n experimentsStore.listExperimentResults({\n experimentId: otherExperimentId,\n pagination: { page: 0, perPage: false },\n }),\n ]);\n\n // Build results maps by itemId\n const resultsMapA = new Map(resultsA.results.map(r => [r.itemId, r]));\n const resultsMapB = new Map(resultsB.results.map(r => [r.itemId, r]));\n\n // Transform internal items to MVP shape\n const items = internal.items.map(item => {\n const resultA = resultsMapA.get(item.itemId);\n const resultB = resultsMapB.get(item.itemId);\n\n return {\n itemId: item.itemId,\n input: resultA?.input ?? resultB?.input ?? null,\n groundTruth: resultA?.groundTruth ?? resultB?.groundTruth ?? null,\n results: {\n [resolvedBaseline]: resultA ? { output: resultA.output, scores: item.scoresA } : null,\n [otherExperimentId]: resultB ? { output: resultB.output, scores: item.scoresB } : null,\n },\n };\n });\n\n return {\n baselineId: resolvedBaseline,\n items,\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"manager-DDRcONBK.js","names":["#entries","#served","#liveCalls","#failure","#mastra","#scope","#getDatasetsStore","#datasetsStore","#getExperimentsStore","#experimentsStore","#assertScope","#ownsChild","#assertExperimentOwnership","#mastra","#getDatasetsStore","#datasetsStore","#getExperimentsStore","#experimentsStore","compareExperimentsInternal"],"sources":["../src/datasets/experiment/tool-mocks.ts","../src/datasets/experiment/executor.ts","../src/datasets/experiment/scorer.ts","../src/datasets/experiment/analytics/aggregate.ts","../src/datasets/experiment/analytics/compare.ts","../src/datasets/experiment/index.ts","../src/datasets/dataset.ts","../src/datasets/manager.ts"],"sourcesContent":["import { deepEqual } from '../../utils';\n\n/**\n * A single static tool mock authored on a dataset item.\n *\n * v1 is output-only: when matched, `output` is served to the agent in place of\n * executing the real tool. Error mocks are intentionally not supported in v1\n * (the agent `beforeToolCall` hook can only short-circuit with an output).\n *\n * Tool mocks only apply to experiments with `targetType: 'agent'`. They are\n * ignored for `task`, `workflow`, and `scorer` targets (the experiment logs a\n * warning if a dataset carrying `toolMocks` is run against a non-agent target).\n */\n/**\n * How a mock's `args` are matched against the agent's tool call.\n * - `strict` (default): deep-equality on `args` (key order ignored, array order\n * significant, no coercion).\n * - `ignore`: match on `toolName` only; `args` are not compared. Useful for\n * tools whose arguments are noisy or LLM-authored — notably sub-agent\n * delegation calls (`agent-*`), whose `prompt` is free text.\n */\nexport type ToolMockMatchArgs = 'strict' | 'ignore';\n\nexport interface ItemToolMock {\n /** Name of the tool this mock applies to. */\n toolName: string;\n /**\n * Arguments to match against the agent's tool call. Compared with deep\n * equality when `matchArgs` is `strict`; ignored when `matchArgs` is `ignore`.\n */\n args: Record<string, unknown>;\n /** Output served to the agent when this mock is matched and consumed. */\n output: unknown;\n /**\n * Argument matching mode for this mock. Defaults to `strict`.\n *\n * @example\n * // strict (default): served only when args deep-equal the call\n * { toolName: 'getWeather', args: { city: 'Seattle' }, output: { tempF: 52 }, matchArgs: 'strict' }\n * // ignore: served for any args to `getWeather` (tool-name-only match)\n * { toolName: 'getWeather', args: {}, output: { tempF: 52 }, matchArgs: 'ignore' }\n */\n matchArgs?: ToolMockMatchArgs;\n}\n\n/** Deterministic failure codes surfaced via `ExecutionResult.error.code`. */\nexport const TOOL_MOCK_MISMATCH = 'TOOL_MOCK_MISMATCH';\nexport const TOOL_MOCK_EXHAUSTED = 'TOOL_MOCK_EXHAUSTED';\n\nexport type ToolMockFailureCode = typeof TOOL_MOCK_MISMATCH | typeof TOOL_MOCK_EXHAUSTED;\n\n/** Diagnostic receipt produced for a single item run. Persisted on experiment results. */\nexport interface ToolMockReport {\n /** Mocks that were matched and served, in consumption order. */\n served: { mockIndex: number; toolName: string; args: unknown }[];\n /** Mocks declared on the item that the agent never consumed (report-only — does NOT fail the item). */\n unconsumed: { mockIndex: number; toolName: string; args: unknown }[];\n /** Unmocked tools that ran live — flags that the item was not fully deterministic. */\n liveCalls: { toolName: string; args: unknown }[];\n /** Present when a mocked tool was mis-called and the item failed. */\n failure?: { code: ToolMockFailureCode; toolName: string; args: unknown };\n}\n\n/** Result of attempting to resolve a single tool call against the item's mocks. */\nexport type ToolMockResolution =\n | { kind: 'serve'; output: unknown }\n | { kind: 'live' }\n | { kind: 'fail'; code: ToolMockFailureCode };\n\ninterface MockEntry {\n mockIndex: number;\n toolName: string;\n args: Record<string, unknown>;\n output: unknown;\n matchArgs: ToolMockMatchArgs;\n consumed: boolean;\n}\n\n/**\n * Per-item mock matcher. Built fresh for each item run; consumption is tracked\n * in local state so repeated `(toolName, args)` mocks are served top-to-bottom.\n *\n * Tool execution must be forced sequential while an item has mocks so that\n * ordered consumption is deterministic (the matcher itself is order-sensitive).\n */\nexport class ToolMockMatcher {\n readonly #entries: MockEntry[];\n readonly #served: ToolMockReport['served'] = [];\n readonly #liveCalls: ToolMockReport['liveCalls'] = [];\n #failure: ToolMockReport['failure'];\n\n constructor(mocks: ItemToolMock[] | undefined) {\n this.#entries = (mocks ?? []).map((mock, mockIndex) => ({\n mockIndex,\n toolName: mock.toolName,\n args: mock.args,\n output: mock.output,\n matchArgs: mock.matchArgs ?? 'strict',\n consumed: false,\n }));\n }\n\n /** True when the item declares at least one mock (tool execution should run sequentially). */\n get hasMocks(): boolean {\n return this.#entries.length > 0;\n }\n\n /**\n * Resolve a single tool call:\n * - no mock for this tool → `live`\n * - unconsumed mock whose args match (deep-equal for `strict`, always for\n * `ignore`) → `serve`\n * - tool is mocked but no unconsumed entry matches → `fail`\n * (`TOOL_MOCK_EXHAUSTED` if args matched but all consumed, else `TOOL_MOCK_MISMATCH`)\n */\n resolve(toolName: string, args: unknown): ToolMockResolution {\n // Once any mock has failed, the item is already doomed and being aborted.\n // Fail every subsequent resolution so no further tool runs live/serves\n // during the abort-propagation race.\n if (this.#failure) {\n return { kind: 'fail', code: this.#failure.code };\n }\n\n const candidates = this.#entries.filter(entry => entry.toolName === toolName);\n\n if (candidates.length === 0) {\n this.#liveCalls.push({ toolName, args });\n return { kind: 'live' };\n }\n\n const argsMatch = (entry: MockEntry): boolean => entry.matchArgs === 'ignore' || deepEqual(entry.args, args);\n\n const next = candidates.find(entry => !entry.consumed && argsMatch(entry));\n if (next) {\n next.consumed = true;\n this.#served.push({ mockIndex: next.mockIndex, toolName, args });\n return { kind: 'serve', output: next.output };\n }\n\n const argsMatchedButConsumed = candidates.some(entry => argsMatch(entry));\n const code: ToolMockFailureCode = argsMatchedButConsumed ? TOOL_MOCK_EXHAUSTED : TOOL_MOCK_MISMATCH;\n // Record only the first failure — the item fails on it and stops.\n this.#failure ??= { code, toolName, args };\n return { kind: 'fail', code };\n }\n\n /** Build the diagnostic report for this item run. */\n report(): ToolMockReport {\n const unconsumed = this.#entries\n .filter(entry => !entry.consumed)\n .map(entry => ({ mockIndex: entry.mockIndex, toolName: entry.toolName, args: entry.args }));\n\n return {\n served: this.#served,\n unconsumed,\n liveCalls: this.#liveCalls,\n ...(this.#failure ? { failure: this.#failure } : {}),\n };\n }\n}\n","import type { Agent } from '../../agent';\nimport { isSupportedLanguageModel } from '../../agent';\nimport type { MessageListInput } from '../../agent/message-list';\nimport type { MastraScorer } from '../../evals/base';\nimport type { ScorerRunInputForAgent, ScorerRunOutputForAgent } from '../../evals/types';\nimport type { ScoringData } from '../../llm/model/base.types';\nimport type { VersionOverrides } from '../../mastra/types';\nimport { resolveObservabilityContext } from '../../observability';\nimport { RequestContext } from '../../request-context';\nimport type { TargetType } from '../../storage/types';\nimport type { ToolHooks } from '../../tools/types';\nimport type { StepResult, Workflow } from '../../workflows';\nimport type { ItemToolMock, ToolMockReport } from './tool-mocks';\nimport { ToolMockMatcher } from './tool-mocks';\n\n/**\n * Common fields extracted from both FullOutput (v2/v3) and GenerateTextResult/GenerateObjectResult (v1).\n * Used to type the agent result uniformly without coupling to the full return types.\n */\ninterface AgentGenerateResult {\n text?: string;\n object?: unknown;\n toolCalls?: unknown[];\n toolResults?: unknown[];\n sources?: unknown[];\n files?: unknown[];\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n reasoningText?: string;\n traceId?: string;\n error?: Error;\n scoringData?: ScoringData;\n}\n\n/**\n * Target types supported for dataset execution.\n * Agent and Workflow are Phase 2; scorer and processor are Phase 4.\n */\nexport type Target = Agent | Workflow | MastraScorer<any, any, any, any>;\n\n/**\n * Result from executing a target against a dataset item.\n */\nexport interface ExecutionResult {\n /** Output from the target (null if failed) */\n output: unknown;\n /** Structured error if execution failed */\n error: { message: string; stack?: string; code?: string } | null;\n /** Trace ID from agent/workflow execution (null for scorers or errors) */\n traceId: string | null;\n /** Root span ID from agent/workflow execution (null when not traced) */\n spanId?: string | null;\n /** Structured input for scorers (extracted from agent scoring data) */\n scorerInput?: ScorerRunInputForAgent;\n /** Structured output for scorers (extracted from agent scoring data) */\n scorerOutput?: ScorerRunOutputForAgent;\n /** Per-step results from a workflow run, keyed by step ID */\n stepResults?: Record<string, StepResult<any, any, any, any>>;\n /** Order in which workflow steps actually executed */\n stepExecutionPath?: string[];\n /** Diagnostic receipt for item-level tool mocks (agent targets only) */\n toolMockReport?: ToolMockReport;\n}\n\n/**\n * Execute a dataset item against a scorer (LLM-as-judge calibration).\n * item.input should contain exactly what the scorer expects - direct passthrough.\n * For calibration: item.input = { input, output, groundTruth } (user structures it)\n */\nasync function executeScorer(\n scorer: MastraScorer<any, any, any, any>,\n item: { input: unknown; groundTruth?: unknown },\n): Promise<ExecutionResult> {\n try {\n // Direct passthrough - scorer receives item.input exactly as provided\n // User structures item.input to match scorer's expected shape (e.g., { input, output, groundTruth })\n const result = await scorer.run(item.input as any);\n\n // Validate score is a number\n const score = typeof result.score === 'number' && !isNaN(result.score) ? result.score : null;\n\n if (score === null && result.score !== undefined) {\n console.warn(`Scorer ${scorer.id} returned invalid score: ${result.score}`);\n }\n\n return {\n output: {\n score,\n reason: typeof result.reason === 'string' ? result.reason : null,\n },\n error: null,\n traceId: null, // Scorers don't produce traces\n };\n } catch (error) {\n return {\n output: null,\n error: {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n traceId: null,\n };\n }\n}\n\n/** Maximum number of suspend/resume cycles to prevent infinite loops */\nconst MAX_RESUME_CYCLES = 10;\n\n/**\n * Execute a dataset item against a target (agent, workflow, scorer, processor).\n * Phase 2: agent/workflow. Phase 4: scorer. Processor deferred.\n */\nexport async function executeTarget(\n target: Target,\n targetType: TargetType,\n item: {\n input: unknown;\n groundTruth?: unknown;\n metadata?: Record<string, unknown>;\n resumeSteps?: Record<string, unknown>;\n resumeData?: unknown;\n },\n options?: {\n signal?: AbortSignal;\n requestContext?: Record<string, unknown>;\n experimentId?: string;\n versions?: VersionOverrides;\n /** Item-level static tool mocks (agent targets only). */\n toolMocks?: ItemToolMock[];\n },\n): Promise<ExecutionResult> {\n try {\n const signal = options?.signal;\n\n // Check if already aborted before starting\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException('The operation was aborted.', 'AbortError');\n }\n\n let executionPromise: Promise<ExecutionResult>;\n switch (targetType) {\n case 'agent':\n executionPromise = executeAgent(\n target as Agent,\n item,\n signal,\n options?.requestContext,\n options?.experimentId,\n options?.versions,\n options?.toolMocks,\n );\n break;\n case 'workflow':\n executionPromise = executeWorkflow(target as Workflow, item, options?.requestContext);\n break;\n case 'scorer':\n executionPromise = executeScorer(target as MastraScorer<any, any, any, any>, item);\n break;\n case 'processor':\n // Processor targets dropped from roadmap - not a core use case\n throw new Error(`Target type '${targetType}' not yet supported.`);\n default:\n throw new Error(`Unknown target type: ${targetType}`);\n }\n\n // Race execution against signal abort (ensures timeout works even if target ignores signal)\n if (signal) {\n return await raceWithSignal(executionPromise, signal);\n }\n\n return await executionPromise;\n } catch (error) {\n return {\n output: null,\n error: {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n traceId: null,\n };\n }\n}\n\n/**\n * Race a promise against an AbortSignal. Rejects with the signal's reason when aborted.\n */\nfunction raceWithSignal<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) {\n return Promise.reject(signal.reason ?? new DOMException('The operation was aborted.', 'AbortError'));\n }\n\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n reject(signal.reason ?? new DOMException('The operation was aborted.', 'AbortError'));\n };\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n promise.then(\n value => {\n signal.removeEventListener('abort', onAbort);\n resolve(value);\n },\n err => {\n signal.removeEventListener('abort', onAbort);\n reject(err);\n },\n );\n });\n}\n\n/**\n * Execute a dataset item against an agent.\n * Uses generate() for both v1 and v2 models.\n */\nasync function executeAgent(\n agent: Agent,\n item: { input: unknown; groundTruth?: unknown },\n signal?: AbortSignal,\n requestContext?: Record<string, unknown>,\n experimentId?: string,\n versions?: VersionOverrides,\n toolMocks?: ItemToolMock[],\n): Promise<ExecutionResult> {\n const model = await agent.getModel();\n\n // Both generate() and generateLegacy() return different types (FullOutput vs GenerateTextResult)\n // but share the fields we extract. Cast input to MessageListInput at the boundary.\n const input = item.input as MessageListInput;\n\n const reqCtx: RequestContext | undefined = requestContext\n ? new RequestContext(Object.entries(requestContext))\n : undefined;\n\n // Pass experimentId as tracing metadata so it appears on the AGENT_RUN span\n const tracingOptions = experimentId ? { metadata: { experimentId } } : undefined;\n\n // Build a fresh matcher per item run so ordered consumption is deterministic and\n // not leaked across retries. Compose with the agent's configured hooks.\n const matcher = new ToolMockMatcher(toolMocks);\n\n // When the item declares mocks, abort the whole run the instant a mocked tool is\n // mis-called so the model cannot go on to invoke later (possibly side-effecting,\n // unmocked) tools live. The mock-abort signal is combined with the outer signal.\n const mockAbort = matcher.hasMocks ? new AbortController() : undefined;\n const mockHooks = matcher.hasMocks ? buildToolMockHooks(agent, matcher, mockAbort!) : undefined;\n const generateSignal =\n mockAbort && signal ? AbortSignal.any([signal, mockAbort.signal]) : (mockAbort?.signal ?? signal);\n\n // Force sequential tool execution when mocks exist so the provider's tool-call\n // order equals the execution (and consumption) order — deterministic ordered\n // consumption of repeated (toolName, args) mocks. No cost for mock-free runs.\n const mockConcurrency = matcher.hasMocks ? { toolCallConcurrency: 1 } : undefined;\n\n let rawResult: unknown;\n try {\n rawResult = isSupportedLanguageModel(model)\n ? await agent.generate(input, {\n scorers: {},\n returnScorerData: true,\n abortSignal: generateSignal,\n ...(reqCtx ? { requestContext: reqCtx } : {}),\n ...(tracingOptions ? { tracingOptions } : {}),\n ...(versions ? { versions } : {}),\n ...(mockHooks ? { hooks: mockHooks } : {}),\n ...(mockConcurrency ?? {}),\n })\n : await agent.generateLegacy(input, {\n scorers: {},\n returnScorerData: true,\n abortSignal: generateSignal,\n ...(reqCtx ? { requestContext: reqCtx } : {}),\n ...(tracingOptions ? { tracingOptions } : {}),\n ...(mockHooks ? { hooks: mockHooks } : {}),\n ...(mockConcurrency ?? {}),\n });\n } catch (error) {\n // A mock failure aborts the run mid-flight: surface the deterministic coded\n // error instead of the raw abort. Any other error rethrows unchanged.\n const mockReport = matcher.hasMocks ? matcher.report() : undefined;\n if (mockReport?.failure) {\n return toolMockFailureResult(mockReport, null);\n }\n throw error;\n }\n\n // Narrow to the common fields we need — both v1 and v2 results share these\n const result = rawResult as AgentGenerateResult;\n\n const traceId = result.traceId ?? null;\n const scoringData = result.scoringData;\n\n const toolMockReport = matcher.hasMocks ? matcher.report() : undefined;\n\n // Fallback for the race where the model finishes a step before the abort\n // propagates: the matcher still recorded the first failure, so fail the item\n // deterministically with the coded error. The mis-called tool never ran live.\n if (toolMockReport?.failure) {\n return toolMockFailureResult(toolMockReport, traceId);\n }\n\n // Only persist fields relevant to experiment evaluation — drop provider metadata,\n // duplicate messages, steps trace, and other debugging internals\n const trimmedOutput = {\n text: result.text,\n object: result.object,\n toolCalls: result.toolCalls,\n toolResults: result.toolResults,\n sources: result.sources,\n files: result.files,\n usage: result.usage,\n reasoningText: result.reasoningText,\n traceId,\n error: result.error ?? null,\n };\n\n return {\n output: trimmedOutput,\n error: null,\n traceId,\n scorerInput: scoringData?.input,\n scorerOutput: scoringData?.output,\n ...(toolMockReport ? { toolMockReport } : {}),\n };\n}\n\n/** Build the deterministic, non-retryable failure result for a mis-called mock. */\nfunction toolMockFailureResult(report: ToolMockReport, traceId: string | null): ExecutionResult {\n const failure = report.failure!;\n return {\n output: null,\n error: {\n message: `Mocked tool \"${failure.toolName}\" was called with arguments that did not match an available mock (${failure.code}).`,\n code: failure.code,\n },\n traceId,\n toolMockReport: report,\n };\n}\n\n/**\n * Compose item-level tool mocks with the agent's configured tool hooks into a\n * single set of run-level hooks.\n *\n * Composition order (per spec):\n * 1. User `beforeToolCall` (if `{ proceed: false }`, short-circuit — the mock is\n * left unconsumed and reported as such; user `afterToolCall` is NOT called,\n * matching the agent's own short-circuit behavior).\n * 2. Mock matcher — `serve` returns the mocked output; `fail` aborts the run so\n * the model cannot call any further (possibly unmocked, side-effecting) tools\n * live; `live` falls through to the real tool.\n * 3. User `afterToolCall` runs for served mocks (the agent skips its own on\n * short-circuit, so it is invoked here to honor the documented composition).\n *\n * Ordered consumption of repeated `(toolName, args)` mocks is deterministic because\n * the caller forces `toolCallConcurrency: 1` when mocks exist, so tool calls arrive\n * (and consume) in the provider's call order — no mutex needed.\n */\nfunction buildToolMockHooks(agent: Agent, matcher: ToolMockMatcher, mockAbort: AbortController): ToolHooks {\n const userHooks = agent.getConfiguredToolHooks();\n\n return {\n beforeToolCall: async context => {\n // 1. User hook first — a short-circuit leaves the mock unconsumed.\n const userResult = await userHooks?.beforeToolCall?.(context);\n if (userResult?.proceed === false) {\n return userResult;\n }\n\n // 2. Mock matcher.\n const resolution = matcher.resolve(context.toolName, context.input);\n if (resolution.kind === 'serve') {\n await userHooks?.afterToolCall?.({ ...context, output: resolution.output });\n return { proceed: false, output: resolution.output };\n }\n if (resolution.kind === 'fail') {\n // Abort the whole run immediately. The matcher recorded the first failure;\n // the item fails deterministically via the catch path. Short-circuit the\n // tool here too so the mis-called tool never runs live even before the\n // abort propagates.\n mockAbort.abort(new Error(`Tool mock failure for \"${context.toolName}\" (${resolution.code})`));\n return { proceed: false, output: { error: resolution.code } };\n }\n\n // 3. `live` — fall through to the real tool.\n return undefined;\n },\n // Pass the user's afterToolCall through as-is (preserving undefined) so the\n // agent skips a no-op call when the user configured no afterToolCall. Served\n // mocks invoke it manually above, since they short-circuit the real tool.\n afterToolCall: userHooks?.afterToolCall,\n };\n}\n\n/**\n * Extract resume data from item fields and metadata.\n *\n * Checks top-level `resumeSteps`/`resumeData` first (inline data path),\n * then falls back to `metadata.resumeSteps`/`metadata.resumeData` (storage-backed path).\n *\n * Supports two shapes:\n * 1. Keyed by step ID: `resumeSteps: { \"step-id\": <payload> }`\n * Used when the workflow may suspend on multiple steps and each needs distinct data.\n * 2. Flat payload: `resumeData: <payload>`\n * Used when the workflow has a single suspended step (auto-detected).\n */\nfunction extractResumeData(item: {\n metadata?: Record<string, unknown>;\n resumeSteps?: Record<string, unknown>;\n resumeData?: unknown;\n}): {\n perStep?: Record<string, unknown>;\n flat?: unknown;\n} {\n // Top-level fields (from inline DataItem) take precedence.\n // Use explicit `undefined` checks rather than `??` so that falsy values\n // like `null`, `false`, `0`, `\"\"` are treated as valid resume payloads.\n const perStep =\n item.resumeSteps !== undefined\n ? item.resumeSteps\n : (item.metadata?.resumeSteps as Record<string, unknown> | undefined);\n const flat = item.resumeData !== undefined ? item.resumeData : item.metadata?.resumeData;\n return { perStep, flat };\n}\n\n/**\n * Execute a dataset item against a workflow.\n * Creates a run with scorers disabled to avoid double-scoring.\n *\n * When the workflow suspends, checks for resume data in `item.metadata`\n * (via `resumeSteps` keyed by step ID or `resumeData` for single-step workflows)\n * and automatically resumes. Loops through multiple suspend/resume cycles up to\n * MAX_RESUME_CYCLES to support multi-step suspend workflows.\n *\n * Mirrors `executeWorkflow` in evals/run so dataset experiments and runEvals\n * produce the same observability spans and scoring data for workflow targets.\n */\nasync function executeWorkflow(\n workflow: Workflow,\n item: {\n input: unknown;\n groundTruth?: unknown;\n metadata?: Record<string, unknown>;\n resumeSteps?: Record<string, unknown>;\n resumeData?: unknown;\n },\n requestContext?: Record<string, unknown>,\n): Promise<ExecutionResult> {\n const reqCtx: RequestContext | undefined = requestContext\n ? new RequestContext(Object.entries(requestContext))\n : undefined;\n const observabilityContext = resolveObservabilityContext({});\n\n const run = await workflow.createRun({ disableScorers: true });\n let result = await run.start({\n inputData: item.input,\n ...(reqCtx ? { requestContext: reqCtx } : {}),\n ...observabilityContext,\n });\n\n // Auto-resume loop: if the workflow suspends and resume data is provided,\n // resume the workflow automatically. Cap iterations to prevent infinite loops.\n const { perStep, flat } = extractResumeData(item);\n const hasResumeData = perStep !== undefined || flat !== undefined;\n\n if (hasResumeData) {\n let cycle = 0;\n while (result.status === 'suspended' && cycle < MAX_RESUME_CYCLES) {\n cycle++;\n\n // Determine which steps are suspended\n const suspendedPaths: string[][] = result.suspended ?? [];\n if (suspendedPaths.length === 0) break;\n\n // For each suspended step, look up resume data\n const firstSuspendedStep = suspendedPaths[0]?.[0];\n if (!firstSuspendedStep) break;\n\n // Resolve resume data: per-step map takes precedence, then flat fallback.\n // Use explicit undefined check so falsy values (null, false, 0) are forwarded.\n const perStepValue = perStep?.[firstSuspendedStep];\n const stepResumeData = perStepValue !== undefined ? perStepValue : flat;\n if (stepResumeData === undefined) break; // No data for this step, stop resuming\n\n result = await run.resume({\n resumeData: stepResumeData,\n step: firstSuspendedStep,\n ...(reqCtx ? { requestContext: reqCtx } : {}),\n ...observabilityContext,\n });\n }\n }\n\n return handleWorkflowResult(result);\n}\n\n/**\n * Map a terminal WorkflowResult to an ExecutionResult.\n * Uses a loose `result: any` parameter because WorkflowResult is heavily generic;\n * status-narrowing guards below keep accesses safe.\n */\n\nfunction handleWorkflowResult(result: any): ExecutionResult {\n // TracingProperties is intersected on every WorkflowResult variant\n const traceId = result.traceId ?? null;\n const spanId = result.spanId ?? null;\n\n if (result.status === 'success') {\n return {\n output: result.result,\n error: null,\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n if (result.status === 'failed') {\n return {\n output: null,\n error: { message: result.error?.message ?? 'Workflow failed', stack: result.error?.stack },\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n if (result.status === 'tripwire') {\n return {\n output: null,\n error: { message: `Workflow tripwire: ${result.tripwire?.reason ?? 'Unknown reason'}` },\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n if (result.status === 'suspended') {\n // Workflow suspended but no resume data was provided (or exhausted).\n // Return partial results with suspend payload for debugging.\n return {\n output: result.suspendPayload ?? null,\n error: {\n message:\n 'Workflow suspended — provide resume data via item.resumeSteps/item.resumeData (or metadata.resumeSteps/metadata.resumeData) to auto-resume',\n },\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n if (result.status === 'paused') {\n return {\n output: null,\n error: { message: 'Workflow paused - not yet supported in dataset experiments' },\n traceId,\n spanId,\n stepResults: result.steps as Record<string, StepResult<any, any, any, any>>,\n stepExecutionPath: result.stepExecutionPath,\n };\n }\n\n // Catch-all for any other status\n return {\n output: null,\n error: { message: `Workflow ended with unexpected status: ${result.status}` },\n traceId,\n spanId,\n };\n}\n","import type { MastraScorer } from '../../evals/base';\nimport { extractTrajectory, extractTrajectoryFromTrace } from '../../evals/types';\nimport type { ScorerRunInputForAgent, ScorerRunOutputForAgent, Trajectory } from '../../evals/types';\nimport type { Mastra } from '../../mastra';\nimport { validateAndSaveScore } from '../../mastra/hooks';\nimport { EntityType } from '../../observability';\nimport type { CorrelationContext } from '../../observability';\nimport type { MastraCompositeStore } from '../../storage/base';\nimport type { TargetType } from '../../storage/types';\nimport type { StepResult } from '../../workflows';\nimport type { ScorerResult } from './types';\n\nfunction toScorerTargetEntityType(targetType?: TargetType): EntityType | undefined {\n switch (targetType) {\n case 'agent':\n return EntityType.AGENT;\n case 'workflow':\n return EntityType.WORKFLOW_RUN;\n case 'scorer':\n return EntityType.SCORER;\n default:\n return undefined;\n }\n}\n\n/**\n * Resolve scorers from mixed array of instances and string IDs.\n * String IDs are looked up from Mastra's scorer registry.\n */\nexport function resolveScorers(\n mastra: Mastra,\n scorers?: (MastraScorer<any, any, any, any> | string)[],\n): MastraScorer<any, any, any, any>[] {\n if (!scorers || scorers.length === 0) return [];\n\n return scorers\n .map(scorer => {\n if (typeof scorer === 'string') {\n const resolved = mastra.getScorerById(scorer);\n if (!resolved) {\n console.warn(`Scorer not found: ${scorer}`);\n return null;\n }\n return resolved;\n }\n return scorer;\n })\n .filter((s): s is MastraScorer<any, any, any, any> => s !== null);\n}\n\n/**\n * Attempt to extract a Trajectory from the observability trace store.\n * Falls back to undefined if storage is unavailable or the trace has no spans.\n */\nasync function extractTrajectoryFromStorage(\n storage: MastraCompositeStore | null,\n traceId?: string,\n): Promise<Trajectory | undefined> {\n if (!storage || !traceId) return undefined;\n try {\n const observabilityStore = await storage.getStore('observability');\n if (!observabilityStore) return undefined;\n const trace = await observabilityStore.getTrace({ traceId });\n if (!trace?.spans?.length) return undefined;\n return extractTrajectoryFromTrace(trace.spans);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Workflow-specific data forwarded to scorers so they can inspect step-level\n * input/output and the executed step path. Surfaced via `targetMetadata` on\n * the scorer run so existing scorer signatures stay unchanged.\n */\nexport interface WorkflowScorerData {\n stepResults?: Record<string, StepResult<any, any, any, any>>;\n stepExecutionPath?: string[];\n spanId?: string | null;\n}\n\n/**\n * Run all scorers for a single item result.\n * Errors are isolated per scorer - one failing scorer doesn't affect others.\n * Trajectory scorers (scorer.type === 'trajectory') receive a pre-extracted\n * Trajectory as their output, mirroring the dispatch runEvals performs.\n */\nexport async function runScorersForItem(\n scorers: MastraScorer<any, any, any, any>[],\n item: { input: unknown; groundTruth?: unknown; metadata?: Record<string, unknown> },\n output: unknown,\n storage: MastraCompositeStore | null,\n runId: string,\n targetType: TargetType,\n targetId: string,\n itemId: string,\n scorerInput?: ScorerRunInputForAgent,\n scorerOutput?: ScorerRunOutputForAgent,\n traceId?: string,\n workflowData?: WorkflowScorerData,\n): Promise<ScorerResult[]> {\n if (scorers.length === 0) return [];\n\n // Pre-extract trajectory once for all trajectory scorers in this batch.\n // Try the trace store first (requires observability storage + traceId), then\n // fall back to extracting from the raw MastraDBMessage[] scoring output.\n const hasTrajectoryScorer = scorers.some(s => s.type === 'trajectory');\n let trajectoryOutput: Trajectory | undefined;\n if (hasTrajectoryScorer) {\n const traceTrajectory = await extractTrajectoryFromStorage(storage, traceId);\n trajectoryOutput = traceTrajectory ?? (scorerOutput ? extractTrajectory(scorerOutput) : { steps: [] });\n }\n\n // Build correlation context so scorers can emit scores with full experiment context\n const targetCorrelationContext: CorrelationContext = {\n ...(traceId ? { traceId } : {}),\n entityType: toScorerTargetEntityType(targetType),\n entityId: targetId,\n entityName: targetId,\n experimentId: runId,\n };\n\n const settled = await Promise.allSettled(\n scorers.map(async scorer => {\n const { result, promptMetadata } = await runScorerSafe(\n scorer,\n item,\n output,\n scorerInput,\n scorerOutput,\n targetType,\n traceId,\n targetCorrelationContext,\n scorer.type === 'trajectory' ? trajectoryOutput : undefined,\n workflowData,\n );\n\n // Persist score if storage available and score was computed\n if (storage && result.score !== null) {\n try {\n // Legacy score-store emission. This path is being deprecated.\n await validateAndSaveScore(storage, {\n scorerId: scorer.id,\n score: result.score,\n reason: result.reason ?? undefined,\n input: item.input,\n output,\n additionalContext: item.metadata,\n entityType: targetType.toUpperCase(),\n entityId: itemId,\n source: 'TEST',\n runId,\n traceId,\n scorer: {\n id: scorer.id,\n name: scorer.name,\n description: scorer.description ?? '',\n hasJudge: !!scorer.judge,\n },\n entity: {\n id: targetId,\n name: targetId,\n },\n ...promptMetadata,\n });\n } catch (saveError) {\n // TODO: Remove this warning path once the old scores storage is deprecated.\n // Log but don't fail - score persistence is best-effort\n console.warn(`Failed to save score for scorer ${scorer.id}:`, saveError);\n }\n }\n\n return result;\n }),\n );\n\n return settled.map((s, i) => {\n if (s.status === 'fulfilled') return s.value;\n const scorer = scorers[i]!;\n return {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: String(s.reason),\n targetScope: scorer.type === 'trajectory' ? 'trajectory' : 'span',\n };\n });\n}\n\n/** Prompt/step metadata returned by scorer.run() for DB persistence. */\ninterface ScorerPromptMetadata {\n generateScorePrompt?: string;\n generateReasonPrompt?: string;\n preprocessStepResult?: Record<string, unknown>;\n preprocessPrompt?: string;\n analyzeStepResult?: Record<string, unknown>;\n analyzePrompt?: string;\n}\n\n/**\n * Run a single scorer safely, catching any errors.\n * Returns both the ScorerResult and prompt metadata for DB persistence.\n * When trajectoryOutput is provided the scorer receives it as run.output,\n * honoring the type: 'trajectory' contract.\n */\nasync function runScorerSafe(\n scorer: MastraScorer<any, any, any, any>,\n item: { input: unknown; groundTruth?: unknown; metadata?: Record<string, unknown> },\n output: unknown,\n scorerInput?: ScorerRunInputForAgent,\n scorerOutput?: ScorerRunOutputForAgent,\n targetType?: TargetType,\n targetTraceId?: string,\n targetCorrelationContext?: CorrelationContext,\n trajectoryOutput?: Trajectory,\n workflowData?: WorkflowScorerData,\n): Promise<{ result: ScorerResult; promptMetadata: ScorerPromptMetadata }> {\n try {\n const effectiveOutput = trajectoryOutput ?? scorerOutput ?? output;\n const effectiveScope = trajectoryOutput ? 'trajectory' : 'span';\n\n // Surface step-level data via targetMetadata so workflow scorers can\n // inspect per-step input/output without changing the scorer signature.\n // Trajectory scorers already receive the Trajectory as their output, so\n // the step metadata is only relevant for non-trajectory workflow scorers.\n const targetMetadata: Record<string, unknown> | undefined =\n !trajectoryOutput && workflowData && (workflowData.stepResults || workflowData.stepExecutionPath)\n ? {\n ...(workflowData.stepResults ? { stepResults: workflowData.stepResults } : {}),\n ...(workflowData.stepExecutionPath ? { stepExecutionPath: workflowData.stepExecutionPath } : {}),\n }\n : undefined;\n\n const scoreResult: unknown = await scorer.run({\n input: scorerInput ?? item.input,\n output: effectiveOutput,\n groundTruth: item.groundTruth,\n scoreSource: 'experiment',\n targetScope: effectiveScope,\n targetEntityType: toScorerTargetEntityType(targetType),\n targetTraceId,\n ...(workflowData?.spanId ? { targetSpanId: workflowData.spanId } : {}),\n ...(targetCorrelationContext ? { targetCorrelationContext } : {}),\n ...(targetMetadata ? { targetMetadata } : {}),\n });\n\n // Extract fields with typeof guards — scorer run result types use complex\n // conditional generics that don't resolve cleanly with MastraScorer<any,…>.\n if (typeof scoreResult !== 'object' || scoreResult === null) {\n return {\n result: {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: `Scorer ${scorer.name} (${scorer.id}) returned invalid result: expected object, got ${scoreResult === null ? 'null' : typeof scoreResult} (${String(scoreResult)})`,\n },\n promptMetadata: {},\n };\n }\n\n const fields = scoreResult as Record<string, unknown>;\n const score = typeof fields.score === 'number' ? fields.score : null;\n const reason = typeof fields.reason === 'string' ? fields.reason : null;\n\n const str = (key: string): string | undefined =>\n typeof fields[key] === 'string' ? (fields[key] as string) : undefined;\n const obj = (key: string): Record<string, unknown> | undefined => {\n const val = fields[key];\n return typeof val === 'object' && val !== null ? (val as Record<string, unknown>) : undefined;\n };\n\n return {\n result: {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score,\n reason,\n error: null,\n targetScope: effectiveScope,\n },\n promptMetadata: {\n generateScorePrompt: str('generateScorePrompt'),\n generateReasonPrompt: str('generateReasonPrompt'),\n preprocessStepResult: obj('preprocessStepResult'),\n preprocessPrompt: str('preprocessPrompt'),\n analyzeStepResult: obj('analyzeStepResult'),\n analyzePrompt: str('analyzePrompt'),\n },\n };\n } catch (error) {\n return {\n result: {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: error instanceof Error ? error.message : String(error),\n targetScope: trajectoryOutput ? 'trajectory' : 'span',\n },\n promptMetadata: {},\n };\n }\n}\n\n/**\n * Resolve step-scoped scorers from a `Record<stepId, (MastraScorer | string)[]>`.\n * String IDs are looked up from Mastra's scorer registry; missing IDs are skipped\n * with a warning (matching `resolveScorers`).\n */\nexport function resolveStepScorers(\n mastra: Mastra,\n stepsConfig?: Record<string, (MastraScorer<any, any, any, any> | string)[]>,\n): Record<string, MastraScorer<any, any, any, any>[]> {\n if (!stepsConfig) return {};\n const resolved: Record<string, MastraScorer<any, any, any, any>[]> = {};\n for (const [stepId, scorers] of Object.entries(stepsConfig)) {\n const stepScorers = resolveScorers(mastra, scorers);\n if (stepScorers.length > 0) resolved[stepId] = stepScorers;\n }\n return resolved;\n}\n\n/**\n * Run step-scoped scorers for a single workflow item. Mirrors the per-step\n * dispatch in `runEvals`: each scorer runs against `stepResult.payload` and\n * `stepResult.output`, with `targetScope: 'span'` and\n * `targetEntityType: WORKFLOW_STEP`. The returned `ScorerResult` carries the\n * originating `stepId` so callers can disambiguate per-step results in the\n * flat `scores` array. Steps whose result is missing or did not succeed\n * surface as an error `ScorerResult` rather than disappearing silently.\n *\n * Errors are isolated per scorer (consistent with `runScorersForItem`); a\n * failing scorer produces a `ScorerResult` with `error` set, not a throw.\n */\nexport async function runStepScorersForItem(\n stepScorers: Record<string, MastraScorer<any, any, any, any>[]>,\n item: { input: unknown; groundTruth?: unknown; metadata?: Record<string, unknown> },\n workflowData: WorkflowScorerData | undefined,\n storage: MastraCompositeStore | null,\n runId: string,\n targetType: TargetType,\n targetId: string,\n itemId: string,\n traceId?: string,\n): Promise<ScorerResult[]> {\n const stepIds = Object.keys(stepScorers);\n if (stepIds.length === 0) return [];\n\n const results: ScorerResult[] = [];\n const stepResults = workflowData?.stepResults;\n\n for (const stepId of stepIds) {\n const scorers = stepScorers[stepId]!;\n const stepResult = stepResults?.[stepId];\n\n // Skip silently when the step didn't run or didn't succeed — matches runEvals.\n // Surface this as an \"error\" ScorerResult so consumers can see the skip in the\n // flat results array (rather than disappear without a trace).\n if (!stepResult || stepResult.status !== 'success' || stepResult.output === undefined) {\n for (const scorer of scorers) {\n results.push({\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: `Step \"${stepId}\" did not produce a successful output (status: ${stepResult?.status ?? 'missing'})`,\n targetScope: 'span',\n stepId,\n });\n }\n continue;\n }\n\n const stepInput = stepResult.payload !== undefined ? stepResult.payload : item.input;\n const stepOutput = stepResult.output;\n\n const targetCorrelationContext: CorrelationContext = {\n ...(traceId ? { traceId } : {}),\n entityType: EntityType.WORKFLOW_STEP,\n entityId: stepId,\n entityName: stepId,\n experimentId: runId,\n };\n\n const settled = await Promise.allSettled(\n scorers.map(async scorer => {\n try {\n const scoreResult: unknown = await scorer.run({\n input: stepInput,\n output: stepOutput,\n groundTruth: item.groundTruth,\n scoreSource: 'experiment',\n targetScope: 'span',\n targetEntityType: EntityType.WORKFLOW_STEP,\n targetTraceId: traceId,\n ...(targetCorrelationContext ? { targetCorrelationContext } : {}),\n });\n\n if (typeof scoreResult !== 'object' || scoreResult === null) {\n return {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: `Scorer ${scorer.name} (${scorer.id}) returned invalid result on step ${stepId}`,\n targetScope: 'span' as const,\n stepId,\n };\n }\n const fields = scoreResult as Record<string, unknown>;\n const score = typeof fields.score === 'number' ? fields.score : null;\n const reason = typeof fields.reason === 'string' ? fields.reason : null;\n\n // Persist score (best-effort, mirrors runScorersForItem)\n if (storage && score !== null) {\n try {\n await validateAndSaveScore(storage, {\n scorerId: scorer.id,\n score,\n reason: reason ?? undefined,\n input: stepInput,\n output: stepOutput,\n additionalContext: { ...item.metadata, stepId },\n entityType: 'WORKFLOW_STEP',\n entityId: itemId,\n source: 'TEST',\n runId,\n traceId,\n scorer: {\n id: scorer.id,\n name: scorer.name,\n description: scorer.description ?? '',\n hasJudge: !!scorer.judge,\n },\n entity: {\n id: targetId,\n name: targetId,\n },\n });\n } catch (saveError) {\n console.warn(`Failed to save score for step scorer ${scorer.id} on ${stepId}:`, saveError);\n }\n }\n\n return {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score,\n reason,\n error: null,\n targetScope: 'span' as const,\n stepId,\n };\n } catch (error) {\n return {\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: error instanceof Error ? error.message : String(error),\n targetScope: 'span' as const,\n stepId,\n };\n }\n }),\n );\n\n for (let i = 0; i < settled.length; i++) {\n const s = settled[i]!;\n if (s.status === 'fulfilled') {\n results.push(s.value);\n } else {\n const scorer = scorers[i]!;\n results.push({\n scorerId: scorer.id,\n scorerName: scorer.name,\n score: null,\n reason: null,\n error: String(s.reason),\n targetScope: 'span',\n stepId,\n });\n }\n }\n }\n\n // targetType/targetId are intentionally accepted but only used for persistence\n // entity context; the dispatch itself is workflow-step scoped.\n void targetType;\n return results;\n}\n","/**\n * Experiment Analytics Aggregation Helpers\n *\n * Pure functions for computing statistics from raw score data.\n * Used by compareExperiments to build ScorerStats and detect regressions.\n */\n\nimport type { ScoreRowData } from '../../../evals/types';\nimport type { ScorerStats } from './types';\n\n/**\n * Compute the arithmetic mean of an array of numbers.\n *\n * @param values - Array of numbers to average\n * @returns Mean value, or 0 if array is empty\n */\nexport function computeMean(values: number[]): number {\n if (values.length === 0) {\n return 0;\n }\n const sum = values.reduce((acc, val) => acc + val, 0);\n return sum / values.length;\n}\n\n/**\n * Compute aggregate statistics for a set of scores.\n *\n * Metrics:\n * - errorRate: proportion of items with null scores (errors)\n * - passRate: proportion of scored items meeting threshold\n * - avgScore: mean of non-null scores\n *\n * @param scores - Score records from storage\n * @param passThreshold - Absolute threshold for pass (score >= threshold)\n * @returns ScorerStats with all computed metrics\n */\nexport function computeScorerStats(scores: ScoreRowData[], passThreshold: number = 0.5): ScorerStats {\n const totalItems = scores.length;\n\n if (totalItems === 0) {\n return {\n errorRate: 0,\n errorCount: 0,\n passRate: 0,\n passCount: 0,\n avgScore: 0,\n scoreCount: 0,\n totalItems: 0,\n };\n }\n\n // Separate null scores (errors) from valid scores\n const validScores: number[] = [];\n let errorCount = 0;\n\n for (const score of scores) {\n if (score.score === null || score.score === undefined) {\n errorCount++;\n } else {\n validScores.push(score.score);\n }\n }\n\n const scoreCount = validScores.length;\n const errorRate = errorCount / totalItems;\n\n // Pass rate is computed over items with valid scores only\n const passCount = validScores.filter(s => s >= passThreshold).length;\n const passRate = scoreCount > 0 ? passCount / scoreCount : 0;\n\n // Average score excludes errors\n const avgScore = computeMean(validScores);\n\n return {\n errorRate,\n errorCount,\n passRate,\n passCount,\n avgScore,\n scoreCount,\n totalItems,\n };\n}\n\n/**\n * Determine if a score delta represents a regression.\n *\n * @param delta - Score difference (experiment B - experiment A)\n * @param threshold - Absolute threshold for regression detection\n * @param direction - Score direction ('higher-is-better' or 'lower-is-better')\n * @returns True if delta represents a regression\n *\n * @example\n * // Higher is better (default): negative delta is bad\n * isRegression(-0.1, 0.05, 'higher-is-better') // true (dropped more than 0.05)\n * isRegression(-0.01, 0.05, 'higher-is-better') // false (within tolerance)\n *\n * // Lower is better: positive delta is bad\n * isRegression(0.1, 0.05, 'lower-is-better') // true (increased more than 0.05)\n */\nexport function isRegression(\n delta: number,\n threshold: number,\n direction: 'higher-is-better' | 'lower-is-better' = 'higher-is-better',\n): boolean {\n if (direction === 'higher-is-better') {\n // Regression if score dropped below threshold\n // delta < -threshold means score dropped by more than threshold\n return delta < -threshold;\n } else {\n // Regression if score increased above threshold\n // delta > threshold means score increased by more than threshold\n return delta > threshold;\n }\n}\n","/**\n * Experiment Comparison\n *\n * Compare two experiments to detect score regressions.\n * Returns per-scorer deltas and per-item score diffs.\n */\n\nimport type { ScoreRowData } from '../../../evals/types';\nimport type { Mastra } from '../../../mastra';\nimport { computeScorerStats, isRegression } from './aggregate';\nimport type {\n CompareExperimentsConfig,\n ComparisonResult,\n ItemComparison,\n ScorerComparison,\n ScorerThreshold,\n} from './types';\n\n/**\n * Default threshold when not specified: no tolerance for regression.\n */\nconst DEFAULT_THRESHOLD: ScorerThreshold = {\n value: 0,\n direction: 'higher-is-better',\n};\n\n/**\n * Default pass threshold for computing pass rate.\n */\nconst DEFAULT_PASS_THRESHOLD = 0.5;\n\n/**\n * Compare two experiments to detect score regressions.\n *\n * @param mastra - Mastra instance for storage access\n * @param config - Comparison configuration\n * @returns ComparisonResult with per-scorer and per-item comparisons\n *\n * @example\n * ```typescript\n * const result = await compareExperiments(mastra, {\n * experimentIdA: 'baseline-experiment-id',\n * experimentIdB: 'candidate-experiment-id',\n * thresholds: {\n * 'accuracy': { value: 0.05, direction: 'higher-is-better' },\n * 'latency': { value: 100, direction: 'lower-is-better' },\n * },\n * });\n *\n * if (result.hasRegression) {\n * console.log('Quality regression detected!');\n * }\n * ```\n */\nexport async function compareExperiments(mastra: Mastra, config: CompareExperimentsConfig): Promise<ComparisonResult> {\n const { experimentIdA, experimentIdB, thresholds = {} } = config;\n const warnings: string[] = [];\n\n // 1. Get storage\n const storage = mastra.getStorage();\n if (!storage) {\n throw new Error('Storage not configured. Configure storage in Mastra instance.');\n }\n\n const experimentsStore = await storage.getStore('experiments');\n const scoresStore = await storage.getStore('scores');\n\n if (!experimentsStore) {\n throw new Error('ExperimentsStorage not configured.');\n }\n if (!scoresStore) {\n throw new Error('ScoresStorage not configured.');\n }\n\n // 2. Load both experiments\n const [experimentA, experimentB] = await Promise.all([\n experimentsStore.getExperimentById({ id: experimentIdA }),\n experimentsStore.getExperimentById({ id: experimentIdB }),\n ]);\n\n if (!experimentA) {\n throw new Error(`Experiment not found: ${experimentIdA}`);\n }\n if (!experimentB) {\n throw new Error(`Experiment not found: ${experimentIdB}`);\n }\n\n // 3. Check version mismatch\n const versionMismatch = experimentA.datasetVersion !== experimentB.datasetVersion;\n if (versionMismatch) {\n warnings.push(\n `Experiments have different dataset versions: ${experimentA.datasetVersion} vs ${experimentB.datasetVersion}`,\n );\n }\n\n // 4. Load results for both experiments\n const [resultsA, resultsB] = await Promise.all([\n experimentsStore.listExperimentResults({ experimentId: experimentIdA, pagination: { page: 0, perPage: false } }),\n experimentsStore.listExperimentResults({ experimentId: experimentIdB, pagination: { page: 0, perPage: false } }),\n ]);\n\n // 5. Load scores for both experiments\n const [scoresA, scoresB] = await Promise.all([\n scoresStore.listScoresByRunId({ runId: experimentIdA, pagination: { page: 0, perPage: false } }),\n scoresStore.listScoresByRunId({ runId: experimentIdB, pagination: { page: 0, perPage: false } }),\n ]);\n\n // 6. Handle empty experiments\n if (resultsA.results.length === 0 && resultsB.results.length === 0) {\n warnings.push('Both experiments have no results.');\n return buildEmptyResult(experimentA, experimentB, versionMismatch, warnings);\n }\n if (resultsA.results.length === 0) {\n warnings.push('Experiment A has no results.');\n }\n if (resultsB.results.length === 0) {\n warnings.push('Experiment B has no results.');\n }\n\n // 7. Find overlapping items\n const itemIdsA = new Set(resultsA.results.map(r => r.itemId));\n const itemIdsB = new Set(resultsB.results.map(r => r.itemId));\n const overlappingItemIds = [...itemIdsA].filter(id => itemIdsB.has(id));\n\n if (overlappingItemIds.length === 0) {\n warnings.push('No overlapping items between experiments.');\n }\n\n // 8. Group scores by scorer and item\n const scoresMapA = groupScoresByScorerAndItem(scoresA.scores);\n const scoresMapB = groupScoresByScorerAndItem(scoresB.scores);\n\n // 9. Find all unique scorers\n const allScorerIds = new Set([...Object.keys(scoresMapA), ...Object.keys(scoresMapB)]);\n\n // 10. Build per-scorer comparison\n const scorers: Record<string, ScorerComparison> = {};\n let hasRegression = false;\n\n for (const scorerId of allScorerIds) {\n const scorerScoresA = scoresMapA[scorerId] ?? {};\n const scorerScoresB = scoresMapB[scorerId] ?? {};\n\n // Get scores as arrays for stats computation\n const scoresArrayA = Object.values(scorerScoresA);\n const scoresArrayB = Object.values(scorerScoresB);\n\n // Get threshold config for this scorer\n const thresholdConfig = thresholds[scorerId] ?? DEFAULT_THRESHOLD;\n const threshold = thresholdConfig.value;\n const direction = thresholdConfig.direction ?? 'higher-is-better';\n\n // Compute stats\n const statsA = computeScorerStats(scoresArrayA, DEFAULT_PASS_THRESHOLD);\n const statsB = computeScorerStats(scoresArrayB, DEFAULT_PASS_THRESHOLD);\n\n // Compute delta and check regression\n const delta = statsB.avgScore - statsA.avgScore;\n const regressed = isRegression(delta, threshold, direction);\n\n if (regressed) {\n hasRegression = true;\n }\n\n scorers[scorerId] = {\n statsA,\n statsB,\n delta,\n regressed,\n threshold,\n };\n }\n\n // 11. Build per-item comparison\n const allItemIds = new Set([...itemIdsA, ...itemIdsB]);\n const items: ItemComparison[] = [];\n\n for (const itemId of allItemIds) {\n const inBothExperiments = itemIdsA.has(itemId) && itemIdsB.has(itemId);\n\n // Build scores for this item\n const itemScoresA: Record<string, number | null> = {};\n const itemScoresB: Record<string, number | null> = {};\n\n for (const scorerId of allScorerIds) {\n const scoreA = scoresMapA[scorerId]?.[itemId];\n const scoreB = scoresMapB[scorerId]?.[itemId];\n\n itemScoresA[scorerId] = scoreA?.score ?? null;\n itemScoresB[scorerId] = scoreB?.score ?? null;\n }\n\n items.push({\n itemId,\n inBothExperiments,\n scoresA: itemScoresA,\n scoresB: itemScoresB,\n });\n }\n\n return {\n experimentA: {\n id: experimentA.id,\n datasetVersion: experimentA.datasetVersion,\n },\n experimentB: {\n id: experimentB.id,\n datasetVersion: experimentB.datasetVersion,\n },\n versionMismatch,\n hasRegression,\n scorers,\n items,\n warnings,\n };\n}\n\n/**\n * Group scores by scorer ID, then by item ID.\n */\nfunction groupScoresByScorerAndItem(scores: ScoreRowData[]): Record<string, Record<string, ScoreRowData>> {\n const result: Record<string, Record<string, ScoreRowData>> = {};\n\n for (const score of scores) {\n const scorerId = score.scorerId;\n const itemId = score.entityId; // entityId is the item ID for experiment scores\n\n if (!result[scorerId]) {\n result[scorerId] = {};\n }\n result[scorerId][itemId] = score;\n }\n\n return result;\n}\n\n/**\n * Build an empty comparison result for edge cases.\n */\nfunction buildEmptyResult(\n experimentA: { id: string; datasetVersion: number | null },\n experimentB: { id: string; datasetVersion: number | null },\n versionMismatch: boolean,\n warnings: string[],\n): ComparisonResult {\n return {\n experimentA: {\n id: experimentA.id,\n datasetVersion: experimentA.datasetVersion,\n },\n experimentB: {\n id: experimentB.id,\n datasetVersion: experimentB.datasetVersion,\n },\n versionMismatch,\n hasRegression: false,\n scorers: {},\n items: [],\n warnings,\n };\n}\n","import { MastraError } from '../../error/index.js';\nimport type { MastraScorer } from '../../evals/base';\nimport type { Mastra } from '../../mastra';\nimport type { DatasetRecord } from '../../storage/types';\nimport { executeTarget } from './executor';\nimport type { Target, ExecutionResult } from './executor';\nimport { resolveScorers, resolveStepScorers, runScorersForItem, runStepScorersForItem } from './scorer';\nimport { TOOL_MOCK_MISMATCH, TOOL_MOCK_EXHAUSTED } from './tool-mocks';\nimport type { ItemToolMock } from './tool-mocks';\nimport type { ExperimentConfig, ExperimentSummary, ItemWithScores, ItemResult } from './types';\n\n/** Unified item shape used within experiment execution (bridges inline + versioned data) */\ntype ExperimentItem = {\n id: string; // item id (or generated for inline)\n datasetVersion: number | null; // null for inline experiments\n input: unknown;\n groundTruth?: unknown;\n requestContext?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n /** Resume data for suspended workflow steps, keyed by step ID */\n resumeSteps?: Record<string, unknown>;\n /** Flat resume data for single-step suspend workflows */\n resumeData?: unknown;\n /** Item-level static tool mocks (agent targets only) */\n toolMocks?: ItemToolMock[];\n};\n\n// Re-export types and helpers\nexport type {\n DataItem,\n ExperimentConfig,\n ExperimentSummary,\n ItemWithScores,\n ItemResult,\n ScorerResult,\n StartExperimentConfig,\n} from './types';\nexport { executeTarget, type Target, type ExecutionResult } from './executor';\nexport { resolveScorers, runScorersForItem } from './scorer';\nexport {\n ToolMockMatcher,\n TOOL_MOCK_MISMATCH,\n TOOL_MOCK_EXHAUSTED,\n type ItemToolMock,\n type ToolMockMatchArgs,\n type ToolMockReport,\n type ToolMockResolution,\n type ToolMockFailureCode,\n} from './tool-mocks';\n\n// Re-export analytics\nexport * from './analytics';\n\n/**\n * Run a dataset experiment against a target with optional scoring.\n *\n * Executes all items in the dataset concurrently (up to maxConcurrency) against\n * the specified target (agent or workflow). Optionally applies scorers to each\n * result and persists both results and scores to storage.\n *\n * @param mastra - Mastra instance for storage and target resolution\n * @param config - Experiment configuration\n * @returns ExperimentSummary with results and scores\n *\n * @example\n * ```typescript\n * const summary = await runExperiment(mastra, {\n * datasetId: 'my-dataset',\n * targetType: 'agent',\n * targetId: 'my-agent',\n * scorers: [accuracyScorer, latencyScorer],\n * maxConcurrency: 10,\n * });\n * console.log(`${summary.succeededCount}/${summary.totalItems} succeeded`);\n * ```\n */\nexport async function runExperiment(mastra: Mastra, config: ExperimentConfig): Promise<ExperimentSummary> {\n const {\n datasetId,\n targetType,\n targetId,\n scorers: scorerInput,\n version,\n maxConcurrency = 5,\n signal,\n itemTimeout,\n maxRetries = 0,\n experimentId: providedExperimentId,\n name,\n description,\n metadata,\n requestContext: globalRequestContext,\n agentVersion,\n versions,\n } = config;\n\n const startedAt = new Date();\n // Use provided experimentId (async trigger) or generate new one\n const experimentId = providedExperimentId ?? crypto.randomUUID();\n\n // 1. Get storage and resolve components\n const storage = mastra.getStorage();\n const datasetsStore = await storage?.getStore('datasets');\n const experimentsStore = await storage?.getStore('experiments');\n\n // Helper: if the experiment record was pre-created (async path) and we fail\n // during setup (Phase A/B), mark the experiment as failed so it doesn't stay stuck in 'pending'.\n const markFailedOnSetupError = async (err: unknown) => {\n if (providedExperimentId && experimentsStore) {\n try {\n await experimentsStore.updateExperiment({\n id: experimentId,\n status: 'failed',\n completedAt: new Date(),\n });\n } catch (updateErr) {\n mastra.getLogger()?.error(`Failed to mark experiment ${experimentId} as failed: ${updateErr}`);\n }\n }\n throw err;\n };\n\n // Phase A — Resolve items\n let items: ExperimentItem[];\n let datasetVersion: number | null;\n let datasetRecord: DatasetRecord | null | undefined;\n\n try {\n if (config.data) {\n // Inline data path — array or factory function\n const rawData = typeof config.data === 'function' ? await config.data() : config.data;\n items = rawData.map(dataItem => {\n const id = dataItem.id ?? crypto.randomUUID();\n return {\n id,\n datasetVersion: null,\n input: dataItem.input,\n groundTruth: dataItem.groundTruth,\n requestContext: dataItem.requestContext,\n metadata: dataItem.metadata,\n resumeSteps: dataItem.resumeSteps,\n resumeData: dataItem.resumeData,\n toolMocks: dataItem.toolMocks,\n };\n });\n datasetVersion = null;\n } else if (datasetId) {\n // Storage-backed data path (existing)\n if (!datasetsStore) {\n throw new Error('DatasetsStorage not configured. Configure storage in Mastra instance.');\n }\n\n datasetRecord = await datasetsStore.getDatasetById({ id: datasetId, filters: config.filters });\n if (!datasetRecord) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: `Dataset not found: ${datasetId}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n datasetVersion = version ?? datasetRecord.version;\n const versionItems = await datasetsStore.getItemsByVersion({\n datasetId,\n version: datasetVersion,\n });\n\n if (versionItems.length === 0) {\n throw new MastraError({\n id: 'EXPERIMENT_NO_ITEMS',\n text: `No items in dataset ${datasetId} at version ${datasetVersion}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n items = versionItems.map(v => ({\n id: v.id,\n datasetVersion: v.datasetVersion,\n input: v.input,\n groundTruth: v.groundTruth,\n requestContext: v.requestContext,\n metadata: v.metadata,\n toolMocks: v.toolMocks,\n }));\n } else {\n throw new Error('No data source: provide datasetId or data');\n }\n } catch (err) {\n await markFailedOnSetupError(err);\n throw err; // unreachable, but satisfies TS control flow\n }\n\n // Phase B — Resolve task function\n let execFn: (item: ExperimentItem, signal?: AbortSignal) => Promise<ExecutionResult>;\n\n try {\n if (config.task) {\n // Inline task path\n const taskFn = config.task;\n execFn = async (item, itemSignal) => {\n try {\n const result = await taskFn({\n input: item.input,\n mastra,\n groundTruth: item.groundTruth,\n metadata: item.metadata,\n signal: itemSignal,\n });\n return { output: result, error: null, traceId: null };\n } catch (err: unknown) {\n return {\n output: null,\n error: {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n },\n traceId: null,\n };\n }\n };\n } else if (targetType && targetId) {\n // Registry-based target path (existing)\n const resolved = await resolveTarget(mastra, targetType, targetId, agentVersion);\n if (!resolved) {\n throw new Error(`Target not found: ${targetType}/${targetId}`);\n }\n const { target } = resolved;\n execFn = (item, itemSignal) => {\n // Merge global request context with per-item request context (item takes precedence)\n const mergedRequestContext =\n globalRequestContext || item.requestContext ? { ...globalRequestContext, ...item.requestContext } : undefined;\n return executeTarget(target, targetType, item, {\n signal: itemSignal,\n requestContext: mergedRequestContext,\n experimentId,\n versions,\n toolMocks: targetType === 'agent' ? item.toolMocks : undefined,\n });\n };\n } else {\n throw new Error('No task: provide targetType+targetId or task');\n }\n } catch (err) {\n await markFailedOnSetupError(err);\n throw err; // unreachable, but satisfies TS control flow\n }\n\n // Tool mocks only apply to agent targets. If a dataset carrying toolMocks is reused\n // against a task/workflow/scorer target, the mocks are silently ignored — warn once\n // (not per item) so the misconfiguration is visible without log spam.\n const itemsWithToolMocks = items.filter(item => item.toolMocks?.length).length;\n if (targetType !== 'agent' && itemsWithToolMocks > 0) {\n mastra\n .getLogger()\n ?.warn(\n `Experiment target is \"${config.task ? 'task' : targetType}\" but ${itemsWithToolMocks} of ${items.length} dataset items declare toolMocks. ` +\n `Tool mocks only apply to agent targets and will be ignored.`,\n );\n }\n\n // Normalize categorized scorer config (AgentScorerConfig | WorkflowScorerConfig) to a flat\n // array so the existing merge/dedup/resolve logic below is unchanged.\n // Trajectory dispatch is handled per-scorer in runScorerSafe based on scorer.type.\n // Step scorers are kept separate (keyed by step ID) and dispatched per-step\n // after the flat scorers run, mirroring runEvals.\n let stepsConfigInput: Record<string, (MastraScorer<any, any, any, any> | string)[]> | undefined;\n const flatScorerInput: (MastraScorer<any, any, any, any> | string)[] | undefined = (() => {\n if (!scorerInput) return undefined;\n if (Array.isArray(scorerInput)) return scorerInput;\n // Categorized shape — flatten flat-style buckets into one array, keep steps separate\n const flat: (MastraScorer<any, any, any, any> | string)[] = [];\n if ('agent' in scorerInput && scorerInput.agent) flat.push(...scorerInput.agent);\n if ('workflow' in scorerInput && scorerInput.workflow) flat.push(...scorerInput.workflow);\n if ('trajectory' in scorerInput && scorerInput.trajectory) flat.push(...scorerInput.trajectory);\n if ('steps' in scorerInput && scorerInput.steps) {\n stepsConfigInput = scorerInput.steps;\n }\n return flat;\n })();\n\n // Merge dataset-attached scorers with explicitly provided scorers, then deduplicate\n let mergedScorerInput = flatScorerInput;\n const datasetScorerIds = datasetRecord?.scorerIds ?? [];\n if (datasetScorerIds.length > 0) {\n mergedScorerInput = [...(flatScorerInput ?? []), ...datasetScorerIds];\n }\n if (mergedScorerInput && mergedScorerInput.length > 0) {\n const seen = new Set<string>();\n mergedScorerInput = mergedScorerInput.filter(entry => {\n if (typeof entry === 'string') {\n if (seen.has(entry)) return false;\n seen.add(entry);\n return true;\n }\n // Keep all scorer instances — they are resolved by reference, not by ID\n return true;\n });\n }\n\n // Resolve scorers\n const scorers = resolveScorers(mastra, mergedScorerInput);\n // Resolve per-step scorers (keyed by step ID) for workflow targets\n const stepScorers = resolveStepScorers(mastra, stepsConfigInput);\n\n // 5. Create experiment record (if storage available and not pre-created)\n if (experimentsStore) {\n if (!providedExperimentId) {\n // Create new experiment record (sync trigger path)\n await experimentsStore.createExperiment({\n id: experimentId,\n name,\n description,\n metadata,\n datasetId: datasetId ?? null,\n datasetVersion,\n targetType: targetType ?? 'agent',\n targetId: targetId ?? 'inline',\n totalItems: items.length,\n agentVersion,\n organizationId: datasetRecord?.organizationId ?? null,\n projectId: datasetRecord?.projectId ?? null,\n });\n }\n // Update status to running (both sync and async paths)\n // Also set totalItems — needed for the async path where the experiment\n // was created with totalItems: 0 before items were resolved.\n await experimentsStore.updateExperiment({\n id: experimentId,\n status: 'running',\n totalItems: items.length,\n startedAt,\n });\n }\n\n // 6. Execute items with p-map\n let succeededCount = 0;\n let failedCount = 0;\n // Rows whose target run completed but whose persistence to\n // `mastra_experiment_results` failed. Surfaced on the summary so callers\n // can detect the DB being out of sync with the returned results.\n let persistenceFailures = 0;\n // Pre-allocate for deterministic ordering (results[i] matches items[i])\n const results: ItemWithScores[] = new Array(items.length);\n\n // Throttled progress updates\n const PROGRESS_UPDATE_INTERVAL = 2000;\n let lastProgressUpdate = 0;\n\n try {\n const pMap = (await import('p-map')).default;\n\n await pMap(\n items.map((item, idx) => ({ item, idx })),\n async ({ item, idx }) => {\n // Check for cancellation\n if (signal?.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n const itemStartedAt = new Date();\n // Compose per-item signal (timeout + run-level abort)\n let itemSignal: AbortSignal | undefined = signal;\n if (itemTimeout) {\n const timeoutSignal = AbortSignal.timeout(itemTimeout);\n itemSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;\n }\n\n // Retry loop\n let retryCount = 0;\n let execResult = await execFn(item, itemSignal);\n\n while (execResult.error && retryCount < maxRetries) {\n // Don't retry abort errors\n if (execResult.error.message.toLowerCase().includes('abort')) break;\n\n // Don't retry deterministic tool-mock failures — the matcher state cannot\n // change between attempts, so retrying would always fail identically.\n if (execResult.error.code === TOOL_MOCK_MISMATCH || execResult.error.code === TOOL_MOCK_EXHAUSTED) {\n break;\n }\n\n retryCount++;\n const delay = Math.min(1000 * Math.pow(2, retryCount - 1), 30000);\n const jitter = delay * 0.2 * Math.random();\n await new Promise(r => setTimeout(r, delay + jitter));\n\n // Re-check cancellation before retry\n if (signal?.aborted) {\n throw new DOMException('Aborted', 'AbortError');\n }\n\n execResult = await execFn(item, itemSignal);\n }\n\n const itemCompletedAt = new Date();\n\n // Track success/failure\n if (execResult.error) {\n failedCount++;\n } else {\n succeededCount++;\n }\n\n // Build item result. `persistenceError` starts null and is set below\n // if `addExperimentResult` throws so callers can detect rows that\n // never landed in storage.\n const itemResult: ItemResult = {\n itemId: item.id,\n itemVersion: item.datasetVersion ?? 0,\n input: item.input,\n output: execResult.output,\n groundTruth: item.groundTruth ?? null,\n error: execResult.error,\n startedAt: itemStartedAt,\n completedAt: itemCompletedAt,\n retryCount,\n persistenceError: null,\n ...(execResult.toolMockReport ? { toolMockReport: execResult.toolMockReport } : {}),\n };\n\n // Run scorers (inline, after target completes)\n const workflowData =\n execResult.stepResults || execResult.stepExecutionPath\n ? {\n stepResults: execResult.stepResults,\n stepExecutionPath: execResult.stepExecutionPath,\n spanId: execResult.spanId,\n }\n : undefined;\n\n const flatScores = await runScorersForItem(\n scorers,\n item,\n execResult.output,\n storage ?? null,\n experimentId,\n targetType ?? 'agent',\n targetId ?? 'inline',\n item.id,\n execResult.scorerInput,\n execResult.scorerOutput,\n execResult.traceId ?? undefined,\n workflowData,\n );\n\n // Per-step scorer dispatch (mirrors runEvals). Only meaningful for workflow\n // targets; for non-workflow targets stepScorers will be empty.\n const stepScores = await runStepScorersForItem(\n stepScorers,\n item,\n workflowData,\n storage ?? null,\n experimentId,\n targetType ?? 'agent',\n targetId ?? 'inline',\n item.id,\n execResult.traceId ?? undefined,\n );\n\n const itemScores = [...flatScores, ...stepScores];\n\n // Persist result with scores (if storage available). A throw here does\n // NOT abort the run — persistence is best-effort and the target run's\n // outcome is already recorded in `itemResult`. Instead we surface the\n // failure on the item (`persistenceError`) and bump the run-level\n // `persistenceFailures` counter so callers can detect rows that never\n // landed in `mastra_experiment_results`.\n if (experimentsStore) {\n try {\n await experimentsStore.addExperimentResult({\n experimentId,\n itemId: item.id,\n itemDatasetVersion: item.datasetVersion,\n input: item.input,\n output: execResult.output,\n groundTruth: item.groundTruth ?? null,\n error: execResult.error,\n startedAt: itemStartedAt,\n completedAt: itemCompletedAt,\n retryCount,\n traceId: execResult.traceId,\n organizationId: datasetRecord?.organizationId ?? null,\n projectId: datasetRecord?.projectId ?? null,\n ...(execResult.toolMockReport ? { toolMockReport: execResult.toolMockReport } : {}),\n });\n } catch (persistError) {\n persistenceFailures++;\n itemResult.persistenceError = {\n message: persistError instanceof Error ? persistError.message : String(persistError),\n };\n // Log the raw error (including stack) internally, but do NOT attach the\n // stack to the returned `persistenceError` — the summary can cross a\n // trust boundary (e.g. UIs, API responses) and stacks leak internal paths.\n mastra\n .getLogger()\n ?.error(\n `Failed to persist experiment result for item ${item.id} in experiment ${experimentId}: ${itemResult.persistenceError.message}`,\n { error: persistError },\n );\n }\n\n // Throttled progress update\n const now = Date.now();\n if (now - lastProgressUpdate >= PROGRESS_UPDATE_INTERVAL) {\n lastProgressUpdate = now;\n try {\n await experimentsStore.updateExperiment({\n id: experimentId,\n succeededCount,\n failedCount,\n });\n } catch {\n // Non-fatal — progress updates are best-effort\n }\n }\n }\n\n // Store at original index for deterministic ordering\n results[idx] = {\n ...itemResult,\n scores: itemScores,\n };\n },\n { concurrency: maxConcurrency },\n );\n } catch {\n // Handle abort or other fatal errors — return partial summary instead of throwing\n const completedAt = new Date();\n const skippedCount = items.length - succeededCount - failedCount;\n\n if (experimentsStore) {\n await experimentsStore.updateExperiment({\n id: experimentId,\n status: 'failed',\n succeededCount,\n failedCount,\n skippedCount,\n completedAt,\n });\n }\n\n return {\n experimentId,\n status: 'failed' as const,\n totalItems: items.length,\n succeededCount,\n failedCount,\n skippedCount,\n persistenceFailures,\n completedWithErrors: false,\n startedAt,\n completedAt,\n results: results.filter(Boolean),\n };\n }\n\n // 7. Finalize experiment record\n const completedAt = new Date();\n const status = failedCount === items.length ? 'failed' : 'completed';\n const completedWithErrors = status === 'completed' && failedCount > 0;\n\n const skippedCount = items.length - succeededCount - failedCount;\n if (experimentsStore) {\n await experimentsStore.updateExperiment({\n id: experimentId,\n status,\n succeededCount,\n failedCount,\n skippedCount,\n completedAt,\n });\n }\n\n return {\n experimentId,\n status,\n totalItems: items.length,\n succeededCount,\n failedCount,\n skippedCount,\n persistenceFailures,\n completedWithErrors,\n startedAt,\n completedAt,\n results,\n };\n}\n\n/**\n * Resolve a target from Mastra's registries by type and ID.\n * When `agentVersion` is provided for an agent target, the returned agent\n * will have the versioned config applied (via `applyStoredOverrides`).\n *\n * The result is wrapped in `{ target }` because `Workflow` has a `.then`\n * method for step chaining, which makes it thenable. Returning a thenable\n * from an async function causes the Promise machinery to attempt to unwrap\n * it, which hangs forever since the builder `.then` never invokes its\n * callbacks. Wrapping in a plain object avoids the unwrap.\n */\nasync function resolveTarget(\n mastra: Mastra,\n targetType: string,\n targetId: string,\n agentVersion?: string,\n): Promise<{ target: Target } | null> {\n let resolved: Target | null = null;\n\n switch (targetType) {\n case 'agent':\n try {\n if (agentVersion) {\n resolved = await mastra.getAgentById(targetId, { versionId: agentVersion });\n } else {\n resolved = mastra.getAgentById(targetId);\n }\n } catch {\n // Try by name if ID lookup fails\n try {\n if (agentVersion) {\n resolved = await mastra.getAgent(targetId, { versionId: agentVersion });\n } else {\n resolved = mastra.getAgent(targetId);\n }\n } catch {\n // leave null\n }\n }\n break;\n case 'workflow':\n try {\n resolved = mastra.getWorkflowById(targetId);\n } catch {\n // Try by name if ID lookup fails\n try {\n resolved = mastra.getWorkflow(targetId);\n } catch {\n // leave null\n }\n }\n break;\n case 'scorer':\n try {\n resolved = mastra.getScorerById(targetId) ?? null;\n } catch {\n // leave null\n }\n break;\n case 'processor':\n // Processors not yet in registry - Phase 4\n break;\n default:\n break;\n }\n\n return resolved ? { target: resolved } : null;\n}\n","import { isZodType } from '@mastra/schema-compat';\nimport { zodToJsonSchema } from '@mastra/schema-compat/zod-to-json';\nimport { MastraError } from '../error/index.js';\nimport type { Mastra } from '../mastra/index.js';\nimport type { DatasetsStorage } from '../storage/domains/datasets/base.js';\nimport type { ExperimentsStorage } from '../storage/domains/experiments/base.js';\nimport type {\n DatasetRecord,\n DatasetItem,\n DatasetItemPayload,\n DatasetItemRow,\n DatasetTenancyFilters,\n DatasetVersion,\n ExperimentResultStatus,\n ExperimentStatus,\n ExperimentTenancyFilters,\n ListDatasetItemsOutput,\n ListExperimentResultsOutput,\n ListExperimentsOutput,\n TargetType,\n UpdateDatasetInput,\n UpdateExperimentResultInput,\n} from '../storage/types.js';\nimport { runExperiment } from './experiment/index.js';\nimport type { ExperimentConfig, StartExperimentConfig, ExperimentSummary } from './experiment/types.js';\n\n/**\n * Public API for interacting with a single dataset.\n *\n * Provides methods for item CRUD, versioning, and experiment management.\n * Obtained via `DatasetsManager.get()` or `DatasetsManager.create()`.\n */\nexport class Dataset {\n readonly id: string;\n #mastra: Mastra;\n #datasetsStore?: DatasetsStorage;\n #experimentsStore?: ExperimentsStorage;\n /**\n * Tenancy read-scope carried by the handle. When set, all internal reads\n * ({@link Dataset.getDetails}, {@link Dataset.startExperimentAsync}) and item\n * mutations forward these filters to storage so cross-tenant reads/mutations\n * over a leaked dataset id are rejected as NOT_FOUND (or silent no-op for\n * deletes) rather than succeeding.\n */\n #scope?: DatasetTenancyFilters;\n\n constructor(id: string, mastra: Mastra, scope?: DatasetTenancyFilters) {\n this.id = id;\n this.#mastra = mastra;\n this.#scope = scope;\n }\n\n // ---------------------------------------------------------------------------\n // Lazy storage resolution\n // ---------------------------------------------------------------------------\n\n async #getDatasetsStore(): Promise<DatasetsStorage> {\n if (this.#datasetsStore) return this.#datasetsStore;\n\n const storage = this.#mastra.getStorage();\n if (!storage) {\n throw new MastraError({\n id: 'DATASETS_STORAGE_NOT_CONFIGURED',\n text: 'Storage not configured. Configure storage in Mastra instance.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const store = await storage.getStore('datasets');\n if (!store) {\n throw new MastraError({\n id: 'DATASETS_STORE_NOT_AVAILABLE',\n text: 'Datasets store not available. Ensure your storage adapter provides a datasets domain.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n this.#datasetsStore = store;\n return store;\n }\n\n async #getExperimentsStore(): Promise<ExperimentsStorage> {\n if (this.#experimentsStore) return this.#experimentsStore;\n\n const storage = this.#mastra.getStorage();\n if (!storage) {\n throw new MastraError({\n id: 'DATASETS_STORAGE_NOT_CONFIGURED',\n text: 'Storage not configured. Configure storage in Mastra instance.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const store = await storage.getStore('experiments');\n if (!store) {\n throw new MastraError({\n id: 'EXPERIMENTS_STORE_NOT_AVAILABLE',\n text: 'Experiments store not available. Ensure your storage adapter provides an experiments domain.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n this.#experimentsStore = store;\n return store;\n }\n\n /**\n * Preflight tenancy gate for storage APIs whose signatures don't accept\n * `filters`. When the handle has a `#scope`, a scoped `getDatasetById` is\n * used to prove the dataset exists in the caller's tenancy; on miss we\n * throw NOT_FOUND, mirroring {@link Dataset.getDetails}. Callers that must\n * return a non-throwing empty result (e.g. list endpoints) should catch and\n * translate.\n */\n async #assertScope(): Promise<void> {\n if (!this.#scope) return;\n const store = await this.#getDatasetsStore();\n const record = await store.getDatasetById({ id: this.id, filters: this.#scope });\n if (!record) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: `Dataset not found: ${this.id}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n }\n\n /**\n * Ownership gate: verifies a child record's `datasetId` matches `this.id`.\n * Prevents a valid scoped handle from reading/mutating child records\n * (items, experiments, results) that live under a different dataset — even\n * one in the same tenant. Returns `null` when the record is missing or\n * belongs to a different dataset, so callers can either return null or\n * translate to NOT_FOUND depending on their contract.\n */\n #ownsChild<T extends { datasetId?: string | null }>(record: T | null | undefined): T | null {\n if (!record) return null;\n if (record.datasetId !== this.id) return null;\n return record;\n }\n\n // ---------------------------------------------------------------------------\n // Dataset metadata\n // ---------------------------------------------------------------------------\n\n /**\n * Get the full dataset record from storage.\n */\n async getDetails(): Promise<DatasetRecord> {\n const store = await this.#getDatasetsStore();\n const record = await store.getDatasetById({ id: this.id, filters: this.#scope });\n if (!record) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: `Dataset not found: ${this.id}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n return record;\n }\n\n /**\n * Update dataset metadata and/or schemas.\n *\n * Accepts Zod schemas for `inputSchema` / `groundTruthSchema` (widened to\n * `unknown`); they are normalized to JSON Schema before being forwarded to\n * the storage-canonical {@link UpdateDatasetInput} shape. All other fields\n * mirror {@link UpdateDatasetInput} exactly (minus `id`, which is supplied\n * from `this.id`).\n */\n async update(\n input: Omit<UpdateDatasetInput, 'id' | 'inputSchema' | 'groundTruthSchema'> & {\n inputSchema?: unknown;\n groundTruthSchema?: unknown;\n },\n ): Promise<DatasetRecord> {\n const store = await this.#getDatasetsStore();\n\n let { inputSchema, groundTruthSchema, ...rest } = input;\n\n if (inputSchema !== undefined && inputSchema !== null && isZodType(inputSchema)) {\n inputSchema = zodToJsonSchema(inputSchema);\n }\n if (groundTruthSchema !== undefined && groundTruthSchema !== null && isZodType(groundTruthSchema)) {\n groundTruthSchema = zodToJsonSchema(groundTruthSchema);\n }\n\n return store.updateDataset({\n id: this.id,\n ...rest,\n inputSchema: inputSchema as Record<string, unknown> | null | undefined,\n groundTruthSchema: groundTruthSchema as Record<string, unknown> | null | undefined,\n filters: this.#scope,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Item CRUD\n // ---------------------------------------------------------------------------\n\n /**\n * Add a single item to the dataset.\n */\n async addItem(input: DatasetItemPayload): Promise<DatasetItem> {\n const store = await this.#getDatasetsStore();\n return store.addItem({ datasetId: this.id, ...input, filters: this.#scope });\n }\n\n /**\n * Add multiple items to the dataset in bulk.\n */\n async addItems(input: { items: DatasetItemPayload[] }): Promise<DatasetItem[]> {\n const store = await this.#getDatasetsStore();\n return store.batchInsertItems({\n datasetId: this.id,\n items: input.items,\n filters: this.#scope,\n });\n }\n\n /**\n * Get a single item by ID, optionally at a specific version.\n */\n async getItem(args: { itemId: string; version?: number }): Promise<DatasetItem | null> {\n await this.#assertScope();\n const store = await this.#getDatasetsStore();\n const item = await store.getItemById({ id: args.itemId, datasetVersion: args.version });\n return this.#ownsChild(item);\n }\n\n /**\n * List items in the dataset, optionally at a specific version, with\n * optional substring search and pagination.\n *\n * Return shape depends on the arguments:\n *\n * - When `version` is the only argument provided (no `search`, `page`, or\n * `perPage`), returns a bare `DatasetItem[]` snapshot of every item at\n * that version. This shape is retained for callers that predate\n * server-side pagination on the versioned path; new code should pass\n * `page` / `perPage` (or `search`) to opt into the paginated shape.\n * - In all other cases (no arguments, or `search` / `page` / `perPage`\n * provided with or without `version`), returns the paginated\n * `{ items, pagination }` shape.\n *\n * @deprecated The `DatasetItem[]` branch of the return type is retained\n * for backwards compatibility with the `version`-only call form; pass\n * `page` / `perPage` (or `search`) to always receive the paginated\n * `{ items, pagination }` shape.\n */\n async listItems(args?: {\n version?: number;\n page?: number;\n perPage?: number;\n search?: string;\n }): Promise<DatasetItem[] | ListDatasetItemsOutput> {\n const store = await this.#getDatasetsStore();\n\n const onlyVersion =\n args?.version !== undefined && args.search === undefined && args.page === undefined && args.perPage === undefined;\n\n if (onlyVersion) {\n // getItemsByVersion is keyed by datasetId — gate via scoped parent existence\n await this.#assertScope();\n return store.getItemsByVersion({ datasetId: this.id, version: args.version! });\n }\n\n return store.listItems({\n datasetId: this.id,\n ...(args?.version !== undefined ? { version: args.version } : {}),\n ...(args?.search ? { search: args.search } : {}),\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n filters: this.#scope,\n });\n }\n\n /**\n * Update an existing item in the dataset. Only the provided payload fields\n * are patched.\n */\n async updateItem(input: { itemId: string } & Partial<Omit<DatasetItemPayload, 'externalId'>>): Promise<DatasetItem> {\n const store = await this.#getDatasetsStore();\n const { itemId, ...rest } = input;\n return store.updateItem({ id: itemId, datasetId: this.id, ...rest, filters: this.#scope });\n }\n\n /**\n * Delete a single item from the dataset.\n */\n async deleteItem(args: { itemId: string }): Promise<void> {\n const store = await this.#getDatasetsStore();\n return store.deleteItem({ id: args.itemId, datasetId: this.id, filters: this.#scope });\n }\n\n /**\n * Delete multiple items from the dataset in bulk.\n */\n async deleteItems(args: { itemIds: string[] }): Promise<void> {\n const store = await this.#getDatasetsStore();\n return store.batchDeleteItems({ datasetId: this.id, itemIds: args.itemIds, filters: this.#scope });\n }\n\n // ---------------------------------------------------------------------------\n // Versioning\n // ---------------------------------------------------------------------------\n\n /**\n * List all versions of this dataset.\n */\n async listVersions(args?: { page?: number; perPage?: number }): Promise<{\n versions: DatasetVersion[];\n pagination: { total: number; page: number; perPage: number | false; hasMore: boolean };\n }> {\n await this.#assertScope();\n const store = await this.#getDatasetsStore();\n return store.listDatasetVersions({\n datasetId: this.id,\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n });\n }\n\n /**\n * Get full SCD-2 history of a specific item across all dataset versions.\n */\n async getItemHistory(args: { itemId: string }): Promise<DatasetItemRow[]> {\n await this.#assertScope();\n const store = await this.#getDatasetsStore();\n const rows = await store.getItemHistory(args.itemId);\n // Ownership gate: SCD-2 history is keyed only by item id — filter out any\n // rows that don't belong to this dataset so a known cross-dataset item id\n // cannot leak history through a valid scoped handle.\n return rows.filter(row => row.datasetId === this.id);\n }\n\n // ---------------------------------------------------------------------------\n // Experiments\n // ---------------------------------------------------------------------------\n\n /**\n * Run an experiment on this dataset and wait for completion.\n */\n async startExperiment<I = unknown, O = unknown, E = unknown>(\n config: StartExperimentConfig<I, O, E>,\n ): Promise<ExperimentSummary> {\n return runExperiment(this.#mastra, {\n datasetId: this.id,\n ...config,\n filters: this.#scope,\n } as ExperimentConfig);\n }\n\n /**\n * Start an experiment asynchronously (fire-and-forget).\n * Returns immediately with the experiment ID and pending status.\n */\n async startExperimentAsync<I = unknown, O = unknown, E = unknown>(\n config: StartExperimentConfig<I, O, E>,\n ): Promise<{ experimentId: string; status: 'pending'; totalItems: number }> {\n const experimentsStore = await this.#getExperimentsStore();\n const datasetsStore = await this.#getDatasetsStore();\n\n const dataset = await datasetsStore.getDatasetById({ id: this.id, filters: this.#scope });\n if (!dataset) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: `Dataset not found: ${this.id}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n // Validate that dataset has items before creating experiment record\n const targetVersion = config.version ?? dataset.version;\n const items = await datasetsStore.getItemsByVersion({\n datasetId: this.id,\n version: targetVersion,\n });\n if (items.length === 0) {\n throw new MastraError({\n id: 'EXPERIMENT_NO_ITEMS',\n text: `Cannot run experiment: dataset \"${this.id}\" has no items at version ${targetVersion}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const run = await experimentsStore.createExperiment({\n datasetId: this.id,\n datasetVersion: targetVersion,\n targetType: config.targetType ?? 'agent',\n targetId: config.targetId ?? 'inline',\n totalItems: items.length,\n name: config.name,\n description: config.description,\n metadata: config.metadata,\n agentVersion: config.agentVersion,\n organizationId: dataset.organizationId ?? null,\n projectId: dataset.projectId ?? null,\n });\n\n const experimentId = run.id;\n\n // Fire-and-forget — runExperiment merges dataset-attached scorers automatically\n void runExperiment(this.#mastra, {\n datasetId: this.id,\n experimentId,\n ...config,\n version: targetVersion,\n filters: this.#scope,\n } as ExperimentConfig).catch(async err => {\n await experimentsStore\n .updateExperiment({\n id: experimentId,\n status: 'failed',\n completedAt: new Date(),\n })\n .catch(() => {});\n this.#mastra.getLogger()?.error(`Experiment ${experimentId} failed: ${err?.message ?? err}`);\n });\n\n return { experimentId, status: 'pending' as const, totalItems: items.length };\n }\n\n /**\n * List experiments (runs) for this dataset, with optional filters and\n * pagination. All filters are pushed to the storage layer.\n *\n * @param args.targetType Restrict to a specific target type (e.g. `agent`).\n * @param args.targetId Restrict to a specific target ID.\n * @param args.agentVersion Restrict to a specific agent version — useful for\n * baseline vs variant read patterns.\n * @param args.status Restrict to a specific experiment status.\n * @param args.filters Multi-tenant scoping filters (organization/project).\n * @param args.page Page number. Defaults to `0`.\n * @param args.perPage Page size. Defaults to `20`.\n */\n async listExperiments(args?: {\n targetType?: TargetType;\n targetId?: string;\n agentVersion?: string;\n status?: ExperimentStatus;\n filters?: ExperimentTenancyFilters;\n page?: number;\n perPage?: number;\n }): Promise<ListExperimentsOutput> {\n await this.#assertScope();\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.listExperiments({\n datasetId: this.id,\n ...(args?.targetType !== undefined ? { targetType: args.targetType } : {}),\n ...(args?.targetId !== undefined ? { targetId: args.targetId } : {}),\n ...(args?.agentVersion !== undefined ? { agentVersion: args.agentVersion } : {}),\n ...(args?.status !== undefined ? { status: args.status } : {}),\n ...(args?.filters !== undefined ? { filters: args.filters } : {}),\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n });\n }\n\n /**\n * Verify the experiment belongs to this dataset (and, by extension, to the\n * handle's tenancy scope which was enforced when the handle was minted).\n * Throws NOT_FOUND on missing or cross-dataset experiments so cross-tenant\n * mutation via a valid scoped handle + a known foreign experimentId is\n * rejected.\n */\n async #assertExperimentOwnership(experimentId: string): Promise<void> {\n await this.#assertScope();\n const experimentsStore = await this.#getExperimentsStore();\n const experiment = await experimentsStore.getExperimentById({\n id: experimentId,\n filters: this.#scope,\n });\n if (!experiment || experiment.datasetId !== this.id) {\n throw new MastraError({\n id: 'EXPERIMENT_NOT_FOUND',\n text: `Experiment not found: ${experimentId}`,\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n }\n\n /**\n * Get a specific experiment (run) by ID.\n */\n async getExperiment(args: { experimentId: string }) {\n await this.#assertScope();\n const experimentsStore = await this.#getExperimentsStore();\n const experiment = await experimentsStore.getExperimentById({\n id: args.experimentId,\n filters: this.#scope,\n });\n if (!experiment || experiment.datasetId !== this.id) return null;\n return experiment;\n }\n\n /**\n * List results for a specific experiment, with optional filters and\n * pagination. All filters are pushed to the storage layer.\n *\n * @param args.experimentId The experiment whose results to list.\n * @param args.traceId Restrict to results linked to a specific trace.\n * @param args.status Restrict to a specific per-result review status.\n * @param args.filters Multi-tenant scoping filters (organization/project).\n * @param args.page Page number. Defaults to `0`.\n * @param args.perPage Page size. Defaults to `20`.\n */\n async listExperimentResults(args: {\n experimentId: string;\n traceId?: string;\n status?: ExperimentResultStatus;\n filters?: ExperimentTenancyFilters;\n page?: number;\n perPage?: number;\n }): Promise<ListExperimentResultsOutput> {\n await this.#assertExperimentOwnership(args.experimentId);\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.listExperimentResults({\n experimentId: args.experimentId,\n ...(args.traceId !== undefined ? { traceId: args.traceId } : {}),\n ...(args.status !== undefined ? { status: args.status } : {}),\n ...(args.filters !== undefined ? { filters: args.filters } : {}),\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n });\n }\n\n /**\n * Update an experiment result's status or tags.\n */\n async updateExperimentResult(input: UpdateExperimentResultInput & { experimentId: string }) {\n // The result's parent experiment must belong to this dataset. If the\n // caller supplied `experimentId`, verify ownership on that; otherwise we\n // cannot bind the update to this dataset and must reject.\n if (!input.experimentId) {\n throw new MastraError({\n id: 'EXPERIMENT_RESULT_MISSING_EXPERIMENT_ID',\n text: 'updateExperimentResult requires experimentId when called via a Dataset handle',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n await this.#assertExperimentOwnership(input.experimentId);\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.updateExperimentResult(input);\n }\n\n /**\n * Delete an experiment (run) by ID.\n *\n * The ownership check above already refuses cross-tenant / cross-dataset\n * requests, but we still forward `this.#scope` to storage so the delete\n * is defense-in-depth: a leaked handle or race that skipped the assertion\n * still cannot delete another tenant's experiment (storage silently no-ops\n * on tenancy mismatch).\n */\n async deleteExperiment(args: { experimentId: string }) {\n await this.#assertExperimentOwnership(args.experimentId);\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.deleteExperiment({ id: args.experimentId, filters: this.#scope });\n }\n}\n","import { isZodType } from '@mastra/schema-compat';\nimport { zodToJsonSchema } from '@mastra/schema-compat/zod-to-json';\nimport { MastraError } from '../error/index.js';\nimport type { Mastra } from '../mastra/index.js';\nimport type { DatasetsStorage } from '../storage/domains/datasets/base.js';\nimport type { ExperimentsStorage } from '../storage/domains/experiments/base.js';\nimport type { DatasetTenancyFilters, TargetType } from '../storage/types.js';\nimport { Dataset } from './dataset.js';\nimport { compareExperiments as compareExperimentsInternal } from './experiment/analytics/compare.js';\n\n/**\n * Build a {@link DatasetTenancyFilters} from public manager args. Returns\n * `undefined` when neither field is set (preserves legacy unscoped behavior).\n * Null values are coerced away — `DatasetTenancyFilters` is `string | undefined`\n * only, matching the existing `listDatasets` filter contract.\n */\nfunction scopeFromArgs(args: {\n organizationId?: string | null;\n projectId?: string | null;\n}): DatasetTenancyFilters | undefined {\n const scope: DatasetTenancyFilters = {};\n if (typeof args.organizationId === 'string') scope.organizationId = args.organizationId;\n if (typeof args.projectId === 'string') scope.projectId = args.projectId;\n return scope.organizationId === undefined && scope.projectId === undefined ? undefined : scope;\n}\n\n/**\n * Public API for managing datasets.\n *\n * Provides methods for dataset CRUD and cross-dataset experiment operations.\n * Typically accessed via `mastra.datasets` (Phase 4).\n */\nexport class DatasetsManager {\n #mastra: Mastra;\n #datasetsStore?: DatasetsStorage;\n #experimentsStore?: ExperimentsStorage;\n\n constructor(mastra: Mastra) {\n this.#mastra = mastra;\n }\n\n // ---------------------------------------------------------------------------\n // Lazy storage resolution\n // ---------------------------------------------------------------------------\n\n async #getDatasetsStore(): Promise<DatasetsStorage> {\n if (this.#datasetsStore) return this.#datasetsStore;\n\n const storage = this.#mastra.getStorage();\n if (!storage) {\n throw new MastraError({\n id: 'DATASETS_STORAGE_NOT_CONFIGURED',\n text: 'Storage not configured. Configure storage in Mastra instance.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const store = await storage.getStore('datasets');\n if (!store) {\n throw new MastraError({\n id: 'DATASETS_STORE_NOT_AVAILABLE',\n text: 'Datasets store not available. Ensure your storage adapter provides a datasets domain.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n this.#datasetsStore = store;\n return store;\n }\n\n async #getExperimentsStore(): Promise<ExperimentsStorage> {\n if (this.#experimentsStore) return this.#experimentsStore;\n\n const storage = this.#mastra.getStorage();\n if (!storage) {\n throw new MastraError({\n id: 'DATASETS_STORAGE_NOT_CONFIGURED',\n text: 'Storage not configured. Configure storage in Mastra instance.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const store = await storage.getStore('experiments');\n if (!store) {\n throw new MastraError({\n id: 'EXPERIMENTS_STORE_NOT_AVAILABLE',\n text: 'Experiments store not available. Ensure your storage adapter provides an experiments domain.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n this.#experimentsStore = store;\n return store;\n }\n\n // ---------------------------------------------------------------------------\n // Dataset CRUD\n // ---------------------------------------------------------------------------\n\n /**\n * Create a new dataset.\n *\n * Accepts Zod schemas for `inputSchema` / `groundTruthSchema` (typed as\n * `unknown` here); they are normalized to JSON Schema via `zodToJsonSchema`\n * before being forwarded to the storage-canonical\n * {@link import('../storage/types.js').CreateDatasetInput} shape. All other\n * fields mirror `CreateDatasetInput` exactly.\n */\n async create(input: {\n id?: string;\n name: string;\n description?: string;\n inputSchema?: unknown;\n groundTruthSchema?: unknown;\n requestContextSchema?: Record<string, unknown> | null;\n metadata?: Record<string, unknown>;\n targetType?: TargetType;\n targetIds?: string[];\n scorerIds?: string[];\n organizationId?: string | null;\n projectId?: string | null;\n candidateKey?: string | null;\n candidateId?: string | null;\n }): Promise<Dataset> {\n const store = await this.#getDatasetsStore();\n\n let { inputSchema, groundTruthSchema, ...rest } = input;\n\n if (inputSchema !== undefined && isZodType(inputSchema)) {\n inputSchema = zodToJsonSchema(inputSchema);\n }\n if (groundTruthSchema !== undefined && isZodType(groundTruthSchema)) {\n groundTruthSchema = zodToJsonSchema(groundTruthSchema);\n }\n\n const result = await store.createDataset({\n ...rest,\n inputSchema: inputSchema as Record<string, unknown> | undefined,\n groundTruthSchema: groundTruthSchema as Record<string, unknown> | undefined,\n });\n\n // Preserve the tenancy the caller created the dataset under so subsequent\n // reads/updates on the returned handle stay bound to the same tenant.\n const createScope = scopeFromArgs(input);\n return new Dataset(result.id, this.#mastra, createScope);\n }\n\n /**\n * Get an existing dataset by ID, optionally scoped to a tenant.\n *\n * When `organizationId` / `projectId` are provided, the read is scoped to\n * that tenancy: a dataset row that exists but belongs to a different tenant\n * returns NOT_FOUND (same 404 as a truly missing row) rather than leaking\n * cross-tenant existence. The returned {@link Dataset} handle carries the\n * scope forward on all subsequent reads and item mutations.\n */\n async get(args: { id: string; organizationId?: string; projectId?: string }): Promise<Dataset> {\n const store = await this.#getDatasetsStore();\n const scope = scopeFromArgs(args);\n const record = await store.getDatasetById({ id: args.id, filters: scope });\n if (!record) {\n throw new MastraError({\n id: 'DATASET_NOT_FOUND',\n text: 'Dataset not found',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n return new Dataset(args.id, this.#mastra, scope);\n }\n\n /**\n * List all datasets with pagination.\n *\n * Supports optional tenancy and candidate-identity filters. When omitted, all\n * datasets visible to the configured storage instance are returned.\n */\n async list(args?: {\n page?: number;\n perPage?: number;\n filters?: {\n organizationId?: string;\n projectId?: string;\n candidateKey?: string;\n candidateId?: string;\n /** Filter by dataset target type. */\n targetType?: TargetType;\n /**\n * Filter to datasets whose `targetIds` intersect this list (any overlap matches).\n */\n targetIds?: string[];\n /** Substring match on dataset `name`, case-insensitive. */\n name?: string;\n };\n }) {\n const store = await this.#getDatasetsStore();\n return store.listDatasets({\n pagination: { page: args?.page ?? 0, perPage: args?.perPage ?? 20 },\n ...(args?.filters ? { filters: args.filters } : {}),\n });\n }\n\n /**\n * Delete a dataset by ID, optionally scoped to a tenant.\n *\n * When `organizationId` / `projectId` are provided, the delete is scoped to\n * that tenancy: a dataset row in another tenant is a silent no-op (no error)\n * so cross-tenant existence is not leaked via error timing/text.\n */\n async delete(args: { id: string; organizationId?: string; projectId?: string }) {\n const store = await this.#getDatasetsStore();\n return store.deleteDataset({ id: args.id, filters: scopeFromArgs(args) });\n }\n\n // ---------------------------------------------------------------------------\n // Cross-dataset experiment operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get a specific experiment (run) by ID, optionally scoped to a tenant.\n *\n * When `organizationId` / `projectId` are provided, the read is scoped to\n * that tenancy: an experiment row that exists but belongs to a different\n * tenant returns `null` (same as a truly missing row) rather than leaking\n * cross-tenant existence via error timing/text.\n */\n async getExperiment(args: { experimentId: string; organizationId?: string; projectId?: string }) {\n const experimentsStore = await this.#getExperimentsStore();\n return experimentsStore.getExperimentById({\n id: args.experimentId,\n filters: scopeFromArgs(args),\n });\n }\n\n /**\n * Compare two or more experiments.\n *\n * Uses the internal `compareExperiments` function for pairwise comparison,\n * then enriches results with per-item input/groundTruth/output data.\n */\n async compareExperiments(args: { experimentIds: string[]; baselineId?: string }) {\n const { experimentIds, baselineId } = args;\n\n if (experimentIds.length < 2) {\n throw new MastraError({\n id: 'COMPARE_INVALID_INPUT',\n text: 'compareExperiments requires at least 2 experiment IDs.',\n domain: 'STORAGE',\n category: 'USER',\n });\n }\n\n const resolvedBaseline = baselineId ?? experimentIds[0]!;\n const otherExperimentId = experimentIds.find(id => id !== resolvedBaseline) ?? experimentIds[1]!;\n\n const internal = await compareExperimentsInternal(this.#mastra, {\n experimentIdA: resolvedBaseline,\n experimentIdB: otherExperimentId,\n });\n\n // Load results for both runs to get input/groundTruth/output\n const experimentsStore = await this.#getExperimentsStore();\n const [resultsA, resultsB] = await Promise.all([\n experimentsStore.listExperimentResults({\n experimentId: resolvedBaseline,\n pagination: { page: 0, perPage: false },\n }),\n experimentsStore.listExperimentResults({\n experimentId: otherExperimentId,\n pagination: { page: 0, perPage: false },\n }),\n ]);\n\n // Build results maps by itemId\n const resultsMapA = new Map(resultsA.results.map(r => [r.itemId, r]));\n const resultsMapB = new Map(resultsB.results.map(r => [r.itemId, r]));\n\n // Transform internal items to MVP shape\n const items = internal.items.map(item => {\n const resultA = resultsMapA.get(item.itemId);\n const resultB = resultsMapB.get(item.itemId);\n\n return {\n itemId: item.itemId,\n input: resultA?.input ?? resultB?.input ?? null,\n groundTruth: resultA?.groundTruth ?? resultB?.groundTruth ?? null,\n results: {\n [resolvedBaseline]: resultA ? { output: resultA.output, scores: item.scoresA } : null,\n [otherExperimentId]: resultB ? { output: resultB.output, scores: item.scoresB } : null,\n },\n };\n });\n\n return {\n baselineId: resolvedBaseline,\n items,\n };\n }\n}\n"],"mappings":"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"}
|