@mastra/memory 1.11.1-alpha.0 → 1.12.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +32 -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 +7 -7
  38. package/dist/chunk-2NZR2XHO.js.map +0 -1
  39. package/dist/chunk-W2RTLXNQ.cjs.map +0 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { __commonJS, require_token_error, __toESM } from './chunk-SVPZMV27.js';
2
2
  import { __commonJS as __commonJS$1, require_token_error as require_token_error$1, __toESM as __toESM$1 } from './chunk-RC6RZVYE.js';
3
- import { truncateStringByTokens, resolveToolResultValue, formatToolResultForObserver } from './chunk-2NZR2XHO.js';
4
- export { ModelByInputTokens, getObservationsAsOf } from './chunk-2NZR2XHO.js';
3
+ import { truncateStringByTokens, resolveToolResultValue, formatToolResultForObserver } from './chunk-DDQHE4NV.js';
4
+ export { ModelByInputTokens, getObservationsAsOf } from './chunk-DDQHE4NV.js';
5
5
  import { ZodFirstPartyTypeKind } from 'zod/v3';
6
6
  import { z } from 'zod';
7
7
  import * as z4 from 'zod/v4';
@@ -15465,18 +15465,54 @@ async function resolveCursorMessage(memory, cursor, access) {
15465
15465
  }
15466
15466
  const memoryStore = await memory.getMemoryStore();
15467
15467
  const result = await memoryStore.listMessagesById({ messageIds: [normalized] });
15468
- const message = result.messages.find((message2) => message2.id === normalized);
15468
+ let message = result.messages.find((message2) => message2.id === normalized) ?? null;
15469
+ if (!message) {
15470
+ message = await resolveCursorMessageByRecall(memory, normalized, access);
15471
+ }
15469
15472
  if (!message) {
15470
15473
  throw new Error(`Could not resolve cursor message: ${cursor}`);
15471
15474
  }
15472
15475
  if (access?.resourceId && message.resourceId !== access.resourceId) {
15473
15476
  throw new Error(`Could not resolve cursor message: ${cursor}`);
15474
15477
  }
15475
- if (access?.threadScope && message.threadId !== access.threadScope) {
15478
+ if (access?.enforceThreadScope && access.threadScope && message.threadId !== access.threadScope) {
15476
15479
  throw new Error(`Could not resolve cursor message: ${cursor}`);
15477
15480
  }
15478
15481
  return message;
15479
15482
  }
