@mastra/memory 1.11.1-alpha.0 → 1.12.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +1 -1
  3. package/dist/{chunk-2NZR2XHO.js → chunk-DDQHE4NV.js} +38 -20
  4. package/dist/chunk-DDQHE4NV.js.map +1 -0
  5. package/dist/{chunk-W2RTLXNQ.cjs → chunk-HLGFIN4J.cjs} +38 -20
  6. package/dist/chunk-HLGFIN4J.cjs.map +1 -0
  7. package/dist/docs/SKILL.md +1 -1
  8. package/dist/docs/assets/SOURCE_MAP.json +39 -39
  9. package/dist/docs/references/docs-memory-message-history.md +6 -4
  10. package/dist/docs/references/docs-memory-observational-memory.md +20 -11
  11. package/dist/docs/references/docs-memory-overview.md +4 -4
  12. package/dist/docs/references/docs-memory-semantic-recall.md +28 -19
  13. package/dist/docs/references/docs-memory-storage.md +4 -4
  14. package/dist/docs/references/reference-memory-observational-memory.md +1 -1
  15. package/dist/docs/references/reference-storage-dynamodb.md +1 -1
  16. package/dist/docs/references/reference-storage-upstash.md +1 -1
  17. package/dist/index.cjs +137 -22
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.js +130 -15
  20. package/dist/index.js.map +1 -1
  21. package/dist/{observational-memory-JCPPBSVG.cjs → observational-memory-34W4S4I5.cjs} +26 -26
  22. package/dist/{observational-memory-JCPPBSVG.cjs.map → observational-memory-34W4S4I5.cjs.map} +1 -1
  23. package/dist/{observational-memory-SASGM6OW.js → observational-memory-B25SASRW.js} +3 -3
  24. package/dist/{observational-memory-SASGM6OW.js.map → observational-memory-B25SASRW.js.map} +1 -1
  25. package/dist/processors/index.cjs +24 -24
  26. package/dist/processors/index.js +1 -1
  27. package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts +1 -0
  28. package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts.map +1 -1
  29. package/dist/processors/observational-memory/observation-strategies/base.d.ts +7 -2
  30. package/dist/processors/observational-memory/observation-strategies/base.d.ts.map +1 -1
  31. package/dist/processors/observational-memory/observation-strategies/resource-scoped.d.ts +1 -0
  32. package/dist/processors/observational-memory/observation-strategies/resource-scoped.d.ts.map +1 -1
  33. package/dist/processors/observational-memory/observation-strategies/sync.d.ts +1 -0
  34. package/dist/processors/observational-memory/observation-strategies/sync.d.ts.map +1 -1
  35. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  36. package/dist/tools/om-tools.d.ts.map +1 -1
  37. package/package.json +2 -2
  38. package/dist/chunk-2NZR2XHO.js.map +0 -1
  39. package/dist/chunk-W2RTLXNQ.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var chunkCK4U3AYR_cjs = require('./chunk-CK4U3AYR.cjs');
4
4
  var chunkIDRQZVB4_cjs = require('./chunk-IDRQZVB4.cjs');
5
- var chunkW2RTLXNQ_cjs = require('./chunk-W2RTLXNQ.cjs');
5
+ var chunkHLGFIN4J_cjs = require('./chunk-HLGFIN4J.cjs');
6
6
  var v3 = require('zod/v3');
7
7
  var zod = require('zod');
8
8
  var z4 = require('zod/v4');
@@ -15487,18 +15487,54 @@ async function resolveCursorMessage(memory, cursor, access) {
15487
15487
  }
15488
15488
  const memoryStore = await memory.getMemoryStore();
15489
15489
  const result = await memoryStore.listMessagesById({ messageIds: [normalized] });
15490
- const message = result.messages.find((message2) => message2.id === normalized);
15490
+ let message = result.messages.find((message2) => message2.id === normalized) ?? null;
15491
+ if (!message) {
15492
+ message = await resolveCursorMessageByRecall(memory, normalized, access);
15493
+ }
15491
15494
  if (!message) {
15492
15495
  throw new Error(`Could not resolve cursor message: ${cursor}`);
15493
15496
  }
15494
15497
  if (access?.resourceId && message.resourceId !== access.resourceId) {
15495
15498
  throw new Error(`Could not resolve cursor message: ${cursor}`);
15496
15499
  }
15497
- if (access?.threadScope && message.threadId !== access.threadScope) {
15500
+ if (access?.enforceThreadScope && access.threadScope && message.threadId !== access.threadScope) {
15498
15501
  throw new Error(`Could not resolve cursor message: ${cursor}`);
15499
15502
  }
15500
15503
  return message;
15501
15504
  }
