@mastra/memory 1.29.1-alpha.0 → 1.30.0-alpha.2
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 +4 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-guides-context-engineering.md +1 -1
- package/dist/docs/references/docs-harness-background-tasks.md +30 -24
- package/dist/docs/references/docs-memory-message-history.md +6 -2
- package/dist/docs/references/docs-subagents.md +25 -0
- package/dist/docs/references/reference-memory-cloneThread.md +2 -0
- package/dist/docs/references/reference-memory-copyThread.md +65 -0
- package/dist/docs/references/reference-memory-memory-class.md +2 -1
- package/dist/docs/references/reference-memory-updateThreadResourceId.md +46 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +64 -3
- 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/{src-CkIFee1t.cjs → src-Bs9_1MCb.cjs} +190 -19
- package/dist/{src-CkIFee1t.cjs.map → src-Bs9_1MCb.cjs.map} +1 -1
- package/dist/{src-C4x5Wx9t.js → src-TN3MwGgP.js} +190 -19
- package/dist/{src-C4x5Wx9t.js.map → src-TN3MwGgP.js.map} +1 -1
- package/package.json +4 -4
|
@@ -30238,7 +30238,24 @@ function isSystemReminderMessage(message) {
|
|
|
30238
30238
|
const firstTextPart = message.content.parts.find((part) => part.type === "text");
|
|
30239
30239
|
return typeof firstTextPart?.text === "string" && firstTextPart.text.startsWith("<system-reminder");
|
|
30240
30240
|
}
|
|
30241
|
-
function
|
|
30241
|
+
function isRecallSignalType(type) {
|
|
30242
|
+
return type === "user" || type === "state" || type === "reactive" || type === "notification" || type === "user-message" || type === "system-reminder";
|
|
30243
|
+
}
|
|
30244
|
+
function getRecallSignalType(message) {
|
|
30245
|
+
if (!isRecord(message.content)) return void 0;
|
|
30246
|
+
for (const part of message.content.parts) if ((part.type === "data-signal" || part.type === "data-user-message") && isRecord(part.data) && isRecallSignalType(part.data.type)) return part.data.type;
|
|
30247
|
+
const metadata = message.content.metadata;
|
|
30248
|
+
if (message.role === "signal" && isRecord(metadata) && isRecord(metadata.signal)) {
|
|
30249
|
+
if (isRecallSignalType(metadata.signal.type)) return metadata.signal.type;
|
|
30250
|
+
}
|
|
30251
|
+
return isSystemReminderMessage(message) ? "system-reminder" : void 0;
|
|
30252
|
+
}
|
|
30253
|
+
function filterSystemReminderMessages(messages, includeSystemReminders, hideSignals) {
|
|
30254
|
+
if (hideSignals === false) return messages;
|
|
30255
|
+
if (hideSignals !== void 0) return messages.filter((message) => {
|
|
30256
|
+
const type = getRecallSignalType(message);
|
|
30257
|
+
return type === void 0 || hideSignals !== true && !hideSignals.includes(type);
|
|
30258
|
+
});
|
|
30242
30259
|
if (includeSystemReminders) return messages;
|
|
30243
30260
|
return messages.filter((message) => !isSystemReminderMessage(message));
|
|
30244
30261
|
}
|
|
@@ -30265,8 +30282,35 @@ const DEFAULT_TOP_K = 4;
|
|
|
30265
30282
|
const VECTOR_DELETE_BATCH_SIZE = 100;
|
|
30266
30283
|
const DEFAULT_EMBEDDING_CACHE_MAX_SIZE = 1e3;
|
|
30267
30284
|
/**
|
|
30268
|
-
*
|
|
30269
|
-
* and
|
|
30285
|
+
* Gives Mastra agents conversation history, with optional working memory,
|
|
30286
|
+
* semantic recall, and observational memory.
|
|
30287
|
+
*
|
|
30288
|
+
* @remarks
|
|
30289
|
+
* Configure storage on this instance or its Mastra instance before use.
|
|
30290
|
+
* See the bundled docs for setup and conversation identifiers.
|
|
30291
|
+
*
|
|
30292
|
+
* @example
|
|
30293
|
+
* Attach memory to an agent; `yourModel` is your configured model.
|
|
30294
|
+
* ```typescript
|
|
30295
|
+
* import { Agent } from '@mastra/core/agent';
|
|
30296
|
+
* import { Memory } from '@mastra/memory';
|
|
30297
|
+
*
|
|
30298
|
+
* const agent = new Agent({
|
|
30299
|
+
* id: 'assistant',
|
|
30300
|
+
* name: 'Assistant',
|
|
30301
|
+
* instructions: 'You are a helpful assistant.',
|
|
30302
|
+
* model: yourModel,
|
|
30303
|
+
* memory: new Memory(),
|
|
30304
|
+
* });
|
|
30305
|
+
* ```
|
|
30306
|
+
*
|
|
30307
|
+
* @see For documentation bundled with your installed package, locate
|
|
30308
|
+
* `@mastra/memory/package.json` with your project's resolver or package-manager
|
|
30309
|
+
* tooling, then read `dist/docs/SKILL.md` from that package root and follow its
|
|
30310
|
+
* reference links. Use package-manager tools for virtual or archived packages.
|
|
30311
|
+
*
|
|
30312
|
+
* @see [Memory documentation](https://mastra.ai/docs/memory/overview)
|
|
30313
|
+
* if packaged docs are unavailable.
|
|
30270
30314
|
*/
|
|
30271
30315
|
var Memory = class Memory extends _mastra_core_memory.MastraMemory {
|
|
30272
30316
|
_omEngine;
|
|
@@ -30456,7 +30500,7 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
|
|
|
30456
30500
|
});
|
|
30457
30501
|
}
|
|
30458
30502
|
async recall(args) {
|
|
30459
|
-
const { threadId, resourceId, perPage: perPageArg, page, orderBy, threadConfig, vectorSearchString, includeSystemReminders, filter, includeTotal } = args;
|
|
30503
|
+
const { threadId, resourceId, perPage: perPageArg, page, orderBy, threadConfig, vectorSearchString, includeSystemReminders, hideSignals, filter, includeTotal } = args;
|
|
30460
30504
|
const config = this.getMergedThreadConfig(threadConfig || {});
|
|
30461
30505
|
const semanticRecallEnabled = Boolean(config.semanticRecall);
|
|
30462
30506
|
const span = this.createMemorySpan("recall", args.observabilityContext, {
|
|
@@ -30555,7 +30599,7 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
|
|
|
30555
30599
|
const messages = filterSystemReminderMessages(new _mastra_core_agent.MessageList({
|
|
30556
30600
|
threadId,
|
|
30557
30601
|
resourceId
|
|
30558
|
-
}).add(rawMessages, "memory").get.all.db(), includeSystemReminders);
|
|
30602
|
+
}).add(rawMessages, "memory").get.all.db(), includeSystemReminders, hideSignals);
|
|
30559
30603
|
const { total, page: resultPage, perPage: resultPerPage, hasMore } = paginatedResult;
|
|
30560
30604
|
const recallResult = {
|
|
30561
30605
|
messages,
|
|
@@ -31865,10 +31909,40 @@ Notes:
|
|
|
31865
31909
|
* ```
|
|
31866
31910
|
*/
|
|
31867
31911
|
async cloneThread(args, memoryConfig) {
|
|
31912
|
+
const result = await this.copyThread(args, memoryConfig);
|
|
31913
|
+
const { messages } = await (await this.getMemoryStore()).listMessages({
|
|
31914
|
+
threadId: result.thread.id,
|
|
31915
|
+
resourceId: result.thread.resourceId,
|
|
31916
|
+
perPage: false,
|
|
31917
|
+
orderBy: {
|
|
31918
|
+
field: "createdAt",
|
|
31919
|
+
direction: "ASC"
|
|
31920
|
+
}
|
|
31921
|
+
});
|
|
31922
|
+
return {
|
|
31923
|
+
...result,
|
|
31924
|
+
clonedMessages: messages
|
|
31925
|
+
};
|
|
31926
|
+
}
|
|
31927
|
+
/**
|
|
31928
|
+
* Copies a thread with all its messages to a new thread without returning the
|
|
31929
|
+
* message payloads. Working memory, observational memory, and semantic-recall
|
|
31930
|
+
* embeddings are carried over exactly as with `cloneThread`; the only difference
|
|
31931
|
+
* is that message content never has to be held in the Node heap at once.
|
|
31932
|
+
*
|
|
31933
|
+
* Use this instead of `cloneThread` when only the new thread id is needed
|
|
31934
|
+
* (e.g. forking a conversation for a subagent).
|
|
31935
|
+
*
|
|
31936
|
+
* @param args - Clone parameters, same as `cloneThread`
|
|
31937
|
+
* @param memoryConfig - Optional memory configuration override
|
|
31938
|
+
* @returns The newly created thread and the source→new message id map
|
|
31939
|
+
*/
|
|
31940
|
+
async copyThread(args, memoryConfig) {
|
|
31868
31941
|
const memoryStore = await this.getMemoryStore();
|
|
31869
|
-
const result = await memoryStore.cloneThread(args);
|
|
31870
31942
|
const config = this.getMergedThreadConfig(memoryConfig);
|
|
31943
|
+
const result = await memoryStore.copyThread(args);
|
|
31871
31944
|
const sourceResourceId = (await this.getThreadById({ threadId: args.sourceThreadId }))?.resourceId;
|
|
31945
|
+
let priorDestinationResourceWm;
|
|
31872
31946
|
if (config.workingMemory?.enabled) {
|
|
31873
31947
|
const scope = config.workingMemory.scope || "resource";
|
|
31874
31948
|
if (scope === "thread" || scope === "resource" && args.resourceId && args.resourceId !== sourceResourceId) {
|
|
@@ -31877,28 +31951,125 @@ Notes:
|
|
|
31877
31951
|
resourceId: sourceResourceId,
|
|
31878
31952
|
memoryConfig
|
|
31879
31953
|
});
|
|
31880
|
-
if (sourceWm)
|
|
31881
|
-
|
|
31882
|
-
|
|
31883
|
-
|
|
31884
|
-
|
|
31885
|
-
|
|
31954
|
+
if (sourceWm) {
|
|
31955
|
+
if (scope === "resource") priorDestinationResourceWm = (await memoryStore.getResourceById({ resourceId: result.thread.resourceId }))?.workingMemory ?? null;
|
|
31956
|
+
await this.updateWorkingMemory({
|
|
31957
|
+
threadId: result.thread.id,
|
|
31958
|
+
resourceId: result.thread.resourceId,
|
|
31959
|
+
workingMemory: sourceWm,
|
|
31960
|
+
memoryConfig
|
|
31961
|
+
});
|
|
31962
|
+
}
|
|
31886
31963
|
}
|
|
31887
31964
|
}
|
|
31888
31965
|
if (memoryStore.supportsObservationalMemory && sourceResourceId) try {
|
|
31889
31966
|
await this.cloneObservationalMemory(memoryStore, args.sourceThreadId, sourceResourceId, result);
|
|
31890
31967
|
} catch (error) {
|
|
31891
|
-
|
|
31892
|
-
|
|
31893
|
-
|
|
31894
|
-
|
|
31895
|
-
|
|
31968
|
+
await this.rollbackCopiedThread(memoryStore, result.thread, "OM clone", false, priorDestinationResourceWm);
|
|
31969
|
+
throw error;
|
|
31970
|
+
}
|
|
31971
|
+
if (this.vector && this.embedder && config.semanticRecall) try {
|
|
31972
|
+
await this.embedCopiedMessagesInBatches(memoryStore, result, config);
|
|
31973
|
+
} catch (error) {
|
|
31974
|
+
await this.rollbackCopiedThread(memoryStore, result.thread, "embedding", true, priorDestinationResourceWm);
|
|
31896
31975
|
throw error;
|
|
31897
31976
|
}
|
|
31898
|
-
if (this.vector && config.semanticRecall && result.clonedMessages.length > 0) await this.embedClonedMessages(result.clonedMessages, config);
|
|
31899
31977
|
return result;
|
|
31900
31978
|
}
|
|
31901
31979
|
/**
|
|
31980
|
+
* Best-effort compensation when a later step of copyThread fails after the destination thread
|
|
31981
|
+
* was persisted. deleteThread removes the thread, its messages and thread-scoped working memory.
|
|
31982
|
+
* `priorDestinationResourceWm` is the destination resource's working memory before the copy
|
|
31983
|
+
* overwrote it (`null` = none existed); when defined it is restored. When `afterOmClone` is set the OM step already succeeded, so the thread-scoped OM record and
|
|
31984
|
+
* any vectors written so far are dropped too. Resource-scoped OM is left alone: it may be
|
|
31985
|
+
* shared with a pre-existing resource and isn't safe to clear blindly.
|
|
31986
|
+
*/
|
|
31987
|
+
async rollbackCopiedThread(memoryStore, thread, failedStep, afterOmClone, priorDestinationResourceWm) {
|
|
31988
|
+
const threadId = thread.id;
|
|
31989
|
+
try {
|
|
31990
|
+
await memoryStore.deleteThread({ threadId });
|
|
31991
|
+
} catch (rollbackError) {
|
|
31992
|
+
this.logger.error(`Failed to rollback copied thread after ${failedStep} failure`, rollbackError);
|
|
31993
|
+
}
|
|
31994
|
+
if (priorDestinationResourceWm !== void 0) try {
|
|
31995
|
+
await memoryStore.updateResource({
|
|
31996
|
+
resourceId: thread.resourceId,
|
|
31997
|
+
workingMemory: priorDestinationResourceWm ?? ""
|
|
31998
|
+
});
|
|
31999
|
+
} catch (rollbackError) {
|
|
32000
|
+
this.logger.error(`Failed to restore resource working memory after ${failedStep} failure`, rollbackError);
|
|
32001
|
+
}
|
|
32002
|
+
if (!afterOmClone) return;
|
|
32003
|
+
if (memoryStore.supportsObservationalMemory) try {
|
|
32004
|
+
await memoryStore.clearObservationalMemory(threadId, thread.resourceId);
|
|
32005
|
+
} catch (rollbackError) {
|
|
32006
|
+
this.logger.error(`Failed to rollback copied thread OM after ${failedStep} failure`, rollbackError);
|
|
32007
|
+
}
|
|
32008
|
+
try {
|
|
32009
|
+
const messageIndexes = await this.getMemoryVectorIndexes([this.messageIndexPrefix]);
|
|
32010
|
+
await Promise.all(messageIndexes.map((indexName) => this.vector.deleteVectors({
|
|
32011
|
+
indexName,
|
|
32012
|
+
filter: { thread_id: threadId }
|
|
32013
|
+
})));
|
|
32014
|
+
} catch (rollbackError) {
|
|
32015
|
+
this.logger.error(`Failed to rollback copied thread vectors after ${failedStep} failure`, rollbackError);
|
|
32016
|
+
}
|
|
32017
|
+
}
|
|
32018
|
+
static CLONE_EMBED_PAGE_SIZE = 100;
|
|
32019
|
+
async embedCopiedMessagesInBatches(memoryStore, copied, config) {
|
|
32020
|
+
const size = Memory.CLONE_EMBED_PAGE_SIZE;
|
|
32021
|
+
const copiedIds = Object.values(copied.messageIdMap ?? {});
|
|
32022
|
+
if (copiedIds.length > 0) {
|
|
32023
|
+
for (let i = 0; i < copiedIds.length; i += size) {
|
|
32024
|
+
const { messages } = await memoryStore.listMessagesById({ messageIds: copiedIds.slice(i, i + size) });
|
|
32025
|
+
if (messages.length > 0) await this.embedClonedMessages(messages, config);
|
|
32026
|
+
}
|
|
32027
|
+
return;
|
|
32028
|
+
}
|
|
32029
|
+
const { messages } = await memoryStore.listMessages({
|
|
32030
|
+
threadId: copied.thread.id,
|
|
32031
|
+
resourceId: copied.thread.resourceId,
|
|
32032
|
+
perPage: false,
|
|
32033
|
+
includeTotal: false
|
|
32034
|
+
});
|
|
32035
|
+
for (let i = 0; i < messages.length; i += size) await this.embedClonedMessages(messages.slice(i, i + size), config);
|
|
32036
|
+
}
|
|
32037
|
+
async updateThreadResourceId({ threadId, resourceId, memoryConfig }) {
|
|
32038
|
+
const memoryStore = await this.getMemoryStore();
|
|
32039
|
+
const config = this.getMergedThreadConfig(memoryConfig);
|
|
32040
|
+
const migratesVectors = Boolean(this.vector && this.embedder && config.semanticRecall);
|
|
32041
|
+
if (!migratesVectors) {
|
|
32042
|
+
const existing = await memoryStore.getThreadById({ threadId });
|
|
32043
|
+
if (existing && existing.resourceId === resourceId) return existing;
|
|
32044
|
+
}
|
|
32045
|
+
const thread = await memoryStore.updateThreadResourceId({
|
|
32046
|
+
threadId,
|
|
32047
|
+
resourceId
|
|
32048
|
+
});
|
|
32049
|
+
if (migratesVectors) try {
|
|
32050
|
+
const { messages } = await memoryStore.listMessages({
|
|
32051
|
+
threadId,
|
|
32052
|
+
perPage: false
|
|
32053
|
+
});
|
|
32054
|
+
const messageIndexes = await this.getMemoryVectorIndexes([this.messageIndexPrefix]);
|
|
32055
|
+
await Promise.all(messageIndexes.map(async (indexName) => {
|
|
32056
|
+
await this.vector.deleteVectors({
|
|
32057
|
+
indexName,
|
|
32058
|
+
filter: { thread_id: threadId }
|
|
32059
|
+
});
|
|
32060
|
+
}));
|
|
32061
|
+
if (messages.length > 0) await this.embedClonedMessages(messages, config);
|
|
32062
|
+
} catch (error) {
|
|
32063
|
+
this.logger.error("Failed to migrate semantic-recall vectors during thread transfer", {
|
|
32064
|
+
threadId,
|
|
32065
|
+
resourceId,
|
|
32066
|
+
error: error instanceof Error ? error.message : String(error)
|
|
32067
|
+
});
|
|
32068
|
+
throw new Error(`Thread "${threadId}" was transferred to resource "${resourceId}", but migrating its semantic-recall vectors failed. The thread's messages may not surface under resource-scoped recall until the vectors are re-indexed. Cause: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
32069
|
+
}
|
|
32070
|
+
return thread;
|
|
32071
|
+
}
|
|
32072
|
+
/**
|
|
31902
32073
|
* Clone observational memory records when cloning a thread.
|
|
31903
32074
|
* Thread-scoped: always cloned to the new thread.
|
|
31904
32075
|
* Resource-scoped: cloned only when the resourceId changes (same resourceId shares OM naturally).
|
|
@@ -32482,4 +32653,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
32482
32653
|
}
|
|
32483
32654
|
});
|
|
32484
32655
|
|
|
32485
|
-
//# sourceMappingURL=src-
|
|
32656
|
+
//# sourceMappingURL=src-Bs9_1MCb.cjs.map
|