@mastra/react 1.12.0-alpha.9 → 1.13.0-alpha.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/dist/{accumulator-BQGsraqS.cjs → accumulator-BmD8-x9I.cjs} +52 -4
- package/dist/accumulator-BmD8-x9I.cjs.map +1 -0
- package/dist/{accumulator-C8kIc450.js → accumulator-D9jAph99.js} +52 -4
- package/dist/accumulator-D9jAph99.js.map +1 -0
- package/dist/chat/index.cjs +1 -1
- package/dist/chat/index.js +1 -2
- package/dist/combine-by-ids-D_lp6Dvq.cjs.map +1 -1
- package/dist/experiments-B7vRMK5T.js +306 -0
- package/dist/experiments-B7vRMK5T.js.map +1 -0
- package/dist/experiments-CJw1N3FB.cjs +353 -0
- package/dist/experiments-CJw1N3FB.cjs.map +1 -0
- package/dist/hooks/agents/index.cjs +2 -2
- package/dist/hooks/agents/index.cjs.map +1 -1
- package/dist/hooks/agents/index.js +2 -2
- package/dist/hooks/agents/index.js.map +1 -1
- package/dist/hooks/auth/index.cjs +2 -2
- package/dist/hooks/auth/index.cjs.map +1 -1
- package/dist/hooks/auth/index.js +2 -2
- package/dist/hooks/auth/index.js.map +1 -1
- package/dist/hooks/capabilities/index.cjs +58 -1
- package/dist/hooks/capabilities/index.cjs.map +1 -1
- package/dist/hooks/capabilities/index.d.ts +4 -0
- package/dist/hooks/capabilities/index.d.ts.map +1 -1
- package/dist/hooks/capabilities/index.js +55 -2
- package/dist/hooks/capabilities/index.js.map +1 -1
- package/dist/hooks/capabilities/use-span-aggregate-available.d.ts +9 -0
- package/dist/hooks/capabilities/use-span-aggregate-available.d.ts.map +1 -0
- package/dist/hooks/capabilities/use-span-query-available.d.ts +9 -0
- package/dist/hooks/capabilities/use-span-query-available.d.ts.map +1 -0
- package/dist/hooks/capabilities/use-thread-query-available.d.ts +9 -0
- package/dist/hooks/capabilities/use-thread-query-available.d.ts.map +1 -0
- package/dist/hooks/capabilities/use-trace-query-delta-polling-available.d.ts +10 -0
- package/dist/hooks/capabilities/use-trace-query-delta-polling-available.d.ts.map +1 -0
- package/dist/hooks/configuration/index.cjs.map +1 -1
- package/dist/hooks/datasets/index.cjs +25 -1
- package/dist/hooks/datasets/index.cjs.map +1 -1
- package/dist/hooks/datasets/index.js +25 -2
- package/dist/hooks/datasets/index.js.map +1 -1
- package/dist/hooks/datasets/use-datasets.d.ts +7 -0
- package/dist/hooks/datasets/use-datasets.d.ts.map +1 -1
- package/dist/hooks/embedders/index.cjs.map +1 -1
- package/dist/hooks/experiments/index.cjs +9 -235
- package/dist/hooks/experiments/index.d.ts +1 -0
- package/dist/hooks/experiments/index.d.ts.map +1 -1
- package/dist/hooks/experiments/index.js +1 -229
- package/dist/hooks/experiments/usage-accumulator.d.ts +25 -0
- package/dist/hooks/experiments/usage-accumulator.d.ts.map +1 -0
- package/dist/hooks/experiments/use-experiment-item-usage.d.ts +2 -7
- package/dist/hooks/experiments/use-experiment-item-usage.d.ts.map +1 -1
- package/dist/hooks/experiments/use-experiments-list-metrics.d.ts +19 -0
- package/dist/hooks/experiments/use-experiments-list-metrics.d.ts.map +1 -0
- package/dist/hooks/feedback/index.cjs.map +1 -1
- package/dist/hooks/llm/index.cjs.map +1 -1
- package/dist/hooks/logs/index.cjs.map +1 -1
- package/dist/hooks/mcps/index.cjs.map +1 -1
- package/dist/hooks/memory/index.cjs +10 -10
- package/dist/hooks/memory/index.cjs.map +1 -1
- package/dist/hooks/memory/index.js +10 -10
- package/dist/hooks/memory/index.js.map +1 -1
- package/dist/hooks/metrics/index.cjs +13 -11
- package/dist/hooks/metrics/index.cjs.map +1 -1
- package/dist/hooks/metrics/index.js +13 -11
- package/dist/hooks/metrics/index.js.map +1 -1
- package/dist/hooks/processors/index.cjs.map +1 -1
- package/dist/hooks/prompt-blocks/index.cjs.map +1 -1
- package/dist/hooks/query/index.cjs.map +1 -1
- package/dist/hooks/review/index.cjs +2 -2
- package/dist/hooks/review/index.cjs.map +1 -1
- package/dist/hooks/review/index.js +1 -1
- package/dist/hooks/schedules/index.cjs.map +1 -1
- package/dist/hooks/scores/index.cjs.map +1 -1
- package/dist/hooks/templates/index.cjs +20 -18
- package/dist/hooks/templates/index.cjs.map +1 -1
- package/dist/hooks/templates/index.js +20 -18
- package/dist/hooks/templates/index.js.map +1 -1
- package/dist/hooks/templates/use-templates.d.ts.map +1 -1
- package/dist/hooks/tool-providers/index.cjs +1 -1
- package/dist/hooks/tool-providers/index.cjs.map +1 -1
- package/dist/hooks/tool-providers/index.js +1 -1
- package/dist/hooks/tool-providers/index.js.map +1 -1
- package/dist/hooks/tools/index.cjs.map +1 -1
- package/dist/hooks/traces/index.cjs +292 -9
- package/dist/hooks/traces/index.cjs.map +1 -1
- package/dist/hooks/traces/index.d.ts +2 -0
- package/dist/hooks/traces/index.d.ts.map +1 -1
- package/dist/hooks/traces/index.js +285 -10
- package/dist/hooks/traces/index.js.map +1 -1
- package/dist/hooks/traces/use-query-spans.d.ts +27 -0
- package/dist/hooks/traces/use-query-spans.d.ts.map +1 -0
- package/dist/hooks/traces/use-query-threads.d.ts +30 -0
- package/dist/hooks/traces/use-query-threads.d.ts.map +1 -0
- package/dist/hooks/traces/use-trace-query.d.ts +50 -1
- package/dist/hooks/traces/use-trace-query.d.ts.map +1 -1
- package/dist/hooks/traces/use-traces.d.ts +37 -37
- package/dist/hooks/vectors/index.cjs.map +1 -1
- package/dist/hooks/voice/index.cjs.map +1 -1
- package/dist/hooks/workflows/index.cjs +1 -1
- package/dist/hooks/workflows/index.cjs.map +1 -1
- package/dist/hooks/workflows/index.js +1 -1
- package/dist/hooks/workspace/index.cjs +1 -1
- package/dist/hooks/workspace/index.cjs.map +1 -1
- package/dist/hooks/workspace/index.js +1 -1
- package/dist/hooks/workspace/index.js.map +1 -1
- package/dist/{hooks-CIutb3DO.cjs → hooks-C6CJtoOR.cjs} +6 -4
- package/dist/hooks-C6CJtoOR.cjs.map +1 -0
- package/dist/{hooks-0L0RNfau.js → hooks-DG-Y1KFe.js} +2 -2
- package/dist/{hooks-0L0RNfau.js.map → hooks-DG-Y1KFe.js.map} +1 -1
- package/dist/{hooks-FVbeHlov.js → hooks-DvLSZtUd.js} +6 -4
- package/dist/{hooks-FVbeHlov.js.map → hooks-DvLSZtUd.js.map} +1 -1
- package/dist/{hooks-_YevKidX.cjs → hooks-XYsmqFCz.cjs} +2 -2
- package/dist/hooks-XYsmqFCz.cjs.map +1 -0
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/lib/mastra-db/accumulator.d.ts +0 -6
- package/dist/lib/mastra-db/accumulator.d.ts.map +1 -1
- package/dist/mastra-client-context-DzX3f0RF.cjs.map +1 -1
- package/dist/ui/index.cjs +4 -4
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.js +3 -3
- package/dist/ui/index.js.map +1 -1
- package/dist/use-in-view-B6eJO9Zi.cjs.map +1 -1
- package/dist/voice-BOtUdMi8.cjs.map +1 -1
- package/package.json +7 -7
- package/dist/accumulator-BQGsraqS.cjs.map +0 -1
- package/dist/accumulator-C8kIc450.js.map +0 -1
- package/dist/hooks/experiments/index.cjs.map +0 -1
- package/dist/hooks/experiments/index.js.map +0 -1
- package/dist/hooks-CIutb3DO.cjs.map +0 -1
- package/dist/hooks-_YevKidX.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accumulator-C8kIc450.js","names":[],"sources":["../src/agent/signal-data.ts","../src/lib/mastra-db/formatCompletionFeedback.ts","../src/lib/mastra-db/types.ts","../src/lib/mastra-db/accumulator.ts"],"sourcesContent":["export const uint8ArrayToBase64 = (bytes: Uint8Array): string => {\n const chunkSize = 0x8000;\n let binary = '';\n for (let i = 0; i < bytes.length; i += chunkSize) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));\n }\n return btoa(binary);\n};\n\nexport function convertSignalDataToBase64String(content: string | ArrayBuffer | Uint8Array): string {\n if (typeof content === 'string') {\n return content;\n }\n\n const bytes = content instanceof ArrayBuffer ? new Uint8Array(content) : content;\n return uint8ArrayToBase64(bytes);\n}\n\n/** Canonical DB `file` part `data` for optimistic UI and memory-shaped storage. */\nexport function encodeFilePartDataForStorage(data: string | URL | ArrayBuffer | Uint8Array, mimeType: string): string {\n if (typeof data === 'string') {\n return data;\n }\n\n if (data instanceof URL) {\n return data.toString();\n }\n\n const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n const base64 = uint8ArrayToBase64(bytes);\n if (base64.startsWith('data:')) {\n return base64;\n }\n\n return `data:${mimeType};base64,${base64}`;\n}\n","type CompletionScorerResult = {\n duration?: number;\n passed: boolean;\n reason?: string;\n score: number;\n scorerId: string;\n scorerName: string;\n};\n\ntype CompletionResult = {\n complete: boolean;\n completionReason?: string;\n scorers: CompletionScorerResult[];\n timedOut: boolean;\n totalDuration: number;\n};\n\n// Browser-safe copy of the core completion-feedback formatter.\n// Keep this local so @mastra/react does not pull @mastra/core/loop into client bundles.\nconst formatBaseCompletionFeedback = (\n result: CompletionResult,\n maxIterationReached: boolean,\n formatScorerHeading: (scorer: CompletionScorerResult) => string,\n incompleteMessage: string,\n) => {\n const lines: string[] = [];\n\n lines.push('#### Completion Check Results');\n lines.push('');\n lines.push(`Overall: ${result.complete ? '✅ COMPLETE' : '❌ NOT COMPLETE'}`);\n lines.push(`Duration: ${result.totalDuration}ms`);\n if (result.timedOut) {\n lines.push('⚠️ Scoring timed out');\n }\n lines.push('');\n\n for (const scorer of result.scorers) {\n lines.push(formatScorerHeading(scorer));\n lines.push(`Score: ${scorer.score} ${scorer.passed ? '✅' : '❌'}`);\n if (scorer.reason) {\n lines.push(`Reason: ${scorer.reason}`);\n }\n lines.push('');\n }\n\n if (result.complete) {\n lines.push('✅ The task is complete.');\n } else if (maxIterationReached) {\n lines.push('⚠️ Max iterations reached.');\n } else {\n lines.push(incompleteMessage);\n }\n\n return lines.join('\\n');\n};\n\nexport const formatCompletionFeedback = (result: CompletionResult, maxIterationReached: boolean): string => {\n return formatBaseCompletionFeedback(\n result,\n maxIterationReached,\n scorer => `###### ${scorer.scorerName} (${scorer.scorerId})`,\n '🔄 Will continue working on the task.',\n );\n};\n\nexport const formatStreamCompletionFeedback = (result: CompletionResult, maxIterationReached: boolean): string => {\n return formatBaseCompletionFeedback(\n result,\n maxIterationReached,\n scorer => `**${scorer.scorerName}** (${scorer.scorerId})`,\n '🔄 The task is not yet complete. Please continue working based on the feedback above.',\n );\n};\n","import type { MastraMessagePart, AIV5Type } from '@mastra/core/agent/message-list';\nimport type { TripwirePayload } from '@mastra/core/stream';\n\nexport type MastraProviderMetadata = Record<string, Record<string, unknown>>;\n\n/**\n * Tripwire metadata included when a processor triggers a tripwire.\n * Canonical shape sourced from core's `tripwire` stream-chunk payload.\n */\nexport type TripwireMetadata = TripwirePayload;\n\nexport type ToolApprovalArgs = Record<string, unknown>;\n\nexport type RequireApprovalEntry = {\n toolCallId: string;\n toolName: string;\n args: ToolApprovalArgs;\n runId?: string;\n};\n\nexport type SuspendedToolEntry = {\n toolCallId: string;\n toolName: string;\n args: ToolApprovalArgs;\n suspendPayload: unknown;\n runId?: string;\n};\n\nexport type PendingToolApprovalEntry = {\n toolCallId: string;\n toolName: string;\n args: ToolApprovalArgs;\n runId?: string;\n};\n\nexport type BackgroundTaskEntry = {\n startedAt: Date;\n completedAt?: Date;\n suspendedAt?: Date;\n taskId: string;\n};\n\nexport type CompletionResult = {\n passed: boolean;\n suppressFeedback?: boolean;\n};\n\n/**\n * Canonical metadata block stored under `MastraDBMessage.content.metadata`.\n *\n * Every UX hint the React accumulator needs to surface lives here. Mode-specific\n * fields are all optional so a single record can carry the union without forcing\n * narrowing on the consumer side.\n */\n/**\n * Metadata key carrying a client-generated correlation id. The optimistic\n * pending user bubble and the outgoing `sendMessage` request both stamp this\n * id; the server echoes it back on the `data-user-message` data part so the\n * accumulator can reconcile the pending bubble deterministically (decoupled\n * from the server-assigned signal id). This is transient client state and is\n * stripped once the echo is reconciled and on reload.\n */\nexport const CLIENT_MESSAGE_ID_KEY = 'clientMessageId';\n\nexport type MastraDBMessageMetadata = {\n /** Which run mode produced this message. */\n mode?: 'generate' | 'stream' | 'network';\n /** Execution that produced or resumed this message; not inferred from history order. */\n runId?: string;\n /** Client-generated correlation id (see {@link CLIENT_MESSAGE_ID_KEY}). */\n clientMessageId?: string;\n /**\n * Streaming/abort/error/tripwire surface status. `'pending'` marks an\n * optimistically-appended user message that is awaiting its server signal\n * echo; it is cleared once the echo arrives and is stripped on reload.\n */\n status?: 'warning' | 'error' | 'tripwire' | 'pending';\n /** Reason recorded by the upstream stream when it finishes. */\n finishReason?: string;\n /** Tripwire metadata when status === 'tripwire'. */\n tripwire?: TripwireMetadata;\n /** Per-toolName approval requirements declared mid-stream. */\n requireApprovalMetadata?: Record<string, RequireApprovalEntry>;\n /** Per-toolName suspension records from suspended tool calls. */\n suspendedTools?: Record<string, SuspendedToolEntry>;\n /** Pending approvals keyed by toolCallId (for runtime resolution). */\n pendingToolApprovals?: Record<string, PendingToolApprovalEntry>;\n /** Per-toolCallId background-task bookkeeping. */\n backgroundTasks?: Record<string, BackgroundTaskEntry>;\n /** Number of background tasks currently executing for this message. */\n runningBackgroundTasksCount?: number;\n /** Task-completion result returned by the run (network mode). */\n completionResult?: CompletionResult;\n /**\n * Task-completion verdict from the supervisor `isTaskComplete` path. Shares\n * the `{ passed, suppressFeedback }` shape with `completionResult`; core\n * persists it as an object and reads it back as one (see `MessageMerger`).\n */\n isTaskCompleteResult?: CompletionResult;\n /** Signal-echo dedupe: signalId of the user message echoed back. */\n signalEchoIds?: string[];\n /** Network-mode bookkeeping. */\n from?: 'AGENT' | 'WORKFLOW' | 'TOOL';\n selectionReason?: string;\n agentInput?: string | object | Array<object>;\n hasMoreMessages?: boolean;\n /**\n * Structured decision emitted by the routing agent. Parsed from the\n * routing-agent text stream when it forms a balanced JSON object so the\n * raw payload never reaches the rendered thread.\n */\n routingDecision?: Record<string, unknown>;\n /**\n * Raw routing-agent text used when the stream did not parse as JSON. Kept\n * out of the visible parts but exposed for downstream UI (badge tooltips,\n * metadata dialogs, debugging).\n */\n routingDecisionText?: string;\n /**\n * Internal buffer for partial routing-agent text deltas. Cleared once the\n * buffer parses as JSON and is promoted to `routingDecision`.\n */\n routingDecisionBuffer?: string;\n};\n\n/**\n * Mastra-extended text part. Adds `textId` (per-stream identifier) and\n * `state` (streaming/done) on top of the V4 text part shape, mirroring the\n * `MastraStepStartPart` extension pattern in core.\n */\nexport type MastraTextPart = {\n type: 'text';\n text: string;\n textId?: string;\n state?: 'streaming' | 'done';\n providerMetadata?: MastraProviderMetadata;\n createdAt?: number;\n};\n\n/**\n * Mastra-extended reasoning part with per-stream identifier and streaming state.\n * `redacted: true` indicates the upstream provider redacted the reasoning content.\n */\nexport type MastraReasoningPart = {\n type: 'reasoning';\n reasoning: string;\n reasoningId?: string;\n state?: 'streaming' | 'done';\n redacted?: boolean;\n providerMetadata?: MastraProviderMetadata;\n createdAt?: number;\n};\n\n/**\n * Streaming buffer attached to a tool-invocation part while `tool-call-delta`\n * fragments arrive. The accumulator concatenates JSON chunks into `argsText`\n * and parses them on `tool-call-input-streaming-end`. Stored alongside the\n * canonical `args` so the persisted shape still satisfies `MastraDBMessage`.\n */\nexport type StreamingToolInvocationExtension = {\n argsText?: string;\n};\n\n/**\n * Custom `data-*` chunk part shape persisted on a `MastraDBMessage`. Mirrors\n * AI SDK v5 `DataUIPart` structurally so it is structurally compatible with\n * `MastraMessagePart`, while keeping the React-side accumulator independent\n * of the v5 type machinery.\n */\nexport type StreamingDataPart = {\n type: `data-${string}`;\n data: unknown;\n id?: string;\n};\n\n/**\n * Union of part types the accumulator emits. Compatible with `MastraMessagePart`\n * at runtime; the extended text/reasoning parts add optional fields that\n * downstream consumers (e.g. `AIV5Adapter.toUIMessage`) preserve via\n * providerMetadata round-tripping.\n *\n * `AIV5Type.SourceUrlUIPart` is the flat `type: 'source-url'` shape the\n * accumulator actually pushes for URL source citations (the typed\n * `MastraMessagePart` only models the nested `type: 'source'` shape), so it is\n * listed explicitly as a first-class member of the runtime union.\n */\nexport type AccumulatorPart =\n | MastraMessagePart\n | MastraTextPart\n | MastraReasoningPart\n | StreamingDataPart\n | AIV5Type.SourceUrlUIPart;\n","import type {\n AIV5Type,\n MastraDBMessage,\n MastraMessagePart,\n MastraMessageContentV2,\n MastraToolInvocation,\n MastraToolInvocationPart,\n} from '@mastra/core/agent/message-list';\nimport type { AgentChunkType, ChunkType, NetworkChunkType } from '@mastra/core/stream';\nimport type { StepResult, WorkflowStreamResult } from '@mastra/core/workflows';\nimport { uint8ArrayToBase64, encodeFilePartDataForStorage } from '../../agent/signal-data';\nimport { formatCompletionFeedback, formatStreamCompletionFeedback } from './formatCompletionFeedback';\nimport { CLIENT_MESSAGE_ID_KEY } from './types';\nimport type {\n BackgroundTaskEntry,\n MastraDBMessageMetadata,\n MastraProviderMetadata,\n MastraReasoningPart,\n MastraTextPart,\n} from './types';\n\n// Boundary cast policy\n// --------------------\n// `MastraMessagePart` (from @mastra/core) is V4-shaped:\n// - text/reasoning parts have no `state`, `textId`, `reasoningId`, or `redacted`\n// - the V4 reasoning part requires a `details` array we do not synthesize\n// - file parts use the canonical DB shape `{ mimeType, data }` so MessageList /\n// `toAISdkMessages` adapters can read them (V5-shaped `{ mediaType, url }`\n// only survives conversion on the way *out* to AI SDK UI parts)\n// - V4 source parts wrap a `LanguageModelV1Source` object; we emit V5-shaped\n// flat `source-url` / `source-document` parts\n//\n// The React SDK targets AI SDK v5 only, so the accumulator stores a V5-flavored\n// superset of `MastraMessagePart`. Every `as unknown as MastraMessagePart` site\n// in this file is a deliberate storage-boundary cast for one of the above\n// extensions, not an accident. Downstream consumers (`toAISdkV5Messages`,\n// playground `to-assistant-ui-message`) read the V5 fields directly.\n\ntype StreamChunk = {\n type: string;\n payload: any;\n runId: string;\n from: 'AGENT' | 'WORKFLOW';\n};\n\nfunction toolErrorText(error: unknown): string {\n if (error && typeof error === 'object') {\n if ('message' in error && typeof error.message === 'string') return error.message;\n // Recover only the delegation wrapper's model-facing message, never an\n // arbitrary provider cause. Native Error.message can be lost over JSON.\n if ('cause' in error) {\n const cause = error.cause;\n if (cause && typeof cause === 'object') {\n const code = 'id' in cause ? cause.id : 'code' in cause ? cause.code : undefined;\n if (code === 'AGENT_AGENT_TOOL_EXECUTION_FAILED' && 'message' in cause && typeof cause.message === 'string') {\n return cause.message;\n }\n }\n }\n }\n return String(error);\n}\n\ntype AgentChildMessage =\n | { type: 'text'; content: string }\n | {\n type: 'tool';\n toolCallId: string;\n toolName: string;\n args?: unknown;\n toolOutput?: unknown;\n };\n\ntype AgentDelegationBoundary = {\n toolCallId: string;\n toolName: string;\n};\n\ntype NormalizedNestedAgentOutput = {\n leaf: AgentChunkType;\n boundaries: AgentDelegationBoundary[];\n};\n\n/**\n * Agent-as-tool boundaries wrap progressive chunks in nested `tool-output`\n * envelopes. Peel only agent boundaries; workflow/tool envelopes remain the\n * leaf so existing child-message accumulation can process them normally.\n */\nconst normalizeNestedAgentOutput = (output: unknown): NormalizedNestedAgentOutput | undefined => {\n const boundaries: AgentDelegationBoundary[] = [];\n const seen = new Set<object>();\n let current = output;\n\n while (current !== null && typeof current === 'object') {\n if (seen.has(current)) return undefined;\n seen.add(current);\n\n const chunk = current as { type?: unknown; payload?: Record<string, unknown> };\n if (chunk.type !== 'tool-output') {\n return { leaf: current as AgentChunkType, boundaries };\n }\n\n const toolCallId = chunk.payload?.toolCallId;\n const toolName = chunk.payload?.toolName;\n if (typeof toolName !== 'string' || !toolName.startsWith('agent-')) {\n return { leaf: current as AgentChunkType, boundaries };\n }\n if (typeof toolCallId !== 'string' || !('output' in (chunk.payload ?? {}))) return undefined;\n\n boundaries.push({ toolCallId, toolName });\n current = chunk.payload?.output;\n }\n\n return undefined;\n};\n\nconst cloneMetadata = (metadata: MastraDBMessageMetadata | undefined): MastraDBMessageMetadata =>\n metadata ? { ...metadata } : {};\n\nconst withParts = (message: MastraDBMessage, parts: MastraMessagePart[]): MastraDBMessage => ({\n ...message,\n content: {\n ...message.content,\n parts,\n },\n});\n\nconst withMetadata = (message: MastraDBMessage, metadata: MastraDBMessageMetadata): MastraDBMessage => ({\n ...message,\n content: {\n ...message.content,\n metadata,\n },\n});\n\n// Drops the transient `pending` status and the `clientMessageId` correlation\n// key from an optimistic user message once its server echo confirms it, leaving\n// the rest of the metadata intact.\nconst clearPendingStatus = (message: MastraDBMessage): MastraDBMessage => {\n const { status: _status, [CLIENT_MESSAGE_ID_KEY]: _clientMessageId, ...rest } = message.content.metadata ?? {};\n return withMetadata(message, rest);\n};\n\n// Like `clearPendingStatus` but retains the `clientMessageId` correlation key.\n// Used during `data-user-message` reconciliation so the rendered row key (which\n// prefers `clientMessageId`) stays stable across the id swap, preventing a\n// React unmount/remount and the resulting layout shift. `clientMessageId` is\n// still stripped from persisted threads by `resolveInitialMessages`.\nconst clearPendingStatusKeepClientId = (message: MastraDBMessage): MastraDBMessage => {\n const { status: _status, ...rest } = message.content.metadata ?? {};\n return withMetadata(message, rest);\n};\n\nconst replaceLast = (conversation: MastraDBMessage[], message: MastraDBMessage): MastraDBMessage[] => [\n ...conversation.slice(0, -1),\n message,\n];\n\nconst replaceAt = (conversation: MastraDBMessage[], index: number, message: MastraDBMessage): MastraDBMessage[] => [\n ...conversation.slice(0, index),\n message,\n ...conversation.slice(index + 1),\n];\n\nconst newAssistantMessage = (\n id: string,\n parts: MastraMessagePart[],\n metadata: MastraDBMessageMetadata,\n): MastraDBMessage => ({\n id,\n role: 'assistant',\n createdAt: new Date(),\n content: {\n format: 2,\n parts,\n metadata: cloneMetadata(metadata),\n } satisfies MastraMessageContentV2,\n});\n\nconst appendAssistantMessage = (\n conversation: MastraDBMessage[],\n id: string,\n parts: MastraMessagePart[],\n metadata: MastraDBMessageMetadata,\n): MastraDBMessage[] => [...conversation, newAssistantMessage(id, parts, metadata)];\n\nconst isToolPart = (part: MastraMessagePart): part is MastraToolInvocationPart => part.type === 'tool-invocation';\n\nconst partTextId = (part: MastraMessagePart): string | undefined =>\n part.type === 'text' ? (part as MastraTextPart).textId : undefined;\n\nconst partState = (part: MastraMessagePart): string | undefined => (part as { state?: string }).state;\n\nconst partProviderMetadata = (part: MastraMessagePart): Record<string, unknown> | undefined =>\n (part as { providerMetadata?: Record<string, unknown> }).providerMetadata;\n\n/**\n * Set any streaming text/reasoning parts on the trailing assistant message to\n * `state: 'done'`. Mirrors the previous `finishStreamingAssistantMessage` from\n * the AI-SDK accumulator.\n */\nexport const finishStreamingAssistantMessage = (conversation: MastraDBMessage[]): MastraDBMessage[] => {\n const lastMessage = conversation[conversation.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') return conversation;\n if (lastMessage.content.parts.length === 0) return conversation.slice(0, -1);\n\n const nextParts = lastMessage.content.parts.map(part => {\n if ((part.type === 'text' || part.type === 'reasoning') && partState(part) === 'streaming') {\n return {\n ...(part as MastraTextPart | MastraReasoningPart),\n state: 'done' as const,\n } as unknown as MastraMessagePart;\n }\n return part;\n });\n\n return replaceLast(conversation, withParts(lastMessage, nextParts));\n};\n\n/**\n * Locate the assistant message + tool part owning `toolCallId`. Prefers the\n * most recent assistant message and walks back up to 10 messages, matching the\n * historical accumulator's lookup behavior.\n */\nconst locateToolPart = (\n messages: MastraDBMessage[],\n toolCallId: string,\n allowMetadataOnlyMatch: boolean,\n): { messageIndex: number; toolPartIndex: number } | null => {\n const findIndex = (parts: MastraMessagePart[]) =>\n parts.findIndex(part => isToolPart(part) && part.toolInvocation.toolCallId === toolCallId);\n\n const lastMessage = messages[messages.length - 1];\n if (lastMessage && lastMessage.role === 'assistant') {\n const idx = findIndex(lastMessage.content.parts);\n if (idx !== -1) return { messageIndex: messages.length - 1, toolPartIndex: idx };\n }\n\n let count = 0;\n const maxMessagesBack = 10;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (count > maxMessagesBack) break;\n const message = messages[i];\n if (message.role !== 'assistant') continue;\n const idx = findIndex(message.content.parts);\n if (idx !== -1) return { messageIndex: i, toolPartIndex: idx };\n count++;\n }\n\n if (!allowMetadataOnlyMatch) return null;\n\n // Fall back to most-recent assistant message for metadata-only updates.\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'assistant') return { messageIndex: i, toolPartIndex: -1 };\n }\n return null;\n};\n\n/**\n * Merge per-toolCallId background-task bookkeeping onto message metadata.\n */\nconst mergeBgTaskMetadata = (\n existing: MastraDBMessageMetadata | undefined,\n mode: 'stream' | 'generate' | 'network' | undefined,\n args: {\n resetRunningCount?: boolean;\n perTaskEntry?: {\n toolCallId: string;\n startedAt?: Date;\n completedAt?: Date;\n suspendedAt?: Date;\n taskId: string;\n };\n },\n otherMetadata?: MastraDBMessageMetadata,\n): MastraDBMessageMetadata => {\n const base = cloneMetadata(existing);\n const existingBgTasks = (base.backgroundTasks ?? {}) as Record<string, BackgroundTaskEntry>;\n\n const nextBgTasks: Record<string, BackgroundTaskEntry> = { ...existingBgTasks };\n if (args.perTaskEntry) {\n const { toolCallId, startedAt, completedAt, taskId, suspendedAt } = args.perTaskEntry;\n const prev = existingBgTasks[toolCallId] ?? ({ taskId } as BackgroundTaskEntry);\n nextBgTasks[toolCallId] = {\n ...prev,\n taskId,\n ...(startedAt !== undefined ? { startedAt } : {}),\n ...(completedAt !== undefined ? { completedAt } : {}),\n ...(suspendedAt !== undefined ? { suspendedAt } : {}),\n };\n }\n\n const merged: MastraDBMessageMetadata = {\n ...base,\n ...(otherMetadata ?? {}),\n mode,\n backgroundTasks: nextBgTasks,\n };\n if (args.resetRunningCount) merged.runningBackgroundTasksCount = undefined;\n return merged;\n};\n\n/**\n * Workflow chunk accumulation. Mirrors\n * `mapWorkflowStreamChunkToWatchResult` from the previous accumulator.\n */\nexport const mapWorkflowStreamChunkToWatchResult = (\n prev: WorkflowStreamResult<any, any, any, any> | undefined,\n chunk: StreamChunk,\n): WorkflowStreamResult<any, any, any, any> => {\n // On replay, `prev` may be a finished tool result (e.g. `{ result, runId }`) with no `steps`.\n const previous =\n prev && typeof prev === 'object' && prev.steps && typeof prev.steps === 'object'\n ? prev\n : { status: 'running' as const, input: undefined, steps: {} };\n if (chunk.type === 'workflow-start') {\n return { input: previous.input, status: 'running', steps: previous.steps };\n }\n\n if (chunk.type === 'workflow-canceled') {\n return { ...previous, status: 'canceled' };\n }\n\n if (chunk.type === 'workflow-paused') {\n return { ...previous, status: 'paused' };\n }\n\n if (chunk.type === 'workflow-finish') {\n const finalStatus = chunk.payload.workflowStatus;\n const lastStep = Object.values(previous.steps).pop();\n return {\n ...previous,\n status: chunk.payload.workflowStatus,\n ...(finalStatus === 'success' && lastStep?.status === 'success'\n ? { result: lastStep?.output }\n : finalStatus === 'failed' && lastStep?.status === 'failed'\n ? { error: lastStep?.error }\n : finalStatus === 'tripwire' && chunk.payload.tripwire\n ? { tripwire: chunk.payload.tripwire }\n : {}),\n };\n }\n\n // writer.custom events carry `data` and no payload: nothing to fold into a step.\n const stepId = chunk.payload?.id;\n if (stepId === undefined) return previous;\n\n const { stepCallId: _stepCallId, stepName: _stepName, ...newPayload } = chunk.payload;\n const newSteps = {\n ...previous.steps,\n [stepId]: {\n ...previous.steps[stepId],\n ...newPayload,\n },\n };\n\n if (chunk.type === 'workflow-step-start') return { ...previous, steps: newSteps };\n\n if (chunk.type === 'workflow-step-suspended') {\n const suspendedStepIds = Object.entries(newSteps as Record<string, StepResult<any, any, any, any>>).flatMap(\n ([stepId, stepResult]) => {\n if (stepResult?.status === 'suspended') {\n const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;\n return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];\n }\n return [];\n },\n );\n // A suspended chunk contributes at least its own step path.\n const suspended = suspendedStepIds as [string[], ...string[][]];\n return {\n ...previous,\n status: 'suspended',\n steps: newSteps,\n suspendPayload: chunk.payload.suspendPayload,\n suspended,\n };\n }\n\n if (chunk.type === 'workflow-step-waiting') return { ...previous, status: 'waiting', steps: newSteps };\n\n if (chunk.type === 'workflow-step-progress') {\n return {\n ...previous,\n steps: {\n ...previous.steps,\n [stepId]: {\n ...previous.steps[stepId],\n foreachProgress: {\n completedCount: chunk.payload.completedCount,\n totalCount: chunk.payload.totalCount,\n currentIndex: chunk.payload.currentIndex,\n iterationStatus: chunk.payload.iterationStatus,\n iterationOutput: chunk.payload.iterationOutput,\n },\n },\n },\n };\n }\n\n if (chunk.type === 'workflow-step-result') return { ...previous, steps: newSteps };\n\n return previous;\n};\n\nconst signalContentsToUserMessages = (contents: unknown, metadata: MastraDBMessageMetadata): MastraDBMessage[] => {\n const makeUserMessage = (parts: MastraMessagePart[]): MastraDBMessage => ({\n id: `signal-${Date.now()}`,\n role: 'user',\n createdAt: new Date(),\n content: {\n format: 2,\n parts,\n metadata: cloneMetadata(metadata),\n },\n });\n\n const toMessagePart = (part: unknown): MastraMessagePart[] => {\n if (!part || typeof part !== 'object') return [];\n const typedPart = part as Record<string, unknown>;\n\n if (typedPart.type === 'text' && typeof typedPart.text === 'string') {\n return [{ type: 'text', text: typedPart.text }];\n }\n\n if (typedPart.type === 'image') {\n const image = typedPart.image;\n const mimeType =\n typeof typedPart.mediaType === 'string'\n ? typedPart.mediaType\n : typeof typedPart.mimeType === 'string'\n ? typedPart.mimeType\n : 'image/*';\n if (\n typeof image === 'string' ||\n image instanceof URL ||\n image instanceof ArrayBuffer ||\n image instanceof Uint8Array\n ) {\n return [\n {\n type: 'file',\n mimeType,\n data: encodeFilePartDataForStorage(image, mimeType),\n },\n ];\n }\n return [{ type: 'file', mimeType, data: '' }];\n }\n\n if (typedPart.type === 'file') {\n const data = typedPart.data;\n const mimeType =\n typeof typedPart.mediaType === 'string'\n ? typedPart.mediaType\n : typeof typedPart.mimeType === 'string'\n ? typedPart.mimeType\n : 'application/octet-stream';\n if (\n typeof data === 'string' ||\n data instanceof URL ||\n data instanceof ArrayBuffer ||\n data instanceof Uint8Array\n ) {\n return [\n {\n type: 'file',\n mimeType,\n data: encodeFilePartDataForStorage(data, mimeType),\n ...(typeof typedPart.filename === 'string' ? { filename: typedPart.filename } : {}),\n },\n ];\n }\n const urlFallback = typeof typedPart.url === 'string' ? typedPart.url : '';\n return [\n {\n type: 'file',\n mimeType,\n data: urlFallback,\n ...(typeof typedPart.filename === 'string' ? { filename: typedPart.filename } : {}),\n },\n ];\n }\n\n return [];\n };\n\n if (typeof contents === 'string') {\n return [makeUserMessage([{ type: 'text', text: contents }])];\n }\n\n if (Array.isArray(contents)) {\n const parts = contents.flatMap(toMessagePart);\n return parts.length\n ? [makeUserMessage(parts)]\n : contents.flatMap(content => signalContentsToUserMessages(content, metadata));\n }\n\n if (!contents || typeof contents !== 'object') return [];\n\n const message = contents as { role?: unknown; content?: unknown };\n if (message.role && message.role !== 'user') return [];\n\n const content = message.content;\n if (typeof content === 'string') {\n return [makeUserMessage([{ type: 'text', text: content }])];\n }\n\n if (!Array.isArray(content)) return [];\n\n const parts = content.flatMap(toMessagePart);\n return parts.length ? [makeUserMessage(parts)] : [];\n};\n\nconst reconcilePendingUserEcho = (\n message: MastraDBMessage,\n echoedContents: unknown,\n metadata: MastraDBMessageMetadata,\n options: { signalId?: string; keepClientMessageId: boolean },\n): MastraDBMessage => {\n const echoedMessages = signalContentsToUserMessages(echoedContents, metadata);\n const echoedParts = echoedMessages[0]?.content.parts;\n let reconciled = typeof options.signalId === 'string' ? { ...message, id: options.signalId } : message;\n if (echoedParts?.length) {\n reconciled = { ...reconciled, content: { ...reconciled.content, parts: echoedParts } };\n }\n return options.keepClientMessageId ? clearPendingStatusKeepClientId(reconciled) : clearPendingStatus(reconciled);\n};\n\nconst makeToolInvocationPart = (invocation: MastraToolInvocation): MastraToolInvocationPart => ({\n type: 'tool-invocation',\n toolInvocation: invocation,\n});\n\n/**\n * Narrow the chunk to the template-literal passthrough variants from\n * `NetworkChunkType`. Encoded as a type guard so the surrounding `switch`\n * statement can stay exhaustive over the remaining string-literal cases.\n */\nconst isTemplateLiteralPassthrough = <T extends { type: string }>(\n chunk: T,\n): chunk is T & { type: `agent-execution-event-${string}` | `workflow-execution-event-${string}` } =>\n chunk.type.startsWith('agent-execution-event-') || chunk.type.startsWith('workflow-execution-event-');\n\n/**\n * Narrow the chunk to the `data-${string}` family. Used so the trailing\n * exhaustiveness check can prove the switch covers every remaining variant.\n */\nconst isDataChunk = <T extends { type: string }>(chunk: T): chunk is T & { type: `data-${string}` } =>\n chunk.type.startsWith('data-');\n\nexport interface AccumulateChunkArgs {\n chunk: ChunkType;\n conversation: MastraDBMessage[];\n metadata: MastraDBMessageMetadata;\n}\n\n/**\n * Reduce a single stream chunk into the running `MastraDBMessage[]`\n * conversation. The accumulator owns the entire chunk→DB mapping for the\n * React SDK; consumers downstream (e.g. `toAISdkV5Messages` in the playground)\n * translate the result into AI SDK / assistant-ui shapes as needed.\n */\nexport const accumulateChunk = ({ chunk, conversation, metadata }: AccumulateChunkArgs): MastraDBMessage[] => {\n const result = [...conversation];\n\n // ----- Template-literal passthrough chunk types from NetworkChunkType -----\n // `agent-execution-event-*` and `workflow-execution-event-*` carry nested\n // events that are surfaced through other mechanisms (e.g. tool-output\n // routing); at the top-level DB accumulator they are no-ops. The narrow is\n // expressed as a function so the remaining switch can be exhaustive over\n // the literal-typed variants.\n if (isTemplateLiteralPassthrough(chunk)) {\n return result;\n }\n\n // ----- Custom `data-*` chunks (including signal-echo) -----\n if (isDataChunk(chunk)) {\n if (\n chunk.type === 'data-user-message' &&\n 'data' in chunk &&\n ((chunk as any).data?.type === 'user-message' || (chunk as any).data?.type === 'user')\n ) {\n const signalId = (chunk as any).data.id;\n\n // Preferred reconciliation: the optimistic pending bubble and the outgoing\n // message both carry a client-generated `clientMessageId`; the server\n // echoes it back here. Match on it (not the server-assigned signal id) so\n // the single optimistic bubble adopts the server id and clears its\n // transient pending state instead of being duplicated.\n const echoedClientMessageId = (chunk as any).data?.metadata?.[CLIENT_MESSAGE_ID_KEY];\n if (\n typeof echoedClientMessageId === 'string' &&\n result.some(\n message =>\n message.content.metadata?.status === 'pending' &&\n message.content.metadata[CLIENT_MESSAGE_ID_KEY] === echoedClientMessageId,\n )\n ) {\n return finishStreamingAssistantMessage(\n result.map(message =>\n message.content.metadata?.status === 'pending' &&\n message.content.metadata[CLIENT_MESSAGE_ID_KEY] === echoedClientMessageId\n ? reconcilePendingUserEcho(message, (chunk as any).data.contents, metadata, {\n signalId: typeof signalId === 'string' ? signalId : undefined,\n keepClientMessageId: true,\n })\n : message,\n ),\n );\n }\n\n if (typeof signalId === 'string' && result.some(message => message.id === signalId)) {\n return finishStreamingAssistantMessage(\n result.map(message =>\n message.id === signalId && message.content.metadata?.status === 'pending'\n ? reconcilePendingUserEcho(message, (chunk as any).data.contents, metadata, {\n keepClientMessageId: false,\n })\n : message,\n ),\n );\n }\n\n const userMessages = signalContentsToUserMessages((chunk as any).data.contents, metadata);\n if (!userMessages.length) return result;\n\n const conversationWithFinishedAssistant = finishStreamingAssistantMessage(result);\n const messageIdPrefix = typeof signalId === 'string' ? signalId : `signal-${chunk.runId}-${Date.now()}`;\n return [\n ...conversationWithFinishedAssistant,\n ...userMessages.map((message, index) => ({\n ...message,\n id: index === 0 ? messageIdPrefix : `${messageIdPrefix}-${index}`,\n })),\n ];\n }\n\n const dataPart = {\n type: chunk.type as `data-${string}`,\n data: 'data' in chunk ? (chunk as any).data : undefined,\n ...('id' in chunk && typeof (chunk as any).id === 'string' ? { id: (chunk as any).id } : {}),\n } as unknown as MastraMessagePart;\n\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') {\n return appendAssistantMessage(result, `data-${chunk.runId}-${Date.now()}`, [dataPart], metadata);\n }\n\n return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, dataPart]));\n }\n\n switch (chunk.type) {\n case 'tripwire': {\n const newMessage = newAssistantMessage(\n `tripwire-${chunk.runId + Date.now()}`,\n [{ type: 'text', text: chunk.payload.reason } as MastraMessagePart],\n {\n ...metadata,\n status: 'tripwire',\n tripwire: {\n reason: chunk.payload.reason,\n retry: chunk.payload.retry,\n metadata: chunk.payload.metadata,\n processorId: chunk.payload.processorId,\n },\n },\n );\n return [...result, newMessage];\n }\n\n case 'start': {\n // Retained stream history may contain `start` chunks emitted without a payload.\n const messageId = typeof chunk.payload?.messageId === 'string' ? chunk.payload.messageId : undefined;\n if (messageId && result.some(message => message.id === messageId)) return result;\n return [...result, newAssistantMessage(messageId ?? `start-${chunk.runId + Date.now()}`, [], metadata)];\n }\n\n case 'text-start': {\n const lastMessage = result[result.length - 1];\n const textId = chunk.payload.id || `text-${Date.now()}`;\n // Dedupe a repeated text-start only when the currently open (tail) text\n // part already carries this id. Matching anywhere in the message would\n // wrongly swallow a post-tool continuation that reuses the same text id\n // (text → tool → text), leaving the second segment without its own part.\n const tailPart = lastMessage?.content.parts[lastMessage.content.parts.length - 1];\n if (\n chunk.payload.id &&\n lastMessage?.role === 'assistant' &&\n tailPart?.type === 'text' &&\n partTextId(tailPart) === textId\n ) {\n return result;\n }\n\n const newTextPart: MastraTextPart = {\n type: 'text',\n text: '',\n state: 'streaming',\n textId,\n providerMetadata: chunk.payload.providerMetadata,\n };\n\n if (!lastMessage || lastMessage.role !== 'assistant') {\n return appendAssistantMessage(\n result,\n `start-${chunk.runId}-${Date.now()}`,\n [newTextPart as MastraMessagePart],\n metadata,\n );\n }\n\n // If the last message is a completion/isTaskComplete result message, start a new assistant message\n if (lastMessage.content.metadata?.completionResult) {\n return appendAssistantMessage(\n result,\n `start-${chunk.runId}-${Date.now()}`,\n [newTextPart as MastraMessagePart],\n metadata,\n );\n }\n\n return replaceLast(\n result,\n withParts(lastMessage, [...lastMessage.content.parts, newTextPart as MastraMessagePart]),\n );\n }\n\n case 'background-task-progress': {\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') return result;\n\n return replaceLast(\n result,\n withMetadata(lastMessage, {\n mode: metadata.mode,\n ...(lastMessage.content.metadata as MastraDBMessageMetadata | undefined),\n runningBackgroundTasksCount: chunk.payload.runningCount,\n }),\n );\n }\n\n case 'text-delta': {\n const lastMessage = result[result.length - 1];\n const textId = chunk.payload.id;\n\n if (!lastMessage || lastMessage.role !== 'assistant') {\n const newTextPart: MastraTextPart = {\n type: 'text',\n text: chunk.payload.text,\n state: 'streaming',\n textId,\n providerMetadata: chunk.payload.providerMetadata,\n };\n return appendAssistantMessage(\n result,\n `text-${chunk.runId}-${Date.now()}`,\n [newTextPart as MastraMessagePart],\n metadata,\n );\n }\n\n const parts = [...lastMessage.content.parts];\n\n let textPartIndex = textId\n ? parts.findLastIndex(part => part.type === 'text' && partTextId(part) === textId)\n : -1;\n\n if (textPartIndex === -1) {\n textPartIndex = parts.findLastIndex(part => part.type === 'text' && partState(part) === 'streaming');\n }\n\n // A text run is closed once ANY non-text part is emitted after it — a tool\n // call, reasoning, a source/citation, a file, a step marker, etc. If the\n // matched text part is followed by such a part (e.g. text → tool → text or\n // text → reasoning → text, where a provider like DeepSeek reuses the same\n // text id across segments), this delta belongs to a NEW text segment.\n // Appending to the earlier part would merge the two text blocks and push\n // the intervening part out of order in the live view (issue #18964).\n // Storage persists them as separate parts, which is why a reload already\n // renders correctly.\n if (textPartIndex !== -1 && parts.some((part, index) => index > textPartIndex && part.type !== 'text')) {\n textPartIndex = -1;\n }\n\n if (textPartIndex === -1) {\n const newTextPart: MastraTextPart = {\n type: 'text',\n text: chunk.payload.text,\n state: 'streaming',\n textId,\n providerMetadata: chunk.payload.providerMetadata,\n };\n parts.push(newTextPart as MastraMessagePart);\n } else {\n const textPart = parts[textPartIndex] as MastraTextPart;\n parts[textPartIndex] = {\n ...textPart,\n text: textPart.text + chunk.payload.text,\n state: 'streaming',\n } as MastraMessagePart;\n }\n\n return replaceLast(result, withParts(lastMessage, parts));\n }\n\n case 'text-end': {\n // Lifecycle marker only. Streaming text parts stay in `state: 'streaming'`\n // and are finalized by `finish` / `abort` via `finishStreamingAssistantMessage`.\n // Returned as-is so the chunk-to-DB mapping stays total.\n return result;\n }\n\n case 'reasoning-start': {\n const lastMessage = result[result.length - 1];\n const newReasoningPart: MastraReasoningPart = {\n type: 'reasoning',\n reasoning: '',\n state: 'streaming',\n providerMetadata: chunk.payload.providerMetadata,\n };\n\n if (!lastMessage || lastMessage.role !== 'assistant') {\n return appendAssistantMessage(\n result,\n `reasoning-${chunk.runId + Date.now()}`,\n [newReasoningPart as unknown as MastraMessagePart],\n metadata,\n );\n }\n\n return replaceLast(\n result,\n withParts(lastMessage, [...lastMessage.content.parts, newReasoningPart as unknown as MastraMessagePart]),\n );\n }\n\n case 'reasoning-delta': {\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') {\n const newReasoningPart: MastraReasoningPart = {\n type: 'reasoning',\n reasoning: chunk.payload.text,\n state: 'streaming',\n providerMetadata: chunk.payload.providerMetadata,\n };\n return appendAssistantMessage(\n result,\n `reasoning-${chunk.runId + Date.now()}`,\n [newReasoningPart as unknown as MastraMessagePart],\n metadata,\n );\n }\n\n const parts = [...lastMessage.content.parts];\n const lastIndex = parts.length - 1;\n const lastPart = parts[lastIndex];\n\n if (lastPart?.type === 'reasoning') {\n const reasoningPart = lastPart as unknown as MastraReasoningPart;\n parts[lastIndex] = {\n ...reasoningPart,\n reasoning: reasoningPart.reasoning + chunk.payload.text,\n state: 'streaming',\n } as unknown as MastraMessagePart;\n } else {\n const newReasoningPart: MastraReasoningPart = {\n type: 'reasoning',\n reasoning: chunk.payload.text,\n state: 'streaming',\n providerMetadata: chunk.payload.providerMetadata,\n };\n parts.push(newReasoningPart as unknown as MastraMessagePart);\n }\n\n return replaceLast(result, withParts(lastMessage, parts));\n }\n\n case 'reasoning-end': {\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') return result;\n\n const parts = [...lastMessage.content.parts];\n const reasoningIndex = parts.findLastIndex(part => part.type === 'reasoning' && partState(part) === 'streaming');\n if (reasoningIndex === -1) return result;\n\n const reasoningPart = parts[reasoningIndex] as unknown as MastraReasoningPart;\n const existingMeta = reasoningPart.providerMetadata;\n const endMeta = chunk.payload.providerMetadata;\n\n parts[reasoningIndex] = {\n ...reasoningPart,\n state: 'done',\n ...(existingMeta || endMeta ? { providerMetadata: { ...(existingMeta ?? {}), ...(endMeta ?? {}) } } : {}),\n } as unknown as MastraMessagePart;\n\n return replaceLast(result, withParts(lastMessage, parts));\n }\n\n case 'reasoning-signature': {\n // Merge the signature provider metadata into the most recent reasoning part\n // (streaming or done). Mirrors historical AI-SDK behavior where the\n // signature payload becomes part of the reasoning part's providerMetadata.\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') return result;\n\n const parts = [...lastMessage.content.parts];\n const reasoningIndex = parts.findLastIndex(part => part.type === 'reasoning');\n if (reasoningIndex === -1) return result;\n\n const reasoningPart = parts[reasoningIndex] as unknown as MastraReasoningPart;\n const existingMeta = reasoningPart.providerMetadata;\n const sigMeta = chunk.payload.providerMetadata;\n\n parts[reasoningIndex] = {\n ...reasoningPart,\n ...(existingMeta || sigMeta ? { providerMetadata: { ...(existingMeta ?? {}), ...(sigMeta ?? {}) } } : {}),\n } as unknown as MastraMessagePart;\n\n return replaceLast(result, withParts(lastMessage, parts));\n }\n\n case 'redacted-reasoning': {\n // Emit a done reasoning part flagged as redacted. The provider redacted\n // the content; the placeholder preserves the slot in the parts array.\n const lastMessage = result[result.length - 1];\n const redactedData = chunk.payload.data;\n const redactedPart: MastraReasoningPart = {\n type: 'reasoning',\n reasoning: typeof redactedData === 'string' ? redactedData : '',\n state: 'done',\n redacted: true,\n providerMetadata: chunk.payload.providerMetadata,\n };\n\n if (!lastMessage || lastMessage.role !== 'assistant') {\n return appendAssistantMessage(\n result,\n `redacted-reasoning-${chunk.runId + Date.now()}`,\n [redactedPart as unknown as MastraMessagePart],\n metadata,\n );\n }\n\n return replaceLast(\n result,\n withParts(lastMessage, [...lastMessage.content.parts, redactedPart as unknown as MastraMessagePart]),\n );\n }\n\n case 'tool-call': {\n const invocation: MastraToolInvocation = {\n state: 'call',\n toolCallId: chunk.payload.toolCallId,\n toolName: chunk.payload.toolName,\n args: chunk.payload.args,\n };\n const newPart: MastraToolInvocationPart = {\n ...makeToolInvocationPart(invocation),\n title: chunk.payload.title,\n providerMetadata: chunk.payload.providerMetadata,\n };\n\n // Upsert by toolCallId: if `tool-call-input-streaming-start` already created\n // a placeholder part for this id, transition it in place instead of\n // appending a duplicate. `chunk.payload.args` is the authoritative\n // server-side parsed args and overwrites any client-side JSON.parse done\n // during streaming.\n const existing = locateToolPart(result, chunk.payload.toolCallId, false);\n if (existing && existing.toolPartIndex >= 0) {\n const { messageIndex, toolPartIndex } = existing;\n const targetMessage = result[messageIndex];\n if (targetMessage && targetMessage.role === 'assistant') {\n const parts = [...targetMessage.content.parts];\n const prev = parts[toolPartIndex] as MastraToolInvocationPart & { argsText?: string };\n if (isToolPart(prev)) {\n const { argsText: _argsText, ...rest } = prev;\n parts[toolPartIndex] = {\n ...rest,\n toolInvocation: {\n ...prev.toolInvocation,\n state: 'call',\n toolName: chunk.payload.toolName,\n toolCallId: chunk.payload.toolCallId,\n args: chunk.payload.args,\n },\n title: chunk.payload.title ?? prev.title,\n providerMetadata: chunk.payload.providerMetadata ?? prev.providerMetadata,\n };\n return replaceAt(result, messageIndex, withParts(targetMessage, parts));\n }\n }\n }\n\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') {\n return appendAssistantMessage(result, `tool-call-${chunk.runId + Date.now()}`, [newPart], metadata);\n }\n\n return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, newPart]));\n }\n\n case 'tool-call-input-streaming-start': {\n // Create a placeholder tool-invocation part in `partial-call` state with an\n // empty args buffer; subsequent `tool-call-delta` chunks append JSON\n // fragments to `argsText` and `tool-call-input-streaming-end` parses them.\n const lastMessage = result[result.length - 1];\n const invocation: MastraToolInvocation = {\n state: 'partial-call',\n toolCallId: chunk.payload.toolCallId,\n toolName: chunk.payload.toolName,\n args: {},\n };\n const newPart: MastraToolInvocationPart & { argsText?: string } = {\n ...makeToolInvocationPart(invocation),\n title: chunk.payload.title,\n argsText: '',\n };\n\n if (!lastMessage || lastMessage.role !== 'assistant') {\n return appendAssistantMessage(\n result,\n `tool-call-streaming-${chunk.runId + Date.now()}`,\n [newPart as MastraMessagePart],\n metadata,\n );\n }\n\n return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, newPart as MastraMessagePart]));\n }\n\n case 'tool-call-delta': {\n // Append the streamed JSON fragment onto the matching tool invocation's\n // `argsText` buffer. Keep `args` empty/parsed-so-far until the end chunk.\n const location = locateToolPart(result, chunk.payload.toolCallId, false);\n if (!location || location.toolPartIndex < 0) return result;\n const { messageIndex, toolPartIndex } = location;\n const targetMessage = result[messageIndex];\n if (!targetMessage || targetMessage.role !== 'assistant') return result;\n\n const parts = [...targetMessage.content.parts];\n const toolPart = parts[toolPartIndex] as MastraToolInvocationPart & { argsText?: string };\n if (!isToolPart(toolPart)) return result;\n\n const nextArgsText = (toolPart.argsText ?? '') + (chunk.payload.argsTextDelta ?? '');\n parts[toolPartIndex] = {\n ...toolPart,\n argsText: nextArgsText,\n toolInvocation: {\n ...toolPart.toolInvocation,\n state: 'partial-call',\n } as MastraToolInvocation,\n } as MastraMessagePart;\n\n return replaceAt(result, messageIndex, withParts(targetMessage, parts));\n }\n\n case 'tool-call-input-streaming-end': {\n // Finalize the streaming args: parse `argsText` and transition to `call`.\n // If parsing fails, keep `args: {}` so downstream consumers stay safe.\n const location = locateToolPart(result, chunk.payload.toolCallId, false);\n if (!location || location.toolPartIndex < 0) return result;\n const { messageIndex, toolPartIndex } = location;\n const targetMessage = result[messageIndex];\n if (!targetMessage || targetMessage.role !== 'assistant') return result;\n\n const parts = [...targetMessage.content.parts];\n const toolPart = parts[toolPartIndex] as MastraToolInvocationPart & { argsText?: string };\n if (!isToolPart(toolPart)) return result;\n\n let parsedArgs: Record<string, unknown> = {};\n const argsText = toolPart.argsText;\n if (typeof argsText === 'string' && argsText.length > 0) {\n try {\n const maybe = JSON.parse(argsText);\n if (maybe && typeof maybe === 'object' && !Array.isArray(maybe)) {\n parsedArgs = maybe as Record<string, unknown>;\n }\n } catch {\n parsedArgs = {};\n }\n }\n\n parts[toolPartIndex] = {\n ...toolPart,\n toolInvocation: {\n ...toolPart.toolInvocation,\n state: 'call',\n args: parsedArgs,\n } as MastraToolInvocation,\n } as MastraMessagePart;\n\n return replaceAt(result, messageIndex, withParts(targetMessage, parts));\n }\n\n case 'tool-output-denied': {\n const location = locateToolPart(result, chunk.payload.toolCallId, false);\n if (!location || location.toolPartIndex < 0) return result;\n const { messageIndex, toolPartIndex } = location;\n const targetMessage = result[messageIndex];\n if (!targetMessage || targetMessage.role !== 'assistant') return result;\n\n const parts = [...targetMessage.content.parts];\n const toolPart = parts[toolPartIndex];\n if (!isToolPart(toolPart)) return result;\n\n parts[toolPartIndex] = {\n ...toolPart,\n toolInvocation: {\n ...toolPart.toolInvocation,\n state: 'output-denied',\n toolName: chunk.payload.toolName,\n args: chunk.payload.args ?? toolPart.toolInvocation.args,\n approval: chunk.payload.approval,\n },\n } as MastraMessagePart;\n\n return replaceAt(result, messageIndex, withParts(targetMessage, parts));\n }\n\n case 'tool-error':\n case 'tool-result':\n case 'background-task-completed':\n case 'background-task-failed': {\n const isBgTaskEvent = chunk.type === 'background-task-completed' || chunk.type === 'background-task-failed';\n const location = locateToolPart(result, chunk.payload.toolCallId, isBgTaskEvent);\n if (!location) return result;\n const { messageIndex, toolPartIndex } = location;\n const targetMessage = result[messageIndex];\n if (!targetMessage || targetMessage.role !== 'assistant') return result;\n\n const parts = [...targetMessage.content.parts];\n const toolPart = toolPartIndex >= 0 ? parts[toolPartIndex] : undefined;\n\n // Narrow the merged-case payload by chunk.type so each branch has typed\n // access to its specific fields without `as any`.\n let payloadResult: unknown;\n let payloadError: unknown;\n let payloadIsError = false;\n let payloadProviderMetadata: MastraProviderMetadata | undefined;\n let payloadCompletedAt: Date | undefined;\n let payloadTaskId: string | undefined;\n switch (chunk.type) {\n case 'tool-result':\n payloadResult = chunk.payload.result;\n payloadIsError = Boolean(chunk.payload.isError);\n payloadProviderMetadata = chunk.payload.providerMetadata as MastraProviderMetadata | undefined;\n break;\n case 'tool-error':\n payloadError = chunk.payload.error;\n payloadProviderMetadata = chunk.payload.providerMetadata as MastraProviderMetadata | undefined;\n break;\n case 'background-task-completed':\n payloadResult = chunk.payload.result;\n payloadCompletedAt = chunk.payload.completedAt;\n payloadTaskId = chunk.payload.taskId;\n break;\n case 'background-task-failed':\n payloadError = chunk.payload.error;\n payloadCompletedAt = chunk.payload.completedAt;\n payloadTaskId = chunk.payload.taskId;\n break;\n }\n\n if (toolPart && isToolPart(toolPart)) {\n const { toolName, toolCallId, args } = toolPart.toolInvocation;\n // Provider metadata flows through opaquely; cast once at the storage\n // boundary because the V4 part type pins it to SharedV2ProviderMetadata\n // (Record<string, Record<string, JSONValue>>) and Mastra payloads are\n // not constrained to that shape.\n const providerMeta = (payloadProviderMetadata ??\n toolPart.providerMetadata) as MastraToolInvocationPart['providerMetadata'];\n\n const isError = chunk.type === 'tool-error' || chunk.type === 'background-task-failed' || payloadIsError;\n\n if (isError) {\n const error =\n chunk.type === 'tool-error' || chunk.type === 'background-task-failed' ? payloadError : payloadResult;\n const errorText = toolErrorText(error);\n\n parts[toolPartIndex] = {\n ...toolPart,\n providerMetadata: providerMeta,\n toolInvocation: {\n state: 'output-error',\n toolCallId,\n toolName,\n args,\n errorText,\n ...(chunk.from === 'AGENT' ? { result: toolPart.toolInvocation.result } : {}),\n } as MastraToolInvocation,\n };\n } else {\n const resultObj = payloadResult as { result?: { steps?: unknown }; childMessages?: unknown } | undefined;\n // A workflow tool-result is a *finalization* event, not a replacement.\n // The accumulated `WorkflowStreamResult` (steps, status, etc.) was\n // built up by prior `tool-output` chunks via\n // `mapWorkflowStreamChunkToWatchResult`. The terminal `tool-result`\n // payload for dynamic workflows is often just `{ result: <scalar>, runId }`\n // with no `steps` field, so detecting workflows purely from the new\n // payload would clobber that state. Also check the tool name and any\n // previously-accumulated `WorkflowStreamResult`-shaped result.\n const existingResult =\n toolPart.toolInvocation.state === 'partial-call' || toolPart.toolInvocation.state === 'result'\n ? (toolPart.toolInvocation as { result?: unknown }).result\n : undefined;\n const existingLooksLikeWorkflow = Boolean(\n existingResult && typeof existingResult === 'object' && 'steps' in (existingResult as object),\n );\n const isWorkflow =\n Boolean(resultObj?.result?.steps) || toolName?.startsWith('workflow-') || existingLooksLikeWorkflow;\n const isAgent = chunk.from === 'AGENT';\n let output: unknown;\n if (isWorkflow) {\n // Prefer merging the terminal payload into the accumulated\n // workflow state so the UI keeps its step history.\n const accumulated =\n existingLooksLikeWorkflow && existingResult && typeof existingResult === 'object'\n ? (existingResult as Record<string, unknown>)\n : undefined;\n const payloadWorkflow =\n resultObj?.result && typeof resultObj.result === 'object'\n ? (resultObj.result as Record<string, unknown>)\n : undefined;\n if (accumulated || payloadWorkflow) {\n output = {\n ...(accumulated ?? {}),\n ...(payloadWorkflow ?? {}),\n // Preserve `steps` from accumulated state when the terminal\n // payload doesn't carry them.\n steps: (payloadWorkflow?.steps as unknown) ?? (accumulated?.steps as unknown) ?? [],\n status: (payloadWorkflow?.status as unknown) ?? (accumulated?.status as unknown) ?? 'success',\n // Surface the terminal scalar output without losing history.\n output: payloadResult,\n };\n } else {\n output = payloadResult;\n }\n } else if (isAgent) {\n const existingOutput =\n toolPart.toolInvocation.state === 'partial-call' || toolPart.toolInvocation.state === 'result'\n ? toolPart.toolInvocation.result\n : undefined;\n const existingChild = (existingOutput as { childMessages?: unknown[] } | undefined)?.childMessages;\n output = existingOutput\n ? {\n ...(payloadResult as object),\n childMessages: existingChild?.length ? existingChild : resultObj?.childMessages,\n }\n : payloadResult;\n } else {\n output = payloadResult;\n }\n\n parts[toolPartIndex] = {\n ...toolPart,\n providerMetadata: providerMeta,\n toolInvocation: {\n state: 'result',\n toolCallId,\n toolName,\n args,\n result: output,\n } as MastraToolInvocation,\n };\n }\n }\n\n const nextMetadata = mergeBgTaskMetadata(\n targetMessage.content.metadata as MastraDBMessageMetadata | undefined,\n metadata.mode,\n {\n resetRunningCount: isBgTaskEvent,\n perTaskEntry:\n isBgTaskEvent && payloadTaskId\n ? {\n toolCallId: chunk.payload.toolCallId,\n completedAt: payloadCompletedAt,\n taskId: payloadTaskId,\n }\n : undefined,\n },\n );\n\n const nextMessage: MastraDBMessage = {\n ...targetMessage,\n content: {\n ...targetMessage.content,\n parts,\n metadata: nextMetadata,\n },\n };\n\n return replaceAt(result, messageIndex, nextMessage);\n }\n\n case 'background-task-running': {\n const location = locateToolPart(result, chunk.payload.toolCallId, true);\n if (!location) return result;\n const { messageIndex } = location;\n const targetMessage = result[messageIndex];\n if (!targetMessage || targetMessage.role !== 'assistant') return result;\n\n const nextMetadata = mergeBgTaskMetadata(\n targetMessage.content.metadata as MastraDBMessageMetadata | undefined,\n metadata.mode,\n {\n perTaskEntry: {\n toolCallId: chunk.payload.toolCallId,\n startedAt: chunk.payload.startedAt,\n taskId: chunk.payload.taskId,\n },\n },\n );\n\n return replaceAt(result, messageIndex, withMetadata(targetMessage, nextMetadata));\n }\n\n case 'tool-output':\n case 'background-task-output': {\n const isBgTaskOutput = chunk.type === 'background-task-output';\n const location = locateToolPart(result, chunk.payload.toolCallId, isBgTaskOutput);\n if (!location || location.toolPartIndex < 0) return result;\n const { messageIndex, toolPartIndex } = location;\n const targetMessage = result[messageIndex];\n if (!targetMessage || targetMessage.role !== 'assistant') return result;\n\n const parts = [...targetMessage.content.parts];\n const toolPart = parts[toolPartIndex];\n if (!isToolPart(toolPart)) return result;\n\n const { toolName, toolCallId, args } = toolPart.toolInvocation;\n const payloadOutput =\n chunk.type === 'background-task-output' ? chunk.payload.payload.payload.output : chunk.payload.output;\n\n // Workflow stream output: accumulate into watch-result state\n if (payloadOutput?.type?.startsWith('workflow-')) {\n const existingWorkflowState = (toolPart.toolInvocation as any).result as\n | WorkflowStreamResult<any, any, any, any>\n | undefined;\n const updated = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, payloadOutput);\n\n parts[toolPartIndex] = {\n ...toolPart,\n toolInvocation: {\n state: 'partial-call',\n toolCallId,\n toolName,\n args,\n result: updated,\n } as MastraToolInvocation,\n };\n } else if (toolName.startsWith('agent-') || payloadOutput?.from === 'AGENT') {\n const normalized = normalizeNestedAgentOutput(payloadOutput);\n if (!normalized) return result;\n\n const { leaf, boundaries } = normalized;\n if (\n leaf.from === 'AGENT' ||\n (leaf.type === 'tool-output' && leaf.payload?.output?.type?.startsWith('workflow-'))\n ) {\n return accumulateAgentChunk(leaf, result, metadata, toolCallId, toolName, boundaries);\n }\n return result;\n } else {\n const currentResult = (toolPart.toolInvocation as any).result;\n const existing = Array.isArray(currentResult) ? currentResult : [];\n parts[toolPartIndex] = {\n ...toolPart,\n toolInvocation: {\n state: 'partial-call',\n toolCallId,\n toolName,\n args,\n result: [...existing, payloadOutput],\n } as MastraToolInvocation,\n };\n }\n\n return replaceAt(result, messageIndex, withParts(targetMessage, parts));\n }\n\n case 'is-task-complete': {\n if (chunk.payload.suppressFeedback) return result;\n\n const feedback = formatStreamCompletionFeedback(\n {\n complete: chunk.payload.passed,\n scorers: chunk.payload.results,\n totalDuration: chunk.payload.duration,\n timedOut: chunk.payload.timedOut,\n completionReason: chunk.payload.reason,\n },\n chunk.payload.maxIterationReached,\n );\n\n const newMessage = newAssistantMessage(\n `is-task-complete-${chunk.runId + Date.now()}`,\n [{ type: 'text', text: feedback } as MastraMessagePart],\n {\n ...metadata,\n completionResult: { passed: chunk.payload.passed },\n },\n );\n return [...result, newMessage];\n }\n\n case 'source': {\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') return result;\n\n const parts = [...lastMessage.content.parts];\n if (chunk.payload.sourceType === 'url') {\n // Flat V5 `source-url` shape (see boundary cast policy above). Typed as\n // the shared `AIV5Type.SourceUrlUIPart` so the literal is shape-checked,\n // then stored via the storage-boundary cast like the other V5 parts.\n const sourceUrlPart: AIV5Type.SourceUrlUIPart = {\n type: 'source-url',\n sourceId: chunk.payload.id,\n url: chunk.payload.url || '',\n title: chunk.payload.title,\n providerMetadata: chunk.payload.providerMetadata,\n };\n parts.push(sourceUrlPart as unknown as MastraMessagePart);\n } else if (chunk.payload.sourceType === 'document') {\n parts.push({\n type: 'source-document',\n sourceId: chunk.payload.id,\n mediaType: chunk.payload.mimeType || 'application/octet-stream',\n title: chunk.payload.title,\n filename: chunk.payload.filename,\n providerMetadata: chunk.payload.providerMetadata,\n } as MastraMessagePart);\n }\n\n return replaceLast(result, withParts(lastMessage, parts));\n }\n\n case 'file': {\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') return result;\n\n const parts = [...lastMessage.content.parts];\n\n let data: string;\n if (typeof chunk.payload.data === 'string') {\n data = chunk.payload.base64\n ? `data:${chunk.payload.mimeType};base64,${chunk.payload.data}`\n : `data:${chunk.payload.mimeType},${encodeURIComponent(chunk.payload.data)}`;\n } else {\n const base64 = uint8ArrayToBase64(chunk.payload.data);\n data = `data:${chunk.payload.mimeType};base64,${base64}`;\n }\n\n parts.push({\n type: 'file',\n mimeType: chunk.payload.mimeType,\n data,\n providerMetadata: chunk.payload.providerMetadata,\n } as unknown as MastraMessagePart);\n\n return replaceLast(result, withParts(lastMessage, parts));\n }\n\n case 'tool-call-approval': {\n const lastMessage = result[result.length - 1];\n if (!lastMessage || lastMessage.role !== 'assistant') return result;\n\n const existingMeta = (lastMessage.content.metadata as MastraDBMessageMetadata | undefined) ?? {};\n const lastRequireApproval = existingMeta.mode === 'stream' ? (existingMeta.requireApprovalMetadata ?? {}) : {};\n\n return replaceLast(result, {\n ...lastMessage,\n content: {\n ...lastMessage.content,\n metadata: {\n ...existingMeta,\n mode: 'stream',\n requireApprovalMetadata: {\n ...lastRequireApproval,\n [chunk.payload.toolCallId]: {\n toolCallId: chunk.payload.toolCallId,\n toolName: chunk.payload.toolName,\n args: chunk.payload.args as Record<string, unknown>,\n },\n },\n },\n },\n });\n }\n\n case 'tool-call-suspended':\n case 'background-task-suspended': {\n const isBgTaskEvent = chunk.type === 'background-task-suspended';\n // Narrow merged payloads explicitly. Both shapes carry the fields below.\n let suspToolCallId: string;\n let suspToolName: string;\n let suspArgs: Record<string, unknown>;\n let suspPayload: unknown;\n let suspSuspendedAt: Date | undefined;\n let suspTaskId: string | undefined;\n if (chunk.type === 'background-task-suspended') {\n suspToolCallId = chunk.payload.toolCallId;\n suspToolName = chunk.payload.toolName;\n suspArgs = chunk.payload.args;\n suspPayload = chunk.payload.suspendPayload;\n suspSuspendedAt = chunk.payload.suspendedAt;\n suspTaskId = chunk.payload.taskId;\n } else {\n suspToolCallId = chunk.payload.toolCallId;\n suspToolName = chunk.payload.toolName;\n suspArgs = chunk.payload.args as Record<string, unknown>;\n suspPayload = chunk.payload.suspendPayload;\n }\n\n const location = isBgTaskEvent\n ? locateToolPart(result, suspToolCallId, true)\n : { messageIndex: result.length - 1 };\n if (!location) return result;\n const { messageIndex } = location;\n const targetMessage = result[messageIndex];\n if (!targetMessage || targetMessage.role !== 'assistant') return result;\n\n const existingMeta = (targetMessage.content.metadata as MastraDBMessageMetadata | undefined) ?? {};\n const lastSuspendedTools = existingMeta.mode === 'stream' ? (existingMeta.suspendedTools ?? {}) : {};\n\n const nextMetadata = mergeBgTaskMetadata(\n existingMeta,\n 'stream',\n {\n resetRunningCount: isBgTaskEvent,\n perTaskEntry:\n isBgTaskEvent && suspTaskId\n ? {\n toolCallId: suspToolCallId,\n suspendedAt: suspSuspendedAt,\n taskId: suspTaskId,\n }\n : undefined,\n },\n {\n suspendedTools: {\n ...lastSuspendedTools,\n [suspToolName]: {\n toolCallId: suspToolCallId,\n toolName: suspToolName,\n args: suspArgs,\n suspendPayload: suspPayload,\n runId: chunk.runId,\n },\n },\n },\n );\n\n return replaceAt(result, messageIndex, withMetadata(targetMessage, nextMetadata));\n }\n\n case 'tool-call-resumed': {\n const resumedToolCallId = chunk.payload.toolCallId;\n for (let i = result.length - 1; i >= 0; i--) {\n const message = result[i];\n if (!message || message.role !== 'assistant') continue;\n const meta = message.content.metadata as MastraDBMessageMetadata | undefined;\n // Hydrated messages carry `pendingToolApprovals`; live ones carry `requireApprovalMetadata`.\n const metadataKeys =\n chunk.payload.kind === 'approval'\n ? (['pendingToolApprovals', 'requireApprovalMetadata'] as const)\n : (['suspendedTools'] as const);\n let nextMeta: Record<string, any> | undefined;\n for (const metadataKey of metadataKeys) {\n const entries = meta?.[metadataKey] as Record<string, { toolCallId?: string }> | undefined;\n if (!entries) continue;\n const key = Object.keys(entries).find(k => (entries[k]?.toolCallId ?? k) === resumedToolCallId);\n if (!key) continue;\n const { [key]: _removed, ...remaining } = entries;\n nextMeta = { ...(nextMeta ?? meta), [metadataKey]: remaining };\n }\n if (nextMeta) return replaceAt(result, i, withMetadata(message, nextMeta as MastraDBMessageMetadata));\n }\n return result;\n }\n\n case 'finish':\n case 'abort': {\n return finishStreamingAssistantMessage(result);\n }\n\n case 'error': {\n const newMessage = newAssistantMessage(\n `error-${chunk.runId + Date.now()}`,\n [\n {\n type: 'text',\n text: typeof chunk.payload.error === 'string' ? chunk.payload.error : JSON.stringify(chunk.payload.error),\n } as MastraMessagePart,\n ],\n {\n ...metadata,\n status: 'error',\n },\n );\n return [...result, newMessage];\n }\n\n // ----- Rotated response message ids (`step-start.payload.messageId` carries\n // the id the following step's output is persisted under; processors like\n // observational memory can rotate it mid-run) -----\n case 'step-start': {\n const stepMessageId = typeof chunk.payload?.messageId === 'string' ? chunk.payload.messageId : undefined;\n if (!stepMessageId) return result;\n\n const lastMessage = result[result.length - 1];\n if (result.some(message => message.id === stepMessageId)) return result;\n if (!lastMessage || lastMessage.role !== 'assistant') {\n return appendAssistantMessage(result, stepMessageId, [], metadata);\n }\n\n // Re-key the pending message in place while it only holds `data-*` parts\n // (they belong to the run, not a persisted row); once model content has\n // streamed under the previous id, split into a new message instead.\n const hasModelContent = lastMessage.content.parts.some(part => !String(part.type).startsWith('data-'));\n if (!hasModelContent) {\n return replaceLast(result, { ...lastMessage, id: stepMessageId });\n }\n\n return appendAssistantMessage(finishStreamingAssistantMessage(result), stepMessageId, [], metadata);\n }\n\n // ----- Lifecycle / step / framing chunks (not surfaced on DB messages) -----\n case 'step-finish':\n case 'step-output':\n case 'raw':\n case 'watch':\n case 'response-metadata':\n return result;\n\n // ----- Goal evaluation signal (feedback is already injected into the\n // message history by the core goal step; the chunk is a consumer-only\n // signal and is not surfaced as its own DB message). -----\n case 'goal':\n return result;\n\n // ----- Object chunks (object/object-result are not stored on DB messages) -----\n case 'object':\n case 'object-result':\n return result;\n\n // ----- Background-task lifecycle markers not folded into messages -----\n case 'background-task-started':\n case 'background-task-cancelled':\n case 'background-task-resumed':\n return result;\n\n // ----- Workflow lifecycle passthroughs (handled by mapWorkflowStreamChunkToWatchResult inside tool-output) -----\n case 'workflow-start':\n case 'workflow-finish':\n case 'workflow-canceled':\n case 'workflow-paused':\n case 'workflow-step-start':\n case 'workflow-step-finish':\n case 'workflow-step-suspended':\n case 'workflow-step-waiting':\n case 'workflow-step-output':\n case 'workflow-step-progress':\n case 'workflow-step-result':\n return result;\n\n // ----- Nested-execution / routing / network passthroughs -----\n case 'agent-execution-start':\n case 'agent-execution-approval':\n case 'agent-execution-suspended':\n case 'agent-execution-end':\n case 'agent-execution-abort':\n case 'tool-execution-start':\n case 'tool-execution-end':\n case 'tool-execution-approval':\n case 'tool-execution-suspended':\n case 'tool-execution-abort':\n case 'routing-agent-start':\n case 'routing-agent-text-delta':\n case 'routing-agent-text-start':\n case 'routing-agent-end':\n case 'routing-agent-abort':\n case 'workflow-execution-start':\n case 'workflow-execution-end':\n case 'workflow-execution-suspended':\n case 'workflow-execution-abort':\n case 'network-execution-event-step-finish':\n case 'network-execution-event-finish':\n case 'network-validation-start':\n case 'network-validation-end':\n case 'network-object':\n case 'network-object-result':\n return result;\n\n default:\n // Exhaustiveness check: any new `ChunkType` variant must be added above.\n return assertExhaustive(chunk as never, result);\n }\n};\n\n/**\n * Compile-time exhaustiveness helper. At runtime, returns the conversation\n * unchanged so unexpected chunk variants never throw inside the React stream\n * pump; TypeScript will fail to compile if `ChunkType` ever grows a new branch\n * that isn't enumerated above.\n */\nconst assertExhaustive = (_chunk: never, fallback: MastraDBMessage[]): MastraDBMessage[] => fallback;\n\n// ----- Nested agent-chunk accumulation (mirrors `toUIMessageFromAgent`) -----\n\nconst findAgentChildToolIndex = (\n childMessages: AgentChildMessage[],\n toolCallId?: string,\n toolName?: string,\n): number => {\n for (let index = childMessages.length - 1; index >= 0; index--) {\n const message = childMessages[index];\n if (message?.type !== 'tool') continue;\n if (toolCallId ? message.toolCallId === toolCallId : toolName && message.toolName === toolName) return index;\n }\n return -1;\n};\n\nconst accumulateAgentChildMessages = (\n chunk: AgentChunkType,\n childMessages: AgentChildMessage[],\n): AgentChildMessage[] => {\n if (chunk.type === 'text-delta') {\n const text = chunk.payload.text;\n const lastChildMessage = childMessages[childMessages.length - 1];\n const textMessage: AgentChildMessage = {\n type: 'text',\n content: (lastChildMessage?.type === 'text' ? lastChildMessage.content : '') + text,\n };\n return lastChildMessage?.type === 'text'\n ? [...childMessages.slice(0, -1), textMessage]\n : [...childMessages, textMessage];\n }\n\n if (chunk.type === 'tool-call') {\n const existingIndex = findAgentChildToolIndex(childMessages, chunk.payload.toolCallId);\n const toolMessage: AgentChildMessage = {\n ...(existingIndex === -1 ? {} : childMessages[existingIndex]),\n type: 'tool',\n toolCallId: chunk.payload.toolCallId,\n toolName: chunk.payload.toolName,\n args: chunk.payload.args,\n };\n if (existingIndex === -1) return [...childMessages, toolMessage];\n\n const nextMessages = [...childMessages];\n nextMessages[existingIndex] = toolMessage;\n return nextMessages;\n }\n\n if (chunk.type === 'tool-output' && chunk.payload.output?.type?.startsWith('workflow-')) {\n const toolIndex = findAgentChildToolIndex(childMessages, chunk.payload.toolCallId, chunk.payload.toolName);\n if (toolIndex === -1) return childMessages;\n\n const currentMessage = childMessages[toolIndex];\n if (currentMessage?.type !== 'tool') return childMessages;\n const existingWorkflowState =\n currentMessage.toolOutput && typeof currentMessage.toolOutput === 'object'\n ? (currentMessage.toolOutput as WorkflowStreamResult<any, any, any, any>)\n : ({} as WorkflowStreamResult<any, any, any, any>);\n const updated = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, chunk.payload.output);\n const nextMessages = [...childMessages];\n nextMessages[toolIndex] = {\n ...currentMessage,\n toolOutput: { ...updated, runId: chunk.payload.output.runId },\n };\n return nextMessages;\n }\n\n if (chunk.type === 'tool-result') {\n const toolIndex = findAgentChildToolIndex(childMessages, chunk.payload.toolCallId, chunk.payload.toolName);\n if (toolIndex === -1) return childMessages;\n\n const currentMessage = childMessages[toolIndex];\n if (currentMessage?.type !== 'tool') return childMessages;\n const result = chunk.payload.result as { result?: object; runId?: string } | undefined;\n const nextMessages = [...childMessages];\n nextMessages[toolIndex] = {\n ...currentMessage,\n toolOutput: chunk.payload.toolName?.startsWith('workflow-')\n ? { ...(result?.result ?? {}), runId: result?.runId }\n : chunk.payload.result,\n };\n return nextMessages;\n }\n\n return childMessages;\n};\n\nconst routeAgentChunk = (\n chunk: AgentChunkType,\n childMessages: AgentChildMessage[],\n boundaries: AgentDelegationBoundary[],\n): AgentChildMessage[] => {\n const [boundary, ...remaining] = boundaries;\n if (!boundary) return accumulateAgentChildMessages(chunk, childMessages);\n\n let toolIndex = findAgentChildToolIndex(childMessages, boundary.toolCallId, boundary.toolName);\n let nextMessages = childMessages;\n if (toolIndex === -1) {\n toolIndex = childMessages.length;\n nextMessages = [\n ...childMessages,\n {\n type: 'tool',\n toolCallId: boundary.toolCallId,\n toolName: boundary.toolName,\n args: {},\n },\n ];\n }\n\n const currentMessage = nextMessages[toolIndex];\n if (currentMessage?.type !== 'tool' || !currentMessage.toolName.startsWith('agent-')) return childMessages;\n\n const currentOutput =\n currentMessage.toolOutput !== null && typeof currentMessage.toolOutput === 'object'\n ? (currentMessage.toolOutput as Record<string, unknown>)\n : {};\n const nestedMessages = Array.isArray(currentOutput.childMessages)\n ? (currentOutput.childMessages as AgentChildMessage[])\n : [];\n const updatedNestedMessages = routeAgentChunk(chunk, nestedMessages, remaining);\n if (updatedNestedMessages === nestedMessages) return childMessages;\n\n const updatedMessages = [...nextMessages];\n updatedMessages[toolIndex] = {\n ...currentMessage,\n toolOutput: { ...currentOutput, childMessages: updatedNestedMessages },\n };\n return updatedMessages;\n};\n\nconst accumulateAgentChunk = (\n chunk: AgentChunkType,\n conversation: MastraDBMessage[],\n _metadata: MastraDBMessageMetadata,\n parentToolCallId?: string,\n parentToolName?: string,\n boundaries: AgentDelegationBoundary[] = [],\n): MastraDBMessage[] => {\n if (!parentToolCallId) return conversation;\n const location = locateToolPart(conversation, parentToolCallId, false);\n if (!location) return conversation;\n\n const targetMessage = conversation[location.messageIndex];\n if (!targetMessage || targetMessage.role !== 'assistant') return conversation;\n const parts = [...targetMessage.content.parts];\n const toolPart = parts[location.toolPartIndex];\n if (!toolPart || !isToolPart(toolPart)) return conversation;\n if (parentToolName && toolPart.toolInvocation.toolName !== parentToolName) return conversation;\n\n const invocationResult =\n 'result' in toolPart.toolInvocation && toolPart.toolInvocation.result !== null\n ? toolPart.toolInvocation.result\n : undefined;\n const existingResult =\n invocationResult && typeof invocationResult === 'object' ? (invocationResult as Record<string, unknown>) : {};\n const childMessages = Array.isArray(existingResult.childMessages)\n ? (existingResult.childMessages as AgentChildMessage[])\n : [];\n const updatedChildMessages = routeAgentChunk(chunk, childMessages, boundaries);\n if (updatedChildMessages === childMessages) return conversation;\n\n parts[location.toolPartIndex] = {\n ...toolPart,\n toolInvocation: {\n ...toolPart.toolInvocation,\n state: 'partial-call',\n result: { ...existingResult, childMessages: updatedChildMessages },\n } as MastraToolInvocation,\n };\n\n return replaceAt(conversation, location.messageIndex, withParts(targetMessage, parts));\n};\n\nexport interface AccumulateNetworkChunkArgs {\n chunk: NetworkChunkType;\n conversation: MastraDBMessage[];\n metadata: MastraDBMessageMetadata;\n}\n\n// Network-mode helpers\n// --------------------\n// These mirror the historical `AISdkNetworkTransformer` from the AI-SDK layer,\n// translating `NetworkChunkType` into `MastraDBMessage[]`. The transformer's\n// `MastraUIMessage` model (`{ parts, metadata }`) maps onto `MastraDBMessage`\n// (`content.parts` / `content.metadata`). Text and `dynamic-tool` parts are\n// stored as the same V5-flavored superset of `MastraMessagePart` documented in\n// the boundary-cast policy at the top of this file. This is a temporary bridge\n// to keep network mode rendering until the next major.\n\nconst networkMode = (metadata: MastraDBMessageMetadata): MastraDBMessageMetadata => ({ ...metadata, mode: 'network' });\n\nconst findPartIndex = (parts: MastraMessagePart[], predicate: (part: MastraMessagePart) => boolean): number =>\n parts.findIndex(predicate);\n\n// `dynamic-tool` is a V5 part type stored via the boundary-cast policy; it is\n// not present in the V4 `MastraMessagePart` union, so match on the raw string.\nconst isDynamicToolPart = (part: MastraMessagePart): boolean => (part as { type: string }).type === 'dynamic-tool';\n\nconst lastAssistant = (conversation: MastraDBMessage[]): MastraDBMessage | undefined => {\n const last = conversation[conversation.length - 1];\n return last && last.role === 'assistant' ? last : undefined;\n};\n\n/**\n * Try to parse the buffered routing-agent text as a JSON object. Returns the\n * parsed object on success, or `null` while the buffer is still incomplete or\n * not JSON at all.\n */\nconst tryParseRoutingDecision = (buffered: string): Record<string, unknown> | null => {\n const trimmed = buffered.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return null;\n try {\n const parsed = JSON.parse(trimmed);\n if (parsed && typeof parsed === 'object') {\n return parsed as Record<string, unknown>;\n }\n return null;\n } catch {\n return null;\n }\n};\n\n/**\n * Routing-agent text deltas describe the network's routing decision (often a\n * JSON object such as `{ \"isNetwork\": true, \"agentId\": \"...\", ... }`). The raw\n * payload is never useful in the rendered thread, so we buffer it in\n * message-level metadata, promote it to `routingDecision` when it parses as\n * JSON, and fall back to `routingDecisionText` for non-JSON routing models.\n * No visible text part is produced.\n */\nconst handleRoutingAgentDelta = (\n chunk: NetworkChunkType,\n conversation: MastraDBMessage[],\n metadata: MastraDBMessageMetadata,\n): MastraDBMessage[] => {\n const delta = (chunk.payload as { text?: string })?.text ?? '';\n if (!delta) return conversation;\n\n const lastMessage = lastAssistant(conversation);\n\n const mergeRoutingMetadata = (existing: MastraDBMessageMetadata): MastraDBMessageMetadata => {\n const buffered = (existing.routingDecisionBuffer ?? '') + delta;\n const next: MastraDBMessageMetadata = { ...cloneMetadata(existing), mode: 'network' };\n const parsed = tryParseRoutingDecision(buffered);\n if (parsed) {\n next.routingDecision = parsed;\n delete next.routingDecisionBuffer;\n delete next.routingDecisionText;\n } else {\n next.routingDecisionBuffer = buffered;\n next.routingDecisionText = buffered;\n }\n return next;\n };\n\n if (!lastMessage) {\n const seed = mergeRoutingMetadata({});\n return appendAssistantMessage(\n conversation,\n `routing-agent-${(chunk.payload as { runId?: string })?.runId ?? 'unknown'}-${Date.now()}`,\n [],\n { ...networkMode(metadata), ...seed },\n );\n }\n\n return replaceLast(conversation, withMetadata(lastMessage, mergeRoutingMetadata(lastMessage.content.metadata ?? {})));\n};\n\nconst handleAgentNetworkChunk = (\n chunk: NetworkChunkType,\n conversation: MastraDBMessage[],\n metadata: MastraDBMessageMetadata,\n): MastraDBMessage[] => {\n if (chunk.type === 'agent-execution-start') {\n const primitiveId = (chunk.payload as any)?.args?.primitiveId;\n const runId = (chunk.payload as any).runId;\n if (!primitiveId || !runId) return conversation;\n\n const toolPart = {\n type: 'dynamic-tool',\n toolName: primitiveId,\n toolCallId: runId,\n state: 'input-available',\n input: (chunk.payload as any).args,\n } as unknown as MastraMessagePart;\n\n return appendAssistantMessage(conversation, `agent-execution-start-${runId}-${Date.now()}`, [toolPart], {\n ...networkMode(metadata),\n selectionReason: (chunk.payload as any)?.args?.selectionReason || '',\n agentInput: (chunk.payload as any)?.args?.task,\n from: 'AGENT',\n });\n }\n\n if (chunk.type === 'agent-execution-end') {\n const lastMessage = lastAssistant(conversation);\n if (!lastMessage) return conversation;\n\n const parts = [...lastMessage.content.parts];\n const toolPartIndex = findPartIndex(parts, part => isDynamicToolPart(part));\n if (toolPartIndex !== -1) {\n const toolPart = parts[toolPartIndex] as any;\n const currentOutput = toolPart.output as any;\n parts[toolPartIndex] = {\n type: 'dynamic-tool',\n toolName: toolPart.toolName,\n toolCallId: toolPart.toolCallId,\n state: 'output-available',\n input: toolPart.input,\n output: { ...currentOutput, result: currentOutput?.result || (chunk.payload as any)?.result || '' },\n } as unknown as MastraMessagePart;\n }\n\n return replaceLast(conversation, withParts(lastMessage, parts));\n }\n\n if (chunk.type.startsWith('agent-execution-event-')) {\n const lastMessage = lastAssistant(conversation);\n if (!lastMessage) return conversation;\n\n const agentChunk = chunk.payload as any;\n const parts = [...lastMessage.content.parts];\n const toolPartIndex = findPartIndex(parts, part => isDynamicToolPart(part));\n if (toolPartIndex === -1) return conversation;\n const toolPart = parts[toolPartIndex] as any;\n\n if (agentChunk.type === 'text-delta') {\n const childMessages = toolPart?.output?.childMessages || [];\n const lastChildMessage = childMessages[childMessages.length - 1];\n const textMessage = { type: 'text', content: (lastChildMessage?.content || '') + agentChunk.payload.text };\n const nextMessages =\n lastChildMessage?.type === 'text'\n ? [...childMessages.slice(0, -1), textMessage]\n : [...childMessages, textMessage];\n parts[toolPartIndex] = {\n ...toolPart,\n output: { childMessages: nextMessages },\n } as unknown as MastraMessagePart;\n } else if (agentChunk.type === 'tool-call') {\n const childMessages = toolPart?.output?.childMessages || [];\n parts[toolPartIndex] = {\n ...toolPart,\n output: {\n ...toolPart?.output,\n childMessages: [\n ...childMessages,\n {\n type: 'tool',\n toolCallId: agentChunk.payload.toolCallId,\n toolName: agentChunk.payload.toolName,\n args: agentChunk.payload.args,\n },\n ],\n },\n } as unknown as MastraMessagePart;\n } else if (agentChunk.type === 'tool-output') {\n if (agentChunk.payload?.output?.type?.startsWith('workflow-')) {\n const childMessages = toolPart?.output?.childMessages || [];\n const lastToolIndex = childMessages.length - 1;\n const currentMessage = childMessages[lastToolIndex];\n const actualExistingWorkflowState = currentMessage?.toolOutput || {};\n const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(\n actualExistingWorkflowState,\n agentChunk.payload.output,\n );\n if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === 'tool') {\n parts[toolPartIndex] = {\n ...toolPart,\n output: {\n ...toolPart?.output,\n childMessages: [...childMessages.slice(0, -1), { ...currentMessage, toolOutput: updatedWorkflowState }],\n },\n } as unknown as MastraMessagePart;\n }\n }\n } else if (agentChunk.type === 'tool-result') {\n const childMessages = toolPart?.output?.childMessages || [];\n const lastToolIndex = childMessages.length - 1;\n const isWorkflow = Boolean(agentChunk.payload?.result?.result?.steps);\n if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === 'tool') {\n parts[toolPartIndex] = {\n ...toolPart,\n output: {\n ...toolPart?.output,\n childMessages: [\n ...childMessages.slice(0, -1),\n {\n ...childMessages[lastToolIndex],\n toolOutput: isWorkflow ? agentChunk.payload.result.result : agentChunk.payload.result,\n },\n ],\n },\n } as unknown as MastraMessagePart;\n }\n }\n\n return replaceLast(conversation, withParts(lastMessage, parts));\n }\n\n return conversation;\n};\n\nconst handleWorkflowNetworkChunk = (\n chunk: NetworkChunkType,\n conversation: MastraDBMessage[],\n metadata: MastraDBMessageMetadata,\n): MastraDBMessage[] => {\n if (chunk.type === 'workflow-execution-start') {\n const primitiveId = (chunk.payload as any)?.args?.primitiveId;\n const runId = (chunk.payload as any).runId;\n if (!primitiveId || !runId) return conversation;\n\n let agentInput: string | object;\n try {\n agentInput = JSON.parse((chunk.payload as any)?.args?.prompt);\n } catch {\n agentInput = (chunk.payload as any)?.args?.prompt;\n }\n\n const toolPart = {\n type: 'dynamic-tool',\n toolName: primitiveId,\n toolCallId: runId,\n state: 'input-available',\n input: (chunk.payload as any).args,\n } as unknown as MastraMessagePart;\n\n return appendAssistantMessage(conversation, `workflow-start-${runId}-${Date.now()}`, [toolPart], {\n ...networkMode(metadata),\n selectionReason: (chunk.payload as any)?.args?.selectionReason || '',\n from: 'WORKFLOW',\n agentInput,\n });\n }\n\n if (chunk.type === 'workflow-execution-suspended') {\n const lastMessage = lastAssistant(conversation);\n if (!lastMessage) return conversation;\n const existing = lastMessage.content.metadata?.suspendedTools ?? {};\n return replaceLast(\n conversation,\n withMetadata(lastMessage, {\n ...cloneMetadata(lastMessage.content.metadata),\n mode: 'network',\n suspendedTools: {\n ...existing,\n [(chunk.payload as any).toolName]: {\n toolCallId: (chunk.payload as any).toolCallId,\n toolName: (chunk.payload as any).toolName,\n args: (chunk.payload as any).args,\n suspendPayload: (chunk.payload as any).suspendPayload,\n runId: (chunk.payload as any).runId,\n },\n },\n }),\n );\n }\n\n if (chunk.type.startsWith('workflow-execution-event-')) {\n const lastMessage = lastAssistant(conversation);\n if (!lastMessage) return conversation;\n\n const parts = [...lastMessage.content.parts];\n const toolPartIndex = findPartIndex(parts, part => isDynamicToolPart(part));\n if (toolPartIndex === -1) return conversation;\n const toolPart = parts[toolPartIndex] as any;\n\n const existingWorkflowState = (toolPart.output as WorkflowStreamResult<any, any, any, any>) || ({} as any);\n const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, chunk.payload as any);\n\n parts[toolPartIndex] = { ...toolPart, output: updatedWorkflowState } as unknown as MastraMessagePart;\n return replaceLast(conversation, withParts(lastMessage, parts));\n }\n\n return conversation;\n};\n\nconst handleToolNetworkChunk = (\n chunk: NetworkChunkType,\n conversation: MastraDBMessage[],\n metadata: MastraDBMessageMetadata,\n): MastraDBMessage[] => {\n if (chunk.type === 'tool-execution-start') {\n const argsData = (chunk.payload as any).args;\n const nestedArgs = argsData.args || {};\n const lastMessage = lastAssistant(conversation);\n\n const toolPart = {\n type: 'dynamic-tool',\n toolName: argsData.toolName || 'unknown',\n toolCallId: argsData.toolCallId || 'unknown',\n state: 'input-available',\n input: nestedArgs,\n } as unknown as MastraMessagePart;\n\n if (!lastMessage) {\n return appendAssistantMessage(\n conversation,\n `tool-start-${(chunk.payload as any).runId}-${Date.now()}`,\n [toolPart],\n {\n ...networkMode(metadata),\n selectionReason: metadata.mode === 'network' ? metadata.selectionReason || argsData.selectionReason : '',\n agentInput: nestedArgs,\n },\n );\n }\n\n const parts = [...lastMessage.content.parts, toolPart];\n return replaceLast(conversation, withParts(lastMessage, parts));\n }\n\n if (chunk.type === 'tool-execution-approval') {\n const lastMessage = lastAssistant(conversation);\n if (!lastMessage) return conversation;\n const existing = lastMessage.content.metadata?.requireApprovalMetadata ?? {};\n return replaceLast(\n conversation,\n withMetadata(lastMessage, {\n ...cloneMetadata(lastMessage.content.metadata),\n mode: 'network',\n requireApprovalMetadata: {\n ...existing,\n [(chunk.payload as any).toolName]: {\n toolCallId: (chunk.payload as any).toolCallId,\n toolName: (chunk.payload as any).toolName,\n args: (chunk.payload as any).args,\n runId: (chunk.payload as any).runId,\n },\n },\n }),\n );\n }\n\n if (chunk.type === 'tool-execution-suspended') {\n const lastMessage = lastAssistant(conversation);\n if (!lastMessage) return conversation;\n const existing = lastMessage.content.metadata?.suspendedTools ?? {};\n return replaceLast(\n conversation,\n withMetadata(lastMessage, {\n ...cloneMetadata(lastMessage.content.metadata),\n mode: 'network',\n suspendedTools: {\n ...existing,\n [(chunk.payload as any).toolName]: {\n toolCallId: (chunk.payload as any).toolCallId,\n toolName: (chunk.payload as any).toolName,\n args: (chunk.payload as any).args,\n suspendPayload: (chunk.payload as any).suspendPayload,\n runId: (chunk.payload as any).runId,\n },\n },\n }),\n );\n }\n\n if (chunk.type === 'tool-execution-end') {\n const lastMessage = lastAssistant(conversation);\n if (!lastMessage) return conversation;\n\n const parts = [...lastMessage.content.parts];\n const toolPartIndex = findPartIndex(\n parts,\n part => isDynamicToolPart(part) && (part as any).toolCallId === (chunk.payload as any).toolCallId,\n );\n if (toolPartIndex !== -1) {\n const toolPart = parts[toolPartIndex] as any;\n const currentOutput = toolPart.output as any;\n parts[toolPartIndex] = {\n type: 'dynamic-tool',\n toolName: toolPart.toolName,\n toolCallId: toolPart.toolCallId,\n state: 'output-available',\n input: toolPart.input,\n output: currentOutput?.result || (chunk.payload as any)?.result || '',\n } as unknown as MastraMessagePart;\n }\n\n return replaceLast(conversation, withParts(lastMessage, parts));\n }\n\n return conversation;\n};\n\n/**\n * Reduce a single network-mode chunk into the running `MastraDBMessage[]`\n * conversation. Ports the historical `AISdkNetworkTransformer` so the playground\n * keeps rendering network badges (routing text, agent/workflow/tool execution,\n * suspensions, approvals, completion feedback) until the next major.\n */\nexport const accumulateNetworkChunk = ({\n chunk,\n conversation,\n metadata,\n}: AccumulateNetworkChunkArgs): MastraDBMessage[] => {\n const newConversation = [...conversation];\n\n if (chunk.type === 'routing-agent-text-delta') {\n return handleRoutingAgentDelta(chunk, newConversation, metadata);\n }\n\n if (chunk.type.startsWith('agent-execution-')) {\n return handleAgentNetworkChunk(chunk, newConversation, metadata);\n }\n\n if (chunk.type.startsWith('workflow-execution-')) {\n return handleWorkflowNetworkChunk(chunk, newConversation, metadata);\n }\n\n if (chunk.type.startsWith('tool-execution-')) {\n return handleToolNetworkChunk(chunk, newConversation, metadata);\n }\n\n if (chunk.type === 'network-validation-end') {\n if ((chunk.payload as any).suppressFeedback) return newConversation;\n\n const feedback = formatCompletionFeedback(\n {\n complete: (chunk.payload as any).passed,\n scorers: (chunk.payload as any).results,\n totalDuration: (chunk.payload as any).duration,\n timedOut: (chunk.payload as any).timedOut,\n completionReason: (chunk.payload as any).reason,\n },\n (chunk.payload as any).maxIterationReached,\n );\n\n const textPart = { type: 'text', text: feedback } as unknown as MastraMessagePart;\n return appendAssistantMessage(\n newConversation,\n `network-validation-end-${(chunk.payload as any).runId}-${Date.now()}`,\n [textPart],\n {\n ...networkMode(metadata),\n completionResult: { passed: (chunk.payload as any).passed },\n },\n );\n }\n\n if (chunk.type === 'network-execution-event-step-finish') {\n const lastMessage = lastAssistant(newConversation);\n if (!lastMessage) return newConversation;\n\n const agentChunk = chunk.payload as any;\n const parts = [...lastMessage.content.parts];\n const textPartIndex = findPartIndex(parts, part => part.type === 'text');\n\n if (textPartIndex === -1) {\n parts.push({ type: 'text', text: agentChunk.result, state: 'done' } as unknown as MastraMessagePart);\n return replaceLast(newConversation, withParts(lastMessage, parts));\n }\n\n const textPart = parts[textPartIndex];\n if (textPart.type === 'text') {\n parts[textPartIndex] = {\n ...(textPart as MastraTextPart),\n state: 'done',\n } as unknown as MastraMessagePart;\n return replaceLast(newConversation, withParts(lastMessage, parts));\n }\n\n return newConversation;\n }\n\n return newConversation;\n};\n\n// Re-export the provider-metadata helper for inspection in tests.\nexport { partProviderMetadata as __partProviderMetadata };\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["getOrCreate","useMastraClient","useCombineByIds","useMastraClient","useMastraClient","useMastraClient","useMastraClient","useInView"],"sources":["../../../src/hooks/experiments/use-experiment-item-usage.ts","../../../src/hooks/experiments/use-experiment-metrics.ts","../../../src/hooks/experiments/use-experiment-trace.ts","../../../src/hooks/experiments/use-experiments-for-dataset-filter.ts","../../../src/hooks/experiments/use-infinite-experiments.ts"],"sourcesContent":["import type { GetMetricBreakdownResponse } from '@mastra/core/storage';\nimport { useQueries } from '@tanstack/react-query';\nimport type { Query } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { ExperimentRef } from '../datasets/use-dataset-experiments';\nimport { useCombineByIds } from '../shared/combine-by-ids';\nimport type { ExperimentQueriesResult } from '../shared/combine-by-ids';\nimport { getOrCreate } from '../shared/map';\n\nconst INPUT_TOKEN_METRIC = 'mastra_model_total_input_tokens';\nconst OUTPUT_TOKEN_METRIC = 'mastra_model_total_output_tokens';\nconst POLL_INTERVAL_MS = 2000;\n\nexport interface ExperimentItemUsage {\n inputTokens?: number;\n outputTokens?: number;\n /** Undefined when no group is priced or when groups use different cost units. */\n estimatedCost?: number;\n costUnit?: string;\n}\n\n/** Usage of one experiment: its totals, and each item's usage keyed by the trace id of its run. */\nexport interface ExperimentUsage {\n /** Totals across every item. The cost sums priced groups only. */\n summary: ExperimentItemUsage;\n traces: Record<string, ExperimentItemUsage>;\n}\n\ntype UsageAccumulator = {\n inputTokens?: number;\n outputTokens?: number;\n estimatedCost: number;\n costUnits: Set<string>;\n hasUnknownCostUnit: boolean;\n};\n\nconst createAccumulator = (): UsageAccumulator => ({\n estimatedCost: 0,\n costUnits: new Set(),\n hasUnknownCostUnit: false,\n});\n\ntype BreakdownGroup = GetMetricBreakdownResponse['groups'][number];\n\nfunction accumulate(accumulator: UsageAccumulator, tokenField: 'inputTokens' | 'outputTokens', group: BreakdownGroup) {\n accumulator[tokenField] = (accumulator[tokenField] ?? 0) + group.value;\n\n if (group.estimatedCost == null) return;\n accumulator.estimatedCost += group.estimatedCost;\n if (group.costUnit) {\n accumulator.costUnits.add(group.costUnit.toLowerCase());\n } else {\n accumulator.hasUnknownCostUnit = true;\n }\n}\n\nfunction toUsage(accumulator: UsageAccumulator): ExperimentItemUsage {\n // A single known unit implies at least one priced group.\n const isPriced = !accumulator.hasUnknownCostUnit && accumulator.costUnits.size === 1;\n return {\n inputTokens: accumulator.inputTokens,\n outputTokens: accumulator.outputTokens,\n estimatedCost: isPriced ? accumulator.estimatedCost : undefined,\n costUnit: isPriced ? [...accumulator.costUnits][0] : undefined,\n };\n}\n\n/** Builds the experiment totals and the per-trace usage in a single pass over the groups. */\nfunction toExperimentUsage(response: GetMetricBreakdownResponse): ExperimentUsage {\n const summary = createAccumulator();\n const accumulators = new Map<string, UsageAccumulator>();\n\n for (const group of response.groups) {\n const metricName = group.dimensions.name;\n if (metricName !== INPUT_TOKEN_METRIC && metricName !== OUTPUT_TOKEN_METRIC) continue;\n\n const tokenField = metricName === INPUT_TOKEN_METRIC ? 'inputTokens' : 'outputTokens';\n accumulate(summary, tokenField, group);\n\n const traceId = group.dimensions.traceId;\n if (traceId) accumulate(getOrCreate(accumulators, traceId, createAccumulator), tokenField, group);\n }\n\n const traces: Record<string, ExperimentItemUsage> = {};\n for (const [traceId, accumulator] of accumulators) {\n traces[traceId] = toUsage(accumulator);\n }\n return { summary: toUsage(summary), traces };\n}\n\n/** How many breakdowns to fetch after completion while the exporter may still be flushing metrics. */\nconst MAX_EMPTY_ATTEMPTS = 5;\n\nconst isEmptyUsage = (usage: ExperimentUsage | undefined) =>\n !usage ||\n (Object.keys(usage.traces).length === 0 &&\n usage.summary.inputTokens === undefined &&\n usage.summary.outputTokens === undefined);\n\n/**\n * Token and cost usage of several experiments, keyed by experiment id: each entry holds the\n * experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).\n * Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,\n * so it does not wait for the experiment results. Usage is only fetched once an experiment has\n * finished; while the breakdown is still empty (metrics flushing), it retries every 2 seconds up to\n * 5 attempts. No request is made when the observability store cannot serve metrics.\n */\nexport const useExperimentsItemUsage = ({\n experiments,\n supportsMetrics,\n}: {\n experiments: ExperimentRef[];\n supportsMetrics: boolean;\n}): ExperimentQueriesResult<ExperimentUsage> => {\n const client = useMastraClient();\n const combine = useCombineByIds<ExperimentUsage>(experiments.map(experiment => experiment.id));\n\n return useQueries({\n queries: experiments.map(({ id, status }) => {\n const finished = status !== 'running' && status !== 'pending';\n return {\n queryKey: ['experiment-item-usage', id, finished],\n queryFn: async () =>\n toExperimentUsage(\n await client.getMetricBreakdown({\n name: [INPUT_TOKEN_METRIC, OUTPUT_TOKEN_METRIC],\n aggregation: 'sum',\n groupBy: ['traceId', 'name'],\n filters: { experimentId: id },\n }),\n ),\n enabled: supportsMetrics && finished,\n refetchInterval: (query: Query<ExperimentUsage>) =>\n isEmptyUsage(query.state.data) && query.state.dataUpdateCount < MAX_EMPTY_ATTEMPTS ? POLL_INTERVAL_MS : false,\n };\n }),\n combine,\n });\n};\n","import type { DatasetExperiment } from '@mastra/client-js';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport interface ExperimentMetrics {\n totalTokens: number | null;\n estimatedCost: number | null;\n costUnit: string | null;\n avgAgentDurationMs: number | null;\n agentRuns: number | null;\n}\n\ninterface UseExperimentMetricsArgs {\n experimentId: string | undefined;\n experimentStatus: DatasetExperiment['status'] | undefined;\n /** Whether the observability store can serve metrics; no requests are made when false. */\n supportsMetrics: boolean;\n queryOptions?: MastraQueryOptions<ExperimentMetrics>;\n}\n\n/**\n * Experiment-scoped metrics (tokens, cost, avg agent latency).\n * Filters only by experimentId — no time window, since the experiment already bounds the row set.\n * Polls every 2 seconds while the experiment is running or pending.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentMetrics = ({\n experimentId,\n experimentStatus,\n supportsMetrics,\n queryOptions,\n}: UseExperimentMetricsArgs) => {\n const client = useMastraClient();\n const isEnabled = Boolean(experimentId) && supportsMetrics;\n const isActive = experimentStatus === 'running' || experimentStatus === 'pending';\n\n const query = useQuery({\n queryKey: ['experiment-metrics', experimentId],\n refetchInterval: isActive ? 2000 : false,\n queryFn: async (): Promise<ExperimentMetrics> => {\n // `enabled` already guards this; the check exists to narrow the type.\n if (!experimentId) throw new Error('experimentId is required');\n const filters = { experimentId };\n\n const [tokens, avgDuration, runs] = await Promise.all([\n client.getMetricAggregate({\n name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],\n aggregation: 'sum',\n filters,\n }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'avg', filters }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'count', filters }),\n ]);\n\n return {\n totalTokens: tokens.value ?? null,\n estimatedCost: tokens.estimatedCost ?? null,\n costUnit: tokens.costUnit ?? null,\n avgAgentDurationMs: avgDuration.value ?? null,\n agentRuns: runs.value ?? null,\n };\n },\n ...queryOptions,\n });\n\n return { data: query.data, isLoading: query.isLoading, isEnabled };\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype TraceLightResponse = Awaited<ReturnType<MastraClient['getTraceLight']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentTrace = <TData = TraceLightResponse>({\n traceId,\n queryOptions,\n}: {\n traceId: string | null | undefined;\n queryOptions?: MastraQueryOptions<TraceLightResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['experiment-trace-light', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n return client.getTraceLight(traceId);\n },\n ...queryOptions,\n });\n};\n","import type { ExperimentTargetType, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/** Explicit page size: server defaults are 20 (global) / 10 (per dataset), which is too small for the list. */\nexport const EXPERIMENTS_PAGE_SIZE = 100;\n\nexport interface ExperimentTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\n/**\n * Experiments for the list page: the global list, or the dataset-scoped list when a dataset filter is active.\n * A dataset's runs may not be in the first page of the global list, so filtering client-side is not enough.\n * The optional target filter is applied server-side for the same reason.\n */\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useExperimentsForDatasetFilter<TData = ListExperimentsResponse>({\n datasetId,\n target,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n const params: ListExperimentsParams = { perPage: EXPERIMENTS_PAGE_SIZE };\n if (target?.targetType) params.targetType = target.targetType;\n if (target?.targetId) params.targetId = target.targetId;\n\n return useQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId ? ['dataset-experiments', datasetId, params] : ['experiments', params],\n queryFn: () => (datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params)),\n ...queryOptions,\n });\n}\n","import type { DatasetExperiment, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\nimport type { ExperimentTargetFilter } from './use-experiments-for-dataset-filter';\n\nexport const EXPERIMENTS_PER_PAGE = 100;\n\n/**\n * Infinite-scroll experiments for the list page: the global list, or the dataset-scoped list when a\n * dataset filter is active (a dataset's runs may not be in the first pages of the global list). The\n * optional target filter is applied server-side for the same reason.\n */\nexport type ExperimentsOrderBy = NonNullable<ListExperimentsParams['orderBy']>;\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useInfiniteExperiments<TData = DatasetExperiment[]>({\n datasetId,\n target,\n orderBy,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n orderBy?: ExperimentsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListExperimentsResponse, TData, QueryKey, number>;\n}): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = target?.targetType || undefined;\n const targetId = target?.targetId || undefined;\n\n const query = useInfiniteQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId\n ? ['dataset-experiments', datasetId, 'infinite', { targetType, targetId, orderBy }]\n : ['experiments', 'infinite', { targetType, targetId, orderBy }],\n queryFn: ({ pageParam }) => {\n const params: ListExperimentsParams = { page: pageParam, perPage: EXPERIMENTS_PER_PAGE };\n if (targetType) params.targetType = targetType;\n if (targetId) params.targetId = targetId;\n if (orderBy) params.orderBy = orderBy;\n return datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params);\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.experiments?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListExperimentsResponse, number>) =>\n data.pages.flatMap(page => page?.experiments ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/hooks/experiments/use-experiment-item-usage.ts","../../../src/hooks/experiments/use-experiment-metrics.ts","../../../src/hooks/experiments/use-experiment-trace.ts","../../../src/hooks/experiments/use-experiments-for-dataset-filter.ts","../../../src/hooks/experiments/use-infinite-experiments.ts"],"sourcesContent":["import type { GetMetricBreakdownResponse } from '@mastra/core/storage';\nimport { useQueries } from '@tanstack/react-query';\nimport type { Query } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { ExperimentRef } from '../datasets/use-dataset-experiments';\nimport { useCombineByIds } from '../shared/combine-by-ids';\nimport type { ExperimentQueriesResult } from '../shared/combine-by-ids';\nimport { getOrCreate } from '../shared/map';\n\nconst INPUT_TOKEN_METRIC = 'mastra_model_total_input_tokens';\nconst OUTPUT_TOKEN_METRIC = 'mastra_model_total_output_tokens';\nconst POLL_INTERVAL_MS = 2000;\n\nexport interface ExperimentItemUsage {\n inputTokens?: number;\n outputTokens?: number;\n /** Undefined when no group is priced or when groups use different cost units. */\n estimatedCost?: number;\n costUnit?: string;\n}\n\n/** Usage of one experiment: its totals, and each item's usage keyed by the trace id of its run. */\nexport interface ExperimentUsage {\n /** Totals across every item. The cost sums priced groups only. */\n summary: ExperimentItemUsage;\n traces: Record<string, ExperimentItemUsage>;\n}\n\ntype UsageAccumulator = {\n inputTokens?: number;\n outputTokens?: number;\n estimatedCost: number;\n costUnits: Set<string>;\n hasUnknownCostUnit: boolean;\n};\n\nconst createAccumulator = (): UsageAccumulator => ({\n estimatedCost: 0,\n costUnits: new Set(),\n hasUnknownCostUnit: false,\n});\n\ntype BreakdownGroup = GetMetricBreakdownResponse['groups'][number];\n\nfunction accumulate(accumulator: UsageAccumulator, tokenField: 'inputTokens' | 'outputTokens', group: BreakdownGroup) {\n accumulator[tokenField] = (accumulator[tokenField] ?? 0) + group.value;\n\n if (group.estimatedCost == null) return;\n accumulator.estimatedCost += group.estimatedCost;\n if (group.costUnit) {\n accumulator.costUnits.add(group.costUnit.toLowerCase());\n } else {\n accumulator.hasUnknownCostUnit = true;\n }\n}\n\nfunction toUsage(accumulator: UsageAccumulator): ExperimentItemUsage {\n // A single known unit implies at least one priced group.\n const isPriced = !accumulator.hasUnknownCostUnit && accumulator.costUnits.size === 1;\n return {\n inputTokens: accumulator.inputTokens,\n outputTokens: accumulator.outputTokens,\n estimatedCost: isPriced ? accumulator.estimatedCost : undefined,\n costUnit: isPriced ? [...accumulator.costUnits][0] : undefined,\n };\n}\n\n/** Builds the experiment totals and the per-trace usage in a single pass over the groups. */\nfunction toExperimentUsage(response: GetMetricBreakdownResponse): ExperimentUsage {\n const summary = createAccumulator();\n const accumulators = new Map<string, UsageAccumulator>();\n\n for (const group of response.groups) {\n const metricName = group.dimensions.name;\n if (metricName !== INPUT_TOKEN_METRIC && metricName !== OUTPUT_TOKEN_METRIC) continue;\n\n const tokenField = metricName === INPUT_TOKEN_METRIC ? 'inputTokens' : 'outputTokens';\n accumulate(summary, tokenField, group);\n\n const traceId = group.dimensions.traceId;\n if (traceId) accumulate(getOrCreate(accumulators, traceId, createAccumulator), tokenField, group);\n }\n\n const traces: Record<string, ExperimentItemUsage> = {};\n for (const [traceId, accumulator] of accumulators) {\n traces[traceId] = toUsage(accumulator);\n }\n return { summary: toUsage(summary), traces };\n}\n\n/** How many breakdowns to fetch after completion while the exporter may still be flushing metrics. */\nconst MAX_EMPTY_ATTEMPTS = 5;\n\nconst isEmptyUsage = (usage: ExperimentUsage | undefined) =>\n !usage ||\n (Object.keys(usage.traces).length === 0 &&\n usage.summary.inputTokens === undefined &&\n usage.summary.outputTokens === undefined);\n\n/**\n * Token and cost usage of several experiments, keyed by experiment id: each entry holds the\n * experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).\n * Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,\n * so it does not wait for the experiment results. Usage is only fetched once an experiment has\n * finished; while the breakdown is still empty (metrics flushing), it retries every 2 seconds up to\n * 5 attempts. No request is made when the observability store cannot serve metrics.\n */\nexport const useExperimentsItemUsage = ({\n experiments,\n supportsMetrics,\n}: {\n experiments: ExperimentRef[];\n supportsMetrics: boolean;\n}): ExperimentQueriesResult<ExperimentUsage> => {\n const client = useMastraClient();\n const combine = useCombineByIds<ExperimentUsage>(experiments.map(experiment => experiment.id));\n\n return useQueries({\n queries: experiments.map(({ id, status }) => {\n const finished = status !== 'running' && status !== 'pending';\n return {\n queryKey: ['experiment-item-usage', id, finished],\n queryFn: async () =>\n toExperimentUsage(\n await client.getMetricBreakdown({\n name: [INPUT_TOKEN_METRIC, OUTPUT_TOKEN_METRIC],\n aggregation: 'sum',\n groupBy: ['traceId', 'name'],\n filters: { experimentId: id },\n }),\n ),\n enabled: supportsMetrics && finished,\n refetchInterval: (query: Query<ExperimentUsage>) =>\n isEmptyUsage(query.state.data) && query.state.dataUpdateCount < MAX_EMPTY_ATTEMPTS ? POLL_INTERVAL_MS : false,\n };\n }),\n combine,\n });\n};\n","import type { DatasetExperiment } from '@mastra/client-js';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport interface ExperimentMetrics {\n totalTokens: number | null;\n estimatedCost: number | null;\n costUnit: string | null;\n avgAgentDurationMs: number | null;\n agentRuns: number | null;\n}\n\ninterface UseExperimentMetricsArgs {\n experimentId: string | undefined;\n experimentStatus: DatasetExperiment['status'] | undefined;\n /** Whether the observability store can serve metrics; no requests are made when false. */\n supportsMetrics: boolean;\n queryOptions?: MastraQueryOptions<ExperimentMetrics>;\n}\n\n/**\n * Experiment-scoped metrics (tokens, cost, avg agent latency).\n * Filters only by experimentId — no time window, since the experiment already bounds the row set.\n * Polls every 2 seconds while the experiment is running or pending.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentMetrics = ({\n experimentId,\n experimentStatus,\n supportsMetrics,\n queryOptions,\n}: UseExperimentMetricsArgs) => {\n const client = useMastraClient();\n const isEnabled = Boolean(experimentId) && supportsMetrics;\n const isActive = experimentStatus === 'running' || experimentStatus === 'pending';\n\n const query = useQuery({\n queryKey: ['experiment-metrics', experimentId],\n refetchInterval: isActive ? 2000 : false,\n queryFn: async (): Promise<ExperimentMetrics> => {\n // `enabled` already guards this; the check exists to narrow the type.\n if (!experimentId) throw new Error('experimentId is required');\n const filters = { experimentId };\n\n const [tokens, avgDuration, runs] = await Promise.all([\n client.getMetricAggregate({\n name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],\n aggregation: 'sum',\n filters,\n }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'avg', filters }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'count', filters }),\n ]);\n\n return {\n totalTokens: tokens.value ?? null,\n estimatedCost: tokens.estimatedCost ?? null,\n costUnit: tokens.costUnit ?? null,\n avgAgentDurationMs: avgDuration.value ?? null,\n agentRuns: runs.value ?? null,\n };\n },\n ...queryOptions,\n });\n\n return { data: query.data, isLoading: query.isLoading, isEnabled };\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype TraceLightResponse = Awaited<ReturnType<MastraClient['getTraceLight']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentTrace = <TData = TraceLightResponse>({\n traceId,\n queryOptions,\n}: {\n traceId: string | null | undefined;\n queryOptions?: MastraQueryOptions<TraceLightResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['experiment-trace-light', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n return client.getTraceLight(traceId);\n },\n ...queryOptions,\n });\n};\n","import type { ExperimentTargetType, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/** Explicit page size: server defaults are 20 (global) / 10 (per dataset), which is too small for the list. */\nexport const EXPERIMENTS_PAGE_SIZE = 100;\n\nexport interface ExperimentTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\n/**\n * Experiments for the list page: the global list, or the dataset-scoped list when a dataset filter is active.\n * A dataset's runs may not be in the first page of the global list, so filtering client-side is not enough.\n * The optional target filter is applied server-side for the same reason.\n */\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useExperimentsForDatasetFilter<TData = ListExperimentsResponse>({\n datasetId,\n target,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n const params: ListExperimentsParams = { perPage: EXPERIMENTS_PAGE_SIZE };\n if (target?.targetType) params.targetType = target.targetType;\n if (target?.targetId) params.targetId = target.targetId;\n\n return useQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId ? ['dataset-experiments', datasetId, params] : ['experiments', params],\n queryFn: () => (datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params)),\n ...queryOptions,\n });\n}\n","import type { DatasetExperiment, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\nimport type { ExperimentTargetFilter } from './use-experiments-for-dataset-filter';\n\nexport const EXPERIMENTS_PER_PAGE = 100;\n\n/**\n * Infinite-scroll experiments for the list page: the global list, or the dataset-scoped list when a\n * dataset filter is active (a dataset's runs may not be in the first pages of the global list). The\n * optional target filter is applied server-side for the same reason.\n */\nexport type ExperimentsOrderBy = NonNullable<ListExperimentsParams['orderBy']>;\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useInfiniteExperiments<TData = DatasetExperiment[]>({\n datasetId,\n target,\n orderBy,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n orderBy?: ExperimentsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListExperimentsResponse, TData, QueryKey, number>;\n}): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = target?.targetType || undefined;\n const targetId = target?.targetId || undefined;\n\n const query = useInfiniteQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId\n ? ['dataset-experiments', datasetId, 'infinite', { targetType, targetId, orderBy }]\n : ['experiments', 'infinite', { targetType, targetId, orderBy }],\n queryFn: ({ pageParam }) => {\n const params: ListExperimentsParams = { page: pageParam, perPage: EXPERIMENTS_PER_PAGE };\n if (targetType) params.targetType = targetType;\n if (targetId) params.targetId = targetId;\n if (orderBy) params.orderBy = orderBy;\n return datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params);\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.experiments?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListExperimentsResponse, number>) =>\n data.pages.flatMap(page => page?.experiments ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n}\n"],"mappings":"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"}
|