UNPKG

@mastra/core

Version:

Mastra is the Typescript framework for building AI agents and assistants. It’s used by some of the largest companies in the world to build internal AI automation tooling and customer-facing agents.

1,383 lines (1,368 loc) • 61.9 kB
'use strict'; var chunkO6PQYYT6_cjs = require('../chunk-O6PQYYT6.cjs'); var chunkXUAWHRUO_cjs = require('../chunk-XUAWHRUO.cjs'); var chunkICE3AMTD_cjs = require('../chunk-ICE3AMTD.cjs'); var chunkC73WLCY3_cjs = require('../chunk-C73WLCY3.cjs'); var chunk4L3P3PCP_cjs = require('../chunk-4L3P3PCP.cjs'); // src/storage/domains/legacy-evals/base.ts var LegacyEvalsStorage = class extends chunk4L3P3PCP_cjs.MastraBase { constructor() { super({ component: "STORAGE", name: "LEGACY_EVALS" }); } }; // src/storage/domains/legacy-evals/inmemory.ts var InMemoryLegacyEvals = class extends LegacyEvalsStorage { collection; constructor({ collection }) { super(); this.collection = collection; } async getEvals(options) { this.logger.debug(`MockStore: getEvals called`, options); let evals = Array.from(this.collection.values()); if (options.agentName) { evals = evals.filter((evalR) => evalR.agent_name === options.agentName); } if (options.type === "test") { evals = evals.filter((evalR) => evalR.test_info && evalR.test_info.testPath); } else if (options.type === "live") { evals = evals.filter((evalR) => !evalR.test_info || !evalR.test_info.testPath); } if (options.dateRange?.start) { evals = evals.filter((evalR) => new Date(evalR.created_at) >= options.dateRange.start); } if (options.dateRange?.end) { evals = evals.filter((evalR) => new Date(evalR.created_at) <= options.dateRange.end); } evals.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); const total = evals.length; const page = options.page || 0; const perPage = options.perPage || 100; const start = page * perPage; const end = start + perPage; return { evals: evals.slice(start, end).map((e) => ({ agentName: e.agent_name, input: e.input, output: e.output, instructions: e.instructions, result: e.result, createdAt: e.created_at.toISOString(), testInfo: e.test_info, metricName: e.metric_name, runId: e.run_id, globalRunId: e.global_run_id })), total, page, perPage, hasMore: total > end }; } async getEvalsByAgentName(agentName, type) { this.logger.debug(`MockStore: getEvalsByAgentName called for ${agentName}`); let evals = Array.from(this.collection.values()).filter((e) => e.agent_name === agentName); if (type === "test") { evals = evals.filter((e) => e.test_info && e.test_info.testPath); } else if (type === "live") { evals = evals.filter((e) => !e.test_info || !e.test_info.testPath); } return evals.sort( (a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime() ).map((e) => ({ agentName: e.agent_name, input: e.input, output: e.output, instructions: e.instructions, result: e.result, createdAt: e.created_at.toISOString(), metricName: e.metric_name, runId: e.run_id, testInfo: e.test_info, globalRunId: e.global_run_id })); } }; // src/storage/domains/memory/base.ts var MemoryStorage = class extends chunk4L3P3PCP_cjs.MastraBase { constructor() { super({ component: "STORAGE", name: "MEMORY" }); } async deleteMessages(_messageIds) { throw new Error( `Message deletion is not supported by this storage adapter (${this.constructor.name}). The deleteMessages method needs to be implemented in the storage adapter.` ); } async getResourceById(_) { throw new Error( `Resource working memory is not supported by this storage adapter (${this.constructor.name}). Supported storage adapters: LibSQL (@mastra/libsql), PostgreSQL (@mastra/pg), Upstash (@mastra/upstash). To use per-resource working memory, switch to one of these supported storage adapters.` ); } async saveResource(_) { throw new Error( `Resource working memory is not supported by this storage adapter (${this.constructor.name}). Supported storage adapters: LibSQL (@mastra/libsql), PostgreSQL (@mastra/pg), Upstash (@mastra/upstash). To use per-resource working memory, switch to one of these supported storage adapters.` ); } async updateResource(_) { throw new Error( `Resource working memory is not supported by this storage adapter (${this.constructor.name}). Supported storage adapters: LibSQL (@mastra/libsql), PostgreSQL (@mastra/pg), Upstash (@mastra/upstash). To use per-resource working memory, switch to one of these supported storage adapters.` ); } castThreadOrderBy(v) { return v in THREAD_ORDER_BY_SET ? v : "createdAt"; } castThreadSortDirection(v) { return v in THREAD_THREAD_SORT_DIRECTION_SET ? v : "DESC"; } }; var THREAD_ORDER_BY_SET = { createdAt: true, updatedAt: true }; var THREAD_THREAD_SORT_DIRECTION_SET = { ASC: true, DESC: true }; // src/storage/domains/memory/inmemory.ts var InMemoryMemory = class extends MemoryStorage { collection; operations; constructor({ collection, operations }) { super(); this.collection = collection; this.operations = operations; } async getThreadById({ threadId }) { this.logger.debug(`MockStore: getThreadById called for ${threadId}`); const thread = this.collection.threads.get(threadId); return thread ? { ...thread, metadata: thread.metadata ? { ...thread.metadata } : thread.metadata } : null; } async getThreadsByResourceId({ resourceId, orderBy, sortDirection }) { this.logger.debug(`MockStore: getThreadsByResourceId called for ${resourceId}`); const threads = Array.from(this.collection.threads.values()).filter((t) => t.resourceId === resourceId); const sortedThreads = this.sortThreads( threads, this.castThreadOrderBy(orderBy), this.castThreadSortDirection(sortDirection) ); return sortedThreads.map((thread) => ({ ...thread, metadata: thread.metadata ? { ...thread.metadata } : thread.metadata })); } async saveThread({ thread }) { this.logger.debug(`MockStore: saveThread called for ${thread.id}`); const key = thread.id; this.collection.threads.set(key, thread); return thread; } async updateThread({ id, title, metadata }) { this.logger.debug(`MockStore: updateThread called for ${id}`); const thread = this.collection.threads.get(id); if (!thread) { throw new Error(`Thread with id ${id} not found`); } if (thread) { thread.title = title; thread.metadata = { ...thread.metadata, ...metadata }; thread.updatedAt = /* @__PURE__ */ new Date(); } return thread; } async deleteThread({ threadId }) { this.logger.debug(`MockStore: deleteThread called for ${threadId}`); this.collection.threads.delete(threadId); this.collection.messages.forEach((msg, key) => { if (msg.thread_id === threadId) { this.collection.messages.delete(key); } }); } async getMessages({ threadId, selectBy }) { this.logger.debug(`MockStore: getMessages called for thread ${threadId}`); if (!threadId.trim()) throw new Error("threadId must be a non-empty string"); const messages = []; if (selectBy?.include && selectBy.include.length > 0) { for (const includeItem of selectBy.include) { const targetMessage = this.collection.messages.get(includeItem.id); if (targetMessage) { const convertedMessage = { id: targetMessage.id, threadId: targetMessage.thread_id, content: typeof targetMessage.content === "string" ? JSON.parse(targetMessage.content) : targetMessage.content, role: targetMessage.role, type: targetMessage.type, createdAt: targetMessage.createdAt, resourceId: targetMessage.resourceId }; messages.push(convertedMessage); if (includeItem.withPreviousMessages) { const allThreadMessages = Array.from(this.collection.messages.values()).filter((msg) => msg.thread_id === includeItem.threadId).sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()); const targetIndex = allThreadMessages.findIndex((msg) => msg.id === includeItem.id); if (targetIndex !== -1) { const startIndex = Math.max(0, targetIndex - (includeItem.withPreviousMessages || 0)); for (let i = startIndex; i < targetIndex; i++) { const message = allThreadMessages[i]; if (message && !messages.some((m) => m.id === message.id)) { const convertedPrevMessage = { id: message.id, threadId: message.thread_id, content: typeof message.content === "string" ? JSON.parse(message.content) : message.content, role: message.role, type: message.type, createdAt: message.createdAt, resourceId: message.resourceId }; messages.push(convertedPrevMessage); } } } } if (includeItem.withNextMessages) { const allThreadMessages = Array.from(this.collection.messages.values()).filter((msg) => msg.thread_id === includeItem.threadId).sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()); const targetIndex = allThreadMessages.findIndex((msg) => msg.id === includeItem.id); if (targetIndex !== -1) { const endIndex = Math.min( allThreadMessages.length, targetIndex + (includeItem.withNextMessages || 0) + 1 ); for (let i = targetIndex + 1; i < endIndex; i++) { const message = allThreadMessages[i]; if (message && !messages.some((m) => m.id === message.id)) { const convertedNextMessage = { id: message.id, threadId: message.thread_id, content: typeof message.content === "string" ? JSON.parse(message.content) : message.content, role: message.role, type: message.type, createdAt: message.createdAt, resourceId: message.resourceId }; messages.push(convertedNextMessage); } } } } } } } if (!selectBy?.include || selectBy.include.length === 0 || selectBy?.last) { let threadMessages = Array.from(this.collection.messages.values()).filter((msg) => msg.thread_id === threadId).filter((msg) => !messages.some((m) => m.id === msg.id)); if (selectBy?.last) { threadMessages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()); const lastMessages = threadMessages.slice(-selectBy.last); for (const msg of lastMessages) { const convertedMessage = { id: msg.id, threadId: msg.thread_id, content: typeof msg.content === "string" ? JSON.parse(msg.content) : msg.content, role: msg.role, type: msg.type, createdAt: msg.createdAt, resourceId: msg.resourceId }; messages.push(convertedMessage); } } else if (!selectBy?.include || selectBy.include.length === 0) { for (const msg of threadMessages) { const convertedMessage = this.parseStoredMessage(msg); messages.push(convertedMessage); } } } messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()); return messages; } parseStoredMessage(message) { const { resourceId, content, role, thread_id, ...rest } = message; return { ...rest, threadId: thread_id, ...message.resourceId && { resourceId: message.resourceId }, content: typeof content === "string" ? content : JSON.parse(content), role }; } async getMessagesById({ messageIds, format }) { this.logger.debug(`MockStore: getMessagesById called`); const rawMessages = messageIds.map((id) => this.collection.messages.get(id)).filter((message) => !!message); const list = new chunkICE3AMTD_cjs.MessageList().add(rawMessages.map(this.parseStoredMessage), "memory"); if (format === "v1") return list.get.all.v1(); return list.get.all.v2(); } async saveMessages(args) { const { messages, format = "v1" } = args; this.logger.debug(`MockStore: saveMessages called with ${messages.length} messages`); if (messages.some((msg) => msg.id === "error-message" || msg.resourceId === null)) { throw new Error("Simulated error for testing"); } const threadIds = new Set(messages.map((msg) => msg.threadId).filter((id) => Boolean(id))); for (const threadId of threadIds) { const thread = this.collection.threads.get(threadId); if (thread) { thread.updatedAt = /* @__PURE__ */ new Date(); } } for (const message of messages) { const key = message.id; const storageMessage = { id: message.id, thread_id: message.threadId || "", content: typeof message.content === "string" ? message.content : JSON.stringify(message.content), role: message.role || "user", type: message.type || "text", createdAt: message.createdAt, resourceId: message.resourceId || null }; this.collection.messages.set(key, storageMessage); } const list = new chunkICE3AMTD_cjs.MessageList().add(messages, "memory"); if (format === `v2`) return list.get.all.v2(); return list.get.all.v1(); } async updateMessages(args) { const updatedMessages = []; for (const update of args.messages) { const storageMsg = this.collection.messages.get(update.id); if (!storageMsg) continue; const oldThreadId = storageMsg.thread_id; const newThreadId = update.threadId || oldThreadId; let threadIdChanged = false; if (update.threadId && update.threadId !== oldThreadId) { threadIdChanged = true; } if (update.role !== void 0) storageMsg.role = update.role; if (update.type !== void 0) storageMsg.type = update.type; if (update.createdAt !== void 0) storageMsg.createdAt = update.createdAt; if (update.resourceId !== void 0) storageMsg.resourceId = update.resourceId; if (update.content !== void 0) { let oldContent = typeof storageMsg.content === "string" ? JSON.parse(storageMsg.content) : storageMsg.content; let newContent = update.content; if (typeof newContent === "object" && typeof oldContent === "object") { newContent = { ...oldContent, ...newContent }; if (oldContent.metadata && newContent.metadata) { newContent.metadata = { ...oldContent.metadata, ...newContent.metadata }; } } storageMsg.content = JSON.stringify(newContent); } if (threadIdChanged) { storageMsg.thread_id = newThreadId; const base = Date.now(); let oldThreadNewTime; const oldThread = this.collection.threads.get(oldThreadId); if (oldThread) { const prev = new Date(oldThread.updatedAt).getTime(); oldThreadNewTime = Math.max(base, prev + 1); oldThread.updatedAt = new Date(oldThreadNewTime); } const newThread = this.collection.threads.get(newThreadId); if (newThread) { const prev = new Date(newThread.updatedAt).getTime(); let newThreadNewTime = Math.max(base + 1, prev + 1); if (oldThreadNewTime !== void 0 && newThreadNewTime <= oldThreadNewTime) { newThreadNewTime = oldThreadNewTime + 1; } newThread.updatedAt = new Date(newThreadNewTime); } } else { const thread = this.collection.threads.get(oldThreadId); if (thread) { const prev = new Date(thread.updatedAt).getTime(); let newTime = Date.now(); if (newTime <= prev) newTime = prev + 1; thread.updatedAt = new Date(newTime); } } this.collection.messages.set(update.id, storageMsg); updatedMessages.push({ id: storageMsg.id, threadId: storageMsg.thread_id, content: typeof storageMsg.content === "string" ? JSON.parse(storageMsg.content) : storageMsg.content, role: storageMsg.role === "user" || storageMsg.role === "assistant" ? storageMsg.role : "user", type: storageMsg.type, createdAt: storageMsg.createdAt, resourceId: storageMsg.resourceId === null ? void 0 : storageMsg.resourceId }); } return updatedMessages; } async deleteMessages(messageIds) { if (!messageIds || messageIds.length === 0) { return; } this.logger.debug(`MockStore: deleteMessages called for ${messageIds.length} messages`); const threadIds = /* @__PURE__ */ new Set(); for (const messageId of messageIds) { const message = this.collection.messages.get(messageId); if (message && message.thread_id) { threadIds.add(message.thread_id); } this.collection.messages.delete(messageId); } const now = /* @__PURE__ */ new Date(); for (const threadId of threadIds) { const thread = this.collection.threads.get(threadId); if (thread) { thread.updatedAt = now; } } } async getThreadsByResourceIdPaginated(args) { const { resourceId, page, perPage, orderBy, sortDirection } = args; this.logger.debug(`MockStore: getThreadsByResourceIdPaginated called for ${resourceId}`); const threads = Array.from(this.collection.threads.values()).filter((t) => t.resourceId === resourceId); const sortedThreads = this.sortThreads( threads, this.castThreadOrderBy(orderBy), this.castThreadSortDirection(sortDirection) ); const clonedThreads = sortedThreads.map((thread) => ({ ...thread, metadata: thread.metadata ? { ...thread.metadata } : thread.metadata })); return { threads: clonedThreads.slice(page * perPage, (page + 1) * perPage), total: clonedThreads.length, page, perPage, hasMore: clonedThreads.length > (page + 1) * perPage }; } async getMessagesPaginated({ threadId, selectBy }) { this.logger.debug(`MockStore: getMessagesPaginated called for thread ${threadId}`); if (!threadId.trim()) throw new Error("threadId must be a non-empty string"); const { page = 0, perPage = 40 } = selectBy?.pagination || {}; const messages = []; if (selectBy?.include && selectBy.include.length > 0) { for (const includeItem of selectBy.include) { const targetMessage = this.collection.messages.get(includeItem.id); if (targetMessage) { const convertedMessage = { id: targetMessage.id, threadId: targetMessage.thread_id, content: typeof targetMessage.content === "string" ? JSON.parse(targetMessage.content) : targetMessage.content, role: targetMessage.role, type: targetMessage.type, createdAt: targetMessage.createdAt, resourceId: targetMessage.resourceId }; messages.push(convertedMessage); if (includeItem.withPreviousMessages) { const allThreadMessages = Array.from(this.collection.messages.values()).filter((msg) => msg.thread_id === includeItem.threadId).sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()); const targetIndex = allThreadMessages.findIndex((msg) => msg.id === includeItem.id); if (targetIndex !== -1) { const startIndex = Math.max(0, targetIndex - (includeItem.withPreviousMessages || 0)); for (let i = startIndex; i < targetIndex; i++) { const message = allThreadMessages[i]; if (message && !messages.some((m) => m.id === message.id)) { const convertedPrevMessage = { id: message.id, threadId: message.thread_id, content: typeof message.content === "string" ? JSON.parse(message.content) : message.content, role: message.role, type: message.type, createdAt: message.createdAt, resourceId: message.resourceId }; messages.push(convertedPrevMessage); } } } } if (includeItem.withNextMessages) { const allThreadMessages = Array.from(this.collection.messages.values()).filter((msg) => msg.thread_id === includeItem.threadId).sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()); const targetIndex = allThreadMessages.findIndex((msg) => msg.id === includeItem.id); if (targetIndex !== -1) { const endIndex = Math.min( allThreadMessages.length, targetIndex + (includeItem.withNextMessages || 0) + 1 ); for (let i = targetIndex + 1; i < endIndex; i++) { const message = allThreadMessages[i]; if (message && !messages.some((m) => m.id === message.id)) { const convertedNextMessage = { id: message.id, threadId: message.thread_id, content: typeof message.content === "string" ? JSON.parse(message.content) : message.content, role: message.role, type: message.type, createdAt: message.createdAt, resourceId: message.resourceId }; messages.push(convertedNextMessage); } } } } } } } if (!selectBy?.include || selectBy.include.length === 0 || selectBy?.last) { let threadMessages = Array.from(this.collection.messages.values()).filter((msg) => msg.thread_id === threadId).filter((msg) => !messages.some((m) => m.id === msg.id)); if (selectBy?.pagination?.dateRange) { const { start: from, end: to } = selectBy.pagination.dateRange; threadMessages = threadMessages.filter((msg) => { const msgDate = new Date(msg.createdAt); const fromDate = from ? new Date(from) : null; const toDate = to ? new Date(to) : null; if (fromDate && msgDate < fromDate) return false; if (toDate && msgDate > toDate) return false; return true; }); } if (selectBy?.last) { threadMessages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()); const lastMessages = threadMessages.slice(-selectBy.last); for (const msg of lastMessages) { const convertedMessage = { id: msg.id, threadId: msg.thread_id, content: typeof msg.content === "string" ? JSON.parse(msg.content) : msg.content, role: msg.role, type: msg.type, createdAt: msg.createdAt, resourceId: msg.resourceId }; messages.push(convertedMessage); } } else if (!selectBy?.include || selectBy.include.length === 0) { for (const msg of threadMessages) { const convertedMessage = { id: msg.id, threadId: msg.thread_id, content: typeof msg.content === "string" ? JSON.parse(msg.content) : msg.content, role: msg.role, type: msg.type, createdAt: msg.createdAt, resourceId: msg.resourceId }; messages.push(convertedMessage); } } } messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()); const start = page * perPage; const end = start + perPage; return { messages: messages.slice(start, end), total: messages.length, page, perPage, hasMore: messages.length > end }; } async getResourceById({ resourceId }) { this.logger.debug(`MockStore: getResourceById called for ${resourceId}`); const resource = this.collection.resources.get(resourceId); return resource ? { ...resource, metadata: resource.metadata ? { ...resource.metadata } : resource.metadata } : null; } async saveResource({ resource }) { this.logger.debug(`MockStore: saveResource called for ${resource.id}`); this.collection.resources.set(resource.id, resource); return resource; } async updateResource({ resourceId, workingMemory, metadata }) { this.logger.debug(`MockStore: updateResource called for ${resourceId}`); let resource = this.collection.resources.get(resourceId); if (!resource) { resource = { id: resourceId, workingMemory, metadata: metadata || {}, createdAt: /* @__PURE__ */ new Date(), updatedAt: /* @__PURE__ */ new Date() }; } else { resource = { ...resource, workingMemory: workingMemory !== void 0 ? workingMemory : resource.workingMemory, metadata: { ...resource.metadata, ...metadata }, updatedAt: /* @__PURE__ */ new Date() }; } this.collection.resources.set(resourceId, resource); return resource; } sortThreads(threads, orderBy, sortDirection) { return threads.sort((a, b) => { const aValue = new Date(a[orderBy]).getTime(); const bValue = new Date(b[orderBy]).getTime(); if (sortDirection === "ASC") { return aValue - bValue; } else { return bValue - aValue; } }); } }; // src/storage/domains/observability/base.ts var ObservabilityStorage = class extends chunk4L3P3PCP_cjs.MastraBase { constructor() { super({ component: "STORAGE", name: "OBSERVABILITY" }); } /** * Provides hints for AI tracing strategy selection by the DefaultExporter. * Storage adapters can override this to specify their preferred and supported strategies. */ get aiTracingStrategy() { return { preferred: "batch-with-updates", // Default for most SQL stores supported: ["realtime", "batch-with-updates", "insert-only"] }; } /** * Creates a single AI span record in the storage provider. */ createAISpan(_span) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_CREATE_AI_SPAN_NOT_IMPLEMENTED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "This storage provider does not support creating AI spans" }); } /** * Updates a single AI span with partial data. Primarily used for realtime trace creation. */ updateAISpan(_params) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_STORAGE_UPDATE_AI_SPAN_NOT_IMPLEMENTED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "This storage provider does not support updating AI spans" }); } /** * Retrieves a single AI trace with all its associated spans. */ getAITrace(_traceId) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_STORAGE_GET_AI_TRACE_NOT_IMPLEMENTED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "This storage provider does not support getting AI traces" }); } /** * Retrieves a paginated list of AI traces with optional filtering. */ getAITracesPaginated(_args) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_STORAGE_GET_AI_TRACES_PAGINATED_NOT_IMPLEMENTED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "This storage provider does not support getting AI traces paginated" }); } /** * Creates multiple AI spans in a single batch. */ batchCreateAISpans(_args) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_STORAGE_BATCH_CREATE_AI_SPAN_NOT_IMPLEMENTED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "This storage provider does not support batch creating AI spans" }); } /** * Updates multiple AI spans in a single batch. */ batchUpdateAISpans(_args) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_STORAGE_BATCH_UPDATE_AI_SPAN_NOT_IMPLEMENTED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "This storage provider does not support batch updating AI spans" }); } /** * Deletes multiple AI traces and all their associated spans in a single batch operation. */ batchDeleteAITraces(_args) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_STORAGE_BATCH_DELETE_AI_SPAN_NOT_IMPLEMENTED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "This storage provider does not support batch deleting AI traces" }); } }; // src/storage/domains/observability/inmemory.ts var ObservabilityInMemory = class extends ObservabilityStorage { operations; collection; constructor({ collection, operations }) { super(); this.collection = collection; this.operations = operations; } get aiTracingStrategy() { return { preferred: "realtime", supported: ["realtime", "batch-with-updates", "insert-only"] }; } async createAISpan(span) { this.validateCreateAISpan(span); const id = this.generateId(span); this.collection.set(id, span); } validateCreateAISpan(record) { if (!record.spanId) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_SPAN_ID_REQUIRED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "Span ID is required for creating a span" }); } if (!record.traceId) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_TRACE_ID_REQUIRED", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "Trace ID is required for creating a span" }); } } generateId({ traceId, spanId }) { return `${traceId}-${spanId}`; } async getAITrace(traceId) { const spans = Array.from(this.collection.values()).filter((span) => span.traceId === traceId); if (spans.length === 0) { return null; } spans.sort((a, b) => a.startedAt.getTime() - b.startedAt.getTime()); return { traceId, spans }; } async getAITracesPaginated({ filters, pagination }) { const allRootSpans = this.filterForRootSpans(Array.from(this.collection.values())); const filteredRootSpans = this.filterSpansByFilter(allRootSpans, filters); const startDate = pagination?.dateRange?.start; const endDate = pagination?.dateRange?.end; const filteredRootSpansByDate = this.filterSpansByDate(filteredRootSpans, startDate, endDate); const total = filteredRootSpansByDate.length; const page = pagination?.page ?? 0; const perPage = pagination?.perPage ?? 10; const start = page * perPage; const end = start + perPage; const paged = this.filterSpansByPagination(filteredRootSpansByDate, pagination); return { spans: paged, pagination: { total, page, perPage, hasMore: end < total } }; } filterForRootSpans(spans) { return spans.filter((span) => span.parentSpanId === null); } filterSpansByDate(spans, startDate, endDate) { return spans.filter((span) => { if (startDate && span.startedAt < startDate) return false; if (endDate && span.startedAt > endDate) return false; return true; }); } filterSpansByFilter(spans, filter) { return spans.filter((span) => { if (filter?.name && span.name !== filter.name) return false; if (filter?.spanType && span.spanType !== filter.spanType) return false; if (filter?.entityType === "agent" && filter.entityId !== span.attributes?.agentId) return false; if (filter?.entityType === "workflow" && filter.entityId !== span.attributes?.workflowId) return false; return true; }); } filterSpansByPagination(spans, pagination) { const page = pagination?.page ?? 0; const perPage = pagination?.perPage ?? 10; const start = page * perPage; const end = start + perPage; return spans.slice(start, end); } async updateAISpan(params) { const id = this.generateId({ traceId: params.traceId, spanId: params.spanId }); const span = this.collection.get(id); if (!span) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_UPDATE_AI_SPAN_NOT_FOUND", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "Span not found for update" }); } this.collection.set(id, { ...span, ...params.updates }); } async batchCreateAISpans(args) { for (const record of args.records) { this.validateCreateAISpan(record); const id = this.generateId({ traceId: record.traceId, spanId: record.spanId }); this.collection.set(id, record); } } async batchUpdateAISpans(args) { for (const record of args.records) { const id = this.generateId({ traceId: record.traceId, spanId: record.spanId }); const span = this.collection.get(id); if (!span) { throw new chunkC73WLCY3_cjs.MastraError({ id: "OBSERVABILITY_BATCH_UPDATE_AI_SPAN_NOT_FOUND", domain: "MASTRA_OBSERVABILITY" /* MASTRA_OBSERVABILITY */, category: "SYSTEM" /* SYSTEM */, text: "Span not found for batch update" }); } this.collection.set(id, { ...span, ...record.updates }); } } async batchDeleteAITraces(args) { for (const traceId of args.traceIds) { const spans = Array.from(this.collection.values()).filter((span) => span.traceId === traceId); for (const span of spans) { this.collection.delete(this.generateId({ traceId: span.traceId, spanId: span.spanId })); } } } }; // src/storage/domains/operations/base.ts var StoreOperations = class extends chunk4L3P3PCP_cjs.MastraBase { constructor() { super({ component: "STORAGE", name: "OPERATIONS" }); } getSqlType(type) { switch (type) { case "text": return "TEXT"; case "timestamp": return "TIMESTAMP"; case "float": return "FLOAT"; case "integer": return "INTEGER"; case "bigint": return "BIGINT"; case "jsonb": return "JSONB"; default: return "TEXT"; } } getDefaultValue(type) { switch (type) { case "text": case "uuid": return "DEFAULT ''"; case "timestamp": return "DEFAULT '1970-01-01 00:00:00'"; case "integer": case "bigint": case "float": return "DEFAULT 0"; case "jsonb": return "DEFAULT '{}'"; default: return "DEFAULT ''"; } } /** * DATABASE INDEX MANAGEMENT * Optional methods for database index management. * Storage adapters can override these to provide index management capabilities. */ /** * Creates a database index on specified columns * @throws {MastraError} if not supported by the storage adapter */ async createIndex(_options) { throw new chunkC73WLCY3_cjs.MastraError({ id: "MASTRA_STORAGE_CREATE_INDEX_NOT_SUPPORTED", domain: "STORAGE" /* STORAGE */, category: "SYSTEM" /* SYSTEM */, text: `Index management is not supported by this storage adapter` }); } /** * Drops a database index by name * @throws {MastraError} if not supported by the storage adapter */ async dropIndex(_indexName) { throw new chunkC73WLCY3_cjs.MastraError({ id: "MASTRA_STORAGE_DROP_INDEX_NOT_SUPPORTED", domain: "STORAGE" /* STORAGE */, category: "SYSTEM" /* SYSTEM */, text: `Index management is not supported by this storage adapter` }); } /** * Lists database indexes for a table or all tables * @throws {MastraError} if not supported by the storage adapter */ async listIndexes(_tableName) { throw new chunkC73WLCY3_cjs.MastraError({ id: "MASTRA_STORAGE_LIST_INDEXES_NOT_SUPPORTED", domain: "STORAGE" /* STORAGE */, category: "SYSTEM" /* SYSTEM */, text: `Index management is not supported by this storage adapter` }); } /** * Gets detailed statistics for a specific index * @throws {MastraError} if not supported by the storage adapter */ async describeIndex(_indexName) { throw new chunkC73WLCY3_cjs.MastraError({ id: "MASTRA_STORAGE_DESCRIBE_INDEX_NOT_SUPPORTED", domain: "STORAGE" /* STORAGE */, category: "SYSTEM" /* SYSTEM */, text: `Index management is not supported by this storage adapter` }); } }; // src/storage/domains/operations/inmemory.ts var StoreOperationsInMemory = class extends StoreOperations { data; constructor() { super(); this.data = { mastra_workflow_snapshot: /* @__PURE__ */ new Map(), mastra_evals: /* @__PURE__ */ new Map(), mastra_messages: /* @__PURE__ */ new Map(), mastra_threads: /* @__PURE__ */ new Map(), mastra_traces: /* @__PURE__ */ new Map(), mastra_resources: /* @__PURE__ */ new Map(), mastra_scorers: /* @__PURE__ */ new Map(), mastra_ai_spans: /* @__PURE__ */ new Map() }; } getDatabase() { return this.data; } async insert({ tableName, record }) { const table = this.data[tableName]; let key = record.id; if ([chunkXUAWHRUO_cjs.TABLE_WORKFLOW_SNAPSHOT, chunkXUAWHRUO_cjs.TABLE_EVALS].includes(tableName) && !record.id && record.run_id) { key = record.workflow_name ? `${record.workflow_name}-${record.run_id}` : record.run_id; record.id = key; } else if (!record.id) { key = `auto-${Date.now()}-${Math.random()}`; record.id = key; } table.set(key, record); } async batchInsert({ tableName, records }) { const table = this.data[tableName]; for (const record of records) { let key = record.id; if ([chunkXUAWHRUO_cjs.TABLE_WORKFLOW_SNAPSHOT, chunkXUAWHRUO_cjs.TABLE_EVALS].includes(tableName) && !record.id && record.run_id) { key = record.run_id; record.id = key; } else if (!record.id) { key = `auto-${Date.now()}-${Math.random()}`; record.id = key; } table.set(key, record); } } async load({ tableName, keys }) { this.logger.debug(`MockStore: load called for ${tableName} with keys`, keys); const table = this.data[tableName]; const records = Array.from(table.values()); return records.filter((record) => Object.keys(keys).every((key) => record[key] === keys[key]))?.[0]; } async createTable({ tableName, schema }) { this.logger.debug(`MockStore: createTable called for ${tableName} with schema`, schema); this.data[tableName] = /* @__PURE__ */ new Map(); } async clearTable({ tableName }) { this.logger.debug(`MockStore: clearTable called for ${tableName}`); this.data[tableName].clear(); } async dropTable({ tableName }) { this.logger.debug(`MockStore: dropTable called for ${tableName}`); this.data[tableName].clear(); } async alterTable({ tableName, schema }) { this.logger.debug(`MockStore: alterTable called for ${tableName} with schema`, schema); } async hasColumn(table, column) { this.logger.debug(`MockStore: hasColumn called for ${table} with column ${column}`); return true; } }; // src/storage/domains/scores/base.ts var ScoresStorage = class extends chunk4L3P3PCP_cjs.MastraBase { constructor() { super({ component: "STORAGE", name: "SCORES" }); } }; // src/storage/domains/scores/inmemory.ts var ScoresInMemory = class extends ScoresStorage { scores; constructor({ collection }) { super(); this.scores = collection; } async getScoreById({ id }) { return this.scores.get(id) ?? null; } async saveScore(score) { const newScore = { id: crypto.randomUUID(), createdAt: /* @__PURE__ */ new Date(), updatedAt: /* @__PURE__ */ new Date(), ...score }; this.scores.set(newScore.id, newScore); return { score: newScore }; } async getScoresByScorerId({ scorerId, pagination, entityId, entityType, source }) { const scores = Array.from(this.scores.values()).filter((score) => { let baseFilter = score.scorerId === scorerId; if (entityId) { baseFilter = baseFilter && score.entityId === entityId; } if (entityType) { baseFilter = baseFilter && score.entityType === entityType; } if (source) { baseFilter = baseFilter && score.source === source; } return baseFilter; }); return { scores: scores.slice(pagination.page * pagination.perPage, (pagination.page + 1) * pagination.perPage), pagination: { total: scores.length, page: pagination.page, perPage: pagination.perPage, hasMore: scores.length > (pagination.page + 1) * pagination.perPage } }; } async getScoresByRunId({ runId, pagination }) { const scores = Array.from(this.scores.values()).filter((score) => score.runId === runId); return { scores: scores.slice(pagination.page * pagination.perPage, (pagination.page + 1) * pagination.perPage), pagination: { total: scores.length, page: pagination.page, perPage: pagination.perPage, hasMore: scores.length > (pagination.page + 1) * pagination.perPage } }; } async getScoresByEntityId({ entityId, entityType, pagination }) { const scores = Array.from(this.scores.values()).filter((score) => { const baseFilter = score.entityId === entityId && score.entityType === entityType; return baseFilter; }); return { scores: scores.slice(pagination.page * pagination.perPage, (pagination.page + 1) * pagination.perPage), pagination: { total: scores.length, page: pagination.page, perPage: pagination.perPage, hasMore: scores.length > (pagination.page + 1) * pagination.perPage } }; } }; // src/storage/domains/traces/base.ts var TracesStorage = class extends chunk4L3P3PCP_cjs.MastraBase { constructor() { super({ component: "STORAGE", name: "TRACES" }); } }; // src/storage/domains/traces/inmemory.ts var TracesInMemory = class extends TracesStorage { traces; operations; collection; constructor({ collection, operations }) { super(); this.collection = collection; this.traces = collection; this.operations = operations; } async getTraces({ name, scope, page, perPage, attributes, filters, fromDate, toDate }) { this.logger.debug(`MockStore: getTraces called`); let traces = Array.from(this.collection.values()); if (name) traces = traces.filter((t) => t.name?.startsWith(name)); if (scope) traces = traces.filter((t) => t.scope === scope); if (attributes) { traces = traces.filter( (t) => Object.entries(attributes).every(([key, value]) => t.attributes?.[key] === value) ); } if (filters) { traces = traces.filter((t) => Object.entries(filters).every(([key, value]) => t[key] === value)); } if (fromDate) traces = traces.filter((t) => new Date(t.createdAt) >= fromDate); if (toDate) traces = traces.filter((t) => new Date(t.createdAt) <= toDate); traces.sort((a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime()); const start = page * perPage; const end = start + perPage; return traces.slice(start, end); } async getTracesPaginated({ name, scope, attributes, page = 0, perPage = 10, dateRange }) { this.logger.debug(`MockStore: getTracesPaginated called`); let traces = Array.from(this.collection.values()); if (name) traces = traces.filter((t) => t.name?.startsWith(name)); if (scope) traces = traces.filter((t) => t.scope === scope); if (attributes) { traces = traces.filter( (t) => Object.entries(attributes).every(([key, value]) => t.attributes?.[key] === value) ); } if (dateRange?.start) traces = traces.filter((t) => new Date(t.createdAt) >= dateRange.start); if (dateRange?.end) traces = traces.filter((t) => new Date(t.createdAt) <= dateRange.end); traces.sort((a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime()); const start = page * perPage; const end = start + perPage; return { traces: traces.slice(start, end), total: traces.length, page, perPage, hasMore: traces.length > end }; } async batchTraceInsert({ records }) { this.logger.debug("Batch inserting traces", { count: records.length }); await this.operations.batchInsert({ tableName: chunkXUAWHRUO_cjs.TABLE_TRACES, records }); } }; // src/storage/domains/workflows/base.ts var WorkflowsStorage = class extends chunk4L3P3PCP_cjs.MastraBase { constructor() { super({ component: "STORAGE", name: "WORKFLOWS" }); } }; // src/storage/domains/workflows/inmemory.ts var WorkflowsInMemory = class extends WorkflowsStorage { operations; collection; constructor({ collection, operations }) { super(); this.collection = collection; this.operations = operations; } async updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext }) { this.logger.debug(`MockStore: updateWorkflowResults called for ${workflowName} ${runId} ${stepId}`, result); const run = this.collection.get(`${workflowName}-${runId}`); if (!run) { return {}; } let snapshot; if (!run.snapshot) { snapshot = { context: {}, activePaths: [], timestamp: Date.now(), suspendedPaths: {}, serializedStepGraph: [], value: {}, waitingPaths: {}, status: "pending", runId: run.run_id }; this.collection.set(`${workflowName}-${runId}`, { ...run, snapshot }); } snapshot = typeof run.snapshot === "string" ? JSON.parse(run.snapshot) : run.snapshot; if (!snapshot || !snapshot?.context) { throw new Error(`Snapshot not found for runId ${runId}`); } snapshot.context[stepId] = result; snapshot.runtimeContext = { ...snapshot.runtimeContext, ...runtimeContext }; this.collection.set(`${workflowName}-${runId}`, { ...run, snapshot }); return JSON.parse(JSON.stringify(snapshot.context)); } async updateWorkflowState({ workflowName, runId, opts }) { const run = this.collection.get(`${workflowName}-${runId}`); if (!run) { return; } let snapshot; if (!run.snapshot) { snapshot = { context: {}, activePaths: [], timestamp: Date.now(), suspendedPaths: {}, serializedStepGraph: [], value: {}, waitingPaths: {}, status: "pending", runId: run.run_id }; this.collection.set(`${workflowName}-${runId}`, { ...run, snapshot }); } else { snapshot = typeof run.snapshot === "string" ? JSON.parse(run.snapshot) : run.snapshot; } if (!snapshot || !snapshot?.context) { throw new Error(`Snapshot not found for runId ${runId}`); } snapshot = { ...snapshot, ...opts }; this.collection.set(`${workflowName}-${runId}`, { ...run, snapshot }); return snapshot; } async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot }) { const data = { workflow_name: workflowName, run_id: runId, resourceId, snapshot, createdAt: /* @__PURE__ */ new Date(), updatedAt: /* @__PURE__ */ new Date() }; await this.operations.insert({ tableName: chunkXUAWHRUO_cjs.TABLE_WORKFLOW_SNAPSHOT, record: data }); } async loadWorkflowSnapshot({ workflowName, runId }) { this.logger.debug("Loading workflow snapshot", { workflowName, runId }); const d = await this.operations.load({ tableName: chunkXUAWHRUO_cjs.TABLE_WORKFLOW_SNAPSHOT, keys: { workflow_name: workflowName, run_id: runId } }); return d ? JSON.parse(JSON.stringify(d.snapshot)) : null; } async getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId } = {}) { let runs = Array.from(this.collection.values()); if (workflowName) runs = runs.filter((run) => run.workflow_name === workflowName); if (fromDate && toDate) { runs = runs.filter( (run) => new Date(run.createdAt).getTime() >= fromDate.getTime() && new Date(run.createdAt).getTime() <= toDate.getTime() ); } else if (fromDate) { runs = runs.filter((run) => new Date(run.createdAt).getTime() >= fromDate.getTime()); } else if (toDate) { runs = runs.filter((run) => new Date(run.createdAt).getTime() <= toDate.getTime()); } if (resourceId) runs = runs.filter((run) => run.resourceId === resourceId); const total = runs.length; runs.sort((a, b) =>