15505
+ async function resolveCursorMessageByRecall(memory, cursor, access) {
15506
+ if (access?.enforceThreadScope && access.threadScope) {
15507
+ const result = await memory.recall({
15508
+ threadId: access.threadScope,
15509
+ resourceId: access.resourceId,
15510
+ page: 0,
15511
+ perPage: false
15512
+ });
15513
+ return result.messages.find((message) => message.id === cursor) ?? null;
15514
+ }
15515
+ if (!access?.resourceId) {
15516
+ return null;
15517
+ }
15518
+ const threads = await memory.listThreads({
15519
+ page: 0,
15520
+ perPage: 100,
15521
+ orderBy: { field: "updatedAt", direction: "DESC" },
15522
+ filter: { resourceId: access.resourceId }
15523
+ });
15524
+ for (const thread of threads.threads) {
15525
+ const result = await memory.recall({
15526
+ threadId: thread.id,
15527
+ resourceId: access.resourceId,
15528
+ page: 0,
15529
+ perPage: false
15530
+ });
15531
+ const message = result.messages.find((message2) => message2.id === cursor);
15532
+ if (message) {
15533
+ return message;
15534
+ }
15535
+ }
15536
+ return null;
15537
+ }
15502
15538
  async function listThreadsForResource({
15503
15539
  memory,
15504
15540
  resourceId,
@@ -15666,7 +15702,7 @@ function formatTimestamp(date) {
15666
15702
  }
15667
15703
  function truncateByTokens(text4, maxTokens, hint) {
15668
15704
  if (tokenx.estimateTokenCount(text4) <= maxTokens) return { text: text4, wasTruncated: false };
15669
- const truncated = chunkW2RTLXNQ_cjs.truncateStringByTokens(text4, maxTokens);
15705
+ const truncated = chunkHLGFIN4J_cjs.truncateStringByTokens(text4, maxTokens);
15670
15706
  const suffix = hint ? ` [${hint} for more]` : "";
15671
15707
  return { text: truncated + suffix, wasTruncated: true };
15672
15708
  }
@@ -15699,11 +15735,11 @@ function formatMessageParts(msg, detail) {
15699
15735
  } else if (partType === "tool-invocation") {
15700
15736
  const inv = part.toolInvocation;
15701
15737
  if (inv.state === "result") {
15702
- const { value: resultValue } = chunkW2RTLXNQ_cjs.resolveToolResultValue(
15738
+ const { value: resultValue } = chunkHLGFIN4J_cjs.resolveToolResultValue(
15703
15739
  part,
15704
15740
  inv.result
15705
15741
  );
15706
- const resultStr = chunkW2RTLXNQ_cjs.formatToolResultForObserver(resultValue, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
15742
+ const resultStr = chunkHLGFIN4J_cjs.formatToolResultForObserver(resultValue, { maxTokens: HIGH_DETAIL_TOOL_RESULT_TOKENS });
15707
15743
  const fullText = `[Tool Result: ${inv.toolName}]
15708
15744
  ${resultStr}`;
15709
15745
  parts.push(makePart(msg, i, "tool-result", fullText, detail));
@@ -15749,6 +15785,27 @@ function buildRenderedText(parts, timestamps) {
15749
15785
  }
15750
15786
  return lines.join("\n");
15751
15787
  }
15788
+ async function getNextVisibleMessage({
15789
+ memory,
15790
+ threadId,
15791
+ resourceId,
15792
+ after
15793
+ }) {
15794
+ const result = await memory.recall({
15795
+ threadId,
15796
+ resourceId,
15797
+ page: 0,
15798
+ perPage: 50,
15799
+ orderBy: { field: "createdAt", direction: "ASC" },
15800
+ filter: {
15801
+ dateRange: {
15802
+ start: after,
15803
+ startExclusive: true
15804
+ }
15805
+ }
15806
+ });
15807
+ return result.messages.find(hasVisibleParts) ?? null;
15808
+ }
15752
15809
  var MAX_EXPAND_USER_TEXT_TOKENS = 200;
15753
15810
  var MAX_EXPAND_OTHER_TOKENS = 50;
15754
15811
  function expandLimit(part) {
@@ -15766,7 +15823,7 @@ function renderFormattedParts(parts, timestamps, options) {
15766
15823
  const text4 = buildRenderedText(parts, timestamps);
15767
15824
  let totalTokens = tokenx.estimateTokenCount(text4);
15768
15825
  if (totalTokens > options.maxTokens) {
15769
- const truncated = chunkW2RTLXNQ_cjs.truncateStringByTokens(text4, options.maxTokens);
15826
+ const truncated = chunkHLGFIN4J_cjs.truncateStringByTokens(text4, options.maxTokens);
15770
15827
  return { text: truncated, truncated: true, tokenOffset: totalTokens - options.maxTokens };
15771
15828
  }
15772
15829
  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));
@@ -15799,7 +15856,7 @@ function renderFormattedParts(parts, timestamps, options) {
15799
15856
  if (expandedTokens <= options.maxTokens) {
15800
15857
  return { text: expanded, truncated: false, tokenOffset: 0 };
15801
15858
  }
15802
- const hardTruncated = chunkW2RTLXNQ_cjs.truncateStringByTokens(expanded, options.maxTokens);
15859
+ const hardTruncated = chunkHLGFIN4J_cjs.truncateStringByTokens(expanded, options.maxTokens);
15803
15860
  return { text: hardTruncated, truncated: true, tokenOffset: expandedTokens - options.maxTokens };
15804
15861
  }
15805
15862
  async function recallPart({
@@ -15817,7 +15874,11 @@ async function recallPart({
15817
15874
  if (!threadId) {
15818
15875
  throw new Error("Thread ID is required for recall");
15819
15876
  }
15820
- const resolved = await resolveCursorMessage(memory, cursor, { resourceId, threadScope });
15877
+ const resolved = await resolveCursorMessage(memory, cursor, {
15878
+ resourceId,
15879
+ threadScope,
15880
+ enforceThreadScope: false
15881
+ });
15821
15882
  if ("hint" in resolved) {
15822
15883
  throw new Error(resolved.hint);
15823
15884
  }
@@ -15829,11 +15890,39 @@ async function recallPart({
15829
15890
  }
15830
15891
  const target = allParts.find((p) => p.partIndex === partIndex);
15831
15892
  if (!target) {
15832
- throw new Error(
15833
- `Part index ${partIndex} not found in message ${cursor}. Available indices: ${allParts.map((p) => p.partIndex).join(", ")}`
15834
- );
15893
+ const availableIndices = allParts.map((p) => p.partIndex).join(", ");
15894
+ const highestVisiblePartIndex = Math.max(...allParts.map((p) => p.partIndex));
15895
+ if (partIndex > highestVisiblePartIndex) {
15896
+ const nextMessage = await getNextVisibleMessage({
15897
+ memory,
15898
+ threadId,
15899
+ resourceId,
15900
+ after: resolved.createdAt
15901
+ });
15902
+ if (nextMessage) {
15903
+ const nextParts = formatMessageParts(nextMessage, "high");
15904
+ const firstNextPart = nextParts[0];
15905
+ if (firstNextPart) {
15906
+ const fallbackNote = `Part index ${partIndex} not found in message ${cursor}; showing partIndex ${firstNextPart.partIndex} from next message ${firstNextPart.messageId}.
15907
+
15908
+ `;
15909
+ const fallbackText = `${fallbackNote}${firstNextPart.text}`;
15910
+ const truncatedText2 = chunkHLGFIN4J_cjs.truncateStringByTokens(fallbackText, maxTokens);
15911
+ const wasTruncated2 = truncatedText2 !== fallbackText;
15912
+ return {
15913
+ text: truncatedText2,
15914
+ messageId: firstNextPart.messageId,
15915
+ partIndex: firstNextPart.partIndex,
15916
+ role: firstNextPart.role,
15917
+ type: firstNextPart.type,
15918
+ truncated: wasTruncated2
15919
+ };
15920
+ }
15921
+ }
15922
+ }
15923
+ throw new Error(`Part index ${partIndex} not found in message ${cursor}. Available indices: ${availableIndices}`);
15835
15924
  }
15836
- const truncatedText = chunkW2RTLXNQ_cjs.truncateStringByTokens(target.text, maxTokens);
15925
+ const truncatedText = chunkHLGFIN4J_cjs.truncateStringByTokens(target.text, maxTokens);
15837
15926
  const wasTruncated = truncatedText !== target.text;
15838
15927
  return {
15839
15928
  text: truncatedText,
@@ -15869,7 +15958,11 @@ async function recallMessages({
15869
15958
  const rawPage = page === 0 ? 1 : page;
15870
15959
  const normalizedPage = Math.max(Math.min(rawPage, MAX_PAGE), -MAX_PAGE);
15871
15960
  const normalizedLimit = Math.min(limit, MAX_LIMIT);
15872
- const resolved = await resolveCursorMessage(memory, cursor, { resourceId, threadScope });
15961
+ const resolved = await resolveCursorMessage(memory, cursor, {
15962
+ resourceId,
15963
+ threadScope,
15964
+ enforceThreadScope: false
15965
+ });
15873
15966
  if ("hint" in resolved) {
15874
15967
  return {
15875
15968
  messages: resolved.hint,
@@ -15885,9 +15978,10 @@ async function recallMessages({
15885
15978
  };
15886
15979
  }
15887
15980
  const anchor = resolved;
15888
- if (anchor.threadId && anchor.threadId !== threadId) {
15981
+ const crossThreadId = anchor.threadId && anchor.threadId !== threadId ? anchor.threadId : void 0;
15982
+ if (crossThreadId && threadScope) {
15889
15983
  return {
15890
- messages: `Cursor does not belong to the active thread. Expected thread "${threadId}" but cursor "${cursor}" belongs to "${anchor.threadId}".`,
15984
+ messages: `Cursor does not belong to the active thread. Expected thread "${threadId}" but cursor "${cursor}" belongs to "${anchor.threadId}". Pass threadId="${anchor.threadId}" to browse that thread, or omit threadId and use this cursor directly in resource scope.`,
15891
15985
  count: 0,
15892
15986
  cursor,
15893
15987
  page: normalizedPage,
@@ -15899,7 +15993,10 @@ async function recallMessages({
15899
15993
  tokenOffset: 0
15900
15994
  };
15901
15995
  }
15902
- const resolvedThreadId = threadId;
15996
+ const resolvedThreadId = crossThreadId ?? threadId;
15997
+ if (!resolvedThreadId) {
15998
+ throw new Error("Thread ID is required for recall");
15999
+ }
15903
16000
  const isForward = normalizedPage > 0;
15904
16001
  const pageIndex = Math.max(Math.abs(normalizedPage), 1) - 1;
15905
16002
  const skip = pageIndex * normalizedLimit;
@@ -16181,7 +16278,25 @@ var recallTool = (_memoryConfig, options) => {
16181
16278
  threadScope = currentThreadId || void 0;
16182
16279
  }
16183
16280
  if (hasCursor && !hasExplicitThreadId && !currentThreadId) {
16184
- throw new Error("Current thread is required when browsing by cursor");
16281
+ if (!isResourceScope) {
16282
+ throw new Error("Current thread is required when browsing by cursor");
16283
+ }
16284
+ const resolved = await resolveCursorMessage(memory, cursor, { resourceId });
16285
+ if ("hint" in resolved) {
16286
+ return {
16287
+ messages: resolved.hint,
16288
+ count: 0,
16289
+ cursor,
16290
+ page: page ?? 1,
16291
+ limit: Math.min(limit ?? 20, 20),
16292
+ detail: detail ?? "low",
16293
+ hasNextPage: false,
16294
+ hasPrevPage: false,
16295
+ truncated: false,
16296
+ tokenOffset: 0
16297
+ };
16298
+ }
16299
+ targetThreadId = resolved.threadId;
16185
16300
  }
16186
16301
  if (!targetThreadId) {
16187
16302
  throw new Error("Thread ID is required for recall");
@@ -17248,7 +17363,7 @@ ${workingMemory}`;
17248
17363
  "Observational memory requires @mastra/core support for request-response-id-rotation. Please bump @mastra/core to a newer version."
17249
17364
  );
17250
17365
  }
17251
- const { ObservationalMemory: OMClass } = await import('./observational-memory-JCPPBSVG.cjs');
17366
+ const { ObservationalMemory: OMClass } = await import('./observational-memory-34W4S4I5.cjs');
17252
17367
  const onIndexObservations = this.hasRetrievalSearch(omConfig.retrieval) ? async (observation) => {
17253
17368
  await this.indexObservation(observation);
17254
17369
  } : void 0;
@@ -18136,18 +18251,18 @@ Notes:
18136
18251
  if (!effectiveConfig) return null;
18137
18252
  const engine = await this.omEngine;
18138
18253
  if (!engine) return null;
18139
- const { ObservationalMemoryProcessor } = await import('./observational-memory-JCPPBSVG.cjs');
18254
+ const { ObservationalMemoryProcessor } = await import('./observational-memory-34W4S4I5.cjs');
18140
18255
  return new ObservationalMemoryProcessor(engine, this);
18141
18256
  }
18142
18257
  };
18143
18258
 
18144
18259
  Object.defineProperty(exports, "ModelByInputTokens", {
18145
18260
  enumerable: true,
18146
- get: function () { return chunkW2RTLXNQ_cjs.ModelByInputTokens; }
18261
+ get: function () { return chunkHLGFIN4J_cjs.ModelByInputTokens; }
18147
18262
  });
18148
18263
  Object.defineProperty(exports, "getObservationsAsOf", {
18149
18264
  enumerable: true,
18150
- get: function () { return chunkW2RTLXNQ_cjs.getObservationsAsOf; }
18265
+ get: function () { return chunkHLGFIN4J_cjs.getObservationsAsOf; }
18151
18266
  });
18152
18267
  Object.defineProperty(exports, "extractWorkingMemoryContent", {
18153
18268
  enumerable: true,