@mastra/core
Version:
274 lines (271 loc) • 10.5 kB
JavaScript
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