@mastra/memory 1.14.0-alpha.1 → 1.14.0

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/index.cjs CHANGED
@@ -2,13 +2,14 @@
2
2
 
3
3
  var chunkCK4U3AYR_cjs = require('./chunk-CK4U3AYR.cjs');
4
4
  var chunkIDRQZVB4_cjs = require('./chunk-IDRQZVB4.cjs');
5
- var chunkX7E3WPF2_cjs = require('./chunk-X7E3WPF2.cjs');
5
+ var chunkZVRO2GUN_cjs = require('./chunk-ZVRO2GUN.cjs');
6
6
  var v3 = require('zod/v3');
7
7
  var zod = require('zod');
8
8
  var z4 = require('zod/v4');
9
9
  var agent = require('@mastra/core/agent');
10
10
  var features = require('@mastra/core/features');
11
11
  var memory = require('@mastra/core/memory');
12
+ var observability = require('@mastra/core/observability');
12
13
  var utils = require('@mastra/core/utils');
13
14
  var schema = require('@mastra/schema-compat/schema');
14
15
  var asyncMutex = require('async-mutex');
@@ -15702,7 +15703,7 @@ function formatTimestamp(date) {
15702
15703
  }
15703
15704
  function truncateByTokens(text4, maxTokens, hint) {
15704
15705
  if (tokenx.estimateTokenCount(text4) <= maxTokens) return { text: text4, wasTruncated: false };
15705
- const truncated = chunkX7E3WPF2_cjs.truncateStringByTokens(text4, maxTokens);
15706
+ const truncated = chunkZVRO2GUN_cjs.truncateStringByTokens(text4, maxTokens);
15706
15707
  const suffix = hint ? ` [${hint} for more]` : "";
15707
15708
  return { text: truncated + suffix, wasTruncated: true };
15708
15709
  }
