UNPKG

@mastra/core

Version:

Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.

1,243 lines (1,239 loc) • 57.4 kB
import { getZodTypeName, getZodInnerType } from './chunk-RT2LCNDN.js'; import { SpanType, dbTimestamps, paginationInfoSchema, tagsField, metadataField, spanIdField, traceIdField, spanContextFields, dateRangeSchema, sortDirectionSchema, deltaLimitSchema, deltaCursorSchema, paginationArgsSchema, listModeSchema, refineObservabilityListMode, normalizeObservabilityListArgs, deltaInfoSchema } from './chunk-QAXRURAT.js'; import { z } from 'zod/v4'; var scoringSourceSchema = z.enum(["LIVE", "TEST"]); var scoringEntityTypeSchema = z.enum([ "AGENT", "WORKFLOW", "TRAJECTORY", "STEP", ...Object.values(SpanType) ]); var scoringPromptsSchema = z.object({ description: z.string(), prompt: z.string() }); var recordSchema = z.record(z.string(), z.unknown()); var optionalRecordSchema = recordSchema.optional(); var scoringInputSchema = z.object({ runId: z.string().optional(), input: z.unknown().optional(), output: z.unknown(), additionalContext: optionalRecordSchema, requestContext: optionalRecordSchema // Note: observabilityContext is not serializable, so we don't include it in the schema // It's added at runtime when needed }); var scoringHookInputSchema = z.object({ runId: z.string().optional(), scorer: recordSchema, input: z.unknown(), output: z.unknown(), metadata: optionalRecordSchema, additionalContext: optionalRecordSchema, source: scoringSourceSchema, entity: recordSchema, entityType: scoringEntityTypeSchema, requestContext: optionalRecordSchema, structuredOutput: z.boolean().optional(), traceId: z.string().optional(), spanId: z.string().optional(), resourceId: z.string().optional(), threadId: z.string().optional() // Note: observabilityContext is not serializable, so we don't include it in the schema }); var scoringExtractStepResultSchema = optionalRecordSchema; var scoringValueSchema = z.number(); var scoreResultSchema = z.object({ result: optionalRecordSchema, score: scoringValueSchema, prompt: z.string().optional() }); var scoringInputWithExtractStepResultSchema = scoringInputSchema.extend({ runId: z.string(), // Required in this context extractStepResult: optionalRecordSchema, extractPrompt: z.string().optional() }); var scoringInputWithExtractStepResultAndAnalyzeStepResultSchema = scoringInputWithExtractStepResultSchema.extend({ score: z.number(), analyzeStepResult: optionalRecordSchema, analyzePrompt: z.string().optional() }); var scoringInputWithExtractStepResultAndScoreAndReasonSchema = scoringInputWithExtractStepResultAndAnalyzeStepResultSchema.extend({ reason: z.string().optional(), reasonPrompt: z.string().optional() }); var scoreRowDataSchema = z.object({ id: z.string(), scorerId: z.string(), entityId: z.string(), // From ScoringInputWithExtractStepResultAndScoreAndReason runId: z.string(), input: z.unknown().optional(), output: z.unknown(), additionalContext: optionalRecordSchema, requestContext: optionalRecordSchema, extractStepResult: optionalRecordSchema, extractPrompt: z.string().optional(), score: z.number(), analyzeStepResult: optionalRecordSchema, analyzePrompt: z.string().optional(), reason: z.string().optional(), reasonPrompt: z.string().optional(), // From ScoringHookInput scorer: recordSchema, metadata: optionalRecordSchema, source: scoringSourceSchema, entity: recordSchema, entityType: scoringEntityTypeSchema.optional(), structuredOutput: z.boolean().optional(), traceId: z.string().optional(), spanId: z.string().optional(), resourceId: z.string().optional(), threadId: z.string().optional(), // Additional ScoreRowData fields preprocessStepResult: optionalRecordSchema, preprocessPrompt: z.string().optional(), generateScorePrompt: z.string().optional(), generateReasonPrompt: z.string().optional(), // Timestamps ...dbTimestamps }); var saveScorePayloadSchema = scoreRowDataSchema.omit({ id: true, createdAt: true, updatedAt: true }); var listScoresResponseSchema = z.object({ pagination: paginationInfoSchema, scores: z.array(scoreRowDataSchema) }); function extractTrajectory(output) { const steps = []; for (const message of output) { const legacy = message?.content?.toolInvocations; const fromParts = legacy ? void 0 : message?.content?.parts?.filter((p) => p.type === "tool-invocation").map((p) => p.toolInvocation); const toolInvocations = legacy ?? fromParts; if (!toolInvocations?.length) continue; for (const invocation of toolInvocations) { if (invocation && invocation.toolName && (invocation.state === "result" || invocation.state === "call")) { const toolArgs = invocation.args != null && typeof invocation.args === "object" && !Array.isArray(invocation.args) ? invocation.args : invocation.args != null ? { value: invocation.args } : void 0; const rawResult = invocation.state === "result" ? invocation.result : void 0; const toolResult = rawResult != null && typeof rawResult === "object" && !Array.isArray(rawResult) ? rawResult : rawResult != null ? { value: rawResult } : void 0; steps.push({ stepType: "tool_call", name: invocation.toolName, toolArgs, toolResult, success: invocation.state === "result" }); } } } return { steps, rawOutput: output }; } function extractWorkflowTrajectory(stepResults, stepExecutionPath) { const steps = []; const stepIds = stepExecutionPath ?? Object.keys(stepResults); let totalStartedAt; let totalEndedAt; for (const stepId of stepIds) { const result = stepResults[stepId]; if (!result) continue; if (result.startedAt != null) { if (totalStartedAt == null || result.startedAt < totalStartedAt) { totalStartedAt = result.startedAt; } } const endedAt = "endedAt" in result ? result.endedAt : void 0; if (endedAt != null) { if (totalEndedAt == null || endedAt > totalEndedAt) { totalEndedAt = endedAt; } } const durationMs = result.startedAt != null && endedAt != null ? endedAt - result.startedAt : void 0; const output = "output" in result && result.output != null && typeof result.output === "object" && !Array.isArray(result.output) ? result.output : "output" in result && result.output != null ? { value: result.output } : void 0; steps.push({ stepType: "workflow_step", name: stepId, stepId, status: result.status, output, durationMs, metadata: result.metadata }); } const totalDurationMs = totalStartedAt != null && totalEndedAt != null ? totalEndedAt - totalStartedAt : void 0; return { steps, totalDurationMs, rawWorkflowResult: { stepResults, stepExecutionPath } }; } var SKIPPED_SPAN_TYPES = /* @__PURE__ */ new Set([ "scorer_run" /* SCORER_RUN */, "scorer_step" /* SCORER_STEP */, "generic" /* GENERIC */, "model_step" /* MODEL_STEP */, "model_inference" /* MODEL_INFERENCE */, "model_chunk" /* MODEL_CHUNK */, "workflow_conditional_eval" /* WORKFLOW_CONDITIONAL_EVAL */ ]); function spanToTrajectorySteps(node) { const { span, children: childNodes } = node; if (SKIPPED_SPAN_TYPES.has(span.spanType)) { return childNodes.flatMap(spanToTrajectorySteps); } const durationMs = span.endedAt != null && span.startedAt != null ? span.endedAt.getTime() - span.startedAt.getTime() : void 0; const childSteps = childNodes.flatMap(spanToTrajectorySteps); const base = { name: span.name, durationMs, metadata: span.metadata, ...childSteps.length > 0 ? { children: childSteps } : {} }; const attrs = span.attributes ?? {}; switch (span.spanType) { case "tool_call" /* TOOL_CALL */: { const toolArgs = toRecordOrUndefined(span.input); const toolResult = toRecordOrUndefined(span.output); return [ { ...base, stepType: "tool_call", toolArgs, toolResult, success: typeof attrs.success === "boolean" ? attrs.success : void 0 } ]; } case "mcp_tool_call" /* MCP_TOOL_CALL */: { const toolArgs = toRecordOrUndefined(span.input); const toolResult = toRecordOrUndefined(span.output); return [ { ...base, stepType: "mcp_tool_call", toolArgs, toolResult, mcpServer: typeof attrs.mcpServer === "string" ? attrs.mcpServer : void 0, success: typeof attrs.success === "boolean" ? attrs.success : void 0 } ]; } case "model_generation" /* MODEL_GENERATION */: { const usage = attrs.usage; return [ { ...base, stepType: "model_generation", modelId: typeof attrs.model === "string" ? attrs.model : void 0, promptTokens: usage?.inputTokens, completionTokens: usage?.outputTokens, finishReason: typeof attrs.finishReason === "string" ? attrs.finishReason : void 0 } ]; } case "agent_run" /* AGENT_RUN */: return [{ ...base, stepType: "agent_run", agentId: span.entityId ?? void 0 }]; case "workflow_run" /* WORKFLOW_RUN */: return [{ ...base, stepType: "workflow_run", workflowId: span.entityId ?? void 0 }]; case "workflow_step" /* WORKFLOW_STEP */: { const output = toRecordOrUndefined(span.output); return [{ ...base, stepType: "workflow_step", stepId: span.name, output }]; } case "workflow_conditional" /* WORKFLOW_CONDITIONAL */: return [{ ...base, stepType: "workflow_conditional" }]; case "workflow_parallel" /* WORKFLOW_PARALLEL */: return [{ ...base, stepType: "workflow_parallel" }]; case "workflow_loop" /* WORKFLOW_LOOP */: return [{ ...base, stepType: "workflow_loop" }]; case "workflow_sleep" /* WORKFLOW_SLEEP */: return [{ ...base, stepType: "workflow_sleep" }]; case "workflow_wait_event" /* WORKFLOW_WAIT_EVENT */: return [{ ...base, stepType: "workflow_wait_event" }]; case "processor_run" /* PROCESSOR_RUN */: return [{ ...base, stepType: "processor_run" }]; default: return childSteps; } } function toRecordOrUndefined(value) { if (value == null) return void 0; if (typeof value === "object" && !Array.isArray(value)) { return value; } return { value }; } function extractTrajectoryFromTrace(spans, rootSpanId) { if (spans.length === 0) { return { steps: [] }; } const nodeMap = /* @__PURE__ */ new Map(); for (const span of spans) { nodeMap.set(span.spanId, { span, children: [] }); } const roots = []; for (const span of spans) { const node = nodeMap.get(span.spanId); if (span.parentSpanId && nodeMap.has(span.parentSpanId)) { nodeMap.get(span.parentSpanId).children.push(node); } else { roots.push(node); } } for (const node of nodeMap.values()) { node.children.sort((a, b) => a.span.startedAt.getTime() - b.span.startedAt.getTime()); } let targetRoots; if (rootSpanId) { const rootNode = nodeMap.get(rootSpanId); targetRoots = rootNode ? [rootNode] : roots; } else { targetRoots = roots; } let stepsToConvert; if (targetRoots.length === 1) { const root = targetRoots[0]; const containerTypes = /* @__PURE__ */ new Set(["workflow_run" /* WORKFLOW_RUN */, "agent_run" /* AGENT_RUN */]); if (containerTypes.has(root.span.spanType)) { stepsToConvert = root.children; } else { stepsToConvert = targetRoots; } } else { stepsToConvert = targetRoots; } const steps = stepsToConvert.flatMap(spanToTrajectorySteps); let totalDurationMs; if (targetRoots.length === 1) { const root = targetRoots[0].span; if (root.endedAt && root.startedAt) { totalDurationMs = root.endedAt.getTime() - root.startedAt.getTime(); } } return { steps, totalDurationMs }; } // src/storage/domains/observability/tracing.ts var createOmitKeys = (shape) => Object.fromEntries(Object.keys(shape).map((k) => [k, true])); var spanNameField = z.string().describe("Human-readable span name"); var parentSpanIdField = z.string().describe("Parent span reference (null = root span)"); var spanTypeField = z.nativeEnum(SpanType).describe("Span type (e.g., WORKFLOW_RUN, AGENT_RUN, TOOL_CALL, etc.)"); var attributesField = z.record(z.string(), z.unknown()).describe("Span-type specific attributes (e.g., model, tokens, tools)"); var linksField = z.array(z.unknown()).describe("References to related spans in other traces"); var inputField = z.unknown().describe("Input data passed to the span"); var outputField = z.unknown().describe("Output data returned from the span"); var errorField = z.unknown().describe("Error info - presence indicates failure (status derived from this)"); var isEventField = z.boolean().describe("Whether this is an event (point-in-time) vs a span (duration)"); var startedAtField = z.date().describe("When the span started"); var endedAtField = z.date().describe("When the span ended (null = running, status derived from this)"); var TraceStatus = /* @__PURE__ */ ((TraceStatus2) => { TraceStatus2["SUCCESS"] = "success"; TraceStatus2["ERROR"] = "error"; TraceStatus2["RUNNING"] = "running"; return TraceStatus2; })(TraceStatus || {}); var traceStatusField = z.nativeEnum(TraceStatus).describe("Current status of the trace"); var hasChildErrorField = z.preprocess((v) => { if (v === "true") return true; if (v === "false") return false; return v; }, z.boolean()).describe("True if any span in the trace encountered an error"); var sharedFields = { ...spanContextFields, metadata: metadataField.nullish(), tags: tagsField.nullish() }; var spanIds = { traceId: traceIdField, spanId: spanIdField }; var spanIdsSchema = z.object({ ...spanIds }); var omitDbTimestamps = createOmitKeys(dbTimestamps); var omitSpanIds = createOmitKeys(spanIds); var spanRecordSchema = z.object({ // Required identifiers ...spanIds, name: spanNameField, spanType: spanTypeField, isEvent: isEventField, startedAt: startedAtField, // Shared fields parentSpanId: parentSpanIdField.nullish(), ...sharedFields, // Experimentation experimentId: z.string().nullish().describe("Experiment or eval run identifier"), // Additional span-specific nullish fields attributes: attributesField.nullish(), links: linksField.nullish(), input: inputField.nullish(), output: outputField.nullish(), error: errorField.nullish(), endedAt: endedAtField.nullish(), requestContext: z.record(z.string(), z.unknown()).nullish().describe("Request context data"), // Database timestamps ...dbTimestamps }).describe("Span record data"); function computeTraceStatus(span) { if (span.error != null) return "error" /* ERROR */; if (span.endedAt == null) return "running" /* RUNNING */; return "success" /* SUCCESS */; } var traceSpanSchema = spanRecordSchema.extend({ status: traceStatusField }).describe("Trace span with computed status (root spans only)"); function toTraceSpan(span) { return { ...span, status: computeTraceStatus(span) }; } function toTraceSpans(spans) { return spans.map(toTraceSpan); } var createSpanRecordSchema = spanRecordSchema.omit(omitDbTimestamps); var createSpanArgsSchema = z.object({ span: createSpanRecordSchema }).describe("Arguments for creating a single span"); var batchCreateSpansArgsSchema = z.object({ records: z.array(createSpanRecordSchema) }).describe("Arguments for batch creating spans"); var getSpanArgsSchema = z.object({ traceId: traceIdField.min(1), spanId: spanIdField.min(1) }).describe("Arguments for getting a single span"); var getSpanResponseSchema = z.object({ span: spanRecordSchema }); var getSpansArgsSchema = z.object({ traceId: traceIdField.min(1), spanIds: z.array(spanIdField.min(1)).min(1).describe("Span IDs to fetch within the trace") }).describe("Arguments for batch-fetching spans by spanId within a trace"); var getSpansResponseSchema = z.object({ traceId: traceIdField, spans: z.array(spanRecordSchema) }); var getRootSpanArgsSchema = z.object({ traceId: traceIdField.min(1) }).describe("Arguments for getting a root span"); var getRootSpanResponseSchema = z.object({ span: spanRecordSchema }); var getTraceArgsSchema = z.object({ traceId: traceIdField.min(1) }).describe("Arguments for getting a single trace"); var getTraceResponseSchema = z.object({ traceId: traceIdField, spans: z.array(spanRecordSchema) }); var getBranchArgsSchema = z.object({ traceId: traceIdField.min(1), spanId: spanIdField.min(1), depth: z.coerce.number().int().min(0).optional().describe("Maximum descendant levels below the anchor span (omit for full subtree)") }).describe("Arguments for getting a span branch (subtree rooted at a span)"); var getBranchResponseSchema = z.object({ traceId: traceIdField, spans: z.array(spanRecordSchema) }); function extractBranchSpans(spans, anchorSpanId, maxDepth) { const anchor = spans.find((s) => s.spanId === anchorSpanId); if (!anchor) return []; const childrenByParent = /* @__PURE__ */ new Map(); for (const span of spans) { if (span.parentSpanId == null) continue; const bucket = childrenByParent.get(span.parentSpanId); if (bucket) { bucket.push(span); } else { childrenByParent.set(span.parentSpanId, [span]); } } const visited = /* @__PURE__ */ new Set([anchor.spanId]); const descendants = []; let frontier = [anchor]; let depth = 0; while (frontier.length > 0) { if (maxDepth != null && depth >= maxDepth) break; const next = []; for (const span of frontier) { const children = childrenByParent.get(span.spanId); if (!children) continue; for (const child of children) { if (visited.has(child.spanId)) continue; visited.add(child.spanId); descendants.push(child); next.push(child); } } frontier = next; depth++; } descendants.sort((a, b) => a.startedAt.getTime() - b.startedAt.getTime()); return [anchor, ...descendants]; } var lightSpanRecordSchema = z.object({ // Required identifiers ...spanIds, name: spanNameField, spanType: spanTypeField, isEvent: isEventField, startedAt: startedAtField, // Nullish fields needed for timeline/status parentSpanId: parentSpanIdField.nullish(), endedAt: endedAtField.nullish(), error: errorField.nullish(), // Entity context (needed by TraceKeysAndValues on root span) entityType: spanContextFields.entityType, entityId: spanContextFields.entityId, entityName: spanContextFields.entityName, // Database timestamps ...dbTimestamps }).describe( "Lightweight span record for timeline rendering (excludes input, output, attributes, metadata, tags, links)" ); var getStructureResponseSchema = z.object({ traceId: traceIdField, spans: z.array(lightSpanRecordSchema) }); var getTraceLightResponseSchema = getStructureResponseSchema; var tracesFilterSchema = z.object({ // Date range filters startedAt: dateRangeSchema.optional().describe("Filter by span start time range"), endedAt: dateRangeSchema.optional().describe("Filter by span end time range"), // Span type filter spanType: spanTypeField.optional(), // Identifier filter (matches the root span's trace identifier) traceId: traceIdField.optional().describe("Filter by trace ID (matches root span)"), // Shared fields ...sharedFields, // Filter-specific derived status fields status: traceStatusField.optional(), hasChildError: hasChildErrorField.optional() }).describe("Filters for querying traces"); var tracesOrderByFieldSchema = z.enum(["startedAt", "endedAt"]).describe("Field to order by: 'startedAt' | 'endedAt'"); var tracesOrderBySchema = z.object({ field: tracesOrderByFieldSchema.default("startedAt").describe("Field to order by"), direction: sortDirectionSchema.default("DESC").describe("Sort direction") }).describe("Order by configuration"); var listTracesArgsSchema = z.object({ mode: listModeSchema.optional(), filters: tracesFilterSchema.optional().describe("Optional filters to apply"), pagination: paginationArgsSchema.optional(), orderBy: tracesOrderBySchema.optional(), after: deltaCursorSchema.optional(), limit: deltaLimitSchema }).strict().superRefine(refineObservabilityListMode).transform( (value) => normalizeObservabilityListArgs(value, { orderBy: { field: "startedAt", direction: "DESC" } }) ).describe("Arguments for listing traces."); var listTracesResponseSchema = z.object({ pagination: paginationInfoSchema.optional(), delta: deltaInfoSchema.optional(), deltaCursor: deltaCursorSchema.optional(), spans: z.array(traceSpanSchema) }); var listTracesLightResponseSchema = z.object({ pagination: paginationInfoSchema, spans: z.array(lightSpanRecordSchema) }); var BRANCH_SPAN_TYPES = [ "agent_run" /* AGENT_RUN */, "workflow_run" /* WORKFLOW_RUN */, "processor_run" /* PROCESSOR_RUN */, "scorer_run" /* SCORER_RUN */, "rag_ingestion" /* RAG_INGESTION */, "tool_call" /* TOOL_CALL */, "mcp_tool_call" /* MCP_TOOL_CALL */ ]; var BRANCH_SPAN_TYPE_SET = new Set(BRANCH_SPAN_TYPES); var branchesFilterSchema = z.object({ // Date range filters apply to the branch anchor span itself startedAt: dateRangeSchema.optional().describe("Filter by span start time range"), endedAt: dateRangeSchema.optional().describe("Filter by span end time range"), // Narrow within the branch span-type set; if omitted, all of them match spanType: spanTypeField.optional(), // Identifier filters traceId: traceIdField.optional().describe("Filter by parent trace ID"), // Per-span context fields (apply to the anchor span, not the trace root) ...sharedFields, // Derived status filter (computed from this anchor's own error/endedAt) status: traceStatusField.optional() }).describe("Filters for querying trace branches"); var branchesOrderByFieldSchema = z.enum(["startedAt", "endedAt"]).describe("Field to order by: 'startedAt' | 'endedAt'"); var branchesOrderBySchema = z.object({ field: branchesOrderByFieldSchema.default("startedAt").describe("Field to order by"), direction: sortDirectionSchema.default("DESC").describe("Sort direction") }).describe("Order by configuration"); var listBranchesArgsSchema = z.object({ mode: listModeSchema.optional(), filters: branchesFilterSchema.optional().describe("Optional filters to apply"), pagination: paginationArgsSchema.optional(), orderBy: branchesOrderBySchema.optional(), after: deltaCursorSchema.optional(), limit: deltaLimitSchema }).strict().superRefine(refineObservabilityListMode).transform( (value) => normalizeObservabilityListArgs( value, { orderBy: { field: "startedAt", direction: "DESC" } } ) ).describe("Arguments for listing trace branches."); var listBranchesResponseSchema = z.object({ pagination: paginationInfoSchema.optional(), delta: deltaInfoSchema.optional(), deltaCursor: deltaCursorSchema.optional(), branches: z.array(traceSpanSchema) }); var updateSpanRecordSchema = createSpanRecordSchema.omit(omitSpanIds); var updateSpanArgsSchema = z.object({ spanId: spanIdField, traceId: traceIdField, updates: updateSpanRecordSchema.partial() }).describe("Arguments for updating a single span"); var batchUpdateSpansArgsSchema = z.object({ records: z.array( z.object({ traceId: traceIdField, spanId: spanIdField, updates: updateSpanRecordSchema.partial() }) ) }).describe("Arguments for batch updating spans"); var batchDeleteTracesArgsSchema = z.object({ traceIds: z.array(traceIdField) }).describe("Arguments for batch deleting traces"); var listScoresBySpanResponseSchema = z.object({ pagination: paginationInfoSchema, scores: z.array(scoreRowDataSchema) }); var scoreTracesRequestSchema = z.object({ scorerName: z.string().min(1), targets: z.array( z.object({ traceId: traceIdField, spanId: spanIdField.optional() }) ).min(1) }); var scoreTracesResponseSchema = z.object({ status: z.string(), message: z.string(), traceCount: z.number() }); // src/storage/types.ts var STORAGE_VISIBILITY_VALUES = ["private", "public"]; function unwrapSchema(schema) { let current = schema; let nullable = false; while (true) { const typeName = getZodTypeName(current); if (!typeName) break; if (typeName === "ZodNullable" || typeName === "ZodOptional") { nullable = true; } const inner = getZodInnerType(current, typeName); if (!inner) break; current = inner; } return { base: current, nullable }; } function getZodChecks(schema) { if ("_zod" in schema) { const zodV4 = schema; const checks = zodV4._zod?.def?.checks; if (checks && Array.isArray(checks)) { return checks.map((check) => { if (typeof check === "object" && check !== null && "def" in check && typeof check.def === "object" && check.def !== null) { const def = check.def; if (def.check === "number_format" && def.format === "safeint") { return { kind: "int" }; } if (def.check === "string_format" && typeof def.format === "string") { return { kind: def.format }; } return { kind: typeof def.check === "string" ? def.check : "unknown" }; } return { kind: "unknown" }; }); } } if ("_def" in schema) { const zodV3 = schema; const checks = zodV3._def?.checks; if (checks && Array.isArray(checks)) { return checks; } } return []; } function zodToStorageType(schema) { const typeName = getZodTypeName(schema); if (typeName === "ZodString") { const checks = getZodChecks(schema); if (checks.some((c) => c.kind === "uuid")) { return "uuid"; } return "text"; } if (typeName === "ZodNativeEnum" || typeName === "ZodEnum") { return "text"; } if (typeName === "ZodNumber") { const checks = getZodChecks(schema); return checks.some((c) => c.kind === "int") ? "integer" : "float"; } if (typeName === "ZodBigInt" || typeName === "ZodBigint") { return "bigint"; } if (typeName === "ZodDate") { return "timestamp"; } if (typeName === "ZodBoolean") { return "boolean"; } return "jsonb"; } function buildStorageSchema(zObject) { const shape = zObject.shape; const result = {}; for (const [key, field] of Object.entries(shape)) { const { base, nullable } = unwrapSchema(field); result[key] = { type: zodToStorageType(base), nullable }; } return result; } var STORAGE_FAVORITE_ENTITY_TYPES = ["agent", "skill"]; // src/storage/constants.ts var TABLE_WORKFLOW_SNAPSHOT = "mastra_workflow_snapshot"; var TABLE_MESSAGES = "mastra_messages"; var TABLE_THREADS = "mastra_threads"; var TABLE_TRACES = "mastra_traces"; var TABLE_RESOURCES = "mastra_resources"; var TABLE_SCORERS = "mastra_scorers"; var TABLE_SPANS = "mastra_ai_spans"; var TABLE_AGENTS = "mastra_agents"; var TABLE_AGENT_VERSIONS = "mastra_agent_versions"; var TABLE_OBSERVATIONAL_MEMORY = "mastra_observational_memory"; var TABLE_PROMPT_BLOCKS = "mastra_prompt_blocks"; var TABLE_PROMPT_BLOCK_VERSIONS = "mastra_prompt_block_versions"; var TABLE_SCORER_DEFINITIONS = "mastra_scorer_definitions"; var TABLE_SCORER_DEFINITION_VERSIONS = "mastra_scorer_definition_versions"; var TABLE_MCP_CLIENTS = "mastra_mcp_clients"; var TABLE_MCP_CLIENT_VERSIONS = "mastra_mcp_client_versions"; var TABLE_MCP_SERVERS = "mastra_mcp_servers"; var TABLE_MCP_SERVER_VERSIONS = "mastra_mcp_server_versions"; var TABLE_WORKSPACES = "mastra_workspaces"; var TABLE_WORKSPACE_VERSIONS = "mastra_workspace_versions"; var TABLE_SKILLS = "mastra_skills"; var TABLE_SKILL_VERSIONS = "mastra_skill_versions"; var TABLE_SKILL_BLOBS = "mastra_skill_blobs"; var TABLE_FAVORITES = "mastra_favorites"; var TABLE_DATASETS = "mastra_datasets"; var TABLE_DATASET_ITEMS = "mastra_dataset_items"; var TABLE_DATASET_VERSIONS = "mastra_dataset_versions"; var TABLE_EXPERIMENTS = "mastra_experiments"; var TABLE_EXPERIMENT_RESULTS = "mastra_experiment_results"; var TABLE_BACKGROUND_TASKS = "mastra_background_tasks"; var TABLE_SCHEDULES = "mastra_schedules"; var TABLE_SCHEDULE_TRIGGERS = "mastra_schedule_triggers"; var TABLE_CHANNEL_INSTALLATIONS = "mastra_channel_installations"; var TABLE_CHANNEL_CONFIG = "mastra_channel_config"; var SCORERS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, scorerId: { type: "text" }, traceId: { type: "text", nullable: true }, spanId: { type: "text", nullable: true }, runId: { type: "text" }, scorer: { type: "jsonb" }, preprocessStepResult: { type: "jsonb", nullable: true }, extractStepResult: { type: "jsonb", nullable: true }, analyzeStepResult: { type: "jsonb", nullable: true }, score: { type: "float" }, reason: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, preprocessPrompt: { type: "text", nullable: true }, extractPrompt: { type: "text", nullable: true }, generateScorePrompt: { type: "text", nullable: true }, generateReasonPrompt: { type: "text", nullable: true }, analyzePrompt: { type: "text", nullable: true }, // Deprecated reasonPrompt: { type: "text", nullable: true }, input: { type: "jsonb" }, output: { type: "jsonb" }, // MESSAGE OUTPUT additionalContext: { type: "jsonb", nullable: true }, // DATA FROM THE CONTEXT PARAM ON AN AGENT requestContext: { type: "jsonb", nullable: true }, // THE EVALUATE Request Context FOR THE RUN /** * Things you can evaluate */ entityType: { type: "text", nullable: true }, // WORKFLOW, AGENT, TOOL, STEP, NETWORK entity: { type: "jsonb", nullable: true }, // MINIMAL JSON DATA ABOUT WORKFLOW, AGENT, TOOL, STEP, NETWORK entityId: { type: "text", nullable: true }, source: { type: "text" }, resourceId: { type: "text", nullable: true }, threadId: { type: "text", nullable: true }, createdAt: { type: "timestamp" }, updatedAt: { type: "timestamp" } }; var SPAN_SCHEMA = buildStorageSchema(spanRecordSchema); var OLD_SPAN_SCHEMA = { // Composite primary key of traceId and spanId traceId: { type: "text", nullable: false }, spanId: { type: "text", nullable: false }, parentSpanId: { type: "text", nullable: true }, name: { type: "text", nullable: false }, scope: { type: "jsonb", nullable: true }, // Mastra package info {"core-version": "0.1.0"} spanType: { type: "text", nullable: false }, // WORKFLOW_RUN, WORKFLOW_STEP, AGENT_RUN, AGENT_STEP, TOOL_RUN, TOOL_STEP, etc. attributes: { type: "jsonb", nullable: true }, metadata: { type: "jsonb", nullable: true }, links: { type: "jsonb", nullable: true }, input: { type: "jsonb", nullable: true }, output: { type: "jsonb", nullable: true }, error: { type: "jsonb", nullable: true }, startedAt: { type: "timestamp", nullable: false }, // When the span started endedAt: { type: "timestamp", nullable: true }, // When the span ended createdAt: { type: "timestamp", nullable: false }, // The time the database record was created updatedAt: { type: "timestamp", nullable: true }, // The time the database record was last updated isEvent: { type: "boolean", nullable: false } }; var AGENTS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, status: { type: "text", nullable: false }, // 'draft' or 'published' activeVersionId: { type: "text", nullable: true }, // FK to agent_versions.id authorId: { type: "text", nullable: true }, // Author identifier for multi-tenant filtering visibility: { type: "text", nullable: true }, // 'private' | 'public' | null (legacy) metadata: { type: "jsonb", nullable: true }, // Additional metadata for the agent favoriteCount: { type: "integer", nullable: true }, // Denormalised count of favorites for this agent createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var AGENT_VERSIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, // UUID agentId: { type: "text", nullable: false }, versionNumber: { type: "integer", nullable: false }, // Agent config fields name: { type: "text", nullable: false }, // Agent display name description: { type: "text", nullable: true }, instructions: { type: "text", nullable: false }, model: { type: "jsonb", nullable: false }, tools: { type: "jsonb", nullable: true }, defaultOptions: { type: "jsonb", nullable: true }, workflows: { type: "jsonb", nullable: true }, agents: { type: "jsonb", nullable: true }, integrationTools: { type: "jsonb", nullable: true }, inputProcessors: { type: "jsonb", nullable: true }, outputProcessors: { type: "jsonb", nullable: true }, memory: { type: "jsonb", nullable: true }, scorers: { type: "jsonb", nullable: true }, mcpClients: { type: "jsonb", nullable: true }, requestContextSchema: { type: "jsonb", nullable: true }, workspace: { type: "jsonb", nullable: true }, skills: { type: "jsonb", nullable: true }, skillsFormat: { type: "text", nullable: true }, browser: { type: "jsonb", nullable: true }, // Version metadata changedFields: { type: "jsonb", nullable: true }, // Array of field names changeMessage: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var PROMPT_BLOCKS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, status: { type: "text", nullable: false }, // 'draft', 'published', or 'archived' activeVersionId: { type: "text", nullable: true }, // FK to prompt_block_versions.id authorId: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var PROMPT_BLOCK_VERSIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, blockId: { type: "text", nullable: false }, versionNumber: { type: "integer", nullable: false }, name: { type: "text", nullable: false }, description: { type: "text", nullable: true }, content: { type: "text", nullable: false }, rules: { type: "jsonb", nullable: true }, requestContextSchema: { type: "jsonb", nullable: true }, changedFields: { type: "jsonb", nullable: true }, changeMessage: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var SCORER_DEFINITIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, status: { type: "text", nullable: false }, // 'draft', 'published', or 'archived' activeVersionId: { type: "text", nullable: true }, // FK to scorer_definition_versions.id authorId: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var SCORER_DEFINITION_VERSIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, scorerDefinitionId: { type: "text", nullable: false }, versionNumber: { type: "integer", nullable: false }, name: { type: "text", nullable: false }, description: { type: "text", nullable: true }, type: { type: "text", nullable: false }, // 'llm-judge', 'bias', 'toxicity', etc. model: { type: "jsonb", nullable: true }, instructions: { type: "text", nullable: true }, scoreRange: { type: "jsonb", nullable: true }, presetConfig: { type: "jsonb", nullable: true }, defaultSampling: { type: "jsonb", nullable: true }, changedFields: { type: "jsonb", nullable: true }, changeMessage: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var MCP_CLIENTS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, status: { type: "text", nullable: false }, // 'draft', 'published', or 'archived' activeVersionId: { type: "text", nullable: true }, // FK to mcp_client_versions.id authorId: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var MCP_CLIENT_VERSIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, mcpClientId: { type: "text", nullable: false }, versionNumber: { type: "integer", nullable: false }, name: { type: "text", nullable: false }, description: { type: "text", nullable: true }, servers: { type: "jsonb", nullable: false }, changedFields: { type: "jsonb", nullable: true }, changeMessage: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var MCP_SERVERS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, status: { type: "text", nullable: false }, // 'draft', 'published', or 'archived' activeVersionId: { type: "text", nullable: true }, // FK to mcp_server_versions.id authorId: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var MCP_SERVER_VERSIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, mcpServerId: { type: "text", nullable: false }, versionNumber: { type: "integer", nullable: false }, name: { type: "text", nullable: false }, version: { type: "text", nullable: false }, description: { type: "text", nullable: true }, instructions: { type: "text", nullable: true }, repository: { type: "jsonb", nullable: true }, releaseDate: { type: "text", nullable: true }, isLatest: { type: "boolean", nullable: true }, packageCanonical: { type: "text", nullable: true }, tools: { type: "jsonb", nullable: true }, agents: { type: "jsonb", nullable: true }, workflows: { type: "jsonb", nullable: true }, changedFields: { type: "jsonb", nullable: true }, changeMessage: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var WORKSPACES_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, status: { type: "text", nullable: false }, // 'draft', 'published', or 'archived' activeVersionId: { type: "text", nullable: true }, // FK to workspace_versions.id authorId: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var WORKSPACE_VERSIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, workspaceId: { type: "text", nullable: false }, versionNumber: { type: "integer", nullable: false }, name: { type: "text", nullable: false }, description: { type: "text", nullable: true }, filesystem: { type: "jsonb", nullable: true }, sandbox: { type: "jsonb", nullable: true }, mounts: { type: "jsonb", nullable: true }, search: { type: "jsonb", nullable: true }, skills: { type: "jsonb", nullable: true }, tools: { type: "jsonb", nullable: true }, autoSync: { type: "boolean", nullable: true }, operationTimeout: { type: "integer", nullable: true }, changedFields: { type: "jsonb", nullable: true }, changeMessage: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var SKILLS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, status: { type: "text", nullable: false }, // 'draft', 'published', or 'archived' activeVersionId: { type: "text", nullable: true }, // FK to skill_versions.id authorId: { type: "text", nullable: true }, visibility: { type: "text", nullable: true }, // 'private' | 'public' | null (legacy) favoriteCount: { type: "integer", nullable: true }, // Denormalised count of favorites for this skill createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var FAVORITES_SCHEMA = { userId: { type: "text", nullable: false }, entityType: { type: "text", nullable: false }, // 'agent' | 'skill' entityId: { type: "text", nullable: false }, createdAt: { type: "timestamp", nullable: false } }; var SKILL_VERSIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, skillId: { type: "text", nullable: false }, versionNumber: { type: "integer", nullable: false }, name: { type: "text", nullable: false }, description: { type: "text", nullable: false }, instructions: { type: "text", nullable: false }, license: { type: "text", nullable: true }, compatibility: { type: "jsonb", nullable: true }, source: { type: "jsonb", nullable: true }, references: { type: "jsonb", nullable: true }, scripts: { type: "jsonb", nullable: true }, assets: { type: "jsonb", nullable: true }, files: { type: "jsonb", nullable: true }, metadata: { type: "jsonb", nullable: true }, tree: { type: "jsonb", nullable: true }, changedFields: { type: "jsonb", nullable: true }, changeMessage: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var SKILL_BLOBS_SCHEMA = { hash: { type: "text", nullable: false, primaryKey: true }, content: { type: "text", nullable: false }, size: { type: "integer", nullable: false }, mimeType: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var OBSERVATIONAL_MEMORY_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, lookupKey: { type: "text", nullable: false }, // 'resource:{resourceId}' or 'thread:{threadId}' scope: { type: "text", nullable: false }, // 'resource' or 'thread' resourceId: { type: "text", nullable: true }, threadId: { type: "text", nullable: true }, activeObservations: { type: "text", nullable: false }, // JSON array of observations activeObservationsPendingUpdate: { type: "text", nullable: true }, // JSON array, used during updates originType: { type: "text", nullable: false }, // 'initialization', 'observation', or 'reflection' config: { type: "text", nullable: false }, // JSON object generationCount: { type: "integer", nullable: false }, lastObservedAt: { type: "timestamp", nullable: true }, lastReflectionAt: { type: "timestamp", nullable: true }, pendingMessageTokens: { type: "integer", nullable: false }, // Token count totalTokensObserved: { type: "integer", nullable: false }, // Running total of all observed tokens observationTokenCount: { type: "integer", nullable: false }, // Current observation size in tokens isObserving: { type: "boolean", nullable: false }, isReflecting: { type: "boolean", nullable: false }, observedMessageIds: { type: "jsonb", nullable: true }, // JSON array of message IDs already observed observedTimezone: { type: "text", nullable: true }, // Timezone used for Observer date formatting (e.g., "America/Los_Angeles") // Async buffering columns bufferedObservations: { type: "text", nullable: true }, // JSON string of buffered observation content bufferedObservationTokens: { type: "integer", nullable: true }, // Token count of buffered observations bufferedMessageIds: { type: "jsonb", nullable: true }, // JSON array of message IDs in the buffer bufferedReflection: { type: "text", nullable: true }, // JSON string of buffered reflection content bufferedReflectionTokens: { type: "integer", nullable: true }, // Token count of buffered reflection (post-compression) bufferedReflectionInputTokens: { type: "integer", nullable: true }, // Token count of observations fed to reflector (pre-compression) reflectedObservationLineCount: { type: "integer", nullable: true }, // Number of observation lines that were reflected on during async buffering bufferedObservationChunks: { type: "jsonb", nullable: true }, // JSON array of BufferedObservationChunk objects isBufferingObservation: { type: "boolean", nullable: false }, isBufferingReflection: { type: "boolean", nullable: false }, lastBufferedAtTokens: { type: "integer", nullable: false }, lastBufferedAtTime: { type: "timestamp", nullable: true }, metadata: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var DATASETS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, name: { type: "text", nullable: false }, description: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, inputSchema: { type: "jsonb", nullable: true }, groundTruthSchema: { type: "jsonb", nullable: true }, requestContextSchema: { type: "jsonb", nullable: true }, tags: { type: "jsonb", nullable: true }, targetType: { type: "text", nullable: true }, targetIds: { type: "jsonb", nullable: true }, scorerIds: { type: "jsonb", nullable: true }, version: { type: "integer", nullable: false }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var DATASET_ITEMS_SCHEMA = { id: { type: "text", nullable: false }, datasetId: { type: "text", nullable: false, references: { table: "mastra_datasets", column: "id" } }, datasetVersion: { type: "integer", nullable: false }, validTo: { type: "integer", nullable: true }, isDeleted: { type: "boolean", nullable: false }, input: { type: "jsonb", nullable: false }, groundTruth: { type: "jsonb", nullable: true }, requestContext: { type: "jsonb", nullable: true }, metadata: { type: "jsonb", nullable: true }, source: { type: "jsonb", nullable: true }, expectedTrajectory: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var DATASET_VERSIONS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, datasetId: { type: "text", nullable: false, references: { table: "mastra_datasets", column: "id" } }, version: { type: "integer", nullable: false }, createdAt: { type: "timestamp", nullable: false } }; var EXPERIMENTS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, name: { type: "text", nullable: true }, description: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, datasetId: { type: "text", nullable: true, references: { table: "mastra_datasets", column: "id" } }, datasetVersion: { type: "integer", nullable: true }, targetType: { type: "text", nullable: false }, targetId: { type: "text", nullable: false }, status: { type: "text", nullable: false }, totalItems: { type: "integer", nullable: false }, succeededCount: { type: "integer", nullable: false }, failedCount: { type: "integer", nullable: false }, skippedCount: { type: "integer", nullable: false }, startedAt: { type: "timestamp", nullable: true }, completedAt: { type: "timestamp", nullable: true }, agentVersion: { type: "text", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }; var EXPERIMENT_RESULTS_SCHEMA = { id: { type: "text", nullable: false, primaryKey: true }, experimentId: { type: "text", nullable: false, references: { table: "mastra_experiments", column: "id" } }, itemId: { type: "text", nullable: false, references: { table: "mastra_dataset_items", column: "id" } }, itemDatasetVersion: { type: "integer", nullable: true }, input: { type: "jsonb", nullable: false }, output: { type: "jsonb", nullable: true }, groundTruth: { type: "jsonb", nullable: true }, error: { type: "jsonb", nullable: true }, startedAt: { type: "timestamp", nullable: false }, completedAt: { type: "timestamp", nullable: false }, retryCount: { type: "integer", nullable: false }, traceId: { type: "text", nullable: true }, status: { type: "text", nullable: true }, tags: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false } }; var TABLE_SCHEMAS = { [TABLE_WORKFLOW_SNAPSHOT]: { workflow_name: { type: "text" }, run_id: { type: "text" }, resourceId: { type: "text", nullable: true }, snapshot: { type: "jsonb" }, createdAt: { type: "timestamp" }, updatedAt: { type: "timestamp" } }, [TABLE_SCORERS]: SCORERS_SCHEMA, [TABLE_THREADS]: { id: { type: "text", nullable: false, primaryKey: true }, resourceId: { type: "text", nullable: false }, title: { type: "text", nullable: false }, metadata: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }, [TABLE_MESSAGES]: { id: { type: "text", nullable: false, primaryKey: true }, thread_id: { type: "text", nullable: false }, content: { type: "text", nullable: false }, role: { type: "text", nullable: false }, type: { type: "text", nullable: false }, createdAt: { type: "timestamp", nullable: false }, resourceId: { type: "text", nullable: true } }, [TABLE_SPANS]: SPAN_SCHEMA, [TABLE_TRACES]: { id: { type: "text", nullable: false, primaryKey: true }, parentSpanId: { type: "text", nullable: true }, name: { type: "text", nullable: false }, traceId: { type: "text", nullable: false }, scope: { type: "text", nullable: false }, kind: { type: "integer", nullable: false }, attributes: { type: "jsonb", nullable: true }, status: { type: "jsonb", nullable: true }, events: { type: "jsonb", nullable: true }, links: { type: "jsonb", nullable: true }, other: { type: "text", nullable: true }, startTime: { type: "bigint", nullable: false }, endTime: { type: "bigint", nullable: false }, createdAt: { type: "timestamp", nullable: false } }, [TABLE_RESOURCES]: { id: { type: "text", nullable: false, primaryKey: true }, workingMemory: { type: "text", nullable: true }, metadata: { type: "jsonb", nullable: true }, createdAt: { type: "timestamp", nullable: false }, updatedAt: { type: "timestamp", nullable: false } }, [TABLE_AGENTS]: AGENTS_SCHEMA, [TABLE_AG