'use strict'; var chunkRVD3DGBZ_cjs = require('./chunk-RVD3DGBZ.cjs'); var chunk64ITUOXI_cjs = require('./chunk-64ITUOXI.cjs'); // src/server/handlers/responses.storage.ts function isPlainObject(value) { return typeof value === "object" && value !== null && !Array.isArray(value); } async function getAgentMemoryStore({ agent, requestContext }) { const memory = await agent.getMemory({ requestContext }); if (!memory) { return null; } try { return await memory.storage.getStore("memory") ?? null; } catch { return null; } } function readResponseTurnRecordMetadata(message) { const mastraMetadata = isPlainObject(message.content?.metadata?.mastra) ? message.content.metadata.mastra : null; const responseMetadata = mastraMetadata && isPlainObject(mastraMetadata.response) ? mastraMetadata.response : null; if (!responseMetadata || typeof responseMetadata.agentId !== "string" || typeof responseMetadata.model !== "string" || typeof responseMetadata.createdAt !== "number" || responseMetadata.completedAt !== null && typeof responseMetadata.completedAt !== "number" || responseMetadata.instructions !== void 0 && typeof responseMetadata.instructions !== "string" || responseMetadata.text !== void 0 && (!isPlainObject(responseMetadata.text) || !isPlainObject(responseMetadata.text.format)) || responseMetadata.previousResponseId !== void 0 && typeof responseMetadata.previousResponseId !== "string" || !Array.isArray(responseMetadata.tools) || typeof responseMetadata.store !== "boolean" || !Array.isArray(responseMetadata.messageIds) || responseMetadata.outputItems !== void 0 && !Array.isArray(responseMetadata.outputItems)) { return null; } return { agentId: responseMetadata.agentId, model: responseMetadata.model, createdAt: responseMetadata.createdAt, completedAt: responseMetadata.completedAt, status: responseMetadata.status === "completed" ? "completed" : "incomplete", usage: responseMetadata.usage, instructions: responseMetadata.instructions, text: responseMetadata.text, previousResponseId: responseMetadata.previousResponseId, providerOptions: responseMetadata.providerOptions, tools: responseMetadata.tools, store: responseMetadata.store, messageIds: responseMetadata.messageIds.filter((value) => typeof value === "string"), outputItems: responseMetadata.outputItems }; } function writeResponseTurnRecordMetadata(message, metadata) { const contentMetadata = isPlainObject(message.content?.metadata) ? message.content.metadata : {}; const mastraMetadata = isPlainObject(contentMetadata.mastra) ? contentMetadata.mastra : {}; return { ...message, content: { ...message.content, metadata: { ...contentMetadata, mastra: { ...mastraMetadata, response: metadata } } } }; } async function findResponseTurnRecord({ agent, responseId, requestContext }) { const memoryStore = await getAgentMemoryStore({ agent, requestContext }); if (!memoryStore) { return null; } const effectiveResourceId = chunkRVD3DGBZ_cjs.getEffectiveResourceId(requestContext, void 0); const { messages: matchedMessages } = await memoryStore.listMessagesById({ messageIds: [responseId] }); const message = matchedMessages[0]; if (!message || message.role !== "assistant") { return null; } const metadata = readResponseTurnRecordMetadata(message); if (!metadata || metadata.agentId !== agent.id) { return null; } const thread = message.threadId ? await memoryStore.getThreadById({ threadId: message.threadId }) : null; if (!thread) { return null; } await chunkRVD3DGBZ_cjs.validateThreadOwnership(thread, effectiveResourceId); const messageIds = metadata.messageIds.length > 0 ? metadata.messageIds : [message.id]; const { messages: responseMessages } = await memoryStore.listMessagesById({ messageIds }); const messagesById = new Map(responseMessages.map((storedMessage) => [storedMessage.id, storedMessage])); const orderedMessages = messageIds.map((messageId) => messagesById.get(messageId)).filter((storedMessage) => Boolean(storedMessage)); return { metadata, message, messages: orderedMessages, thread, memoryStore }; } async function findResponseTurnRecordAcrossAgents({ mastra, responseId, requestContext }) { if (!mastra) { return null; } const agents = Object.values(mastra.listAgents()); for (const agent of agents) { const match = await findResponseTurnRecord({ agent, responseId, requestContext }); if (match) { return match; } } return null; } async function findConversationThreadAcrossAgents({ mastra, conversationId, requestContext }) { if (!mastra) { return null; } const effectiveResourceId = chunkRVD3DGBZ_cjs.getEffectiveResourceId(requestContext, void 0); const agents = Object.values(mastra.listAgents()); for (const agent of agents) { const memoryStore = await getAgentMemoryStore({ agent, requestContext }); if (!memoryStore) { continue; } const thread = await memoryStore.getThreadById({ threadId: conversationId }); if (!thread) { continue; } await chunkRVD3DGBZ_cjs.validateThreadOwnership(thread, effectiveResourceId); return { thread, memoryStore }; } return null; } function createSyntheticResponseMessage({ createdAt, responseId, text, threadContext }) { return { id: responseId, role: "assistant", type: "text", createdAt: createdAt ?? /* @__PURE__ */ new Date(), threadId: threadContext.threadId, resourceId: threadContext.resourceId, content: { format: 2, parts: text ? [{ type: "text", text }] : [] } }; } function hasTextPart(message) { return Boolean( message.content?.parts?.some( (part) => isPlainObject(part) && part.type === "text" && typeof part.text === "string" && part.text.length > 0 ) ); } function isEmptyAssistantMessage(message) { return message.role === "assistant" && Array.isArray(message.content?.parts) && message.content.parts.length === 0; } function hasToolInvocationPart(message) { return Boolean( message.content?.parts?.some( (part) => isPlainObject(part) && part.type === "tool-invocation" && isPlainObject(part.toolInvocation) ) ); } function getMessageText(message) { return message.content?.parts?.flatMap( (part) => isPlainObject(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : [] ).join("") ?? ""; } function getOutputMessageText(item) { return item.content.map((part) => part.text).join(""); } function normalizeFallbackComparisonText(text) { return text.trim(); } function matchesFallbackText(messageText, fallbackText) { return messageText === fallbackText || normalizeFallbackComparisonText(messageText) === normalizeFallbackComparisonText(fallbackText); } function hasMatchingAssistantText(messages, item) { const fallbackText = getOutputMessageText(item); return messages.some( (message) => message.role === "assistant" && hasTextPart(message) && matchesFallbackText(getMessageText(message), fallbackText) ); } function shouldReplaceAssistantText(messageText, fallbackText) { const normalizedMessageText = normalizeFallbackComparisonText(messageText); const normalizedFallbackText = normalizeFallbackComparisonText(fallbackText); return normalizedFallbackText !== normalizedMessageText && (fallbackText.startsWith(messageText) || normalizedFallbackText.startsWith(normalizedMessageText)); } function getAssistantMessageTexts(messages) { return messages.flatMap( (message) => message.role === "assistant" && hasTextPart(message) ? [getMessageText(message)] : [] ); } function shouldAddFallbackMessageText(messages, item) { const assistantTexts = getAssistantMessageTexts(messages); if (assistantTexts.length === 0) { return true; } const fallbackText = getOutputMessageText(item); return assistantTexts.every((messageText) => shouldReplaceAssistantText(messageText, fallbackText)); } function shouldReplaceAssistantTextWithFallback({ fallbackMessageTexts, message, textOnlyFallbackMessageTexts }) { if (message.role !== "assistant" || !hasTextPart(message)) { return false; } const messageText = getMessageText(message); if (!messageText) { return false; } const comparisonTexts = hasToolInvocationPart(message) ? fallbackMessageTexts : textOnlyFallbackMessageTexts; return [...comparisonTexts].some((fallbackText) => shouldReplaceAssistantText(messageText, fallbackText)); } function replaceAssistantTextWithFallback({ fallbackMessageTexts, message, textOnlyFallbackMessageTexts }) { if (!shouldReplaceAssistantTextWithFallback({ fallbackMessageTexts, message, textOnlyFallbackMessageTexts })) { return message; } const parts = message.content?.parts ?? []; const remainingParts = parts.filter((part) => !(isPlainObject(part) && part.type === "text")); return { ...message, content: { ...message.content, parts: remainingParts } }; } function parseFunctionCallArguments(value) { try { return JSON.parse(value); } catch { return { __raw: value }; } } function createSyntheticToolResultMessage({ baseMessage, item, responseId, toolCall }) { return { ...baseMessage, id: `${responseId}:tool-result:${item.call_id}`, role: "tool", type: "tool-result", content: { format: 2, parts: [ { type: "tool-invocation", toolInvocation: { state: "result", toolCallId: item.call_id, toolName: toolCall?.toolName ?? "unknown", args: toolCall?.args ?? {}, result: item.output } } ] } }; } function toMastraDBMessage(message) { return message; } function createSyntheticMessagesFromOutputItems({ contextOutputItems, outputItems, responseId, threadContext }) { const toolContextItems = contextOutputItems ?? outputItems; const toolCallsById = new Map( toolContextItems.flatMap( (item) => item.type === "function_call" ? [[item.call_id, { args: parseFunctionCallArguments(item.arguments), toolName: item.name }]] : [] ) ); const baseCreatedAt = Date.now(); return outputItems.map((item, index) => { const baseMessage = { createdAt: new Date(baseCreatedAt + index), threadId: threadContext.threadId, resourceId: threadContext.resourceId }; if (item.type === "function_call") { return { ...baseMessage, id: `${responseId}:tool-call:${item.call_id}`, role: "assistant", type: "tool-call", content: { format: 2, parts: [ { type: "tool-invocation", toolInvocation: { state: "call", toolCallId: item.call_id, toolName: item.name, args: parseFunctionCallArguments(item.arguments) } } ] } }; } if (item.type === "function_call_output") { const toolCall = toolCallsById.get(item.call_id); return toMastraDBMessage(createSyntheticToolResultMessage({ baseMessage, item, responseId, toolCall })); } return { ...baseMessage, id: item.id, role: "assistant", type: "text", content: { format: 2, parts: item.content.map((part) => ({ type: "text", text: part.text })) } }; }); } function getToolInvocationParts(message) { const parts = Array.isArray(message.content?.parts) ? message.content.parts : []; return parts.flatMap( (part) => isPlainObject(part) && part.type === "tool-invocation" && isPlainObject(part.toolInvocation) ? [part.toolInvocation] : [] ); } function getMissingFallbackOutputItems({ fallbackOutputItems = [], messages }) { if (!fallbackOutputItems.length) { return []; } const existingCallIds = /* @__PURE__ */ new Set(); const existingResultCallIds = /* @__PURE__ */ new Set(); for (const message of messages) { for (const toolInvocation of getToolInvocationParts(message)) { const toolCallId = typeof toolInvocation.toolCallId === "string" ? toolInvocation.toolCallId : null; if (!toolCallId) { continue; } if (message.role === "assistant" && (toolInvocation.args !== void 0 || toolInvocation.result === void 0)) { existingCallIds.add(toolCallId); } if (toolInvocation.result !== void 0) { existingResultCallIds.add(toolCallId); } } } return fallbackOutputItems.filter((item) => { if (item.type === "function_call") { return !existingCallIds.has(item.call_id); } if (item.type === "function_call_output") { return !existingResultCallIds.has(item.call_id); } if (item.type === "message") { if (!item.content.some((part) => part.text.length > 0) || hasMatchingAssistantText(messages, item)) { return false; } return shouldAddFallbackMessageText(messages, item); } return false; }); } function getFallbackOutputIdForMessage(message, responseId, fallbackOutputIds) { for (const toolInvocation of getToolInvocationParts(message)) { const toolCallId = typeof toolInvocation.toolCallId === "string" ? toolInvocation.toolCallId : null; if (!toolCallId) { continue; } if (message.role === "assistant" && toolInvocation.args !== void 0) { return toolCallId; } if (toolInvocation.result !== void 0) { return `${toolCallId}:output`; } } if (message.role === "assistant" && hasTextPart(message)) { return fallbackOutputIds.has(message.id) ? message.id : responseId; } return null; } function sortMessagesByFallbackOutputOrder({ fallbackOutputItems = [], messages, responseId }) { if (!fallbackOutputItems.length) { return messages; } const outputOrder = new Map(fallbackOutputItems.map((item, index) => [item.id, index])); const fallbackOutputIds = new Set(outputOrder.keys()); return messages.map((message, index) => ({ index, message, outputIndex: outputOrder.get(getFallbackOutputIdForMessage(message, responseId, fallbackOutputIds) ?? "") ?? Number.MAX_SAFE_INTEGER })).sort((left, right) => left.outputIndex - right.outputIndex || left.index - right.index).map(({ message }) => message); } async function resolveResponseTurnMessagesForStorage({ result, responseId, text, threadContext, fallbackOutputItems }) { const response = await result.response; const responseMessages = response?.dbMessages?.length ? response.dbMessages : []; if (!threadContext) { return responseMessages; } if (responseMessages.length === 0) { if (fallbackOutputItems?.length) { const syntheticMessages = createSyntheticMessagesFromOutputItems({ outputItems: fallbackOutputItems, responseId, threadContext }); return text && !syntheticMessages.some((message) => message.role === "assistant" && hasTextPart(message)) ? [ ...syntheticMessages, createSyntheticResponseMessage({ createdAt: new Date(new Date(syntheticMessages.at(-1)?.createdAt ?? Date.now()).getTime() + 1), responseId, text, threadContext }) ] : syntheticMessages; } return [createSyntheticResponseMessage({ responseId, text, threadContext })]; } const missingFallbackItems = getMissingFallbackOutputItems({ fallbackOutputItems, messages: responseMessages }); const missingFallbackMessageIds = new Set( missingFallbackItems.filter((item) => item.type === "message").map((item) => item.id) ); const fallbackItemsWithMatchingAssistantText = (fallbackOutputItems ?? []).filter( (item) => item.type === "message" && hasMatchingAssistantText(responseMessages, item) ); const textOnlyFallbackMessageTexts = new Set( fallbackItemsWithMatchingAssistantText.map(getOutputMessageText).filter(Boolean) ); const fallbackMessageTexts = new Set( (fallbackOutputItems ?? []).filter((item) => item.type === "message").filter((item) => missingFallbackMessageIds.has(item.id) || fallbackItemsWithMatchingAssistantText.includes(item)).map(getOutputMessageText).filter(Boolean) ); const baseMessages = fallbackMessageTexts.size ? responseMessages.map( (message) => replaceAssistantTextWithFallback({ fallbackMessageTexts, message, textOnlyFallbackMessageTexts }) ) : responseMessages; const syntheticFallbackMessages = createSyntheticMessagesFromOutputItems({ contextOutputItems: fallbackOutputItems ?? [], outputItems: missingFallbackItems, responseId, threadContext }); const resolvedMessages = sortMessagesByFallbackOutputOrder({ fallbackOutputItems, messages: [...baseMessages, ...syntheticFallbackMessages], responseId }); if (text && !resolvedMessages.some((message) => message.role === "assistant" && hasTextPart(message))) { return [...resolvedMessages, createSyntheticResponseMessage({ responseId, text, threadContext })]; } return resolvedMessages; } async function persistResponseTurnRecord({ memoryStore, responseId, metadata, threadContext, messages }) { if (!memoryStore) { throw new chunk64ITUOXI_cjs.HTTPException(500, { message: "Memory storage was not available while storing the response" }); } const normalizedMessages = messages.map((message) => ({ ...message, threadId: message.threadId ?? threadContext.threadId, resourceId: message.resourceId ?? threadContext.resourceId })); const lastAssistantIndex = [...normalizedMessages].map((message) => message.role).lastIndexOf("assistant"); const responseAnchorIndex = [...normalizedMessages].map((message, index) => ({ index, message })).reverse().find(({ message }) => message.role === "assistant" && hasTextPart(message))?.index ?? lastAssistantIndex; const lastAssistantMessage = responseAnchorIndex >= 0 ? { ...normalizedMessages[responseAnchorIndex], id: responseId } : { id: responseId, role: "assistant", type: "text", createdAt: new Date(metadata.completedAt ? metadata.completedAt * 1e3 : Date.now()), threadId: threadContext.threadId, resourceId: threadContext.resourceId, content: { format: 2, parts: [] } }; if (responseAnchorIndex >= 0) { normalizedMessages[responseAnchorIndex] = lastAssistantMessage; } else { normalizedMessages.push(lastAssistantMessage); } const storedMessageIndex = responseAnchorIndex >= 0 ? responseAnchorIndex : normalizedMessages.length - 1; const droppedSupersededMessageIds = normalizedMessages.flatMap( (message, index) => index !== storedMessageIndex && isEmptyAssistantMessage(message) && messages[index]?.id ? [messages[index].id] : [] ); const staleMessageIds = responseAnchorIndex >= 0 && messages[responseAnchorIndex]?.id && messages[responseAnchorIndex]?.id !== responseId ? [messages[responseAnchorIndex].id] : []; const messagesToSave = normalizedMessages.filter( (message, index) => index === storedMessageIndex || !isEmptyAssistantMessage(message) ); const storedMessage = writeResponseTurnRecordMetadata(lastAssistantMessage, { ...metadata, messageIds: messagesToSave.map((message) => message.id) }); if (responseAnchorIndex >= 0) { normalizedMessages[responseAnchorIndex] = storedMessage; } else { normalizedMessages[normalizedMessages.length - 1] = storedMessage; } const savedMessages = normalizedMessages.filter( (message, index) => index === storedMessageIndex || !isEmptyAssistantMessage(message) ); await memoryStore.saveMessages({ messages: savedMessages }); const deleteMessageIds = [.../* @__PURE__ */ new Set([...staleMessageIds, ...droppedSupersededMessageIds])]; if (deleteMessageIds.length > 0) { await memoryStore.deleteMessages(deleteMessageIds); } } async function deleteResponseTurnRecord({ responseTurnRecord }) { const messageIds = responseTurnRecord.messages.length > 0 ? responseTurnRecord.messages.map((message) => message.id) : [responseTurnRecord.message.id]; await responseTurnRecord.memoryStore.deleteMessages(messageIds); } exports.deleteResponseTurnRecord = deleteResponseTurnRecord; exports.findConversationThreadAcrossAgents = findConversationThreadAcrossAgents; exports.findResponseTurnRecord = findResponseTurnRecord; exports.findResponseTurnRecordAcrossAgents = findResponseTurnRecordAcrossAgents; exports.getAgentMemoryStore = getAgentMemoryStore; exports.persistResponseTurnRecord = persistResponseTurnRecord; exports.resolveResponseTurnMessagesForStorage = resolveResponseTurnMessagesForStorage; //# sourceMappingURL=chunk-YLWKZ3VK.cjs.map //# sourceMappingURL=chunk-YLWKZ3VK.cjs.map