UNPKG

@mastra/core

Version:
274 lines (271 loc) • 10.5 kB
import { createSignal, mastraDBMessageToSignal } from './chunk-WEN4YCAX.js'; // src/memory/types.ts function isPlainObject(value) { return typeof value === "object" && value !== null && !Array.isArray(value); } function getThreadOMMetadata(threadMetadata) { if (!threadMetadata) return void 0; const mastra = threadMetadata.mastra; if (!isPlainObject(mastra)) return void 0; const om = mastra.om; if (!isPlainObject(om)) return void 0; return om; } function setThreadOMMetadata(threadMetadata, omMetadata) { const existing = threadMetadata ?? {}; const existingMastra = isPlainObject(existing.mastra) ? existing.mastra : {}; const existingOM = isPlainObject(existingMastra.om) ? existingMastra.om : {}; return { ...existing, mastra: { ...existingMastra, om: { ...existingOM, ...omMetadata } } }; } function parseMemoryRequestContext(requestContext) { if (!requestContext) { return null; } const memoryContext = requestContext.get("MastraMemory"); if (!memoryContext) { return null; } if (typeof memoryContext !== "object" || memoryContext === null) { throw new Error(`Invalid MemoryRequestContext: expected object, got ${typeof memoryContext}`); } const ctx = memoryContext; if (ctx.thread !== void 0) { if (typeof ctx.thread !== "object" || ctx.thread === null) { throw new Error(`Invalid MemoryRequestContext.thread: expected object, got ${typeof ctx.thread}`); } const thread = ctx.thread; if (typeof thread.id !== "string") { throw new Error(`Invalid MemoryRequestContext.thread.id: expected string, got ${typeof thread.id}`); } } if (ctx.resourceId !== void 0 && typeof ctx.resourceId !== "string") { throw new Error(`Invalid MemoryRequestContext.resourceId: expected string, got ${typeof ctx.resourceId}`); } return memoryContext; } function isObservationalMemoryEnabled(config) { if (config === true) return true; if (config === false || config === void 0) return false; return config.enabled !== false; } // src/agent/state-signals.ts function isPlainObject2(value) { return typeof value === "object" && value !== null && !Array.isArray(value); } function getStateSignalsMetadata(threadMetadata) { if (!threadMetadata) return {}; const mastra = threadMetadata.mastra; if (!isPlainObject2(mastra)) return {}; const stateSignals = mastra.stateSignals; return isPlainObject2(stateSignals) ? stateSignals : {}; } function setStateSignalMetadata(threadMetadata, stateId, tracking) { const existing = threadMetadata ?? {}; const existingMastra = isPlainObject2(existing.mastra) ? existing.mastra : {}; const existingStateSignals = isPlainObject2(existingMastra.stateSignals) ? existingMastra.stateSignals : {}; return { ...existing, mastra: { ...existingMastra, stateSignals: { ...existingStateSignals, [stateId]: tracking } } }; } function signalCreatedAt(signal) { const createdAt = signal.createdAt instanceof Date ? signal.createdAt : new Date(signal.createdAt); const timestamp = createdAt.getTime(); return Number.isNaN(timestamp) ? 0 : timestamp; } function sortStateSignals(signals) { return signals.map((signal, index) => ({ signal, index })).sort((left, right) => signalCreatedAt(left.signal) - signalCreatedAt(right.signal) || left.index - right.index).map(({ signal }) => signal); } function dbMessagesToStateSignals(messages, stateId, threadId) { return sortStateSignals( messages.filter((message) => message.role === "signal").map((message) => { try { return mastraDBMessageToSignal(message); } catch { return void 0; } }).filter( (signal) => signal?.type === "state" && isPlainObject2(signal.metadata?.state) && (!stateId || signal.metadata.state.id === stateId) && signal.metadata.state.threadId === threadId ) ); } function getActiveStateSignals(messageList, stateId, threadId) { return dbMessagesToStateSignals(messageList.get.all.db(), stateId, threadId); } function mergeStateSignals(...signalGroups) { const signalsById = /* @__PURE__ */ new Map(); for (const signal of signalGroups.flat()) { signalsById.set(signal.id, signal); } return sortStateSignals([...signalsById.values()]); } function deriveStateSignalHistory(activeStateSignals) { const sortedStateSignals = sortStateSignals(activeStateSignals); const lastSnapshotIndex = sortedStateSignals.findLastIndex((signal) => signal.metadata?.state?.mode === "snapshot"); const lastSnapshot = lastSnapshotIndex >= 0 ? sortedStateSignals[lastSnapshotIndex] : void 0; const deltasSinceSnapshot = sortedStateSignals.slice(lastSnapshotIndex + 1).filter((signal) => signal.metadata?.state?.mode === "delta"); return { activeStateSignals: sortedStateSignals, contextWindow: { hasSnapshot: Boolean(lastSnapshot) }, lastSnapshot, deltasSinceSnapshot }; } async function resolveStateSignalHistory({ messageList, memory, threadId, stateId, tracking }) { const localStateSignals = getActiveStateSignals(messageList, stateId, threadId); const localHistory = deriveStateSignalHistory(localStateSignals); const contextWindow = localHistory.contextWindow; if (localHistory.contextWindow.hasSnapshot || !tracking?.lastSnapshotSignalId) { return { ...localHistory, contextWindow }; } const memoryStore = await memory.storage.getStore("memory"); if (!memoryStore) return { ...localHistory, contextWindow }; const trackedSignalIds = /* @__PURE__ */ new Set(); for (const activeCopy of tracking.activeCopies ?? []) { trackedSignalIds.add(activeCopy.id); } trackedSignalIds.add(tracking.lastSnapshotSignalId); if (trackedSignalIds.size === 0 || typeof memoryStore.listMessagesById !== "function") { return { ...localHistory, contextWindow }; } const storedMessages = await memoryStore.listMessagesById({ messageIds: [...trackedSignalIds] }); const storedStateSignals = dbMessagesToStateSignals(storedMessages.messages, stateId, threadId); const resolvedStateSignals = mergeStateSignals(storedStateSignals, localStateSignals); return { ...deriveStateSignalHistory(resolvedStateSignals.length > 0 ? resolvedStateSignals : localStateSignals), contextWindow }; } function createStateSignalInput(input, options) { const stateId = input.id ?? options?.defaultId; if (!stateId) { throw new Error("state signal id is required"); } if (!input.cacheKey) { throw new Error("state signal cacheKey is required"); } const mode = input.mode ?? "snapshot"; const { id: _stateId, cacheKey, mode: _mode, value, delta, metadata, ...signalInput } = input; const signal = createSignal({ ...signalInput, type: "state", tagName: signalInput.tagName ?? "state", acceptedAt: options?.acceptedAt, metadata: { ...metadata, state: { ...isPlainObject2(metadata?.state) ? metadata.state : {}, id: stateId, cacheKey, mode }, ...value !== void 0 ? { value } : {}, ...delta !== void 0 ? { delta } : {} } }); return { stateId, signal, mode, cacheKey }; } async function applyStateSignal({ input, memory, thread, resourceId, threadId, memoryConfig, messageList, activeStateSignals, defaultId, acceptedAt, beforeAddSignal, writeSignal }) { const { stateId, signal, cacheKey, mode } = createStateSignalInput(input, { defaultId, acceptedAt }); const activeSignals = activeStateSignals ?? (messageList ? getActiveStateSignals(messageList, stateId, threadId) : []); const tracking = getStateSignalsMetadata(thread.metadata)[stateId]; const usesActiveWindow = Boolean(messageList || activeStateSignals); const hasActiveCopy = activeSignals.some( (signal2) => signal2.metadata?.state?.cacheKey === cacheKey && signal2.metadata?.state?.mode === mode ); const matchesCurrentState = tracking?.currentCacheKey === cacheKey && (tracking.currentMode === mode || !tracking.currentMode && hasActiveCopy); if (matchesCurrentState && (!usesActiveWindow || hasActiveCopy)) { return { skipped: true, reason: "unchanged", stateId, tracking }; } const previousVersion = typeof tracking?.version === "number" ? tracking.version : 0; const version = matchesCurrentState ? previousVersion || 1 : previousVersion + 1; const updatedSignal = createSignal({ ...signal, metadata: { ...signal.metadata, state: { ...isPlainObject2(signal.metadata?.state) ? signal.metadata.state : {}, id: stateId, threadId, cacheKey, version, mode } } }); beforeAddSignal?.(); if (messageList) { messageList.addSignal(updatedSignal); } await writeSignal?.(updatedSignal); const updatedAt = (/* @__PURE__ */ new Date()).toISOString(); const updatedActiveSignals = [...activeSignals, updatedSignal]; const nextTracking = { currentCacheKey: cacheKey, currentMode: mode, version, lastSignalId: updatedSignal.id, lastSnapshotSignalId: mode === "snapshot" ? updatedSignal.id : tracking?.lastSnapshotSignalId, updatedAt, activeCopies: updatedActiveSignals.map((activeSignal) => { const activeStateMetadata = isPlainObject2(activeSignal.metadata?.state) ? activeSignal.metadata.state : {}; return { id: activeSignal.id, ...typeof activeStateMetadata.cacheKey === "string" ? { cacheKey: activeStateMetadata.cacheKey } : {}, ...activeStateMetadata.mode === "snapshot" || activeStateMetadata.mode === "delta" ? { mode: activeStateMetadata.mode } : {}, ...typeof activeStateMetadata.version === "number" ? { version: activeStateMetadata.version } : {} }; }) }; await memory.saveThread({ thread: { ...thread, id: threadId, resourceId: thread.resourceId ?? resourceId, createdAt: thread.createdAt ?? /* @__PURE__ */ new Date(), updatedAt: new Date(updatedAt), metadata: setStateSignalMetadata(thread.metadata, stateId, nextTracking) }, memoryConfig }); return { skipped: false, signal: updatedSignal, stateId, version, tracking: nextTracking }; } export { applyStateSignal, getStateSignalsMetadata, getThreadOMMetadata, isObservationalMemoryEnabled, parseMemoryRequestContext, resolveStateSignalHistory, setThreadOMMetadata }; //# sourceMappingURL=chunk-Q277RERI.js.map //# sourceMappingURL=chunk-Q277RERI.js.map