15483
+ async function resolveCursorMessageByRecall(memory, cursor, access) {
15484
+ if (access?.enforceThreadScope && access.threadScope) {
15485
+ const result = await memory.recall({
15486
+ threadId: access.threadScope,
15487
+ resourceId: access.resourceId,
15488
+ page: 0,
15489
+ perPage: false
15490
+ });
15491
+ return result.messages.find((message) => message.id === cursor) ?? null;
15492
+ }
15493
+ if (!access?.resourceId) {
15494
+ return null;
15495
+ }
15496
+ const threads = await memory.listThreads({
15497
+ page: 0,
15498
+ perPage: 100,
15499
+ orderBy: { field: "updatedAt", direction: "DESC" },
15500
+ filter: { resourceId: access.resourceId }
15501
+ });
15502
+ for (const thread of threads.threads) {
15503
+ const result = await memory.recall({
15504
+ threadId: thread.id,
15505
+ resourceId: access.resourceId,
15506
+ page: 0,
15507
+ perPage: false
15508
+ });
15509
+ const message = result.messages.find((message2) => message2.id === cursor);
15510
+ if (message) {
15511
+ return message;
15512
+ }
15513
+ }
15514
+ return null;
15515
+ }
15480
15516
  async function listThreadsForResource({
15481
15517
  memory,
15482
15518
  resourceId,
@@ -15727,6 +15763,27 @@ function buildRenderedText(parts, timestamps) {
15727
15763
  }
15728
15764
  return lines.join("\n");
15729
15765
  }
15766
+ async function getNextVisibleMessage({
15767
+ memory,
15768
+ threadId,
15769
+ resourceId,
15770
+ after
15771
+ }) {
15772
+ const result = await memory.recall({
15773
+ threadId,
15774
+ resourceId,
15775
+ page: 0,
15776
+ perPage: 50,
15777
+ orderBy: { field: "createdAt", direction: "ASC" },
15778
+ filter: {
15779
+ dateRange: {
15780
+ start: after,
15781
+ startExclusive: true
15782
+ }
15783
+ }
15784
+ });
15785
+ return result.messages.find(hasVisibleParts) ?? null;
15786
+ }
15730
15787
  var MAX_EXPAND_USER_TEXT_TOKENS = 200;
15731
15788
  var MAX_EXPAND_OTHER_TOKENS = 50;
15732
15789
  function expandLimit(part) {
@@ -15795,7 +15852,11 @@ async function recallPart({
15795
15852
  if (!threadId) {
15796
15853
  throw new Error("Thread ID is required for recall");
15797
15854
  }
15798
- const resolved = await resolveCursorMessage(memory, cursor, { resourceId, threadScope });
15855
+ const resolved = await resolveCursorMessage(memory, cursor, {
15856
+ resourceId,
15857
+ threadScope,
15858
+ enforceThreadScope: false
15859
+ });
15799
15860
  if ("hint" in resolved) {
15800
15861
  throw new Error(resolved.hint);
15801
15862
  }
@@ -15807,9 +15868,37 @@ async function recallPart({
15807
15868
  }
15808
15869
  const target = allParts.find((p) => p.partIndex === partIndex);
15809
15870
  if (!target) {
15810
- throw new Error(
15811
- `Part index ${partIndex} not found in message ${cursor}. Available indices: ${allParts.map((p) => p.partIndex).join(", ")}`
15812
- );
15871
+ const availableIndices = allParts.map((p) => p.partIndex).join(", ");
15872
+ const highestVisiblePartIndex = Math.max(...allParts.map((p) => p.partIndex));
15873
+ if (partIndex > highestVisiblePartIndex) {
15874
+ const nextMessage = await getNextVisibleMessage({
15875
+ memory,
15876
+ threadId,
15877
+ resourceId,
15878
+ after: resolved.createdAt
15879
+ });
15880
+ if (nextMessage) {
15881
+ const nextParts = formatMessageParts(nextMessage, "high");
15882
+ const firstNextPart = nextParts[0];
15883
+ if (firstNextPart) {
15884
+ const fallbackNote = `Part index ${partIndex} not found in message ${cursor}; showing partIndex ${firstNextPart.partIndex} from next message ${firstNextPart.messageId}.
15885
+
15886
+ `;
15887
+ const fallbackText = `${fallbackNote}${firstNextPart.text}`;
15888
+ const truncatedText2 = truncateStringByTokens(fallbackText, maxTokens);
15889
+ const wasTruncated2 = truncatedText2 !== fallbackText;
15890
+ return {
15891
+ text: truncatedText2,
15892
+ messageId: firstNextPart.messageId,
15893
+ partIndex: firstNextPart.partIndex,
15894
+ role: firstNextPart.role,
15895
+ type: firstNextPart.type,
15896
+ truncated: wasTruncated2
15897
+ };
15898
+ }
15899
+ }
15900
+ }
15901
+ throw new Error(`Part index ${partIndex} not found in message ${cursor}. Available indices: ${availableIndices}`);
15813
15902
  }
15814
15903
  const truncatedText = truncateStringByTokens(target.text, maxTokens);
15815
15904
  const wasTruncated = truncatedText !== target.text;
@@ -15847,7 +15936,11 @@ async function recallMessages({
15847
15936
  const rawPage = page === 0 ? 1 : page;
15848
15937
  const normalizedPage = Math.max(Math.min(rawPage, MAX_PAGE), -MAX_PAGE);
15849
15938
  const normalizedLimit = Math.min(limit, MAX_LIMIT);
15850
- const resolved = await resolveCursorMessage(memory, cursor, { resourceId, threadScope });
15939
+ const resolved = await resolveCursorMessage(memory, cursor, {
15940
+ resourceId,
15941
+ threadScope,
15942
+ enforceThreadScope: false
15943
+ });
15851
15944
  if ("hint" in resolved) {
15852
15945
  return {
15853
15946
  messages: resolved.hint,
@@ -15863,9 +15956,10 @@ async function recallMessages({
15863
15956
  };
15864
15957
  }
15865
15958
  const anchor = resolved;
15866
- if (anchor.threadId && anchor.threadId !== threadId) {
15959
+ const crossThreadId = anchor.threadId && anchor.threadId !== threadId ? anchor.threadId : void 0;
15960
+ if (crossThreadId && threadScope) {
15867
15961
  return {
15868
- messages: `Cursor does not belong to the active thread. Expected thread "${threadId}" but cursor "${cursor}" belongs to "${anchor.threadId}".`,
15962
+ 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.`,
15869
15963
  count: 0,
15870
15964
  cursor,
15871
15965
  page: normalizedPage,
@@ -15877,7 +15971,10 @@ async function recallMessages({
15877
15971
  tokenOffset: 0
15878
15972
  };
15879
15973
  }
15880
- const resolvedThreadId = threadId;
15974
+ const resolvedThreadId = crossThreadId ?? threadId;
15975
+ if (!resolvedThreadId) {
15976
+ throw new Error("Thread ID is required for recall");
15977
+ }
15881
15978
  const isForward = normalizedPage > 0;
15882
15979
  const pageIndex = Math.max(Math.abs(normalizedPage), 1) - 1;
15883
15980
  const skip = pageIndex * normalizedLimit;
@@ -16159,7 +16256,25 @@ var recallTool = (_memoryConfig, options) => {
16159
16256
  threadScope = currentThreadId || void 0;
16160
16257
  }
16161
16258
  if (hasCursor && !hasExplicitThreadId && !currentThreadId) {
16162
- throw new Error("Current thread is required when browsing by cursor");
16259
+ if (!isResourceScope) {
16260
+ throw new Error("Current thread is required when browsing by cursor");
16261
+ }
16262
+ const resolved = await resolveCursorMessage(memory, cursor, { resourceId });
16263
+ if ("hint" in resolved) {
16264
+ return {
16265
+ messages: resolved.hint,
16266
+ count: 0,
16267
+ cursor,
16268
+ page: page ?? 1,
16269
+ limit: Math.min(limit ?? 20, 20),
16270
+ detail: detail ?? "low",
16271
+ hasNextPage: false,
16272
+ hasPrevPage: false,
16273
+ truncated: false,
16274
+ tokenOffset: 0
16275
+ };
16276
+ }
16277
+ targetThreadId = resolved.threadId;
16163
16278
  }
16164
16279
  if (!targetThreadId) {
16165
16280
  throw new Error("Thread ID is required for recall");
@@ -17226,7 +17341,7 @@ ${workingMemory}`;
17226
17341
  "Observational memory requires @mastra/core support for request-response-id-rotation. Please bump @mastra/core to a newer version."
17227
17342
  );
17228
17343
  }
17229
- const { ObservationalMemory: OMClass } = await import('./observational-memory-SASGM6OW.js');
17344
+ const { ObservationalMemory: OMClass } = await import('./observational-memory-B25SASRW.js');
17230
17345
  const onIndexObservations = this.hasRetrievalSearch(omConfig.retrieval) ? async (observation) => {
17231
17346
  await this.indexObservation(observation);
17232
17347
  } : void 0;
@@ -18114,7 +18229,7 @@ Notes:
18114
18229
  if (!effectiveConfig) return null;
18115
18230
  const engine = await this.omEngine;
18116
18231
  if (!engine) return null;
18117
- const { ObservationalMemoryProcessor } = await import('./observational-memory-SASGM6OW.js');
18232
+ const { ObservationalMemoryProcessor } = await import('./observational-memory-B25SASRW.js');
18118
18233
  return new ObservationalMemoryProcessor(engine, this);
18119
18234
  }
18120
18235
  };