@@ -15735,11 +15736,11 @@ function formatMessageParts(msg, detail) {
15735
15736
  } else if (partType === "tool-invocation") {
15736
15737
  const inv = part.toolInvocation;
15737
15738
  if (inv.state === "result") {
15738
- const { value: resultValue } = chunkX7E3WPF2_cjs.resolveToolResultValue(
15739
+ const { value: resultValue } = chunkZVRO2GUN_cjs.resolveToolResultValue(
15739
15740
  part,
15740
15741
  inv.result
15741
15742
  );
15742
- const resultStr = chunkX7E3WPF2_cjs.formatToolResultForObserver(resultValue, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
15743
+ const resultStr = chunkZVRO2GUN_cjs.formatToolResultForObserver(resultValue, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
15743
15744
  const fullText = `[Tool Result: ${inv.toolName}]
15744
15745
  ${resultStr}`;
15745
15746
  parts.push(makePart(msg, i, "tool-result", fullText, detail));
@@ -15823,7 +15824,7 @@ function renderFormattedParts(parts, timestamps, options) {
15823
15824
  const text4 = buildRenderedText(parts, timestamps);
15824
15825
  let totalTokens = tokenx.estimateTokenCount(text4);
15825
15826
  if (totalTokens > options.maxTokens) {
15826
- const truncated = chunkX7E3WPF2_cjs.truncateStringByTokens(text4, options.maxTokens);
15827
+ const truncated = chunkZVRO2GUN_cjs.truncateStringByTokens(text4, options.maxTokens);
15827
15828
  return { text: truncated, truncated: true, tokenOffset: totalTokens - options.maxTokens };
15828
15829
  }
15829
15830
  const truncatedIndices = parts.map((p, i) => ({ part: p, index: i })).filter(({ part }) => part.text !== part.fullText).sort((a, b) => expandPriority(a.part) - expandPriority(b.part));
@@ -15856,7 +15857,7 @@ function renderFormattedParts(parts, timestamps, options) {
15856
15857
  if (expandedTokens <= options.maxTokens) {
15857
15858
  return { text: expanded, truncated: false, tokenOffset: 0 };
15858
15859
  }
15859
- const hardTruncated = chunkX7E3WPF2_cjs.truncateStringByTokens(expanded, options.maxTokens);
15860
+ const hardTruncated = chunkZVRO2GUN_cjs.truncateStringByTokens(expanded, options.maxTokens);
15860
15861
  return { text: hardTruncated, truncated: true, tokenOffset: expandedTokens - options.maxTokens };
15861
15862
  }
15862
15863
  async function recallPart({
@@ -15907,7 +15908,7 @@ async function recallPart({
15907
15908
 
15908
15909
  `;
15909
15910
  const fallbackText = `${fallbackNote}${firstNextPart.text}`;
15910
- const truncatedText2 = chunkX7E3WPF2_cjs.truncateStringByTokens(fallbackText, maxTokens);
15911
+ const truncatedText2 = chunkZVRO2GUN_cjs.truncateStringByTokens(fallbackText, maxTokens);
15911
15912
  const wasTruncated2 = truncatedText2 !== fallbackText;
15912
15913
  return {
15913
15914
  text: truncatedText2,
@@ -15922,7 +15923,7 @@ async function recallPart({
15922
15923
  }
15923
15924
  throw new Error(`Part index ${partIndex} not found in message ${cursor}. Available indices: ${availableIndices}`);
15924
15925
  }
15925
- const truncatedText = chunkX7E3WPF2_cjs.truncateStringByTokens(target.text, maxTokens);
15926
+ const truncatedText = chunkZVRO2GUN_cjs.truncateStringByTokens(target.text, maxTokens);
15926
15927
  const wasTruncated = truncatedText !== target.text;
15927
15928
  return {
15928
15929
  text: truncatedText,
@@ -16621,94 +16622,149 @@ var Memory = class extends memory.MastraMemory {
16621
16622
  );
16622
16623
  }
16623
16624
  }
16625
+ createMemorySpan(operationType, observabilityContext, input, attributes) {
16626
+ const currentSpan = observabilityContext?.tracingContext?.currentSpan;
16627
+ if (!currentSpan) return void 0;
16628
+ return currentSpan.createChildSpan({
16629
+ type: observability.SpanType.MEMORY_OPERATION,
16630
+ name: `memory: ${operationType}`,
16631
+ entityType: observability.EntityType.MEMORY,
16632
+ entityName: "Memory",
16633
+ input,
16634
+ attributes: { operationType, ...attributes }
16635
+ });
16636
+ }
16624
16637
  async recall(args) {
16625
- const { threadId, resourceId, perPage: perPageArg, page, orderBy, threadConfig, vectorSearchString, filter: filter3 } = args;
16626
- const config = this.getMergedThreadConfig(threadConfig || {});
16627
- if (resourceId) await this.validateThreadIsOwnedByResource(threadId, resourceId, config);
16628
- const perPage = perPageArg !== void 0 ? perPageArg : config.lastMessages;
16629
- const historyDisabledByConfig = config.lastMessages === false && perPageArg === void 0;
16630
- const shouldGetNewestAndReverse = !orderBy && perPage !== false;
16631
- const effectiveOrderBy = shouldGetNewestAndReverse ? { field: "createdAt", direction: "DESC" } : orderBy;
16632
- const vectorResults = [];
16633
- this.logger.debug("Memory recall", {
16638
+ const {
16634
16639
  threadId,
16635
- perPage,
16640
+ resourceId,
16641
+ perPage: perPageArg,
16636
16642
  page,
16637
- orderBy: effectiveOrderBy,
16638
- hasWorkingMemorySchema: Boolean(config.workingMemory?.schema),
16639
- workingMemoryEnabled: config.workingMemory?.enabled,
16640
- semanticRecallEnabled: Boolean(config.semanticRecall),
16641
- historyDisabledByConfig
16642
- });
16643
- const defaultRange = DEFAULT_MESSAGE_RANGE;
16644
- const defaultTopK = DEFAULT_TOP_K;
16645
- const vectorConfig = typeof config?.semanticRecall === `boolean` ? {
16646
- topK: defaultTopK,
16647
- messageRange: defaultRange
16648
- } : {
16649
- topK: config?.semanticRecall?.topK ?? defaultTopK,
16650
- messageRange: config?.semanticRecall?.messageRange ?? defaultRange
16651
- };
16652
- const resourceScope = typeof config?.semanticRecall === "object" && config?.semanticRecall?.scope !== `thread` || config.semanticRecall === true;
16653
- if (resourceScope && !resourceId && config?.semanticRecall && vectorSearchString) {
16654
- throw new Error(
16655
- `Memory error: Resource-scoped semantic recall is enabled but no resourceId was provided. Either provide a resourceId or explicitly set semanticRecall.scope to 'thread'.`
16656
- );
16657
- }
16658
- let usage;
16659
- if (historyDisabledByConfig && (!config.semanticRecall || !vectorSearchString || !this.vector)) {
16660
- return { messages: [], usage: void 0, total: 0, page: page ?? 0, perPage: 0, hasMore: false };
16661
- }
16662
- if (config?.semanticRecall && vectorSearchString && this.vector) {
16663
- const result = await this.embedMessageContent(vectorSearchString);
16664
- usage = result.usage;
16665
- const { embeddings, dimension } = result;
16666
- const { indexName } = await this.createEmbeddingIndex(dimension, config);
16667
- await Promise.all(
16668
- embeddings.map(async (embedding) => {
16669
- if (typeof this.vector === `undefined`) {
16670
- throw new Error(
16671
- `Tried to query vector index ${indexName} but this Memory instance doesn't have an attached vector db.`
16643
+ orderBy,
16644
+ threadConfig,
16645
+ vectorSearchString,
16646
+ includeSystemReminders,
16647
+ filter: filter3
16648
+ } = args;
16649
+ const config = this.getMergedThreadConfig(threadConfig || {});
16650
+ const semanticRecallEnabled = Boolean(config.semanticRecall);
16651
+ const span = this.createMemorySpan(
16652
+ "recall",
16653
+ args.observabilityContext,
16654
+ { threadId, resourceId, vectorSearchString },
16655
+ {
16656
+ semanticRecallEnabled,
16657
+ lastMessages: config.lastMessages
16658
+ }
16659
+ );
16660
+ try {
16661
+ if (resourceId) await this.validateThreadIsOwnedByResource(threadId, resourceId, config);
16662
+ const perPage = perPageArg !== void 0 ? perPageArg : config.lastMessages;
16663
+ const historyDisabledByConfig = config.lastMessages === false && perPageArg === void 0;
16664
+ const shouldGetNewestAndReverse = !orderBy && perPage !== false;
16665
+ const effectiveOrderBy = shouldGetNewestAndReverse ? { field: "createdAt", direction: "DESC" } : orderBy;
16666
+ const vectorResults = [];
16667
+ this.logger.debug("Memory recall", {
16668
+ threadId,
16669
+ perPage,
16670
+ page,
16671
+ orderBy: effectiveOrderBy,
16672
+ hasWorkingMemorySchema: Boolean(config.workingMemory?.schema),
16673
+ workingMemoryEnabled: config.workingMemory?.enabled,
16674
+ semanticRecallEnabled,
16675
+ historyDisabledByConfig
16676
+ });
16677
+ const defaultRange = DEFAULT_MESSAGE_RANGE;
16678
+ const defaultTopK = DEFAULT_TOP_K;
16679
+ const vectorConfig = typeof config?.semanticRecall === `boolean` ? {
16680
+ topK: defaultTopK,
16681
+ messageRange: defaultRange
16682
+ } : {
16683
+ topK: config?.semanticRecall?.topK ?? defaultTopK,
16684
+ messageRange: config?.semanticRecall?.messageRange ?? defaultRange
16685
+ };
16686
+ const resourceScope = typeof config?.semanticRecall === "object" && config?.semanticRecall?.scope !== `thread` || config.semanticRecall === true;
16687
+ if (resourceScope && !resourceId && config?.semanticRecall && vectorSearchString) {
16688
+ throw new Error(
16689
+ `Memory error: Resource-scoped semantic recall is enabled but no resourceId was provided. Either provide a resourceId or explicitly set semanticRecall.scope to 'thread'.`
16690
+ );
16691
+ }
16692
+ let usage;
16693
+ if (historyDisabledByConfig && (!config.semanticRecall || !vectorSearchString || !this.vector)) {
16694
+ const result = {
16695
+ messages: [],
16696
+ usage: void 0,
16697
+ total: 0,
16698
+ page: page ?? 0,
16699
+ perPage: 0,
16700
+ hasMore: false
16701
+ };
16702
+ span?.end({ output: { success: true }, attributes: { messageCount: 0 } });
16703
+ return result;
16704
+ }
16705
+ if (config?.semanticRecall && vectorSearchString && this.vector) {
16706
+ const result = await this.embedMessageContent(vectorSearchString);
16707
+ usage = result.usage;
16708
+ const { embeddings, dimension } = result;
16709
+ const { indexName } = await this.createEmbeddingIndex(dimension, config);
16710
+ await Promise.all(
16711
+ embeddings.map(async (embedding) => {
16712
+ if (typeof this.vector === `undefined`) {
16713
+ throw new Error(
16714
+ `Tried to query vector index ${indexName} but this Memory instance doesn't have an attached vector db.`
16715
+ );
16716
+ }
16717
+ vectorResults.push(
16718
+ ...await this.vector.query({
16719
+ indexName,
16720
+ queryVector: embedding,
16721
+ topK: vectorConfig.topK,
16722
+ filter: resourceScope ? {
16723
+ resource_id: resourceId
16724
+ } : {
16725
+ thread_id: threadId
16726
+ }
16727
+ })
16672
16728
  );
16673
- }
16674
- vectorResults.push(
16675
- ...await this.vector.query({
16676
- indexName,
16677
- queryVector: embedding,
16678
- topK: vectorConfig.topK,
16679
- filter: resourceScope ? {
16680
- resource_id: resourceId
16681
- } : {
16682
- thread_id: threadId
16683
- }
16684
- })
16685
- );
16686
- })
16687
- );
16729
+ })
16730
+ );
16731
+ }
16732
+ const memoryStore = await this.getMemoryStore();
16733
+ const effectivePerPage = historyDisabledByConfig ? 0 : perPage;
16734
+ const paginatedResult = await memoryStore.listMessages({
16735
+ threadId,
16736
+ resourceId,
16737
+ perPage: effectivePerPage,
16738
+ page,
16739
+ orderBy: effectiveOrderBy,
16740
+ filter: filter3,
16741
+ ...vectorResults?.length ? {
16742
+ include: vectorResults.map((r) => ({
16743
+ id: r.metadata?.message_id,
16744
+ threadId: r.metadata?.thread_id,
16745
+ withNextMessages: typeof vectorConfig.messageRange === "number" ? vectorConfig.messageRange : vectorConfig.messageRange.after,
16746
+ withPreviousMessages: typeof vectorConfig.messageRange === "number" ? vectorConfig.messageRange : vectorConfig.messageRange.before
16747
+ }))
16748
+ } : {}
16749
+ });
16750
+ const rawMessages = shouldGetNewestAndReverse ? paginatedResult.messages.reverse() : paginatedResult.messages;
16751
+ const list = new agent.MessageList({ threadId, resourceId }).add(rawMessages, "memory");
16752
+ const messages = memory.filterSystemReminderMessages(list.get.all.db(), includeSystemReminders);
16753
+ const { total, page: resultPage, perPage: resultPerPage, hasMore } = paginatedResult;
16754
+ const recallResult = { messages, usage, total, page: resultPage, perPage: resultPerPage, hasMore };
16755
+ span?.end({
16756
+ output: { success: true },
16757
+ attributes: {
16758
+ messageCount: messages.length,
16759
+ embeddingTokens: usage?.tokens,
16760
+ vectorResultCount: vectorResults.length
16761
+ }
16762
+ });
16763
+ return recallResult;
16764
+ } catch (error) {
16765
+ span?.error({ error, endSpan: true });
16766
+ throw error;
16688
16767
  }
16689
- const memoryStore = await this.getMemoryStore();
16690
- const effectivePerPage = historyDisabledByConfig ? 0 : perPage;
16691
- const paginatedResult = await memoryStore.listMessages({
16692
- threadId,
16693
- resourceId,
16694
- perPage: effectivePerPage,
16695
- page,
16696
- orderBy: effectiveOrderBy,
16697
- filter: filter3,
16698
- ...vectorResults?.length ? {
16699
- include: vectorResults.map((r) => ({
16700
- id: r.metadata?.message_id,
16701
- threadId: r.metadata?.thread_id,
16702
- withNextMessages: typeof vectorConfig.messageRange === "number" ? vectorConfig.messageRange : vectorConfig.messageRange.after,
16703
- withPreviousMessages: typeof vectorConfig.messageRange === "number" ? vectorConfig.messageRange : vectorConfig.messageRange.before
16704
- }))
16705
- } : {}
16706
- });
16707
- const rawMessages = shouldGetNewestAndReverse ? paginatedResult.messages.reverse() : paginatedResult.messages;
16708
- const list = new agent.MessageList({ threadId, resourceId }).add(rawMessages, "memory");
16709
- const messages = list.get.all.db();
16710
- const { total, page: resultPage, perPage: resultPerPage, hasMore } = paginatedResult;
16711
- return { messages, usage, total, page: resultPage, perPage: resultPerPage, hasMore };
16712
16768
  }
16713
16769
  async getThreadById({ threadId }) {
16714
16770
  const memoryStore = await this.getMemoryStore();
@@ -16818,45 +16874,60 @@ var Memory = class extends memory.MastraMemory {
16818
16874
  threadId,
16819
16875
  resourceId,
16820
16876
  workingMemory,
16821
- memoryConfig
16877
+ memoryConfig,
16878
+ observabilityContext
16822
16879
  }) {
16823
16880
  const config = this.getMergedThreadConfig(memoryConfig || {});
16824
16881
  if (!config.workingMemory?.enabled) {
16825
16882
  throw new Error("Working memory is not enabled for this memory instance");
16826
16883
  }
16827
- const scope = config.workingMemory.scope || "resource";
16828
- if (scope === "resource" && !resourceId) {
16829
- throw new Error(
16830
- `Memory error: Resource-scoped working memory is enabled but no resourceId was provided. Either provide a resourceId or explicitly set workingMemory.scope to 'thread'.`
16831
- );
16832
- }
16833
- const mutexKey = scope === "resource" ? `resource-${resourceId}` : `thread-${threadId}`;
16834
- const mutex = this.updateWorkingMemoryMutexes.has(mutexKey) ? this.updateWorkingMemoryMutexes.get(mutexKey) : new asyncMutex.Mutex();
16835
- this.updateWorkingMemoryMutexes.set(mutexKey, mutex);
16836
- const release = await mutex.acquire();
16884
+ const span = this.createMemorySpan(
16885
+ "update",
16886
+ observabilityContext,
16887
+ { threadId, resourceId },
16888
+ {
16889
+ workingMemoryEnabled: true
16890
+ }
16891
+ );
16837
16892
  try {
16838
- const memoryStore = await this.getMemoryStore();
16839
- if (scope === "resource" && resourceId) {
16840
- await memoryStore.updateResource({
16841
- resourceId,
16842
- workingMemory
16843
- });
16844
- } else {
16845
- const thread = await this.getThreadById({ threadId });
16846
- if (!thread) {
16847
- throw new Error(`Thread ${threadId} not found`);
16848
- }
16849
- await memoryStore.updateThread({
16850
- id: threadId,
16851
- title: thread.title || "",
16852
- metadata: {
16853
- ...thread.metadata,
16893
+ const scope = config.workingMemory.scope || "resource";
16894
+ if (scope === "resource" && !resourceId) {
16895
+ throw new Error(
16896
+ `Memory error: Resource-scoped working memory is enabled but no resourceId was provided. Either provide a resourceId or explicitly set workingMemory.scope to 'thread'.`
16897
+ );
16898
+ }
16899
+ const mutexKey = scope === "resource" ? `resource-${resourceId}` : `thread-${threadId}`;
16900
+ const mutex = this.updateWorkingMemoryMutexes.has(mutexKey) ? this.updateWorkingMemoryMutexes.get(mutexKey) : new asyncMutex.Mutex();
16901
+ this.updateWorkingMemoryMutexes.set(mutexKey, mutex);
16902
+ const release = await mutex.acquire();
16903
+ try {
16904
+ const memoryStore = await this.getMemoryStore();
16905
+ if (scope === "resource" && resourceId) {
16906
+ await memoryStore.updateResource({
16907
+ resourceId,
16854
16908
  workingMemory
16909
+ });
16910
+ } else {
16911
+ const thread = await this.getThreadById({ threadId });
16912
+ if (!thread) {
16913
+ throw new Error(`Thread ${threadId} not found`);
16855
16914
  }
16856
- });
16915
+ await memoryStore.updateThread({
16916
+ id: threadId,
16917
+ title: thread.title || "",
16918
+ metadata: {
16919
+ ...thread.metadata,
16920
+ workingMemory
16921
+ }
16922
+ });
16923
+ }
16924
+ } finally {
16925
+ release();
16857
16926
  }
16858
- } finally {
16859
- release();
16927
+ span?.end({ output: { success: true } });
16928
+ } catch (error) {
16929
+ span?.error({ error, endSpan: true });
16930
+ throw error;
16860
16931
  }
16861
16932
  }
16862
16933
  updateWorkingMemoryMutexes = /* @__PURE__ */ new Map();
@@ -17034,67 +17105,85 @@ ${workingMemory}`;
17034
17105
  }
17035
17106
  async saveMessages({
17036
17107
  messages,
17037
- memoryConfig
17108
+ memoryConfig,
17109
+ observabilityContext
17038
17110
  }) {
17039
- const updatedMessages = messages.map((m) => {
17040
- return this.updateMessageToHideWorkingMemoryV2(m);
17041
- }).filter((m) => Boolean(m));
17042
- const config = this.getMergedThreadConfig(memoryConfig);
17043
- const dbMessages = new agent.MessageList({
17044
- generateMessageId: () => this.generateId()
17045
- }).add(updatedMessages, "memory").get.all.db();
17046
- const memoryStore = await this.getMemoryStore();
17047
- const result = await memoryStore.saveMessages({
17048
- messages: dbMessages
17111
+ const span = this.createMemorySpan("save", observabilityContext, void 0, {
17112
+ messageCount: messages.length
17049
17113
  });
17050
- let totalTokens = 0;
17051
- if (this.vector && config.semanticRecall) {
17052
- const embeddingData = [];
17053
- let dimension;
17054
- await Promise.all(
17055
- updatedMessages.map(async (message) => {
17056
- let textForEmbedding = null;
17057
- if (message.content.content && typeof message.content.content === "string" && message.content.content.trim() !== "") {
17058
- textForEmbedding = message.content.content;
17059
- } else if (message.content.parts && message.content.parts.length > 0) {
17060
- const joined = message.content.parts.filter((part) => part.type === "text").map((part) => part.text).join(" ").trim();
17061
- if (joined) textForEmbedding = joined;
17114
+ try {
17115
+ const updatedMessages = messages.map((m) => {
17116
+ return this.updateMessageToHideWorkingMemoryV2(m);
17117
+ }).filter((m) => Boolean(m));
17118
+ const config = this.getMergedThreadConfig(memoryConfig);
17119
+ const dbMessages = new agent.MessageList({
17120
+ generateMessageId: () => this.generateId()
17121
+ }).add(updatedMessages, "memory").get.all.db();
17122
+ const memoryStore = await this.getMemoryStore();
17123
+ const result = await memoryStore.saveMessages({
17124
+ messages: dbMessages
17125
+ });
17126
+ let totalTokens = 0;
17127
+ if (this.vector && config.semanticRecall) {
17128
+ const embeddingData = [];
17129
+ let dimension;
17130
+ await Promise.all(
17131
+ updatedMessages.map(async (message) => {
17132
+ let textForEmbedding = null;
17133
+ if (message.content.content && typeof message.content.content === "string" && message.content.content.trim() !== "") {
17134
+ textForEmbedding = message.content.content;
17135
+ } else if (message.content.parts && message.content.parts.length > 0) {
17136
+ const joined = message.content.parts.filter((part) => part.type === "text").map((part) => part.text).join(" ").trim();
17137
+ if (joined) textForEmbedding = joined;
17138
+ }
17139
+ if (!textForEmbedding) return;
17140
+ const result2 = await this.embedMessageContent(textForEmbedding);
17141
+ dimension = result2.dimension;
17142
+ if (result2.usage?.tokens) {
17143
+ totalTokens += result2.usage.tokens;
17144
+ }
17145
+ embeddingData.push({
17146
+ embeddings: result2.embeddings,
17147
+ metadata: result2.chunks.map(() => ({
17148
+ message_id: message.id,
17149
+ thread_id: message.threadId,
17150
+ resource_id: message.resourceId
17151
+ }))
17152
+ });
17153
+ })
17154
+ );
17155
+ if (embeddingData.length > 0 && dimension !== void 0) {
17156
+ if (typeof this.vector === `undefined`) {
17157
+ throw new Error(`Tried to upsert embeddings but this Memory instance doesn't have an attached vector db.`);
17062
17158
  }
17063
- if (!textForEmbedding) return;
17064
- const result2 = await this.embedMessageContent(textForEmbedding);
17065
- dimension = result2.dimension;
17066
- if (result2.usage?.tokens) {
17067
- totalTokens += result2.usage.tokens;
17159
+ const { indexName } = await this.createEmbeddingIndex(dimension, config);
17160
+ const allVectors = [];
17161
+ const allMetadata = [];
17162
+ for (const data of embeddingData) {
17163
+ allVectors.push(...data.embeddings);
17164
+ allMetadata.push(...data.metadata);
17068
17165
  }
17069
- embeddingData.push({
17070
- embeddings: result2.embeddings,
17071
- metadata: result2.chunks.map(() => ({
17072
- message_id: message.id,
17073
- thread_id: message.threadId,
17074
- resource_id: message.resourceId
17075
- }))
17166
+ await this.vector.upsert({
17167
+ indexName,
17168
+ vectors: allVectors,
17169
+ metadata: allMetadata
17076
17170
  });
17077
- })
17078
- );
17079
- if (embeddingData.length > 0 && dimension !== void 0) {
17080
- if (typeof this.vector === `undefined`) {
17081
- throw new Error(`Tried to upsert embeddings but this Memory instance doesn't have an attached vector db.`);
17082
- }
17083
- const { indexName } = await this.createEmbeddingIndex(dimension, config);
17084
- const allVectors = [];
17085
- const allMetadata = [];
17086
- for (const data of embeddingData) {
17087
- allVectors.push(...data.embeddings);
17088
- allMetadata.push(...data.metadata);
17089
17171
  }
17090
- await this.vector.upsert({
17091
- indexName,
17092
- vectors: allVectors,
17093
- metadata: allMetadata
17094
- });
17095
17172
  }
17173
+ const saveResult = { ...result, usage: totalTokens > 0 ? { tokens: totalTokens } : void 0 };
17174
+ span?.end({
17175
+ output: { success: true },
17176
+ attributes: {
17177
+ messageCount: dbMessages.length,
17178
+ embeddingTokens: saveResult.usage?.tokens,
17179
+ semanticRecallEnabled: Boolean(config.semanticRecall)
17180
+ }
17181
+ });
17182
+ return saveResult;
17183
+ } catch (error) {
17184
+ span?.error({ error, endSpan: true });
17185
+ throw error;
17096
17186
  }
17097
- return { ...result, usage: totalTokens > 0 ? { tokens: totalTokens } : void 0 };
17098
17187
  }
17099
17188
  updateMessageToHideWorkingMemoryV2(message) {
17100
17189
  const newMessage = { ...message };
@@ -17366,7 +17455,7 @@ ${workingMemory}`;
17366
17455
  "Observational memory requires @mastra/core support for request-response-id-rotation. Please bump @mastra/core to a newer version."
17367
17456
  );
17368
17457
  }
17369
- const { ObservationalMemory: OMClass } = await import('./observational-memory-22RZ4253.cjs');
17458
+ const { ObservationalMemory: OMClass } = await import('./observational-memory-IRCDSDUB.cjs');
17370
17459
  const onIndexObservations = this.hasRetrievalSearch(omConfig.retrieval) ? async (observation) => {
17371
17460
  await this.indexObservation(observation);
17372
17461
  } : void 0;
@@ -17629,6 +17718,32 @@ Notes:
17629
17718
  }))
17630
17719
  });
17631
17720
  }
17721
+ /**
17722
+ * Update per-record observational memory config overrides for a thread.
17723
+ * The provided config is deep-merged, so you only need to specify fields you want to change.
17724
+ *
17725
+ * @example
17726
+ * ```ts
17727
+ * await memory.updateObservationalMemoryConfig({
17728
+ * threadId: 'thread-1',
17729
+ * config: {
17730
+ * observation: { messageTokens: 2000 },
17731
+ * reflection: { observationTokens: 8000 },
17732
+ * },
17733
+ * });
17734
+ * ```
17735
+ */
17736
+ async updateObservationalMemoryConfig({
17737
+ threadId,
17738
+ resourceId,
17739
+ config
17740
+ }) {
17741
+ const omEngine = await this.omEngine;
17742
+ if (!omEngine) {
17743
+ throw new Error("Observational memory is not enabled");
17744
+ }
17745
+ await omEngine.updateRecordConfig(threadId, resourceId, config);
17746
+ }
17632
17747
  /**
17633
17748
  * Index a list of messages directly (without querying storage).
17634
17749
  * Used by observe-time indexing to vectorize newly-observed messages.
@@ -17802,7 +17917,7 @@ Notes:
17802
17917
  * - Message objects with 'id' properties
17803
17918
  * @returns Promise that resolves when all messages are deleted
17804
17919
  */
17805
- async deleteMessages(input) {
17920
+ async deleteMessages(input, observabilityContext) {
17806
17921
  let messageIds;
17807
17922
  if (!Array.isArray(input)) {
17808
17923
  throw new Error("Invalid input: must be an array of message IDs or message objects");
@@ -17823,10 +17938,19 @@ Notes:
17823
17938
  if (invalidIds.length > 0) {
17824
17939
  throw new Error("All message IDs must be non-empty strings");
17825
17940
  }
17826
- const memoryStore = await this.getMemoryStore();
17827
- await memoryStore.deleteMessages(messageIds);
17828
- if (this.vector) {
17829
- void this.deleteMessageVectors(messageIds);
17941
+ const span = this.createMemorySpan("delete", observabilityContext, void 0, {
17942
+ messageCount: messageIds.length
17943
+ });
17944
+ try {
17945
+ const memoryStore = await this.getMemoryStore();
17946
+ await memoryStore.deleteMessages(messageIds);
17947
+ if (this.vector) {
17948
+ void this.deleteMessageVectors(messageIds);
17949
+ }
17950
+ span?.end({ output: { success: true }, attributes: { messageCount: messageIds.length } });
17951
+ } catch (error) {
17952
+ span?.error({ error, endSpan: true });
17953
+ throw error;
17830
17954
  }
17831
17955
  }
17832
17956
  /**
@@ -18254,18 +18378,18 @@ Notes:
18254
18378
  if (!effectiveConfig) return null;
18255
18379
  const engine = await this.omEngine;
18256
18380
  if (!engine) return null;
18257
- const { ObservationalMemoryProcessor } = await import('./observational-memory-22RZ4253.cjs');
18381
+ const { ObservationalMemoryProcessor } = await import('./observational-memory-IRCDSDUB.cjs');
18258
18382
  return new ObservationalMemoryProcessor(engine, this);
18259
18383
  }
18260
18384
  };
18261
18385
 
18262
18386
  Object.defineProperty(exports, "ModelByInputTokens", {
18263
18387
  enumerable: true,
18264
- get: function () { return chunkX7E3WPF2_cjs.ModelByInputTokens; }
18388
+ get: function () { return chunkZVRO2GUN_cjs.ModelByInputTokens; }
18265
18389
  });
18266
18390
  Object.defineProperty(exports, "getObservationsAsOf", {
18267
18391
  enumerable: true,
18268
- get: function () { return chunkX7E3WPF2_cjs.getObservationsAsOf; }
18392
+ get: function () { return chunkZVRO2GUN_cjs.getObservationsAsOf; }
18269
18393
  });
18270
18394
  Object.defineProperty(exports, "extractWorkingMemoryContent", {
18271
18395
  enumerable: true,