@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
JavaScript
'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) =>