@mastra/memory 1.36.0 → 1.37.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-agents-human-in-the-loop.md +5 -3
- package/dist/docs/references/docs-memory-memory-processors.md +2 -5
- package/dist/docs/references/docs-memory-semantic-recall.md +2 -2
- package/dist/docs/references/docs-memory-working-memory.md +16 -0
- package/dist/docs/references/docs-subagents.md +10 -8
- package/dist/docs/references/reference-memory-memory-class.md +2 -2
- package/dist/docs/references/reference-memory-summarizeConversation.md +1 -1
- package/dist/docs/references/reference-migrations-upgrade-to-v1-memory.md +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +18 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/processors/index.cjs +1 -1
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-turn/turn.d.ts +1 -1
- package/dist/processors/observational-memory/observation-turn/turn.d.ts.map +1 -1
- package/dist/processors/observational-memory/processor.d.ts.map +1 -1
- package/dist/{src-DwfyRK9Q.cjs → src-BYiaPbIt.cjs} +110 -20
- package/dist/src-BYiaPbIt.cjs.map +1 -0
- package/dist/{src-yhShj4JX.js → src-BaiJf9y9.js} +110 -20
- package/dist/{src-yhShj4JX.js.map → src-BaiJf9y9.js.map} +1 -1
- package/dist/tools/working-memory.d.ts +4 -0
- package/dist/tools/working-memory.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/src-DwfyRK9Q.cjs.map +0 -1
|
@@ -3,6 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
import * as z4 from "zod/v4";
|
|
4
4
|
import { z as z$1 } from "zod/v4";
|
|
5
5
|
import { Agent, MessageList } from "@mastra/core/agent";
|
|
6
|
+
import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
|
|
6
7
|
import { coreFeatures } from "@mastra/core/features";
|
|
7
8
|
import { MastraMemory, getMemoryTokenBoundary, getThreadOMMetadata, isAfterMemoryTokenBoundary, isThreadTitlePinned, loadMessageHistory, normalizeMessageHistoryConfig, parseMemoryRequestContext, setThreadOMMetadata } from "@mastra/core/memory";
|
|
8
9
|
import { EntityType, SpanType, createObservabilityContext, getOrCreateSpan } from "@mastra/core/observability";
|
|
@@ -22,7 +23,6 @@ import { AsyncLocalStorage } from "async_hooks";
|
|
|
22
23
|
import { createHash } from "crypto";
|
|
23
24
|
import probeImageSizeSync from "probe-image-size/sync.js";
|
|
24
25
|
import { isStandardSchemaWithJSON as isStandardSchemaWithJSON$1, toStandardSchema as toStandardSchema$1 } from "@mastra/core/schema";
|
|
25
|
-
import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
|
|
26
26
|
import { structuredPatch } from "diff";
|
|
27
27
|
import { inspect } from "util";
|
|
28
28
|
//#region \0rolldown/runtime.js
|
|
@@ -23598,6 +23598,18 @@ const SET_WORKING_MEMORY_TOOL_NAME = "setWorkingMemory";
|
|
|
23598
23598
|
* - Primitive values are overwritten
|
|
23599
23599
|
* - The returned object is always newly constructed and never aliases `update`
|
|
23600
23600
|
*/
|
|
23601
|
+
/**
|
|
23602
|
+
* Parses stored JSON working memory. Invalid or empty data yields `null` (start fresh).
|
|
23603
|
+
*/
|
|
23604
|
+
function parseWorkingMemoryJson(raw) {
|
|
23605
|
+
if (!raw) return null;
|
|
23606
|
+
if (typeof raw !== "string") return raw;
|
|
23607
|
+
try {
|
|
23608
|
+
return JSON.parse(raw);
|
|
23609
|
+
} catch {
|
|
23610
|
+
return null;
|
|
23611
|
+
}
|
|
23612
|
+
}
|
|
23601
23613
|
function deepMergeWorkingMemory(existing, update) {
|
|
23602
23614
|
if (!update || typeof update !== "object" || Object.keys(update).length === 0) return existing && typeof existing === "object" ? { ...existing } : {};
|
|
23603
23615
|
const result = { ...existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {} };
|
|
@@ -23704,17 +23716,6 @@ const updateWorkingMemoryTool = (memoryConfig) => {
|
|
|
23704
23716
|
}
|
|
23705
23717
|
let workingMemory;
|
|
23706
23718
|
if (usesMergeSemantics) {
|
|
23707
|
-
const existingRaw = await memory.getWorkingMemory({
|
|
23708
|
-
threadId,
|
|
23709
|
-
resourceId,
|
|
23710
|
-
memoryConfig
|
|
23711
|
-
});
|
|
23712
|
-
let existingData = null;
|
|
23713
|
-
if (existingRaw) try {
|
|
23714
|
-
existingData = typeof existingRaw === "string" ? JSON.parse(existingRaw) : existingRaw;
|
|
23715
|
-
} catch {
|
|
23716
|
-
existingData = null;
|
|
23717
|
-
}
|
|
23718
23719
|
const memoryInput = workingMemoryInput.memory;
|
|
23719
23720
|
if (memoryInput === void 0 || memoryInput === null) return {
|
|
23720
23721
|
success: true,
|
|
@@ -23728,7 +23729,20 @@ const updateWorkingMemoryTool = (memoryConfig) => {
|
|
|
23728
23729
|
throw new Error(`Failed to parse working memory input as JSON: ${errorMessage}. Raw input: ${memoryInput.length > 500 ? memoryInput.slice(0, 500) + "..." : memoryInput}`);
|
|
23729
23730
|
}
|
|
23730
23731
|
else newData = memoryInput;
|
|
23731
|
-
|
|
23732
|
+
if (scope === "resource" && typeof memory.supportsAtomicWorkingMemoryMerge === "function" && await memory.supportsAtomicWorkingMemoryMerge()) {
|
|
23733
|
+
await memory.mergeWorkingMemory({
|
|
23734
|
+
threadId,
|
|
23735
|
+
resourceId,
|
|
23736
|
+
workingMemory: newData,
|
|
23737
|
+
memoryConfig
|
|
23738
|
+
});
|
|
23739
|
+
return { success: true };
|
|
23740
|
+
}
|
|
23741
|
+
const mergedData = deepMergeWorkingMemory(parseWorkingMemoryJson(await memory.getWorkingMemory({
|
|
23742
|
+
threadId,
|
|
23743
|
+
resourceId,
|
|
23744
|
+
memoryConfig
|
|
23745
|
+
})), newData);
|
|
23732
23746
|
workingMemory = JSON.stringify(mergedData);
|
|
23733
23747
|
} else {
|
|
23734
23748
|
const memoryInput = workingMemoryInput.memory;
|
|
@@ -28093,8 +28107,14 @@ var ObservationStep = class {
|
|
|
28093
28107
|
const newOutput = messageList.clear.response.db();
|
|
28094
28108
|
const messagesToSave = [...newInput, ...newOutput];
|
|
28095
28109
|
if (messagesToSave.length > 0) {
|
|
28096
|
-
await om.persistMessages(messagesToSave, threadId, resourceId);
|
|
28097
28110
|
for (const msg of messagesToSave) messageList.add(msg, "memory");
|
|
28111
|
+
try {
|
|
28112
|
+
await om.persistMessages(messagesToSave, threadId, resourceId);
|
|
28113
|
+
} catch (error) {
|
|
28114
|
+
restoreDrainedMessages(messageList, newInput, "input");
|
|
28115
|
+
restoreDrainedMessages(messageList, newOutput, "response");
|
|
28116
|
+
throw error;
|
|
28117
|
+
}
|
|
28098
28118
|
}
|
|
28099
28119
|
} else {
|
|
28100
28120
|
const pending = [...messageList.get.input.db(), ...messageList.get.response.db()];
|
|
@@ -28321,6 +28341,18 @@ var ObservationStep = class {
|
|
|
28321
28341
|
};
|
|
28322
28342
|
}
|
|
28323
28343
|
};
|
|
28344
|
+
/**
|
|
28345
|
+
* Move messages drained into the memory bucket back to `source` after a failed save. Messages that
|
|
28346
|
+
* have already left the memory bucket (a background tool result moves its message to `response`)
|
|
28347
|
+
* are left where they are. The list's current copy is re-added so changes made during the save
|
|
28348
|
+
* are kept.
|
|
28349
|
+
*/
|
|
28350
|
+
function restoreDrainedMessages(messageList, drained, source) {
|
|
28351
|
+
if (drained.length === 0) return;
|
|
28352
|
+
const stillQueued = new Set([...messageList.get.input.db(), ...messageList.get.response.db()].map((msg) => msg.id));
|
|
28353
|
+
const ids = drained.map((msg) => msg.id).filter((id) => !stillQueued.has(id));
|
|
28354
|
+
for (const msg of messageList.removeByIds(ids)) messageList.add(msg, source, { merge: false });
|
|
28355
|
+
}
|
|
28324
28356
|
//#endregion
|
|
28325
28357
|
//#region src/processors/observational-memory/observation-turn/turn.ts
|
|
28326
28358
|
/**
|
|
@@ -28479,17 +28511,17 @@ var ObservationTurn = class {
|
|
|
28479
28511
|
* proactively while the agent is idle, rather than waiting for the next turn.
|
|
28480
28512
|
* The returned record does not wait for that background buffering pass to finish.
|
|
28481
28513
|
*/
|
|
28482
|
-
async end() {
|
|
28514
|
+
async end(messageList = this.messageList) {
|
|
28483
28515
|
if (this._ended) throw new Error("Turn already ended");
|
|
28484
28516
|
this._ended = true;
|
|
28485
|
-
const unsavedInput =
|
|
28486
|
-
const unsavedOutput =
|
|
28517
|
+
const unsavedInput = messageList.get.input.db();
|
|
28518
|
+
const unsavedOutput = messageList.get.response.db();
|
|
28487
28519
|
const unsavedMessages = [...unsavedInput, ...unsavedOutput];
|
|
28488
28520
|
if (unsavedMessages.length > 0) await this.om.persistMessages(unsavedMessages, this.threadId, this.resourceId);
|
|
28489
28521
|
const asyncObservationEnabled = this.om.buffering.isAsyncObservationEnabled();
|
|
28490
28522
|
const bufferOnIdle = this.om.getObservationConfig().bufferOnIdle;
|
|
28491
28523
|
if (asyncObservationEnabled && bufferOnIdle) {
|
|
28492
|
-
const allMessages = getObservableMessages(
|
|
28524
|
+
const allMessages = getObservableMessages(messageList);
|
|
28493
28525
|
const record = this._record;
|
|
28494
28526
|
const idleMessages = selectSafeBufferPrefix(this.om.getUnobservedMessages(allMessages, record));
|
|
28495
28527
|
if (idleMessages.length > 0) this.om.trackBackgroundWork(this.om.buffer({
|
|
@@ -32825,6 +32857,10 @@ var ObservationalMemoryProcessor = class {
|
|
|
32825
32857
|
} catch (error) {
|
|
32826
32858
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
32827
32859
|
const abortMessage = abortSignal?.aborted ? "Agent execution was aborted" : `Encountered error during memory observation: ${err.message}`;
|
|
32860
|
+
const failedTurn = this.turn;
|
|
32861
|
+
await failedTurn.end().catch(() => {});
|
|
32862
|
+
if (this.turn === failedTurn) this.turn = void 0;
|
|
32863
|
+
state.__omTurn = void 0;
|
|
32828
32864
|
if (typeof abort === "function") abort(abortMessage);
|
|
32829
32865
|
throw err;
|
|
32830
32866
|
}
|
|
@@ -32884,7 +32920,7 @@ var ObservationalMemoryProcessor = class {
|
|
|
32884
32920
|
if (parseMemoryRequestContext(requestContext)?.memoryConfig?.readOnly) return messageList;
|
|
32885
32921
|
const turn = asLiveTurn(state.__omTurn) ?? this.turn;
|
|
32886
32922
|
const liveTurn = turn && !turn.ended ? turn : void 0;
|
|
32887
|
-
if (liveTurn) await liveTurn.end();
|
|
32923
|
+
if (liveTurn) await liveTurn.end(messageList);
|
|
32888
32924
|
this.turn = void 0;
|
|
32889
32925
|
state.__omTurn = void 0;
|
|
32890
32926
|
if (!liveTurn) {
|
|
@@ -33156,6 +33192,12 @@ const DEFAULT_EMBEDDING_CACHE_MAX_SIZE = 1e3;
|
|
|
33156
33192
|
* @see [Memory documentation](https://mastra.ai/docs/memory/overview)
|
|
33157
33193
|
* if packaged docs are unavailable.
|
|
33158
33194
|
*/
|
|
33195
|
+
const invalidMerge = (text) => new MastraError({
|
|
33196
|
+
id: "MEMORY_WORKING_MEMORY_MERGE_INVALID",
|
|
33197
|
+
domain: ErrorDomain.MASTRA_MEMORY,
|
|
33198
|
+
category: ErrorCategory.USER,
|
|
33199
|
+
text
|
|
33200
|
+
});
|
|
33159
33201
|
var Memory = class Memory extends MastraMemory {
|
|
33160
33202
|
createMemoryTokenCounter() {
|
|
33161
33203
|
return new TokenCounter();
|
|
@@ -33685,6 +33727,54 @@ var Memory = class Memory extends MastraMemory {
|
|
|
33685
33727
|
throw error;
|
|
33686
33728
|
}
|
|
33687
33729
|
}
|
|
33730
|
+
/**
|
|
33731
|
+
* Whether the configured storage can merge resource working memory atomically across processes.
|
|
33732
|
+
*/
|
|
33733
|
+
async supportsAtomicWorkingMemoryMerge() {
|
|
33734
|
+
return (await this.getMemoryStore()).supportsAtomicWorkingMemoryMerge === true;
|
|
33735
|
+
}
|
|
33736
|
+
/**
|
|
33737
|
+
* Deep-merges a partial JSON update into resource-scoped working memory as one
|
|
33738
|
+
* atomic storage operation, so concurrent writers (even in other processes) never
|
|
33739
|
+
* lose each other's fields. `null` values delete fields; arrays are replaced.
|
|
33740
|
+
* Requires schema-based working memory, resource scope, and a storage adapter
|
|
33741
|
+
* that supports atomic merges (e.g. PostgreSQL); otherwise throws.
|
|
33742
|
+
*/
|
|
33743
|
+
async mergeWorkingMemory({ threadId, resourceId, workingMemory, memoryConfig, observabilityContext }) {
|
|
33744
|
+
const config = this.getMergedThreadConfig(memoryConfig || {});
|
|
33745
|
+
if (!config.workingMemory?.enabled) throw invalidMerge("Working memory is not enabled for this memory instance");
|
|
33746
|
+
if (!config.workingMemory.schema) throw invalidMerge("Working memory merge requires schema-based (JSON) working memory");
|
|
33747
|
+
if ((config.workingMemory.scope || "resource") !== "resource" || !resourceId) throw invalidMerge("Working memory merge requires resource-scoped working memory and a resourceId");
|
|
33748
|
+
let patch = workingMemory;
|
|
33749
|
+
if (typeof workingMemory === "string") try {
|
|
33750
|
+
patch = JSON.parse(workingMemory);
|
|
33751
|
+
} catch {
|
|
33752
|
+
throw invalidMerge("Working memory merge requires a JSON object");
|
|
33753
|
+
}
|
|
33754
|
+
if (!patch || typeof patch !== "object" || Array.isArray(patch)) throw invalidMerge("Working memory merge requires a JSON object");
|
|
33755
|
+
const memoryStore = await this.getMemoryStore();
|
|
33756
|
+
if (!memoryStore.supportsAtomicWorkingMemoryMerge) throw invalidMerge(`Atomic working memory merge is not supported by this storage adapter (${memoryStore.constructor.name}).`);
|
|
33757
|
+
const span = this.createMemorySpan("update", observabilityContext, {
|
|
33758
|
+
threadId,
|
|
33759
|
+
resourceId
|
|
33760
|
+
}, { workingMemoryEnabled: true });
|
|
33761
|
+
try {
|
|
33762
|
+
await memoryStore.mergeResourceWorkingMemory({
|
|
33763
|
+
resourceId,
|
|
33764
|
+
merge: (existing) => {
|
|
33765
|
+
const parsed = parseWorkingMemoryJson(existing);
|
|
33766
|
+
return JSON.stringify(deepMergeWorkingMemory(parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null, patch));
|
|
33767
|
+
}
|
|
33768
|
+
});
|
|
33769
|
+
span?.end({ output: { success: true } });
|
|
33770
|
+
} catch (error) {
|
|
33771
|
+
span?.error({
|
|
33772
|
+
error,
|
|
33773
|
+
endSpan: true
|
|
33774
|
+
});
|
|
33775
|
+
throw error;
|
|
33776
|
+
}
|
|
33777
|
+
}
|
|
33688
33778
|
updateWorkingMemoryMutexes = /* @__PURE__ */ new Map();
|
|
33689
33779
|
/**
|
|
33690
33780
|
* @warning experimental! can be removed or changed at any time
|
|
@@ -35386,4 +35476,4 @@ Notes:
|
|
|
35386
35476
|
//#endregion
|
|
35387
35477
|
export { formatMessagesForObserver as A, OBSERVATION_CONTEXT_PROMPT_THREAD as B, SUMMARIZE_THREAD_DEFAULTS as C, buildObserverPrompt as D, OBSERVER_SYSTEM_PROMPT as E, parseAnchorId as F, StaleKnowledgeSemanticIndexError as G, getObservationContextPrompt as H, stripEphemeralAnchorIds as I, SUBCONSCIOUS_ACTIVITY_STATE_ID as J, SubconsciousRemindExtractor as K, OBSERVATIONAL_MEMORY_DEFAULTS as L, optimizeObservationsForContext as M, parseObserverOutput as N, buildObserverSystemPrompt as O, injectAnchorIds as P, Extractor as Q, OBSERVATION_CONTEXT_INSTRUCTIONS as R, deepMergeWorkingMemory as S, TokenCounter as T, Subconscious as U, OBSERVATION_CONTINUATION_HINT as V, KnowledgeSemanticIndexCoordinator as W, publishSubconsciousActivity as X, buildSubconsciousActivitySnapshot as Y, renderSubconsciousActivity as Z, reconcileObservationGroupsFromReflection as _, extractWorkingMemoryContent as a, wrapInObservationGroup as b, getObservationsAsOf as c, WORKING_MEMORY_STATE_ID as d, WORKING_MEMORY_STATE_PROCESSOR_ID as f, parseObservationGroups as g, deriveObservationGroupProvenance as h, WorkingMemory as i, hasCurrentTaskSection as j, extractCurrentTask as k, ObservationalMemoryProcessor as l, combineObservationGroupRanges as m, MessageHistory$1 as n, extractWorkingMemoryTags as o, WorkingMemoryStateProcessor as p, ModelByInputTokens as q, SemanticRecall as r, removeWorkingMemoryTags as s, Memory as t, ObservationalMemory as u, renderObservationGroupsForReflection as v, summarizeConversation as w, WorkingMemoryExtractor as x, stripObservationGroups as y, OBSERVATION_CONTEXT_PROMPT as z };
|
|
35388
35478
|
|
|
35389
|
-
//# sourceMappingURL=src-
|
|
35479
|
+
//# sourceMappingURL=src-BaiJf9y9.js.map
|