UNPKG

@mastra/core

Version:
270 lines (269 loc) 10.8 kB
import { n as createSignal, s as mastraDBMessageToSignal } from "./signals-DTzJ08gd.js"; //#region src/agent/state-signals.ts function isPlainObject$1(value) { return typeof value === "object" && value !== null && !Array.isArray(value); } function getStateSignalsMetadata(threadMetadata) { if (!threadMetadata) return {}; const mastra = threadMetadata.mastra; if (!isPlainObject$1(mastra)) return {}; const stateSignals = mastra.stateSignals; return isPlainObject$1(stateSignals) ? stateSignals : {}; } function setStateSignalMetadata(threadMetadata, stateId, tracking) { const existing = threadMetadata ?? {}; const existingMastra = isPlainObject$1(existing.mastra) ? existing.mastra : {}; const existingStateSignals = isPlainObject$1(existingMastra.stateSignals) ? existingMastra.stateSignals : {}; return { ...existing, mastra: { ...existingMastra, stateSignals: { ...existingStateSignals, [stateId]: tracking } } }; } function signalCreatedAt(signal) { const timestamp = (signal.createdAt instanceof Date ? signal.createdAt : new Date(signal.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; } }).filter((signal) => signal?.type === "state" && isPlainObject$1(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 resolvedStateSignals = mergeStateSignals(dbMessagesToStateSignals((await memoryStore.listMessagesById({ messageIds: [...trackedSignalIds] })).messages, stateId, threadId), 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; return { stateId, signal: createSignal({ ...signalInput, type: "state", tagName: signalInput.tagName ?? "state", acceptedAt: options?.acceptedAt, metadata: { ...metadata, state: { ...isPlainObject$1(metadata?.state) ? metadata.state : {}, id: stateId, cacheKey, mode }, ...value !== void 0 ? { value } : {}, ...delta !== void 0 ? { delta } : {} } }), 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((signal) => signal.metadata?.state?.cacheKey === cacheKey && signal.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: { ...isPlainObject$1(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 = isPlainObject$1(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 }; } //#endregion //#region src/memory/types.ts function isPlainObject(value) { return typeof value === "object" && value !== null && !Array.isArray(value); } /** * Helper to get OM metadata from a thread's metadata object. * Returns undefined if not present or if the structure is invalid. */ 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; } /** * Helper to set OM metadata on a thread's metadata object. * Creates the nested structure if it doesn't exist. * Returns a new metadata object (does not mutate the original). * Safely handles cases where existing mastra/om values are not objects. */ 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 } } }; } /** * Parse and validate memory runtime context from RequestContext * @param requestContext - The RequestContext to extract memory context from * @returns The validated MemoryRequestContext or null if not available * @throws Error if the context exists but is malformed */ 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; } /** * Check if observational memory is enabled from a `boolean | ObservationalMemoryOptions` value. * * - `true` → enabled * - `false` → disabled * - `{ enabled: false }` → disabled * - `{ ... }` (without `enabled: false`) → enabled * - `undefined` → disabled */ function isObservationalMemoryEnabled(config) { if (config === true) return true; if (config === false || config === void 0) return false; return config.enabled !== false; } //#endregion export { applyStateSignal as a, setThreadOMMetadata as i, isObservationalMemoryEnabled as n, getStateSignalsMetadata as o, parseMemoryRequestContext as r, resolveStateSignalHistory as s, getThreadOMMetadata as t }; //# sourceMappingURL=types-LyOfO-TK.js.map