@mastra/memory 1.30.0-alpha.1 → 1.30.0-alpha.3
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 +5 -1
- 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 +60 -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/processors/observational-memory/observational-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/tracing.d.ts.map +1 -1
- package/dist/{src-Bze5SVTm.cjs → src-CJgJb_MC.cjs} +182 -27
- package/dist/src-CJgJb_MC.cjs.map +1 -0
- package/dist/{src-BNyqEQlx.js → src-t3Mhge0m.js} +182 -27
- package/dist/{src-BNyqEQlx.js.map → src-t3Mhge0m.js.map} +1 -1
- package/package.json +4 -4
- package/dist/src-Bze5SVTm.cjs.map +0 -1
|
@@ -19819,19 +19819,28 @@ const PHASE_CONFIG = {
|
|
|
19819
19819
|
};
|
|
19820
19820
|
async function withOmTracingSpan({ phase, model, inputTokens, requestContext, observabilityContext, metadata, callback }) {
|
|
19821
19821
|
const config = PHASE_CONFIG[phase];
|
|
19822
|
+
const tracingContext = observabilityContext?.tracingContext ?? observabilityContext?.tracing;
|
|
19823
|
+
const callerMetadata = tracingContext?.currentSpan?.metadata;
|
|
19824
|
+
const inheritedCallerThreadId = callerMetadata?.__mastraObservationalMemoryCallerThreadId;
|
|
19825
|
+
const callerThreadId = callerMetadata?.threadId;
|
|
19826
|
+
const requestThreadId = requestContext?.get(_mastra_core_request_context.MASTRA_THREAD_ID_KEY);
|
|
19827
|
+
const omCallerThreadId = typeof inheritedCallerThreadId === "string" && inheritedCallerThreadId ? inheritedCallerThreadId : typeof callerThreadId === "string" && callerThreadId ? callerThreadId : typeof requestThreadId === "string" && requestThreadId ? requestThreadId : void 0;
|
|
19822
19828
|
const span = (0, _mastra_core_observability.getOrCreateSpan)({
|
|
19823
19829
|
type: _mastra_core_observability.SpanType.MEMORY_OPERATION,
|
|
19824
19830
|
name: config.name,
|
|
19825
19831
|
entityType: _mastra_core_observability.EntityType.MEMORY,
|
|
19826
19832
|
entityName: config.entityName,
|
|
19827
|
-
tracingContext
|
|
19833
|
+
tracingContext,
|
|
19828
19834
|
attributes: {
|
|
19829
19835
|
operationType: config.operationType,
|
|
19830
19836
|
inputTokens,
|
|
19831
19837
|
selectedModel: typeof model === "string" ? model : "(dynamic-model)",
|
|
19832
19838
|
...config.multiThread ? { multiThread: true } : {}
|
|
19833
19839
|
},
|
|
19834
|
-
metadata
|
|
19840
|
+
metadata: omCallerThreadId !== void 0 ? {
|
|
19841
|
+
...metadata,
|
|
19842
|
+
__mastraObservationalMemoryCallerThreadId: omCallerThreadId
|
|
19843
|
+
} : metadata,
|
|
19835
19844
|
requestContext
|
|
19836
19845
|
});
|
|
19837
19846
|
const childObservabilityContext = (0, _mastra_core_observability.createObservabilityContext)({ currentSpan: span });
|
|
@@ -28513,7 +28522,7 @@ ${formattedMessages}
|
|
|
28513
28522
|
if (!this.buffering.isAsyncObservationEnabled()) return false;
|
|
28514
28523
|
const lockKey = this.buffering.getLockKey(opts.threadId, opts.resourceId);
|
|
28515
28524
|
const shouldTrigger = this.buffering.shouldTriggerAsyncObservation(opts.pendingTokens, lockKey, opts.record, this.storage, opts.threshold);
|
|
28516
|
-
if (shouldTrigger) this.trackBackgroundWork(this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext));
|
|
28525
|
+
if (shouldTrigger) this.trackBackgroundWork(this.startAsyncBufferedObservation(opts.record, opts.threadId, opts.unobservedMessages, lockKey, opts.writer, opts.unbufferedPendingTokens, opts.requestContext, opts.observabilityContext));
|
|
28517
28526
|
return shouldTrigger;
|
|
28518
28527
|
}
|
|
28519
28528
|
isMessageList(value) {
|
|
@@ -30282,8 +30291,35 @@ const DEFAULT_TOP_K = 4;
|
|
|
30282
30291
|
const VECTOR_DELETE_BATCH_SIZE = 100;
|
|
30283
30292
|
const DEFAULT_EMBEDDING_CACHE_MAX_SIZE = 1e3;
|
|
30284
30293
|
/**
|
|
30285
|
-
*
|
|
30286
|
-
* and
|
|
30294
|
+
* Gives Mastra agents conversation history, with optional working memory,
|
|
30295
|
+
* semantic recall, and observational memory.
|
|
30296
|
+
*
|
|
30297
|
+
* @remarks
|
|
30298
|
+
* Configure storage on this instance or its Mastra instance before use.
|
|
30299
|
+
* See the bundled docs for setup and conversation identifiers.
|
|
30300
|
+
*
|
|
30301
|
+
* @example
|
|
30302
|
+
* Attach memory to an agent; `yourModel` is your configured model.
|
|
30303
|
+
* ```typescript
|
|
30304
|
+
* import { Agent } from '@mastra/core/agent';
|
|
30305
|
+
* import { Memory } from '@mastra/memory';
|
|
30306
|
+
*
|
|
30307
|
+
* const agent = new Agent({
|
|
30308
|
+
* id: 'assistant',
|
|
30309
|
+
* name: 'Assistant',
|
|
30310
|
+
* instructions: 'You are a helpful assistant.',
|
|
30311
|
+
* model: yourModel,
|
|
30312
|
+
* memory: new Memory(),
|
|
30313
|
+
* });
|
|
30314
|
+
* ```
|
|
30315
|
+
*
|
|
30316
|
+
* @see For documentation bundled with your installed package, locate
|
|
30317
|
+
* `@mastra/memory/package.json` with your project's resolver or package-manager
|
|
30318
|
+
* tooling, then read `dist/docs/SKILL.md` from that package root and follow its
|
|
30319
|
+
* reference links. Use package-manager tools for virtual or archived packages.
|
|
30320
|
+
*
|
|
30321
|
+
* @see [Memory documentation](https://mastra.ai/docs/memory/overview)
|
|
30322
|
+
* if packaged docs are unavailable.
|
|
30287
30323
|
*/
|
|
30288
30324
|
var Memory = class Memory extends _mastra_core_memory.MastraMemory {
|
|
30289
30325
|
_omEngine;
|
|
@@ -31882,18 +31918,40 @@ Notes:
|
|
|
31882
31918
|
* ```
|
|
31883
31919
|
*/
|
|
31884
31920
|
async cloneThread(args, memoryConfig) {
|
|
31885
|
-
const
|
|
31886
|
-
const
|
|
31887
|
-
|
|
31888
|
-
|
|
31889
|
-
|
|
31890
|
-
|
|
31891
|
-
|
|
31892
|
-
|
|
31893
|
-
hydrateMessages: effectiveHydrate
|
|
31921
|
+
const result = await this.copyThread(args, memoryConfig);
|
|
31922
|
+
const { messages } = await (await this.getMemoryStore()).listMessages({
|
|
31923
|
+
threadId: result.thread.id,
|
|
31924
|
+
resourceId: result.thread.resourceId,
|
|
31925
|
+
perPage: false,
|
|
31926
|
+
orderBy: {
|
|
31927
|
+
field: "createdAt",
|
|
31928
|
+
direction: "ASC"
|
|
31894
31929
|
}
|
|
31895
31930
|
});
|
|
31931
|
+
return {
|
|
31932
|
+
...result,
|
|
31933
|
+
clonedMessages: messages
|
|
31934
|
+
};
|
|
31935
|
+
}
|
|
31936
|
+
/**
|
|
31937
|
+
* Copies a thread with all its messages to a new thread without returning the
|
|
31938
|
+
* message payloads. Working memory, observational memory, and semantic-recall
|
|
31939
|
+
* embeddings are carried over exactly as with `cloneThread`; the only difference
|
|
31940
|
+
* is that message content never has to be held in the Node heap at once.
|
|
31941
|
+
*
|
|
31942
|
+
* Use this instead of `cloneThread` when only the new thread id is needed
|
|
31943
|
+
* (e.g. forking a conversation for a subagent).
|
|
31944
|
+
*
|
|
31945
|
+
* @param args - Clone parameters, same as `cloneThread`
|
|
31946
|
+
* @param memoryConfig - Optional memory configuration override
|
|
31947
|
+
* @returns The newly created thread and the source→new message id map
|
|
31948
|
+
*/
|
|
31949
|
+
async copyThread(args, memoryConfig) {
|
|
31950
|
+
const memoryStore = await this.getMemoryStore();
|
|
31951
|
+
const config = this.getMergedThreadConfig(memoryConfig);
|
|
31952
|
+
const result = await memoryStore.copyThread(args);
|
|
31896
31953
|
const sourceResourceId = (await this.getThreadById({ threadId: args.sourceThreadId }))?.resourceId;
|
|
31954
|
+
let priorDestinationResourceWm;
|
|
31897
31955
|
if (config.workingMemory?.enabled) {
|
|
31898
31956
|
const scope = config.workingMemory.scope || "resource";
|
|
31899
31957
|
if (scope === "thread" || scope === "resource" && args.resourceId && args.resourceId !== sourceResourceId) {
|
|
@@ -31902,28 +31960,125 @@ Notes:
|
|
|
31902
31960
|
resourceId: sourceResourceId,
|
|
31903
31961
|
memoryConfig
|
|
31904
31962
|
});
|
|
31905
|
-
if (sourceWm)
|
|
31906
|
-
|
|
31907
|
-
|
|
31908
|
-
|
|
31909
|
-
|
|
31910
|
-
|
|
31963
|
+
if (sourceWm) {
|
|
31964
|
+
if (scope === "resource") priorDestinationResourceWm = (await memoryStore.getResourceById({ resourceId: result.thread.resourceId }))?.workingMemory ?? null;
|
|
31965
|
+
await this.updateWorkingMemory({
|
|
31966
|
+
threadId: result.thread.id,
|
|
31967
|
+
resourceId: result.thread.resourceId,
|
|
31968
|
+
workingMemory: sourceWm,
|
|
31969
|
+
memoryConfig
|
|
31970
|
+
});
|
|
31971
|
+
}
|
|
31911
31972
|
}
|
|
31912
31973
|
}
|
|
31913
31974
|
if (memoryStore.supportsObservationalMemory && sourceResourceId) try {
|
|
31914
31975
|
await this.cloneObservationalMemory(memoryStore, args.sourceThreadId, sourceResourceId, result);
|
|
31915
31976
|
} catch (error) {
|
|
31916
|
-
|
|
31917
|
-
|
|
31918
|
-
|
|
31919
|
-
|
|
31920
|
-
|
|
31977
|
+
await this.rollbackCopiedThread(memoryStore, result.thread, "OM clone", false, priorDestinationResourceWm);
|
|
31978
|
+
throw error;
|
|
31979
|
+
}
|
|
31980
|
+
if (this.vector && this.embedder && config.semanticRecall) try {
|
|
31981
|
+
await this.embedCopiedMessagesInBatches(memoryStore, result, config);
|
|
31982
|
+
} catch (error) {
|
|
31983
|
+
await this.rollbackCopiedThread(memoryStore, result.thread, "embedding", true, priorDestinationResourceWm);
|
|
31921
31984
|
throw error;
|
|
31922
31985
|
}
|
|
31923
|
-
if (this.vector && config.semanticRecall && result.clonedMessages.length > 0) await this.embedClonedMessages(result.clonedMessages, config);
|
|
31924
31986
|
return result;
|
|
31925
31987
|
}
|
|
31926
31988
|
/**
|
|
31989
|
+
* Best-effort compensation when a later step of copyThread fails after the destination thread
|
|
31990
|
+
* was persisted. deleteThread removes the thread, its messages and thread-scoped working memory.
|
|
31991
|
+
* `priorDestinationResourceWm` is the destination resource's working memory before the copy
|
|
31992
|
+
* 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
|
|
31993
|
+
* any vectors written so far are dropped too. Resource-scoped OM is left alone: it may be
|
|
31994
|
+
* shared with a pre-existing resource and isn't safe to clear blindly.
|
|
31995
|
+
*/
|
|
31996
|
+
async rollbackCopiedThread(memoryStore, thread, failedStep, afterOmClone, priorDestinationResourceWm) {
|
|
31997
|
+
const threadId = thread.id;
|
|
31998
|
+
try {
|
|
31999
|
+
await memoryStore.deleteThread({ threadId });
|
|
32000
|
+
} catch (rollbackError) {
|
|
32001
|
+
this.logger.error(`Failed to rollback copied thread after ${failedStep} failure`, rollbackError);
|
|
32002
|
+
}
|
|
32003
|
+
if (priorDestinationResourceWm !== void 0) try {
|
|
32004
|
+
await memoryStore.updateResource({
|
|
32005
|
+
resourceId: thread.resourceId,
|
|
32006
|
+
workingMemory: priorDestinationResourceWm ?? ""
|
|
32007
|
+
});
|
|
32008
|
+
} catch (rollbackError) {
|
|
32009
|
+
this.logger.error(`Failed to restore resource working memory after ${failedStep} failure`, rollbackError);
|
|
32010
|
+
}
|
|
32011
|
+
if (!afterOmClone) return;
|
|
32012
|
+
if (memoryStore.supportsObservationalMemory) try {
|
|
32013
|
+
await memoryStore.clearObservationalMemory(threadId, thread.resourceId);
|
|
32014
|
+
} catch (rollbackError) {
|
|
32015
|
+
this.logger.error(`Failed to rollback copied thread OM after ${failedStep} failure`, rollbackError);
|
|
32016
|
+
}
|
|
32017
|
+
try {
|
|
32018
|
+
const messageIndexes = await this.getMemoryVectorIndexes([this.messageIndexPrefix]);
|
|
32019
|
+
await Promise.all(messageIndexes.map((indexName) => this.vector.deleteVectors({
|
|
32020
|
+
indexName,
|
|
32021
|
+
filter: { thread_id: threadId }
|
|
32022
|
+
})));
|
|
32023
|
+
} catch (rollbackError) {
|
|
32024
|
+
this.logger.error(`Failed to rollback copied thread vectors after ${failedStep} failure`, rollbackError);
|
|
32025
|
+
}
|
|
32026
|
+
}
|
|
32027
|
+
static CLONE_EMBED_PAGE_SIZE = 100;
|
|
32028
|
+
async embedCopiedMessagesInBatches(memoryStore, copied, config) {
|
|
32029
|
+
const size = Memory.CLONE_EMBED_PAGE_SIZE;
|
|
32030
|
+
const copiedIds = Object.values(copied.messageIdMap ?? {});
|
|
32031
|
+
if (copiedIds.length > 0) {
|
|
32032
|
+
for (let i = 0; i < copiedIds.length; i += size) {
|
|
32033
|
+
const { messages } = await memoryStore.listMessagesById({ messageIds: copiedIds.slice(i, i + size) });
|
|
32034
|
+
if (messages.length > 0) await this.embedClonedMessages(messages, config);
|
|
32035
|
+
}
|
|
32036
|
+
return;
|
|
32037
|
+
}
|
|
32038
|
+
const { messages } = await memoryStore.listMessages({
|
|
32039
|
+
threadId: copied.thread.id,
|
|
32040
|
+
resourceId: copied.thread.resourceId,
|
|
32041
|
+
perPage: false,
|
|
32042
|
+
includeTotal: false
|
|
32043
|
+
});
|
|
32044
|
+
for (let i = 0; i < messages.length; i += size) await this.embedClonedMessages(messages.slice(i, i + size), config);
|
|
32045
|
+
}
|
|
32046
|
+
async updateThreadResourceId({ threadId, resourceId, memoryConfig }) {
|
|
32047
|
+
const memoryStore = await this.getMemoryStore();
|
|
32048
|
+
const config = this.getMergedThreadConfig(memoryConfig);
|
|
32049
|
+
const migratesVectors = Boolean(this.vector && this.embedder && config.semanticRecall);
|
|
32050
|
+
if (!migratesVectors) {
|
|
32051
|
+
const existing = await memoryStore.getThreadById({ threadId });
|
|
32052
|
+
if (existing && existing.resourceId === resourceId) return existing;
|
|
32053
|
+
}
|
|
32054
|
+
const thread = await memoryStore.updateThreadResourceId({
|
|
32055
|
+
threadId,
|
|
32056
|
+
resourceId
|
|
32057
|
+
});
|
|
32058
|
+
if (migratesVectors) try {
|
|
32059
|
+
const { messages } = await memoryStore.listMessages({
|
|
32060
|
+
threadId,
|
|
32061
|
+
perPage: false
|
|
32062
|
+
});
|
|
32063
|
+
const messageIndexes = await this.getMemoryVectorIndexes([this.messageIndexPrefix]);
|
|
32064
|
+
await Promise.all(messageIndexes.map(async (indexName) => {
|
|
32065
|
+
await this.vector.deleteVectors({
|
|
32066
|
+
indexName,
|
|
32067
|
+
filter: { thread_id: threadId }
|
|
32068
|
+
});
|
|
32069
|
+
}));
|
|
32070
|
+
if (messages.length > 0) await this.embedClonedMessages(messages, config);
|
|
32071
|
+
} catch (error) {
|
|
32072
|
+
this.logger.error("Failed to migrate semantic-recall vectors during thread transfer", {
|
|
32073
|
+
threadId,
|
|
32074
|
+
resourceId,
|
|
32075
|
+
error: error instanceof Error ? error.message : String(error)
|
|
32076
|
+
});
|
|
32077
|
+
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 });
|
|
32078
|
+
}
|
|
32079
|
+
return thread;
|
|
32080
|
+
}
|
|
32081
|
+
/**
|
|
31927
32082
|
* Clone observational memory records when cloning a thread.
|
|
31928
32083
|
* Thread-scoped: always cloned to the new thread.
|
|
31929
32084
|
* Resource-scoped: cloned only when the resourceId changes (same resourceId shares OM naturally).
|
|
@@ -32507,4 +32662,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
32507
32662
|
}
|
|
32508
32663
|
});
|
|
32509
32664
|
|
|
32510
|
-
//# sourceMappingURL=src-
|
|
32665
|
+
//# sourceMappingURL=src-CJgJb_MC.cjs.map
|